【问题标题】:Makefile pattern rule with variable in target目标中带有变量的 Makefile 模式规则
【发布时间】:2014-10-21 13:17:26
【问题描述】:

我正在使用 Gnu Make 3.81,但在尝试匹配其中也包含变量的模式规则时出错。

这是我能想到的最小的例子:

YYMMDD:=$(shell date +%y%m%d)
TMP_DIR:=/tmp/$(YYMMDD)

# create a temporary directory, and put a "source" file in it
$(TMP_DIR):
    mkdir $(TMP_DIR)
    echo something > $(TMP_DIR)/somefile.orig

# to build an "object" file in the temp dir, process the "source" file
$(TMP_DIR)/%.new: $(TMP_DIR)/%.orig
    wc -l $< > $@

atarget: $(TMP_DIR) $(TMP_DIR)/somefile.new

然后当我运行make atarget 时,我得到:

mkdir /tmp/141021
echo something > /tmp/141021/somefile.orig
make: *** No rule to make target `/tmp/141021/somefile.new', needed by `atarget'.  Stop.

这不应该吗?看起来模式规则应该很好地匹配这个。

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    这是因为 make 不知道 .orig 文件存在:您有一个构建 $(TMP_DIR) 的规则,但 make 不知道该规则也构建 $(TMP_DIR)/somefile.orig。因此,当 make 尝试匹配模式规则时,它会看到 .orig 文件不存在,并且它没有任何方法知道如何制作该文件,因此模式不匹配,之后没有办法构建.new 文件。

    你应该写:

    $(TMP_DIR)/%.orig:
            mkdir -p $(TMP_DIR)
            echo $* > $@
    

    然后它会工作。

    【讨论】:

    • 我想那时我有些不明白。为什么不直接检查“.orig”文件是否确实存在?
    • 出于性能原因,Make 缓存了哪些文件存在。当 make 知道某个文件已创建时,缓存会更新。在这种情况下,没有运行任何规则说它将创建该文件。另外,请注意,如果您启用了并行性 (-j),您的 makefile 将无效,因为 make 将开始构建 $(TMP_DIR) 然后立即开始尝试查找下一个目标,因为构建命令 @987654329 后它无法找到该目标@ 未完成。一般来说,依赖规则的“副作用”而不是明确的先决条件是一个坏主意。
    • 如果是这样,为什么默认的“%.o: %.c”规则会起作用?
    • 如果 .c 文件是作为另一个规则的副作用而创建的,该规则没有将 .c 文件列为该规则的目标,则它不会(可靠地)工作建造。这就是您在这里所做的:将 $(TMP_DIR) 列为要构建的目标,但实际上构建了一个额外的文件 $(TMP_DIR)/somefile.orig 并将其用作另一个目标的先决条件..
    猜你喜欢
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    相关资源
    最近更新 更多