迭代 submake 的值
Iterating the values of a submake
我正在尝试自动执行我在 Makefile 中经常使用的一些命令,但我似乎无法找出正确的语法。
给定以下目标:
.PHONY: params-list
params-list:
@aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name'
.PHONY: params-get
params-get:
@aws ssm get-parameter --name ${PARAM} --with-decryption | jq -c -r .Parameter.Value
我试图调用 params-list
,然后将结果输入 params-get
。我最好的尝试是:
.PHONY: params
params:
for param in $(MAKE) params-list; do \
$(MAKE) params-get PARAM=$${param}; \
done
但是显然不行。实现这一目标的正确方法是什么?
你可以做一个(长)target/recipe如下:
.PHONY: params-get
params-get:
@for p in $$(aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name'); do \
aws ssm get-parameter --name $$p --with-decryption | jq -c -r .Parameter.Value; \
done
这假定您的参数中没有空格
------------编辑--------------
为了能够访问另一个配方中的参数,您可以创建一个规则来创建一个文件,其中包含一个配方中的文件列表,然后在另一个配方中访问该文件:
# note that in this case .params-list is actually the name of a file,
# but it is declared as phony to force it to be rebuilt every time.
.PHONY: .params-list
.params-list:
aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name' > $@
.PHONY: params-get
params-get: .params-list
@for param in $$(cat .params-list); do \
aws ssm get-parameter --name $${param} --with-decryption | jq -c -r .Parameter.Value; \
done;
一个提示是避开 shell 构造 make 构造。一步一步来。
对于get操作,我们为每个参数编码一个目标。因此,对于参数 p1
(比方说),我们发明了一个目标 params-get<p1>
。我们注意到在配方内部(即 shell 命令),$@
将扩展为 params-get<p1>
。因此 ${@:params-get<%>=%}
将扩展为 p1
.
用 make 语法写出来:
.PHONY: params-get<p1>
params-get<p1>:
@aws ssm get-parameter --name ${@:params-get<%>=%} --with-decryption | jq -c -r .Parameter.Value
我注意到,使用中间变量,我们可以获得与您之前的咒语完全相同的配方。
PARAM = ${@:params-get<%>=%}
.PHONY: params-get<p1>
params-get<p1>:
@aws ssm get-parameter --name ${PARAM} --with-decryption | jq -c -r .Parameter.Value
如果我们有第二个参数 pa
(比方说),那很容易添加:
PARAM = ${@:params-get<%>=%}
.PHONY: params-get<p1> params-get<pa>
params-get<p1> params-get<pa>:
@aws ssm get-parameter --name ${PARAM} …
我希望你能看到一些样板出现在这里。
转向一些更动态生成的 make,而不是对每个参数进行硬编码,让我们将所有可能的参数放在一个名为 $PARAMS
[=28= 的列表中]
PARAMS := p1 pa another
get-targets := ${PARAMS:%=params-get<%>}
PARAM = ${@:params-get<%>=%}
.PHONY: ${get-targets}
${get-targets}:
@aws ssm get-parameter --name ${PARAM} …
.PHONY: params-get
params-get: ${get-targets}
echo $@ Done
我已经添加了您原来的 params-get
目标。现在所有的工作都由依赖完成。
- 看不到 shell 循环。
- 每个
aws ssm get-parameter
的退出代码由 make 检查。
- 代码是并行安全的:make -j9 将运行 9 个并行作业,直到工作耗尽。如果你有 8 个 CPU 就好了。 (如果你的 make 不是并行安全的,那么它 broken 顺便说一下。)
我们现在很接近了。我们只需要确保 $PARAMS
设置为 ssm get-parameters-by-path
.
的输出
类似于:
.PHONY: params-list
params-list:
@aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name'
PARAMS := $(shell ${MAKE} params-list)
get-targets := ${PARAMS:%=params-get<%>}
PARAM = ${@:params-get<%>=%}
.PHONY: ${get-targets}
${get-targets}:
@aws ssm get-parameter --name ${PARAM} --with-decryption | jq -c -r .Parameter.Value
.PHONY: params-get
params-get: ${get-targets}
echo $@ Done
绝对不喜欢使用 $(shell …)
,但这只是一个草图。
我正在尝试自动执行我在 Makefile 中经常使用的一些命令,但我似乎无法找出正确的语法。
给定以下目标:
.PHONY: params-list
params-list:
@aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name'
.PHONY: params-get
params-get:
@aws ssm get-parameter --name ${PARAM} --with-decryption | jq -c -r .Parameter.Value
我试图调用 params-list
,然后将结果输入 params-get
。我最好的尝试是:
.PHONY: params
params:
for param in $(MAKE) params-list; do \
$(MAKE) params-get PARAM=$${param}; \
done
但是显然不行。实现这一目标的正确方法是什么?
你可以做一个(长)target/recipe如下:
.PHONY: params-get
params-get:
@for p in $$(aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name'); do \
aws ssm get-parameter --name $$p --with-decryption | jq -c -r .Parameter.Value; \
done
这假定您的参数中没有空格
------------编辑--------------
为了能够访问另一个配方中的参数,您可以创建一个规则来创建一个文件,其中包含一个配方中的文件列表,然后在另一个配方中访问该文件:
# note that in this case .params-list is actually the name of a file,
# but it is declared as phony to force it to be rebuilt every time.
.PHONY: .params-list
.params-list:
aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name' > $@
.PHONY: params-get
params-get: .params-list
@for param in $$(cat .params-list); do \
aws ssm get-parameter --name $${param} --with-decryption | jq -c -r .Parameter.Value; \
done;
一个提示是避开 shell 构造 make 构造。一步一步来。
对于get操作,我们为每个参数编码一个目标。因此,对于参数 p1
(比方说),我们发明了一个目标 params-get<p1>
。我们注意到在配方内部(即 shell 命令),$@
将扩展为 params-get<p1>
。因此 ${@:params-get<%>=%}
将扩展为 p1
.
用 make 语法写出来:
.PHONY: params-get<p1>
params-get<p1>:
@aws ssm get-parameter --name ${@:params-get<%>=%} --with-decryption | jq -c -r .Parameter.Value
我注意到,使用中间变量,我们可以获得与您之前的咒语完全相同的配方。
PARAM = ${@:params-get<%>=%}
.PHONY: params-get<p1>
params-get<p1>:
@aws ssm get-parameter --name ${PARAM} --with-decryption | jq -c -r .Parameter.Value
如果我们有第二个参数 pa
(比方说),那很容易添加:
PARAM = ${@:params-get<%>=%}
.PHONY: params-get<p1> params-get<pa>
params-get<p1> params-get<pa>:
@aws ssm get-parameter --name ${PARAM} …
我希望你能看到一些样板出现在这里。
转向一些更动态生成的 make,而不是对每个参数进行硬编码,让我们将所有可能的参数放在一个名为 $PARAMS
[=28= 的列表中]
PARAMS := p1 pa another
get-targets := ${PARAMS:%=params-get<%>}
PARAM = ${@:params-get<%>=%}
.PHONY: ${get-targets}
${get-targets}:
@aws ssm get-parameter --name ${PARAM} …
.PHONY: params-get
params-get: ${get-targets}
echo $@ Done
我已经添加了您原来的 params-get
目标。现在所有的工作都由依赖完成。
- 看不到 shell 循环。
- 每个
aws ssm get-parameter
的退出代码由 make 检查。 - 代码是并行安全的:make -j9 将运行 9 个并行作业,直到工作耗尽。如果你有 8 个 CPU 就好了。 (如果你的 make 不是并行安全的,那么它 broken 顺便说一下。)
我们现在很接近了。我们只需要确保 $PARAMS
设置为 ssm get-parameters-by-path
.
类似于:
.PHONY: params-list
params-list:
@aws ssm get-parameters-by-path --path /${SERVICE}/${ENV} | jq -c -r '.Parameters[] | .Name'
PARAMS := $(shell ${MAKE} params-list)
get-targets := ${PARAMS:%=params-get<%>}
PARAM = ${@:params-get<%>=%}
.PHONY: ${get-targets}
${get-targets}:
@aws ssm get-parameter --name ${PARAM} --with-decryption | jq -c -r .Parameter.Value
.PHONY: params-get
params-get: ${get-targets}
echo $@ Done
绝对不喜欢使用 $(shell …)
,但这只是一个草图。