Issue when linking with `-lrt` on Mac OSX - c

On my Mac OSX 10.13, I always use the following makefile to compile C codes:
TARGET = run
LIBS = -O2 -lm -lrt
CC = gcc
.PHONY: default all clean
all: $(TARGET)
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) $(CFLAGS) $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
Note that I use -lrt on purpose because I use #include <aio.h> for some of my codes. Because of that, I keep getting this error:
ld: library not found for -lrt
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [run] Error 1
This error does not show up when running on Linux systems. How do I fix that to be runnable on Mac OSX?

Related

"clang: error: cannot specify -o when generating multiple output files" fix

I'm trying to compile my C project using clang (I'm on MacOS Monterry) and a Makefile, but I keep getting the same error from clang in the command line:
> make
gcc -c src/ji.c src/main.c -o src/ji.o
clang: error: cannot specify -o when generating multiple output files
make: *** [src/ji.o] Error 1
These are the only files I have in the project so far:
src/main.c
src/ji.c
include/ji.h
The Makefile looks like this:
cc = gcc
src = $(wildcard src/*.c)
obj = $(src:.c=.o)
exec = ji
$(exec): $(obj)
$(cc) -Iinclude $< -o build/$#
%.o: %.c
$(cc) -c $(src) -o $#
clean:
-rm src/*.o
-rm ji
From YouTube videos I've seen, this should be the ideal Makefile for the project but no matter what I change I get the error.
There are a few issues:
-Iinclude needs to be on the %.o: %.c rule command
In %.o: %.c, we don't want $(src) but rather $<
We want patsubst to get the .o list obj
The $(exec) target doesn't match the -o option
The clean doesn't match the placement of the executable
Here's a refactored version (e.g. one way to do this--there are others):
cc = gcc
src = $(wildcard src/*.c)
obj = $(patsubst %.c,%.o,$(src))
exec = build/ji
$(exec): $(obj)
mkdir -p build
$(cc) $^ -o $#
%.o: %.c
$(cc) -c $< -o $# -Iinclude
clean:
rm -f src/*.o
rm -fr build
Here's the output of make:
gcc -c src/ji.c -o src/ji.o -Iinclude
gcc -c src/main.c -o src/main.o -Iinclude
mkdir -p build
gcc src/ji.o src/main.o -o build/ji
Here's the output of make clean:
rm -f src/*.o
rm -fr build

`makefile` not working as expected

How can I have it so that when I run make that:
prog.s is created then prog is created if prog.s and prog does not exist
prog.s is created if prog.s is newer than prog.c (eg. after manually modifying prog.s)
prog.s then prog is created if prog.c is newer than prog
In other words, have make create the files it needs to build prog, if the dependencies have been modified
My current makefile:
CC = gcc
CFLAGS =
TARGET = prog
all: $(TARGET).s $(TARGET).c
$(TARGET).c: $(TARGET).s
$(CC) $(CFLAGS) $(TARGET).s -o $(TARGET)
$(TARGET).s:
$(CC) $(CFLAGS) -S -o $(TARGET).s $(TARGET).c
clean:
$(RM) $(TARGET)
$(RM) $(TARGET).s
It works if I have:
only prog.c
manually modified prog.s
but does not work if I have manually modified prog.c
(make: Nothing to be done for 'all'.)
You define your target: source in the reversed order. For instance, your assembly code depends on your C code, you must write:
$(TARGET).s: $(TARGET).c
however, you have written (wrong order)
$(TARGET).c: $(TARGET).s
Here is the version with the right order for "target: sources" :
CC = gcc
CFLAGS =
TARGET = prog
all: $(TARGET)
$(TARGET): $(TARGET).s
$(CC) $(CFLAGS) $(TARGET).s -o $(TARGET)
$(TARGET).s: $(TARGET).c
$(CC) $(CFLAGS) -S -o $(TARGET).s $(TARGET).c
clean:
$(RM) $(TARGET)
$(RM) $(TARGET).s

GNU make undefined reference to functions defined in shared library

I am trying to link to a shared library. But I kept getting the undefined reference error. The following is makefile:
LIBDIR :=./lib
LIB :=-lminus
OBJDIR :=objdir
SOURCES=$(wildcard ./src/*.c)
OBJS :=$(patsubst ./src/%.c, $(OBJDIR)/%.o, $(SOURCES))
INCPATH = -Ilib -Isrc
vpath %.h ./src ./lib
vpath %.c ./src ./lib
optest : $(OBJS)
cc -o optest $(OBJS)
$(OBJDIR)/main.o : main.c add.h mul.h did.h minus.h
cc $(INCPATH) -o $# -c $< -L$(LIBDIR) $(LIB)
$(OBJDIR)/%.o: %.c %.h | $(OBJDIR)
cc -o $# -c $<
$(OBJDIR):
mkdir $#
clean :
rm -rf $(OBJDIR)
rm -f optest
rm -f ./src/*.o
The shared library is called libminus, which is put in the ./lib directory. The main function in main.c uses the function minus defined in this library. I searched online, people met this problem before. Most of their problems were solved after the shared libraries were put after the object files in the rule command. I also tried this, but it didn't work for me. The error I got is as follows:
mkdir objdir
cc -o objdir/mul.o -c ./src/mul.c
cc -o objdir/did.o -c ./src/did.c
cc -Ilib -Isrc -o objdir/main.o -c ./src/main.c -L./lib -lminus
cc -o objdir/add.o -c ./src/add.c
cc -o optest objdir/mul.o objdir/did.o objdir/main.o objdir/add.o
objdir/main.o: In function `main':
main.c:(.text+0xa5): undefined reference to `minus'
collect2: error: ld returned 1 exit status
makefile:11: recipe for target 'optest' failed
make: *** [optest] Error 1
Can any one give some suggestion? Thank you.
You're putting the lib stuff into the wrong rule:
$(OBJDIR)/main.o : main.c add.h mul.h did.h minus.h
cc $(INCPATH) -o $# -c $< -L$(LIBDIR) $(LIB)
This just compiles main.c to main.o. The -L and $(LIB) don't belong here. They have to be in the build recipe of this rule, which links the executable:
optest : $(OBJS)
cc -o optest $(OBJS)

C- Makefile for the entire folder

I have been using a makefile for my c++ projects. However I tried to convert it into C and tried to compile with gcc and getting a such error: make: *** No rule to make target*.o', needed by microc'. Stop.
This is my makefile:
CC=gcc
CFLAGS=-c -std=gnu99 -Wall -pedantic
LDFLAGS=
SOURCES=*.c
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=microc
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.c.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf *o microc
You can't use SOURCES=*.c. That just sets the variable to the string *.c, so OBJECTS is the string *.o. You want (assuming you're using GNU make):
SOURCES := $(wildcard *.c)

Makefile C subdirectory rule to make obj

I am running a simple Makefile with no problems:
CC=gcc
CFLAGS= -std=c99 -ggdb -Wall -I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ)
gcc -o $# $^ $(CFLAGS)
The files are in the main project's directory:
./project/Makefile
./project/hellomake.c
./project/hellomake.h
Then I tried to organized the files, and put things like:
./project/Makefile
./project/src/hellomake.c
./project/include/hellomake.h
and extra subdirectories directories:
./project/lib
./project/obj
Then the new version of the Makefile:
IDIR =include
CC=gcc
CFLAGS= -std=c99 -ggdb -Wall -I$(IDIR)
ODIR=obj
LDIR =lib
LIBS=-lm
_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = hellomake.o hellofunc.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ)
gcc -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
I am compiling on Linux using Emacs with the gcc compiler:
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Then, I run on Emacs:
<Esc>
x
compile
make
And it gives the message:
"./project/src/" -*-
make: *** No rule to make target `obj/hellomake.o', needed by `hellomake'. Stop.
Compilation exited abnormally with code 2 at Wed Oct 3 17:10:01
What rule should be missing to be included in the Makefile file?
All comments and suggestions are highly appreciated.
Thanks for your suggestion, it is added to the code. Then the compiler complains:
make -k
make: *** No rule to make target `src/hellomake.c', needed by `obj/hellomake.o'.
make: *** No rule to make target `../include/hellomake.h', needed by `obj/hellomake.o'.
make: Target `obj/hellomake.o' not remade because of errors
Some other suggestion?
Thanks in advance!
To fix the error make: *** No rule to make target 'obj/hellomake.o', needed by 'hellomake'. Stop.
Change this line:
$(ODIR)/%.o: %.c $(DEPS)
To:
$(OBJ): $(ODIR)/%.o: src/%.c $(DEPS)
This creates a rule for all objects in the $(OBJ) variable. The second parameter ('$(ODIR)/%.o') extracts the file name from the full path in order to pass just the file name to the third parameter ('src/%.c').
Ok. Now I am trying another example found here [ How can I create a Makefile for C projects with SRC, OBJ, and BIN subdirectories? ] and here it goes:
TARGET = hi.sh
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -ggdb -Wall -I./src
TARGET = bin/hi.sh
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to set the proper directories where each files shoould be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
.PHONEY: clean
clean:
#$(rm) $(OBJECTS)
#echo "Cleanup complete!"
.PHONEY: remove
remove: clean
#$(rm) $(BINDIR)/$(TARGET)
#echo "Executable removed!"
The files are organized as:
./project/bin/ executable
./project/ojb/*.0
./project/src/*.c and *.h
./project/Makefile
The compiler persists giving only one complaint:
make -k
/usr/bin/ld: cannot open output file /bin/hi.sh: Permission denied
collect2: ld returned 1 exit status
make: *** [bin/bin/hi.sh] Error 1
Thanks a lot for all comments and suggestions!
I think you should change this line
$(ODIR)/%.o: %.c $(DEPS)
change to
$(ODIR)/%.o : %.c $(DEPS)
add a Space after %.o.

Resources