如何通过遍历 Makefile 列表来创建多个食谱?
How to create a multiple recipes by looping over a Makefile list?
我有以下 makefile,其中有多个 cp
命令将目录从源复制到目标。
process:
cp dir/level/2000/config.json output/2000/config.json
cp dir/level/2001/config.json output/2001/config.json
cp dir/level/2002/config.json output/2002/config.json
stage:
mkdir -p output/2000 output/2001 output/2002
cp dir/common/2000/esc output/2000/esc
cp dir/common/2001/esc output/2001/esc
cp dir/common/2002/esc output/2002/esc
apply: stage process
我想通过引入一个 2000 2001 2002
的变量列表来使上面的 Makefile 更加动态,然后它会在每次迭代时遍历变量和 运行 规则。像...
var := 2000 2001 2002
process:
cp dir/level/${var}/config.json output/${var}/config.json
stage:
mkdir -p output/${var}
cp dir/common/${var}/esc output/${var}/esc
apply: stage process
现在,如果我 运行 make apply
它应该重新创建与第一个 makefile 相同的步骤。
我尝试使用多个目标作为 ${var}
,它按我想要的方式工作,但它只能用于替代目标之一,不能同时用于 stage
和 process
。我做到了
process:
cp dir/level/2000/config.json output/2000/config.json
cp dir/level/2001/config.json output/2001/config.json
cp dir/level/2002/config.json output/2002/config.json
${var}:
mkdir -p output/$@
cp dir/common/$@/esc output/$@/esc
apply: ${var} process
现在如果我 运行 申请,它会像我预期的那样 运行 但是如何使用相同的多个目标来代替 process
呢?
最简单的解决方案可能是在您的食谱中使用 shell for
循环:
var := 2000 2001 2002
process:
for year in $(var); do \
cp dir/level/$$year/config.json output/$$year/config.json; \
done
请注意,在食谱中我们需要写 $$year
来引用
shell 变量名为 year
因为单个 $
会引入一个
makefile 变量引用。
仅使用 make
语法,您可以这样做:
var = 2000 2001 2002
outputs = $(patsubst %,output/%/config.json,$(var))
output/%/config.json: dir/level/%/config.json
echo cp $< $@
all: $(outputs)
这将创建一个变量 outputs
,其内容为:
output/2000/config.json output/2001/config.json output/2002/config.json
然后使用模式规则隐式创建用于从相应输入创建这些输出的配方。
您最有可能使用模式规则:
apply: stage process
var := 2000 2001 2002
process: $(foreach V,$(var),output/$V/config.json)
stage: $(foreach V,$(var),output/$V/esc)
output/%/config.json: dir/level/%/config.json
cp $< $@
output/%/esc : dir/common/%/esc
mkdir -p $(@D)
cp $< $@
我有以下 makefile,其中有多个 cp
命令将目录从源复制到目标。
process:
cp dir/level/2000/config.json output/2000/config.json
cp dir/level/2001/config.json output/2001/config.json
cp dir/level/2002/config.json output/2002/config.json
stage:
mkdir -p output/2000 output/2001 output/2002
cp dir/common/2000/esc output/2000/esc
cp dir/common/2001/esc output/2001/esc
cp dir/common/2002/esc output/2002/esc
apply: stage process
我想通过引入一个 2000 2001 2002
的变量列表来使上面的 Makefile 更加动态,然后它会在每次迭代时遍历变量和 运行 规则。像...
var := 2000 2001 2002
process:
cp dir/level/${var}/config.json output/${var}/config.json
stage:
mkdir -p output/${var}
cp dir/common/${var}/esc output/${var}/esc
apply: stage process
现在,如果我 运行 make apply
它应该重新创建与第一个 makefile 相同的步骤。
我尝试使用多个目标作为 ${var}
,它按我想要的方式工作,但它只能用于替代目标之一,不能同时用于 stage
和 process
。我做到了
process:
cp dir/level/2000/config.json output/2000/config.json
cp dir/level/2001/config.json output/2001/config.json
cp dir/level/2002/config.json output/2002/config.json
${var}:
mkdir -p output/$@
cp dir/common/$@/esc output/$@/esc
apply: ${var} process
现在如果我 运行 申请,它会像我预期的那样 运行 但是如何使用相同的多个目标来代替 process
呢?
最简单的解决方案可能是在您的食谱中使用 shell for
循环:
var := 2000 2001 2002
process:
for year in $(var); do \
cp dir/level/$$year/config.json output/$$year/config.json; \
done
请注意,在食谱中我们需要写 $$year
来引用
shell 变量名为 year
因为单个 $
会引入一个
makefile 变量引用。
仅使用 make
语法,您可以这样做:
var = 2000 2001 2002
outputs = $(patsubst %,output/%/config.json,$(var))
output/%/config.json: dir/level/%/config.json
echo cp $< $@
all: $(outputs)
这将创建一个变量 outputs
,其内容为:
output/2000/config.json output/2001/config.json output/2002/config.json
然后使用模式规则隐式创建用于从相应输入创建这些输出的配方。
您最有可能使用模式规则:
apply: stage process
var := 2000 2001 2002
process: $(foreach V,$(var),output/$V/config.json)
stage: $(foreach V,$(var),output/$V/esc)
output/%/config.json: dir/level/%/config.json
cp $< $@
output/%/esc : dir/common/%/esc
mkdir -p $(@D)
cp $< $@