【问题标题】:make: setting up a complex prerequisit listmake:设置一个复杂的先决条件列表
【发布时间】:2015-03-26 07:42:33
【问题描述】:

我在为我的用例编写合适的 makefile 目标时遇到问题。

我有一个可以生成头文件和源文件的脚本。生成头文件 myHeader.h 的输入文件是 config/myHeader.h.template 和 config/myHeader.xlsx。 可以看到,输入文件和头文件不在同一个目录,而是在“config”子目录中。

在 makefile 中,我有一个列表,包含脚本生成的所有头文件和源代码。

MY_GENERATED_HEADERS =  $(sort \
            foo/bar/myHeader1.h \
            foo/bar/myHeader2.h)

此外,我还有一个可以从“外部”调用的目标:

generate: $(MY_GENERATED_HEADERS)

所以当我写的时候

make generate

在命令行上,我想检查列表中的每个标题是否需要再次生成。

所以,现在是复杂的部分。 当 .h.template 或 .xlsx 发生变化时,我必须编写一个最终调用我的脚本的目标。

$(MY_GENERATED_HEADERS): %.h: %.h.template %.xlsx
    @echo $@
    #invoke the script...

在规则中,我可以设置调用脚本所需的绝对文件名。没问题,jsut使用一些自动变量和字符串操作函数。

实际的问题是先决条件列表:在上述解决方案中,假设 .h.template 和 .xlsx 文件与输出标头 (foo/bar/) 位于同一目录中,但是,我希望它们是在 foo/bar/config 中稍微清理一下文件系统。

在上述解决方案中,我会收到错误消息

No rule to make target 'foo/bar/myHeader1.h.template'.

是的,没错,因为 myHeader1.h.template 在 foo/bar/config...

我已将所有目录添加到 VPATH,但这并没有改变任何东西。

对此有什么想法吗?

【问题讨论】:

  • 试试$(MY_GENERATED_HEADERS): %.h: $(dir %)/config/$(notdir %).h.template $(dir %)/config/$(notdir %).xlsx
  • 似乎 $(dir %) 返回 "."并且 $(notdir %) 返回“foo/bar/myHeader1”。所以,你的解决方案抛出错误:没有规则使目标'config/foo/bar/myHeader1.h.template"。根据gnu.org/software/make/manual/html_node/File-Name-Functions.html,这不是dir和notdir应该工作的方式。也许他们不工作先决条件清单?
  • 我只是在 ./ 中尝试我的建议,所以我没有看到这个。感谢 Louis 的最终更正答案

标签: c++ c shell makefile


【解决方案1】:

什么Garf365 suggested 不能工作,除非你使用.SECONDEXPANSION 开启第二次扩展依赖。下面是一个 Makefile,说明了解决方案的工作原理:

# Some value for the sake of illustration.
MY_GENERATED_HEADERS=foo/bar/1.h foo/baz/2.h

all: $(MY_GENERATED_HEADERS)

.SECONDEXPANSION:
$(MY_GENERATED_HEADERS): %.h: $$(dir %)config/$$(notdir %).h.template $$(dir %)config/$$(notdir %).xlsx
    @echo Target: $@
    @echo Dependencies: $^

在将示例发布到此处之前,我已经对其进行了测试。

当您使用.SECONDEXPANSION 时,您必须小心在正确的时间扩展您的变量和函数调用。第一次扩展是在第一次读取规则时完成的。之前% 获取任何值(对于自动变量也是如此)。第二个扩展是在 Make 即将对特定目标应用规则时完成的:那时,% 有一个值(自动变量也是如此)。您使用 $$ 在第二次扩展时扩展您想要扩展的内容。在第一次扩展的时候,依赖会被转换为:

$(dir %)config/$(notdir %).h.template $(dir %)config/$(notdir %).xlsx

然后在第二次扩展时(每个目标发生一次)% 将被其值替换,并且 $(dir ...) 和 $(notdir ...) 将被调用。

【讨论】:

  • 非常感谢路易斯!同时,我测试了另一种方法:创建一个 .xlsx 文件列表并从该列表中计算其他文件名。我发现列出“输入文件”更容易,它们将被“编译”为头文件。但是,这种方法也不起作用。我尝试使用 patsubst 删除第一个先决条件的 /config/ 部分,但没有奏效。我想我也需要在那里使用 SECONDEXPANSION 吗?也许你可以给我一个提示?但是,您的解决方案也很好,再次感谢您!
猜你喜欢
  • 1970-01-01
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-29
  • 1970-01-01
相关资源
最近更新 更多