【问题标题】:Force rebuild from within makefile从 makefile 中强制重建
【发布时间】:2021-12-31 16:23:06
【问题描述】:

有没有办法从 makefile 中强制进行完全重建(例如 -B)?

我添加了一个预构建步骤,它增加了一个构建号,存储在一个文本文件中,供我的项目使用。仅当 newbuild=1 作为参数传递给“make”时,内部版本号才会递增。

    pre-build:
        # This option increments build number
        ifdef newbuild
        increment_build_number
        endif

如果调用此代码,我想强制进行完全重建,这样就不会出现任何不同步的情况,并且在使用newbuild=1 时我不必键入-B。有没有办法做到这一点?

谢谢!

【问题讨论】:

  • -B 标志不会强制重建所有目标,它只是要求重建所有考虑的目标。也就是说,Make 不会因为它是最新的而跳过任何目标。因此,如果您 make -B foo,那么 Make 将重建 foo 及其所有先决条件,但将不会重建不相关的目标 bar。这就是你想要的吗?
  • 并非如此。如果我输入make newbuild=1,我希望将其解释为make -B newbuild=1。当然,可以触及每个源文件,但有没有更优雅的方法来做到这一点?

标签: makefile build gnu rebuild


【解决方案1】:

你可以:

  1. 将带有内部版本号的文本文件声明为其他目标的先决条件,
  2. 如果定义了newbuild,也可以使用make 条件来声明它是假的。

演示,其中build.txt 是带有内部版本号的文本文件,target 是定义newbuild 时要重建的目标之一:

# Makefile
BUILD   := build.txt
TARGETS := target

ifdef newbuild
.PHONY: $(BUILD)
endif

$(TARGETS): $(BUILD)
    touch $@

$(BUILD):
    @[ -f "$@" ] && build=$$(cat "$@") || build=0; \
    printf 'build '; \
    printf '%d\n' "$$((build+1))" | tee "$@"; \
$ make
build 1
touch target
$ make
make: 'target' is up to date.
$ make newbuild=1
build 2
touch target

【讨论】:

  • 这就是答案。所需要的只是在内部版本号更新时触摸受影响的源文件。感谢 Beta 和 Renaud 的想法。
  • 嗯。我不会碰源文件。这看起来像一个肮脏的黑客。如果您的源文件没有更改,则无需触摸它们。真正表达你的依赖关系会更干净。如果这个带有内部版本号的文本文件在你的构建过程中用于构建目标,只需将文本文件本身添加到目标的先决条件列表中。如果不使用,您的问题是没有问题的,您不需要重建。