【问题标题】:Build make target if contents of directory have changed如果目录的内容已更改,则构建 make 目标
【发布时间】:2019-02-05 17:47:33
【问题描述】:

我需要一个允许我输入 make foo-program 的 Makefile,如果自上次构建以来有任何 foo-program/**/*.hs 文件发生更改,则构建目标(foo-program/.stack-work 中的输出)。

这是我的目录树:

project/
|-bar-other-program/
  |-.stack-work/ # Generated output goes here
  |-src/
    |-BarOtherProgram.hs
  |-test/
    |-Tests.hs
|-foo-program/
  |-.stack-work/ # Generated output goes here
  |-src/
    |-FooProgram.hs
  |-test/
    |-Tests.hs
|-notes/ # non-source, so no Make target for this

这是我目前所拥有的:

# evaluates to 'bar-other-program foo-program'
PROGS := $(shell find * -type f -name '*.hs' | cut -d'/' -f1 | uniq)

.SECONDEXPANSION:
$(PROGS): $$(wildcard $$@/src/*.hs) $$(wildcard $$@/test/*.hs)
    # do-build $@

当我运行make foo-program时,无论来源是否改变,我都会得到:

make: Nothing to be done for 'foo-program'

更新:我的最终(非抽象)Makefile 可以在on GitHub 找到。请注意,当我写下这个问题时,我的解决方案与我预期的不同。查看那个 Makefile 也可能会让我更清楚我最初的目标。

【问题讨论】:

    标签: makefile prerequisites


    【解决方案1】:

    我不太确定cut -d'/' 的用途。

    但是如果你只想要当前目录中的*.hs文件列表(递归找到),然后根据它们是否发生变化来构建一个目标/可执行文件,你可以这样做:

    PROGS = $(subst ./,,$(shell find . -type f -name '*.hs'))
    DEPS = $(addprefix stackwork/,$(addsuffix .dep,$(basename $(PROGS))))
    DIRS = $(dir $(DEPS))
    
    .PHONY: foo-program
    foo-program: $(DEPS) $(DIRS)
    
    stackwork/%.dep: %.hs | $(DIRS)
        @echo making $@
        @touch $@
    
    $(DIRS):
        @echo creating dir $@
        @mkdir -p $@
    
    clean:
        @rm -rf $(DEPS) $(DIRS)
    

    地点:

    • PROGS 是您的 .hs 文件列表
    • DEPS 是生成的依赖文件列表(为空但会使用日期戳)
    • DIRS 是需要创建的输出目录列表(我猜它们默认不存在,因为它们是输出文件夹?)
    • foo-program 是您可以调用的规则(PHONY 因为目前它不会创建真实文件)
    • %.dep: %.hs 是如何生成 .dep 文件(这可能是 .o .obj 或任何其他文件类型)的规则,这取决于其 .hs 文件等效项。
    • $(DIRS): 是根据需要创建输出目录的规则。

    所以如果.dep 文件不存在,所有.hs 文件都将被“编译”。如果所有.dep 文件都存在并且是最新的,则不会编译任何内容。如果一个或多个文件已过期,则只会构建这些文件。以下是在我的 PC 上使用一些测试文件运行它的输出:

    admin@osboxes:~/sandbox$ make
        creating dir stackwork/
        creating dir stackwork/test/
        creating dir stackwork/test/test2/
        making stackwork/file.dep
        making stackwork/test/file.dep
        making stackwork/test/test2/file2.dep
    
    admin@osboxes:~/sandbox$ make
        make: Nothing to be done for 'foo-program'.
    
    admin@osboxes:~/sandbox$ touch test/file.hs      
    admin@osboxes:~/sandbox$ make
        making stackwork/test/file.dep
    
    admin@osboxes:~/sandbox$ make
        make: Nothing to be done for 'foo-program'.
    

    【讨论】:

    • 标记为答案,因为它让我最接近我想要的...我意识到我在问题描述中遗漏了一些细节。我最终走了一条不同的路线。
    • @cmac 如果有用,发布您的更新版本可能有用(对于以后的读者)?我还建议使用make -j4(或您想要的任何-j 值)测试您的新makefile,以确保依赖顺序适用于并行构建:)
    猜你喜欢
    • 2013-11-11
    • 2014-03-11
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 1970-01-01
    • 2012-10-01
    相关资源
    最近更新 更多