【发布时间】:2021-11-15 12:53:14
【问题描述】:
想象一下我的 Makefile 有类似的东西:
CXXFLAGS = -O3 ${INCLUDES} --std=c++17 -g ${AUTO_ARGUMENT}
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
.PHONY: all directories
all: directories programs
directories: obj
obj:
mkdir obj
programs: Foo
Foo: obj/Foo.o
${CXX} obj/Foo.o ${LDFLAGS} -o Foo
obj/%.o : %.cpp
$(COMPILE.cc) $(OUTPUT_OPTION) $<
clean:
rm -rf Foo obj
我可以执行make,它将创建 obj 子目录,然后进行良好的编译和链接。效果很好。但如果我这样做make clean Foo,它就会失败。 clean 删除了子目录,因为我绕过 all 只创建一个目标,它不会重新创建 obj。
所以我可以这样做:
Foo: directories obj/Foo.o
${CXX} obj/Foo.o ${LDFLAGS} -o Foo
但它总是链接:
$ make
g++ obj/Foo.o -o Foo
$ make
g++ obj/Foo.o -o Foo
但如果我从 Foo 中删除 directories 部分:
$ make
make: Nothing to be done for 'all'.
这更糟:
obj/%.o : directories %.cpp
$(COMPILE.cc) $(OUTPUT_OPTION) $<
所以,我的问题...有什么方法可以告诉单个目标在没有该目标的情况下进行一些预设置,然后总是重建?我可能会像这样制作假目标:
makeFoo: directories Foo
但这很烦人。我也可以是:
all: setup programs
setup: directories
然后执行make setup Foo。这只是适度烦人。我真正想要的是对象的规则,以确保目录存在而不添加任何垃圾邮件或不必要的重建。我想我可以在该特定规则中添加一些内容以确保目录存在:
obj/Foo.o: Foo.cpp
if [ -d obj ]; then \
mkdir obj \
fi
$(COMPILE.cc) $(OUTPUT_OPTION) $<
有没有更清洁的方法?
【问题讨论】:
-
make clean Foo不应该按其传统含义工作。是否可以在命令行上一起传递其他目标可以被认为是相关生成文件接口的一部分。换句话说,干净的方式是说“不要”,可能带有输入验证(目标计数 -
至于目录,您是否查看过仅订单依赖项?它们仅在存在时触发,而不是时间戳,是目录的理想选择。
-
@Andreas 我不太明白你在说什么。我做
make clean all40 年了。 -
@Andreas 至于仅订单依赖项——这正是我所需要的。我以前从未使用过它们。我们的行业变得如此庞大。我会坚持为其他想要做同样事情的人提供答案。
-
我在考虑并行性,
make -j clean all,在这种情况下,制作和删除文件会交错。普通的make clean all工作正常,使目标从左到右。
标签: gnu-make