GNU make:在先决条件中获取并修改目标名称

时间:2018-01-31 18:39:16

标签: makefile gnu-make

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

/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需要很长时间(约4分钟!)才能读取Makefile(LIST中约50个文件夹)

我也试过静态模式,但没有运气......

有没有人有更好的解决方案?

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

更好的解决方案可能是使用允许动态依赖的构建系统。这是一个可以与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