How to create reference to an .o file in Makefile - c

I was given two .o files with corresponding .h files to use for an assignment, but I do not know how to get the compiler to use the .o files. This is the Makefile I am currently using:
TARGET = prog
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
I believe I need to add the file1.o and file2.o at the end, but I am not sure if that is right. I do have the .h files in the C source files when appropriate, so the only reason that I can think of for the compilation error is that the .o files are not being compiled with my code.

Add a define for the provided .o's (e.g.):
PREBUILT_O = fludger.o ramble.o plexor.o
Change your target rule to:
$(TARGET): $(OBJECTS) $(PREBUILT_O)
$(CC) $(OBJECTS) $(PREBUILT_O) $(LIBS) -o $#

The compiler doesn't use your .o files. The linker does.
Your link step needs to be
$(TARGET) : $(OBJECTS)
$(LD) $(OBJECTS) $(LIBS) -o $#
(Very possibly missing some other linker flags, but that's the crux of your problem)
Also, you probably don't want the clean step to delete all the .o files since you're provided with at least two of them.

Related

How to use filter with *F in Makefile?

There is this line in my Makefile:
$(CC) $(CFLAGS) -o $# -c $(filter %$(*F).cpp, $(SOURCES))
Suppose I have 2 cpp file like "docinfo.cpp" and "info.cpp", when g++ build "docinfo.cpp" to "docinfo.o", it works.
g++ -I ... -o docinfo.o -c docinfo.cpp
But when g++ build "info.cpp" to "info.o", it has an error.
g++ -I ... -o info.o -c docinfo.cpp info.cpp
How do I make it work?
This is my Makefile:
CC := gcc
RM := rm -rf
WORKSPACE := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
TARGET := $(WORKSPACE)test.so
SOURCES := $(foreach dir,$(WORKSPACE),$(wildcard $(dir)source/*.c))
INCLUDE := -I$(WORKSPACE)include/
CFLAGS := $(INCLUDE) -O0 -Wall -fPIC
#CFLAGS += -g
#CFLAGS += -D__DEBUG__
OBJS := $(notdir $(SOURCES:.c=.o))
OBJ_PATH := $(WORKSPACE)object/
OBJS_O := $(addprefix $(OBJ_PATH), $(OBJS))
LIB_PATH := $(WORKSPACE)lib
LIBS := -ldl -shared
.PHONY: all clean
all: $(OBJ_PATH) $(LIB_TAG) $(TARGET)
$(OBJ_PATH):
mkdir -p $#
$(TARGET): $(OBJS_O)
$(CC) $(CFLAGS) -o $# $^ -L$(LIB_PATH) $(LIBS)
#echo "$#"
$(OBJS_O): $(SOURCES)
$(CC) $(CFLAGS) -o $# -c $(filter %$(*F).c,$(SOURCES))
clean:
-$(RM) $(OBJS_O) $(OBJ_PATH) $(TARGET)
First, why don't you just use $< rather than trying to filter out something from $(SOURCES)?
$(CC) $(CFLAGS) -o $# -c $<
If, for some weird reason, you do need the filter, then if you don't want to return a match for any value ending with $(*F).cpp, then just don't prefix it with the pattern match character (%):
$(CC) $(CFLAGS) -o $# -c $(filter $(*F).cpp, $(SOURCES))
This is weird, though, because $(*F) should expand to foo.cpp which means this would resolve to foo.cpp.cpp.
So, I think there's something quite unusual (or possibly incorrect) about your makefile... but since you've only provided the recipe and not shown us the entire rule we can't say for sure.
ETA
Now that we see your makefile, sure enough it has a problem. This rule is wrong:
$(OBJS_O): $(SOURCES)
$(CC) ...
What does this expand to, once variables are resolved? Say you have SOURCES resolving to source/foo.c source/bar.c and OBJS_O resolving to object/foo.o object/bar.o. Then the above rule resolves to:
object/foo.o object/bar.o: source/foo.c source/bar.c
$(CC) ...
What does make do here? It doesn't magically do some kind of file-by-file matching of targets to prerequisites. It interprets this rule as if you'd written this:
object/foo.o: source/foo.c source/bar.c
$(CC) ...
object/bar.o: source/foo.c source/bar.c
$(CC) ...
That is, every object depends on all the source files, so if any source file is changed every object is rebuilt.
If you want this to work correctly and put all the object files into a single directory regardless of which source directory they exist in, then you'll have to use vpath with a pattern rule, like this:
vpath %.c $(sort $(dir $(SOURCES)))
$(OBJ_PATH)%.o : %.c
$(CC) $(CFLAGS) -o $# -c $<
Now you can use $< instead of the filter function, because each object file depends on exactly and only its source file, not all the source files.

How to explicitly link library path via makefile

I installed a real-time library libre from brew install libre in my macOS. It is located in the directory /usr/local/Cellar/libre/0.5.7. I am trying to explicitly add this path in Makefile so I declare RT_LIBS_PATH=-L/usr/local/Cellar/libre/0.5.7. The entire makefile looks like this:
TARGET = run
LIBS = -O2 -lm
CC = gcc-7
CFLAGS = -fopenmp
RT_LIBS_PATH=-L/usr/local/Cellar/libre/0.5.7/lib
.PHONY: default all clean
all: $(TARGET)
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
#$(CC) $(CFLAGS) $(RT_LIBS_PATH) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
#$(CC) $(OBJECTS) $(CFLAGS) $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
However, it seems makefile does not recognize the libre, thus I assume I use RT_LIBS_PATH=-L/usr/local/Cellar/libre/0.5.7/lib in a wrong way. Kindly, is there something wrong in this way?
You have to specified library path when you are creating .o, you have to specify it when link all objs into executable
$(TARGET): $(OBJECTS)
#$(CC) $(OBJECTS) $(CFLAGS) $(RT_LIBS_PATH) $(LIBS) -o $#

Compile multiple .c files with makefile

I would like to compile multiple .c files at once using a makefile.
I already made this:
CC= gcc
CPPFLAGS = -I.
CFLAGS = -W -Wall -ansi -pedantic
TARGET = test
RM = rm
OBJECTS = xxx.o yyy.o zzz.o
SOURCES = $(OBJECTS:.o =.c)
.PHONY: all clean
all: $(TAREGT)
clean:
$(RM) $(TARGET) $(OBJECTS)
$(TAREGT) : $(OBJECTS)
$(CC) $^ -o $#
$(OBJECTS) : $(SOURCES)
$(CC) $(CFLAGS) $(CPPFLAGS) -c $^
I have no Idea why this does not work("nothing to be done for "all"). Someone has an idea?
This line is creating a circular dependency:
SOURCES = $(OBJECTS:.o =.c)
Try replacing it with this:
SOURCES = $(patsubst %.o,%.c,$(OBJECTS))
You forgot -o $# in your 'sources to objects' rule. Thus it doesn't create anything.
You have also spelling error - your $(TARGET) is 'test', but your 'all' rule depends on $(TAREGT) which is empty. You are also using $(TAREGT) as input to compile 'test'.
You don't need to specify $(SOURCES) or "sources to objects" rule - implicit rules will do the trick.
In fact your "sources to objects" rule is incorrect - it says that each object depends on all sources. If you want each object to depend on one source you should use either suffix rule, pattern rule or static pattern rule. Or just implicit rule.
$(OBJECTS) : $(SOURCES)
The above tells Make that every .o file depends on all sources, i.e. if you change one of your .c files Make will recompile all .o files. Not something what you really want, I guess. I'd rework this rule as follows:
$(foreach s,$(SOURCES),$(eval $(filter %$(basename $(notdir $s)).o,$(OBJECTS)): $s))
This will iterate every source in SOURCES, find corresponding .o file in OBJECTS and create correct rule: <obj>: <source>. It is that complicated to work in case of more complex mapping between source and object files. Say, when building object files in separate directory.
This cryptic code will work even for the following weird source to object file mapping:
SOURCES := a.cpp boo/b.c c.C
OBJECTS := foo/a.o bar/b.o c.o
$(foreach s,$(SOURCES),$(eval $(filter %$(basename $(notdir $s)).o,$(OBJECTS)): $s))
It will generate the following rules:
foo/a.o: a.cpp
bar/b.o: boo/b.c
c.o: c.C
Thank you guys for you help, it is working now
I just added some rules:
CC= gcc
CPPFLAGS = -I.
CFLAGS = -W -Wall -ansi -pedantic
TARGET = test
RM = rm
SOURCES = xxx.c yyy.c zzz.c
OBJECTS = $(SOURCES:.c=.o)
.PHONY: all clean
all: $(TARGET)
clean:
$(RM) $(TARGET) $(OBJECTS)
$(TARGET) : $(OBJECTS)
$(CC) $^ -o $#
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<

Set Option in MakeFile to send object files to specific Folder

I made a test makefile using an online tutorial. It works, but I also want to have all of my .o files go to a specific sub-folder. Is there a way to do this using a makefile? Here is what I have so far.
CC=gcc # specifies the compiler to use.
CFLAGS=-I. # specifies to look in the current directory.
DEPS = path_tools.h # DEPS stores each .h file to be added.
OBJ = checkpath.o path_tools.o # OBJ stores each object file to compile.
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
checkpath.exe: $(OBJ)
gcc -o $# $^ $(CFLAGS)
For GNU make you can use this Makefile.
ODIR:=obj
CC:=gcc
CFLAGS:=-I.
DEPS:=path_tools.h
OBJ_:= checkpath.o path_tools.o
OBJ:=$(addprefix $(ODIR)/, $(OBJ_))
PROG=checkpath.exe
all:$(PROG)
$(OBJ): $(DEPS)
$(ODIR)/%.o: %.c
$(CC) -c -o $# $&lt $(CFLAGS)
$(PROG): $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
clean:
rm -f $(OBJ) $(PROG)
You can pass the path of your folder to makefile to create and put the results in.
To pass parameter to makefile:
make DPATH=your-path
To use in makefile:
$(DPATH)
Create this path and add it to head of your *.o files as a path.

How to use makefile to compile all sources (some only to object files)?

I'm getting an "undefined reference to main" error on one of my files when trying to compile. I know this is because this file doesn't have a main method. This is just an implementation file for some helper methods, so I only want it compiled to an object file not an executable. I know how to do this if I explicitly tell the makefile what to do for each file, but I'm trying to write a makefile that will compile all of my sources at once. I tried using the -c flag, but then it compiled all of my files to only object files rather than executables. How in the world do I do this?
Here it is:
CC = gcc
CFLAGS = -g -Wall
SRCS = ./src/server.c ./src/client_slave.c ./src/sockaddrAL.c
EXECS = ./bin/server ./bin/client_slave
OBJS = $(SRCS:.c=.o)
all: clean $(SRCS) server client
server: $(OBJS)
$(CC) $(CFLAGS) ./src/server.o -o ./bin/server
client: $(OBJS)
$(CC) $(CFLAGS) ./src/client_slave.o -o ./bin/client_slave
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You should add the -c flag to the rule that builds .o files (your .c.o suffix rule) and not add it to the rule that builds the executables (the $(EXECS) rule).
CC = gcc
CFLAGS = -g -Wall
EXECS = ./bin/server ./bin/client_slave
all: $(EXECS)
./bin/%: ./src/%.o ./src/sockaddrAL.o
$(CC) $(CFLAGS) -o $# $^
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You didn't show sockAddrAL at all in your question so I assumed it belonged in both executables. Also note that the above syntax assumes GNU make. If you want to use only features available in POSIX standard make you pretty much have to write it all out.
Let implicit rules be your friend. Your entire Makfefile should just be:
CC = clang
CFLAGS = -O0 -g -Wall
SRCS = server.c client_slave.c sockaddrAL.c
OBJS = $(SRCS:.c=.o)
EXECS = server
server: $(OBJS)
clean:
#rm -f $(EXECS) $(OBJS)
Invoke it from the src directory.

Resources