【问题标题】:multiple Target-specific Variable Values多个目标特定的变量值
【发布时间】:2018-05-14 03:03:24
【问题描述】:

关注文档到manage Target-specific Variable Values

prog : CFLAGS = -g
prog : prog.o foo.o bar.o

我可以设置一个特定于目标的变量。

现在我的问题是,如何设置多个特定于目标的变量。是不是必须一一设置?

dev_deploy: env = dev
dev_deploy: image = abc
dev_deploy: tag = 1.0.4-dev
dev_deploy:
      docker run -t --rm -e env=$(env) \
         $(image):$(tag) \
         sh -c "test.sh"


prod_deploy: env = prod
prod_deploy: image = abc
prod_deploy: tag = 1.0.3-prod
prod_deploy:
      docker run -t --rm -e env=$(env) \
         $(image):$(tag) \
         sh -c "test.sh"

有没有什么方法可以用简单的方式设置本地环境(特定于目标的变量)?

【问题讨论】:

    标签: docker makefile gnu-make


    【解决方案1】:

    您的第一个问题的直接答案是肯定的,您必须为每个特定于目标的变量使用单独的目标行并逐个设置它们。

    第二个问题的答案是肯定的:一个是 uzsolt 描述的。这也是我推荐的方法。 uzsolt 的解决方案和特定于目标的变量解决方案之间的一个区别是特定于目标的变量是inherited by prerequisites。你似乎不需要这种行为,但如果你这样做了,那么这个解决方案对你不起作用。

    如果您需要特定于目标的变量,或者如果每个变量分配一行仍然太痛苦(例如,您有非常多的变量,并且您真的希望每组只有一行),那么可能会有更多的选项理解起来很复杂,但以后使用起来更简单。

    例如,如果您知道所有变量值都不会包含空格,那么您可以创建一个用户定义的宏,该宏使用 eval 来设置特定于目标的变量,如下所示:

    assign-vars = $(foreach A,$2,$(eval $1: $A))
    
    $(call assign-vars, dev_deploy,   env=devenv  image=abc  tag=1.0.4-dev)
    $(call assign-vars, prod_deploy,  env=prod    image=abc  tag=1.0.3-prod)
    

    注意:第一个参数是目标,每个赋值必须是单个“单词”(没有嵌入空格)并且赋值之间没有逗号。

    【讨论】:

    • 您能帮忙修改assign-vars 以接受任意数量的目标吗?喜欢$(call assign-vars, dev_deploy, prod_deploy, env=devenv image=abc tag=1.0.4-dev)
    • 它已经适用于多个目标,但您必须提供 空格分隔 的目标列表,而不是逗号分隔的目标列表。喜欢$(call assign-vars, dev_deploy prod_deploy, env=devenv image=abc tag=1.0.4-dev)
    【解决方案2】:

    我会这样做的:

    dev_deploy_env= devenv
    dev_deploy_image=   abc
    dev_deploy_tag= 1.0.4-dev
    
    prod_deploy_env=    prod
    prod_deploy_image=  abc
    prod_deploy_tag=    1.0.3-prod
    
    dev_deploy prod_deploy:
        @echo docker run -t --rm -e env=${${@}_env} \
          ${${@}_image}:${${@}_tag} \
          sh -c "test.sh"
    
    .PHONY: dev_deploy prod_deploy
    

    查看命令(我使用的是 FreeBSD,GNU make 命令是gmake):

    $  gmake prod_deploy 
    docker run -t --rm -e env=prod abc:1.0.3-prod sh -c test.sh
    $  gmake dev_deploy       
    docker run -t --rm -e env=devenv abc:1.0.4-dev sh -c test.sh
    

    当然你应该删除@echo 来运行命令。

    【讨论】:

    • 看起来很整洁,会测试一下
    • 问题,docker 命令也有一些全局环境要使用,例如,它们并不总是用作${${@}_image}。
    • 在这种情况下你可以使用${or ${${@}_image},default_image}。
    • 非常感谢,这很有道理。
    【解决方案3】:

    正如answer 中所述,您还可以使用$(MAKECMDGOALS) 在运行目标之前覆盖变量。

    根据您的示例,我将其重构为以下内容

    
    ifeq ($(filter dev_deploy,$(MAKECMDGOALS)),dev_deploy)
    env   = dev
    image = abc
    tag   = 1.0.4-dev
    endif
    
    
    ifeq ($(filter prod_deploy,$(MAKECMDGOALS)),prod_deploy)
    env   = prod
    image = abc
    tag   = 1.0.3-prod
    endif
    
    dev_deploy prod_deploy:
        docker run -t --rm -e env=$(env) \
             $(image):$(tag) \
             sh -c "test.sh"
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      • 1970-01-01
      相关资源
      最近更新 更多