问题
I've got a large-ish C project, and I want to generate a static library from all of my sources in the src/ file using the includes from my include/ path, and some other includes for my RTOS.
I have a working set of steps in the line commands that work:
gcc src/drivers/* src/packets/* (...more files) -c -I ./include -I ../SatelliteSim/Source/include/ -I ../SatelliteSim/Project/ -I ../SatelliteSim/Source/portable/GCC/POSIX/ -m32 -DDEBUG=1 -g -UUSE_STDIO -D__GCC_POSIX__=1 -pthread
then, ar -rsc telecommands.a *.o
My current attempt at the Makefile looks like this:
CXXFLAGS := -I./include -I../SatelliteSim/Source/include/ -I../SatelliteSim/Project/ -I../SatelliteSim/Source/portable/GCC/POSIX/ -m32 -DDEBUG=1 -g -UUSE_STDIO -D__GCC_POSIX__=1 -pthread
MODULES := commands/commands \
driver_toolkit/driver_toolkit \
(... more 'modules')
SOURCES := src/$(MODULES).c
OBJS := bin/$(MODULES).o
all: telecommands.a
telecommands.a: $(OBJS)
ar -rsc $@ $^
$(OBJS): $(SOURCES)
$(CXX) $(CXXFLAGS) -c $^ -o $@
But i'm getting an issue with my include files in the compilation step.
Hopefully someone can point out what I'm doing wrong :)
Thanks in advance!
回答1:
You have at least two major problems.
The first is your SOURCES
and OBJS
variable assignments are wrong. Make does straightforward textual replacement when it expands variables. So:
MODULES := foo bar biz
SOURCES := src/$(MODULES).c
OBJS := bin/$(MODULES).o
expands to simply:
SOURCES := src/foo bar biz.c
OBJS := bin/foo bar biz.o
which is clearly not right. If you are willing to use GNU make-specific functions, which operate individually on each word in the variable, you can get what you want:
SOURCES := $(patsubst %,src/%.c,$(MODULES))
OBJS := $(patubst %,bin/%.o,$(MODULES))
The next problem you have is this:
$(OBJS): $(SOURCES)
$(CXX) $(CXXFLAGS) -c $^ -o $@
which expands to something like this:
bin/foo.o bin/bar.o bin/biz.o : src/foo.c src/bar.c src/biz.c
$(CXX) $(CXXFLAGS) -c $^ -o $@
Again, make is not going to somehow infer that you want each object file on the left to somehow be matched with some source file on the right, using some string matching heuristic. That's not how make works. If there are multiple targets on the left side, make creates a separate rule for each one where each one contains all the prerequisites on the right side. So the above is the same as if you'd written:
bin/foo.o : src/foo.c src/bar.c src/biz.c
$(CXX) $(CXXFLAGS) -c $^ -o $@
bin/bar.o : src/foo.c src/bar.c src/biz.c
$(CXX) $(CXXFLAGS) -c $^ -o $@
bin/biz.o : src/foo.c src/bar.c src/biz.c
$(CXX) $(CXXFLAGS) -c $^ -o $@
which means that it will compile all the source files to create each object file.
In makefiles you have to write a rule that builds one target at a time, from the prerequisites of that target. So for example you can use a pattern rule:
bin/%.o : src/%.c
$(CXX) $(CXXFLAGS) -c $< -o $@
Note I used $<
instead of $^
because you only want to compile the source file. Note that this invokes the compiler one time for each source file, to generate that output file. Make is not well-suited to environments where a single invocation of the build tool generates many different outputs (although if you're willing to restrict yourself to GNU make version 4.3 or higher you can do it if you want).
This will not rebuild any object files if headers change because you've not listed any headers as prerequisites.
You mention getting an issue with my include files in the compilation step but that's not helpful information to us. If you still have compilation problems after fixing your makefile, you can open a new question but please include exactly (cut and paste) the kinds of errors you see and also the compile line that make prints that generates these errors.
来源:https://stackoverflow.com/questions/60590641/makefile-to-compile-all-src-and-generate-static-library