代码之家  ›  专栏  ›  技术社区  ›  Halsafar

Makefile规则取决于目录内容更改

  •  16
  • Halsafar  · 技术社区  · 11 年前

    使用Make可以很好地依赖目录内容。

    本质上,我有一些应用程序代码所依赖的生成代码。生成的代码只需要在目录的内容发生变化时进行更改,而不必在目录中的文件发生变化时更改。因此,如果文件被删除、添加或重命名,我需要运行规则。

    我的第一个想法是生成一个目录的文本文件列表,并与上一个列表进行比较。更改意味着重新运行生成。我想我必须将generate和diff部分传递给bash脚本。

    我希望在他们无限的智慧中,能找到一个更简单的解决方案。

    3 回复  |  直到 11 年前
        1
  •  23
  •   Halsafar    11 年前

    感谢让我走上正轨的朱利亚姆。他的解决方案适用于单个目录。

    为了让它递归地工作,我做了以下操作。

    ASSET_DIRS = $(shell find ../../assets/ -type d)
    ASSET_FILES = $(shell find ../../assets/ -type f -name '*')
    
    codegen: ../../assets/ $(ASSET_DIRS) $(ASSET_FILES)
         generate-my-code
    

    现在看来,对目录或文件的任何更改(添加、删除、重命名、修改)都将导致此规则运行。这里的文件名可能有问题(空格可能会导致问题)。

        2
  •  7
  •   gjulianm    11 年前

    假设您的目录名为 dir ,则此makefile将执行您所需的操作:

    FILES = $(wildcard dir/*)
    
    codegen: dir # Add $(FILES) here if you want the rule to run on file changes too.
        generate-my-code
    

    正如评论所说,您还可以添加 FILES 变量,如果您希望代码也依赖于文件内容。

        3
  •  1
  •   Daira-Emma Hopwood    6 年前

    规则依赖于目录的缺点是 任何 对该目录的更改将导致规则过期,包括在该目录中创建生成的文件。因此,除非将源文件和目标文件分隔到不同的目录中,否则该规则将在每个 make .

    这里有一种替代方法,允许您指定与添加、删除和更改相关的文件子集。例如,假设只有 *.foo 文件是相关的。

    # replace indentation with tabs if copy-pasting
    
    .PHONY: codegen
    codegen:
            find . -name '*.foo' |sort >.filelist.new
            diff .filelist.current .filelist.new || cp -f .filelist.new .filelist.current
            rm -f .filelist.new
            $(MAKE) generate
    
    generate: .filelist.current $(shell cat .filelist.current)
            generate-my-code
    
    .PHONY: clean
    clean:
            rm -f .filelist.*
    

    codegen规则中的第二行确保 .filelist.current 仅当相关文件列表更改时才进行修改,以避免 generate 规则