如果目录内容已更改,则生成make target

时间:2019-02-05 17:47:34

标签: makefile prerequisites

我需要一个Makefile,该文件允许我输入make foo-program,并且如果自上次构建以来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'

更新:可以在on GitHub中找到我的最终(非抽象的)Makefile。请注意,我的解决方案与我撰写此问题时的意图有所不同。查看该Makefile还可以使我更清楚地了解我的最初目标。

1 个答案:

答案 0 :(得分:2)

我不确定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是如何生成依赖于其.hs文件等效文件的.dep文件(这可以是.o .obj或任何其他文件类型)的规则。
  • $(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'.