Suppose there are a.c, b.c, c.c, tt/at.c, tt/bt.c, fff/af.c, fff/bf.c. So I make Makefile like this:
OBJS=a.o b.o c.o
SRCS=$(OBJS:.o=.cc)
OBJS_TT=at.o bt.o
SRCS_TT=tt/at.c tt/bt.c
OBJS_FFF=af.o bf.o
SRCS_FFF=fff/af.c fff/bf.c
TARGET=test
.cc.o:
gcc -c $<
$(OBJS_TT):
gcc -c $(SRCS_TT)
$(OBJS_FFF):
gcc -c $(SRCS_FFF)
all:
gcc -o $(TARGET) $(OBJS) $(OBJS_TT) $(OBJS_FFF)
If C files in tt directory are added, I have to add file name in SRCS_TT & OBJS_TT. Is there a way to improve make file? How do I do all c files (including files in directory) using suffix rules?
One common solution when source files reside in different directories is to build an isomorphic directory structure in the build directory. This way you can have multiple sources with the same file name (eg util.cc
) but in different directories and the object files won't collide because they get built into different directories.
A working example that creates an isomorphic build directory structure also with auto-generated header dependencies:
build_dir := build
all : ${build_dir}/test
.SECONDEXPANSION:
.SECONDARY:
test_srcs := a.cc b.cc x/c.cc y/d.cc
${build_dir}/test : ${test_srcs:%.cc=${build_dir}/%.o} | ${build_dir}/
g++ -o $@ ${LDFLAGS} ${LDLIBS} $^
# Include the auto-generated dependencies.
-include ${test_srcs:%.cc=${build_dir}/%.d}
# Compile and generate dependency files.
${build_dir}/%.o : %.cc | $$(dir $$@)
g++ -o $@ -c -MD -MP ${CPPFLAGS} ${CXXFLAGS} $<
# Directory build rules. while loop to handle races on mkdir during parallel builds.
${build_dir}/%/ : | ${build_dir}/
while ! mkdir -p $@; do true; done
# Build root directory rule.
${build_dir}/ :
mkdir -p $@
# Don't try to rebuild these, these are generated when compiling.
${build_dir}/%.d : ;
clean :
rm -rf ${build_dir}
.PHONY : all clean
Usage example:
$ mkdir x y
$ touch b.cc x/c.cc y/d.cc
$ echo "int main() {}" > a.cc
$ make
mkdir -p build/
g++ -o build/a.o -c -MD -MP a.cc
g++ -o build/b.o -c -MD -MP b.cc
while ! mkdir -p build/x/; do true; done
g++ -o build/x/c.o -c -MD -MP x/c.cc
while ! mkdir -p build/y/; do true; done
g++ -o build/y/d.o -c -MD -MP y/d.cc
g++ -o build/test build/a.o build/b.o build/x/c.o build/y/d.o
$ tree build/
build/
├── a.d
├── a.o
├── b.d
├── b.o
├── test
├── x
│ ├── c.d
│ └── c.o
└── y
├── d.d
└── d.o
2 directories, 9 files
$ make
make: Nothing to be done for 'all'.
$ make clean
rm -rf build
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.