假设我有一个源文件列表,每个文件都要编译为单独的二进制文件:
SRCS = abcd.c efgh.c ijkl.c
我想根据文件名将输出文件放在不同的子目录中:
我认为静态模式规则是要走的路。伪制规则可以是:
$(TARGETS): build/%/%: %.c
# stuff ...
我首先根据文件名制作子目录列表:
DIRS = $(SRCS:%.c=build/%)
所以现在我们有DIRS = build / abcd build / efgh build / ijkl。我想我现在可以通过以下方式制作目标列表:
BLDS = $(DIRS:%=%/$(basename %))
但是当然这不起作用,因为通配符不能在模式中多次使用。所以我现在卡在BLDS = build / abcd /%build / efgh /%build / ijkl /%.
显然,我完全是错误的做法。你会怎么做?
现在我明确地写了每条规则,这开始变得有点单调乏味:
compile = # command to do stuff
BD = build
all: $(BD)/abcd/abcd $(BD)/efgh/efgh $(BD)/ijkl/ijkl
$(BD)/abcd/abcd: abcd.c
$(call compile)
$(BD)/efgh/efgh: efgh.c
$(call compile)
$(BD)/ijkl/ijkl: ijkl.c
$(call compile)
clean:
rm -rf build/*
.PHONY: all
答案 0 :(得分:3)
我相信这可以做你想要的:
SRCS:=abcd.c efgh.c ijkl.c
# We could fold NAMES into BLDS's definition if NAMES is not used elsewhere.
NAMES:=$(SRCS:%.c=%)
BLDS:=$(foreach name,$(NAMES),$(subst foo,$(name),build/foo/foo))
# We don't use DIRS below but the question had this variable.
DIRS:=$(dir $(BLDS))
TARGETS:=$(BLDS)
.PHONY: all
all: $(TARGETS)
.SECONDEXPANSION:
$(TARGETS): $$(notdir $$@).c
@echo Build $@ from $^
mkdir -p $(dir $@)
touch $@
有两个重要的变化。第一种是重新排序变量的创建方式,并使用subst
,它允许多次替换匹配的字符串。第二种是使用secondary expansion,以便为每个目标构建规则。您最初是一个包含两个%
,but the docs say:
模式规则看起来像普通规则,除了它的目标包含字符'%'(其中只有一个)。
(强调补充。)
我使用假文件abcd.c
efgh.c
和ijkl.c
对上述内容进行了测试,并得到以下输出:
$ make
Build build/abcd/abcd from abcd.c
mkdir -p build/abcd/
touch build/abcd/abcd
Build build/efgh/efgh from efgh.c
mkdir -p build/efgh/
touch build/efgh/efgh
Build build/ijkl/ijkl from ijkl.c
mkdir -p build/ijkl/
touch build/ijkl/ijkl