我有一个像
这样的目录结构packages/
foo/
lib/
a.js
b.js
bar/
lib/
c.js
d.js
我正在尝试编写一个简单的Makefile
来通过编译器运行源文件,并将packages/foo/lib/a.js
的结果输出到packages/foo/build/a.js
。在过去,我做过像
JS = $(shell find packages/foo/lib -name "*.js")
BUILD = $(patsubst packages/foo/lib/%.js, packages/foo/build/%.js, $(JS))
.PHONY: all
all: $(BUILD)
packages/foo/lib/%.js: packages/foo/build/%.js
# Compile $^ and output to $@
效果很好。但是,我现在正在做
JS = $(shell find packages/*/lib -name "*.js")
BUILD = $(patsubst ...)
这里的问题是patsubst
似乎不喜欢多个%
通配符(即packages/%/lib/%.js
)。但是,如果我使用packages/%.js
,那么我无法知道在替换中使用哪个目录。我确信有一种非常简单的方法可以在make docs中找不到。
答案 0 :(得分:1)
要定义BUILD
,您可以使用愚蠢但简单的解决方案:
BUILD = $(subst /lib/,/build/,$(JS))
只要您不担心源中的其他“lib”和“build”路径名组件。
但是,除非您想为每个目录foo
,bar
等手动指定规则,否则这将为您留下如何定义实际Makefile规则的问题。
相反,也许尝试这样的事情(如果你剪切和粘贴,请记得在适当的地方再次用标签替换空格):
PACKAGES = $(wildcard packages/*)
ALL :=
define add_package
JS := $$(shell find $(1)/lib -name "*.js")
BUILD := $$(patsubst $(1)/lib/%.js, $(1)/build/%.js, $$(JS))
$(1)/build/%.js:: $(1)/lib/%.js
echo COMPILE $$^ '->' $$@
cp $$^ $$@ # super fast compiler!
ALL += $$(BUILD)
endef
$(foreach p, $(PACKAGES), \
$(eval $(call add_package,$(p))))
all: $(ALL)
这会为每个包目录评估一个模板,这样你就可以把任何内容放在那里,只要你把美元符号的正确加倍。