如果目录内容已更改,则构建 make 目标
Build make target if contents of directory have changed
我需要一个允许我输入 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 也可能使我的最初目标更加清晰。
我不太确定 cut -d'/'
的目的。
但是如果你只是想要当前目录中的 *.hs
个文件列表(递归找到),然后根据它们是否已更改构建一个 target/executable,你可以这样做:
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
个文件都将是 "compiled"。如果所有 .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'.
我需要一个允许我输入 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 也可能使我的最初目标更加清晰。
我不太确定 cut -d'/'
的目的。
但是如果你只是想要当前目录中的 *.hs
个文件列表(递归找到),然后根据它们是否已更改构建一个 target/executable,你可以这样做:
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
个文件都将是 "compiled"。如果所有 .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'.