makefile如何将自定义变量写入yaml文件以支持vagrantfile fetch参数
How does the makefile write user-defined variables to the yaml file to support vagrantfile fetch parameters
我有一个项目是用makefile来控制vagrant的,我想把vagrant的参数放到makefile里面,比如cpu
, memory
, ip
, [=15] =]、forwarded_port
等。我找到了一个 way,vagrantfile 读取 yaml 文件来参数化 vagrantfile。因此 makefile 需要一个 target
来读取所有用户选项变量并将它们作为 key-value
对写入 config.yaml。
样本如下
# === BEGIN USER OPTIONS ===
BOX_OS ?= fedora
# Box setup
#BOX_IMAGE
# Disk setup
DISK_COUNT ?= 1
DISK_SIZE_GB ?= 25
# VM Resources
MASTER_CPUS ?= 2
MASTER_MEMORY_SIZE_GB ?= 2
NODE_CPUS ?= 2
NODE_MEMORY_SIZE_GB ?= 2
NODE_COUNT ?= 2
# Network
MASTER_IP ?= 192.168.26.10
NODE_IP_NW ?= 192.168.26.
POD_NW_CIDR ?= 10.244.0.0/16
...
...
# === END USER OPTIONS ===
echo
命令确实实现了它
# Makefile
envInit:
@echo "POD_NW_CIDR : \"$(POD_NW_CIDR)\"" > ${FILECWD}/configs.yaml
但是 too many variables
可能太复杂了。
有没有办法批量读取变量及其值并将它们写入 yml 文件
如果你们能告诉我如何实现批量读取变量及其值并将它们写入 yml 文件,我将不胜感激。
将所有用户选项(连同默认值)定义为一个列表,以便它们是可迭代的:
# list of user options with default values
userOptions = \
BOX_OS=2 \
DISK_COUNT=1 \
MASTER_IP=192.168.26.10
# replace each default value with the env value, if any
userOptionValues = $(foreach i, $(userOptions), \
$(word 1, $(subst =, ,$i))=$(or \
$($(word 1, $(subst =, ,$i))), $($(word 1, $(subst =, ,$i))), $(word 2, $(subst =, ,$i))))
# write the yaml file
envInit:
# empty the file
@printf "" > configs.yaml
# write a line for each option
@for i in $(userOptionValues); do \
printf "%s : %s\n" "$$(printf $$i | cut -d= -f1)" "$$(printf $$i | cut -d= -f2)" >> configs.yaml; \
done
@flyx 谢谢你的回答,你的代码确实很好用。不过我好像找到了更多的convenient way,我也修改了一部分
printvars:
@echo$(foreach V,$(sort $(.VARIABLES)), \
$(if $(filter-out environment% default automatic,$(origin $V)),$(info $V: $($V))))
但离实现目标还有差距
# the Makefile test file
FILECWD = $(shell pwd)
# === BEGIN USER OPTIONS ===
CLOUD_IP ?= 192.168.79.222
CLOUD_NAME ?= cloud
CLOUD_CPU ?= 6
CLOUD_MEMORY ?= 8
# === END USER OPTIONS ===
printvars:
@echo$(foreach V,$(sort $(.VARIABLES)), \
$(if $(filter-out environment% default automatic,$(origin $V)),$(info $V: $($V))))
make printvars
的输出包含许多其他变量
$ make printvars
.DEFAULT_GOAL: printvars
CLOUD_IP: 192.168.79.222
CLOUD_MEMORY: 8
CLOUD_NAME: cloud
CURDIR: /testmakecreateyml0930
FILECWD: /testmakecreateyml0930
GNUMAKEFLAGS:
MAKEFILE_LIST: Makefile
MAKEFLAGS:
SHELL: /bin/sh
而且只能打印不能导出到yamlfile.This离成功只差一步
如果你能帮我修改它以实现我的目标,我将不胜感激
您可以使用 GNUmake
s $(file)
函数直接写入文件:
define newline :=
$(strip)
$(strip)
endef
space := $(strip) $(strip)#
-never-matching := ¥# character 165, this is used as a list element that should never appear as a real element
option-names = $(subst $(-never-matching),,$(filter $(-never-matching)%,$(subst $(-never-matching)$(space),$(-never-matching),$(-never-matching)$(strip $(subst $(newline), $(-never-matching),)))))
# define your user options in as many separate parts as you like, spaces and empty lines included:
define USER_OPTIONS +=
a = spaces are no problem
b = "neither nearly all 'other' characters: 8&)("
endef
define USER_OPTIONS +=
c = baz baf
d = foobar
endef
# make all definition make variables verbatim
$(eval $(USER_OPTIONS))
YAML_FORMAT := $(foreach name,$(call option-names,$(USER_OPTIONS)),$(newline)$(name) : $($(name)))
# write the file. Warning: this happens before any rule is run!
$(file >test.yaml,$(YAML_FORMAT))
$(info $(foreach name,$(call option-names,$(USER_OPTIONS)),<$(name) : $($(name))> ))
诀窍在于将所有相关的用户选项变量聚集在一个多行 make 变量中。函数 option-names
将该变量中的所有标识符提取到一个单独的列表中。
我从 the GNUmake table toolkit 中获取了 newline
等字符定义,它对 "programmatic" make 有很多功能。
我有一个项目是用makefile来控制vagrant的,我想把vagrant的参数放到makefile里面,比如cpu
, memory
, ip
, [=15] =]、forwarded_port
等。我找到了一个 way,vagrantfile 读取 yaml 文件来参数化 vagrantfile。因此 makefile 需要一个 target
来读取所有用户选项变量并将它们作为 key-value
对写入 config.yaml。
样本如下
# === BEGIN USER OPTIONS ===
BOX_OS ?= fedora
# Box setup
#BOX_IMAGE
# Disk setup
DISK_COUNT ?= 1
DISK_SIZE_GB ?= 25
# VM Resources
MASTER_CPUS ?= 2
MASTER_MEMORY_SIZE_GB ?= 2
NODE_CPUS ?= 2
NODE_MEMORY_SIZE_GB ?= 2
NODE_COUNT ?= 2
# Network
MASTER_IP ?= 192.168.26.10
NODE_IP_NW ?= 192.168.26.
POD_NW_CIDR ?= 10.244.0.0/16
...
...
# === END USER OPTIONS ===
echo
命令确实实现了它
# Makefile
envInit:
@echo "POD_NW_CIDR : \"$(POD_NW_CIDR)\"" > ${FILECWD}/configs.yaml
但是 too many variables
可能太复杂了。
有没有办法批量读取变量及其值并将它们写入 yml 文件
如果你们能告诉我如何实现批量读取变量及其值并将它们写入 yml 文件,我将不胜感激。
将所有用户选项(连同默认值)定义为一个列表,以便它们是可迭代的:
# list of user options with default values
userOptions = \
BOX_OS=2 \
DISK_COUNT=1 \
MASTER_IP=192.168.26.10
# replace each default value with the env value, if any
userOptionValues = $(foreach i, $(userOptions), \
$(word 1, $(subst =, ,$i))=$(or \
$($(word 1, $(subst =, ,$i))), $($(word 1, $(subst =, ,$i))), $(word 2, $(subst =, ,$i))))
# write the yaml file
envInit:
# empty the file
@printf "" > configs.yaml
# write a line for each option
@for i in $(userOptionValues); do \
printf "%s : %s\n" "$$(printf $$i | cut -d= -f1)" "$$(printf $$i | cut -d= -f2)" >> configs.yaml; \
done
@flyx 谢谢你的回答,你的代码确实很好用。不过我好像找到了更多的convenient way,我也修改了一部分
printvars:
@echo$(foreach V,$(sort $(.VARIABLES)), \
$(if $(filter-out environment% default automatic,$(origin $V)),$(info $V: $($V))))
但离实现目标还有差距
# the Makefile test file
FILECWD = $(shell pwd)
# === BEGIN USER OPTIONS ===
CLOUD_IP ?= 192.168.79.222
CLOUD_NAME ?= cloud
CLOUD_CPU ?= 6
CLOUD_MEMORY ?= 8
# === END USER OPTIONS ===
printvars:
@echo$(foreach V,$(sort $(.VARIABLES)), \
$(if $(filter-out environment% default automatic,$(origin $V)),$(info $V: $($V))))
make printvars
的输出包含许多其他变量
$ make printvars
.DEFAULT_GOAL: printvars
CLOUD_IP: 192.168.79.222
CLOUD_MEMORY: 8
CLOUD_NAME: cloud
CURDIR: /testmakecreateyml0930
FILECWD: /testmakecreateyml0930
GNUMAKEFLAGS:
MAKEFILE_LIST: Makefile
MAKEFLAGS:
SHELL: /bin/sh
而且只能打印不能导出到yamlfile.This离成功只差一步
如果你能帮我修改它以实现我的目标,我将不胜感激
您可以使用 GNUmake
s $(file)
函数直接写入文件:
define newline :=
$(strip)
$(strip)
endef
space := $(strip) $(strip)#
-never-matching := ¥# character 165, this is used as a list element that should never appear as a real element
option-names = $(subst $(-never-matching),,$(filter $(-never-matching)%,$(subst $(-never-matching)$(space),$(-never-matching),$(-never-matching)$(strip $(subst $(newline), $(-never-matching),)))))
# define your user options in as many separate parts as you like, spaces and empty lines included:
define USER_OPTIONS +=
a = spaces are no problem
b = "neither nearly all 'other' characters: 8&)("
endef
define USER_OPTIONS +=
c = baz baf
d = foobar
endef
# make all definition make variables verbatim
$(eval $(USER_OPTIONS))
YAML_FORMAT := $(foreach name,$(call option-names,$(USER_OPTIONS)),$(newline)$(name) : $($(name)))
# write the file. Warning: this happens before any rule is run!
$(file >test.yaml,$(YAML_FORMAT))
$(info $(foreach name,$(call option-names,$(USER_OPTIONS)),<$(name) : $($(name))> ))
诀窍在于将所有相关的用户选项变量聚集在一个多行 make 变量中。函数 option-names
将该变量中的所有标识符提取到一个单独的列表中。
我从 the GNUmake table toolkit 中获取了 newline
等字符定义,它对 "programmatic" make 有很多功能。