在Makefile中使用后缀规则

问题描述 投票:0回答:1

假设有a.c,b.c,c.c,tt / at.c,tt / bt.c,fff / af.c,fff / bf.c。所以我像这样制作Makefile:

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)

如果添加了tt目录中的C文件,则必须在SRCS_TT和OBJS_TT中添加文件名。有没有办法改善make文件?如何使用后缀规则处理所有c文件(包括目录中的文件)?

makefile
1个回答
0
投票

当源文件位于不同目录中时,一个常见的解决方案是在构建目录中构建同构目录结构。这样,您可以有多个具有相同文件名的源(例如util.cc),但是它们位于不同的目录中,并且目标文件不会冲突,因为它们被构建在不同的目录中。

一个使用自动生成的头文件依赖关系创建同构构建目录结构的工作示例:

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 generated dependency files.
${build_dir}/%.o : %.cc | $$(dir $$@)
    g++ -o $@ -c -MD -MP ${CPPFLAGS} ${CXXFLAGS} $<

# Directory build rules. while loop to support parallel builds and races on mkdir.
${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

用法示例:

$ 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

[max@supernova:~/tmp] $ make
make: Nothing to be done for 'all'.

[max@supernova:~/tmp] $ make clean
rm -rf build 
© www.soinside.com 2019 - 2024. All rights reserved.