Makefile 重建所有文件,即使只有一个文件改变

Makefile rebuilds all files even if only one changes

我正在为一个目录结构复杂的包含大量js文件的项目编写Makefile。当 运行 它需要对每个文件执行一些编译并将结果保存到具有相同树结构的不同目录(现在由 cp 模拟)。当我 运行 make js 它按预期构建时,当我再次 运行 make js 时它说没有工作要做。但是,当我修改其中一个文件并 make js 时,它会重新构建整个树,而不仅仅是修改后的文件。

SHELL := /bin/bash
BUILDDIR := build/gui/

RAWJSFILES := $(shell find app -name '*.js')
BUILT_RAWJSFILES := $(patsubst %, $(BUILDDIR)%,$(RAWJSFILES))

$(BUILDDIR):
    mkdir -p $(BUILDDIR)

$(RAWJSFILES): $(BUILDDIR)

$(BUILT_RAWJSFILES): $(RAWJSFILES)
    mkdir -p $(@D)
    # compile step
    cp $(shell python -c "print '$@'.lstrip('${BUILDDIR}')") $(@D)

.PHONY: js
js: $(BUILT_RAWJSFILES)

$(BUILT_RAWJSFILES): $(RAWJSFILES)设置每个文件$(BUILT_RAWJSFILES)所有文件的先决条件$(RAWJSFILES).

要获得您想要的一对一映射,您需要模式规则或静态模式规则。

此外,嵌入的 python 代码段 根本 没有按照您的预期去做。它从 $@ 的值中删除最长的前导前缀,该前缀包含 BUILDDIR 中的任何字符,即 build/gui/ (仅不作为字符作为字符串,因此相当于 lstrip('/iugdlb')). (哦,你也不需要 $(shell) 这里你已经在 shell 上下文中所以正常的命令替换也可以工作($$(python ...)。)

也就是说,如果您使用模式或静态模式规则,您将有更简单的方法来获取源文件名,然后像那样搞乱 python。

像这样的东西应该可以工作(未经测试):

$(BUILDDIR)%.js: %.js
        mkdir -p $(@D)
        cp $^ $(@D)