【问题标题】:GNU make: get and modify target name in prerequisitesGNU make:在先决条件中获取和修改目标名称
【发布时间】:2018-11-13 08:22:51
【问题描述】:

我有一个这样的文件列表:

/path1/file1.root
/path2/file2.root
...
/pathn/filen.root

我想用作目标。每个目标的唯一先决条件是一个位于/path<>/log/ 文件夹中的文件,具有相同的基本名称但不同的扩展名。比如:

/path1/
  |-- file1.root
  '-- log/
        '-- file1.mac
/path2/
  |-- file2.root
  '-- log/
        '-- file1.mac
...

/pathn/
  |-- filen.root
  '-- log/
        '-- file1.mac

我只能找到所有这些文件夹直接寻找我的目录结构,所有的路径都是不同的,因此不能先验地重现。

我想产生以下规则:

/path1/file1.root : /path1/log/file1.mac
<tab>do_something

/path2/file2.root : /path2/log/file2.mac
<tab>do_something

...

由于自动变量在先决条件中不可用,因此实现起来并不容易(或者至少在我有限的理解中)

我设法做到了以下几点:

define function
  $(1) : $$(dir $(1))log/$$(subst .root,.mac,$$(notdir $(1)))
  <tab>do_something
endef

$(foreach f,$(LIST),$(eval $(call function,$(f))))

但我不知道为什么 make 读取 Makefile 需要很长时间(约 4 分钟!)(LIST 中的约 50 个文件夹)

我也尝试了一些静态模式,但没有运气......

谁有更好的解决方案?

【问题讨论】:

  • 有不止一种方法可以做到这一点,但是...您的FILE 似乎包含.root 文件的路径。搜索.mac 文件不是更好吗?如果foo.mac 存在,但foo.root 不存在,那么您当前的makefile 将不会构建foo.root
  • do_something 指令使用.mac 文件来构建相应的.root 文件,因此我需要将.root 文件作为目标,将.mac 作为目标唯一的先决条件......我不明白你的意思
  • 想象你有/path1/log/file1.mac,但没有/path1/file1.root。如果您搜索根文件,您将找不到与file 对应的任何内容。如果您搜索 mac 文件,您可以将其名称转换为“...root”。
  • 好吧,我明白你的意思了,我应该说我寻找带有.root 文件的目录(因为它们总是存在的其他原因),然后建立.root 路径中的文件名。这是因为我的目录结构是这样组织的,所有.root 文件名都可以从路径中推导出来。找到.root 文件不是我的问题,正确编写规则才是。你能详细说明你的“有不止一种方法可以做到这一点”吗?
  • 长时间的持续时间是否可能来自您的脚本试图查找所有文件?你如何搜索它们? $(wildcard )?顺便说一句,你为什么对你的规则不满意?你想让它以某种方式“更清晰”吗?我认为你的代码已经很短很清晰了。

标签: makefile gnu-make


【解决方案1】:

我个人会从现有的 mac 文件列表开始,然后从中构建所需的根文件列表,而不是现有根文件的列表。但无论哪种方式,我们都会得到一个根文件列表。

我认为最好的方法是静态模式规则。我们可以使用Secondary Expansion来构造必备的mac文件:

.SECONDEXPANSION:
$(ROOTS): %.root: $$(dir $$*)log/$$(notdir $$*).mac
    do something with the target $@ and the prerequisite $<

【讨论】:

  • 谢谢,这就是我要找的。由于某种原因,它比eval 方法快得多。
【解决方案2】:

更好的解决方案可能是使用允许动态依赖的构建系统。这是一个适用于 GoodMake 的 make 文件:

#? *.root
    # Find the corresponding .mac file
    mac=$(echo $1 | sed -E 's+(.*/)(.*).root+\1log/\2.mac+')

    # Flag the .mac file as a dependency
    $0 $mac  

    # Build the .root
    cat "something" >$1

#? !all
    $0 all-roots        # List all the roots
    $0 $(cat all-roots) # Make all the roots

#? all-roots
    # List all desired roots by finding all .mac files
    find -path '*/log/*.mac' | sed -E 's+(.*/)log/(.*).mac+\1\2.root+' >$1

【讨论】:

    猜你喜欢
    • 2021-04-09
    • 1970-01-01
    • 2015-07-31
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多