简体   繁体   中英

Using suffix rules in Makefile

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM