【问题标题】:GNU Make: always build pre-targets but don't rebuild targetGNU Make:总是构建预目标但不重建目标
【发布时间】: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 all 40 年了。
  • @Andreas 至于仅订单依赖项——这正是我所需要的。我以前从未使用过它们。我们的行业变得如此庞大。我会坚持为其他想要做同样事情的人提供答案。
  • 我在考虑并行性,make -j clean all,在这种情况下,制作和删除文件会交错。普通的make clean all 工作正常,使目标从左到右。

标签: gnu-make


【解决方案1】:

感谢 Andreas,我做了一些调整。这是我的整个示例 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 | obj
    $(COMPILE.cc) $(OUTPUT_OPTION) $<

clean:
    rm -rf obj Foo

这是我的跑步:

$ make clean Foo
rm -rf obj Foo
mkdir obj
g++  -O3  --std=c++17 -g    -c -o obj/Foo.o Foo.cpp
g++ obj/Foo.o  -o Foo
$ make Foo
make: 'Foo' is up to date.

诀窍是仅订单的依赖关系——管道的事情。请参阅 obj/%.o 和 directories 的规则。请注意,如果我这样做或我的 obj/%.o 规则使用 directories 代替,它的工作原理相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    相关资源
    最近更新 更多