【问题标题】:Make variable that is only passed from the command line创建仅从命令行传递的变量
【发布时间】:2020-04-25 16:58:15
【问题描述】:

我知道我可以通过两种方式将变量传递给 Makefile:

make <target> FOO=bar

export FOO=bar
make <target>

并且这两个都会使变量FOO在makefile中可用,其值为bar

但是,有没有办法要求变量只来自命令行?我希望变量的传递是明确的,以避免环境变量的某些潜在重叠,所以我想确保make 只接收从命令行传递的变量,如果它只在环境中设置,则忽略它所以它使用的值必须由用户在调用make时定义。

编辑:在研究了更多之后,我意识到环境变量实际上并没有像我想象的那样被访问,它们实际上在 make 中使用为${FOO},只要我没有定义FOOmakefile 中的任何位置,其唯一的设置值将来自命令行(如this answer 中所述)。

【问题讨论】:

    标签: makefile


    【解决方案1】:

    这些将变量传递给 GNU make 的方法并不等效。

    • 来自环境的变量不会覆盖 makefile 中的分配,除非使用 -e 选项调用 make。见variables from the environment。这是因为依赖环境变量在构建可重现性方面是不好的做法(有人忘记设置环境变量并且构建不同):

      makefile 的功能依赖于他们无法控制的环境变量是不明智的,因为这会导致不同的用户从同一个 makefile 获得不同的结果。这违背了大多数 makefile 的全部目的。

    • 来自 make 命令行的变量会覆盖 makefile 中的分配,除非指定了 override。见the override directive

    因此,建议的做法是在 makefile 中无条件地将所有变量显式设置为其默认值,以便只有命令行中的赋值会覆盖它们。

    【讨论】:

    • 关于推荐做法的一个警告。该手册还说环境变量方法 “对于具有标准或传统含义的变量是安全的,因为您知道没有任何 makefile 会将它们用于其他事情。” 它给出了 CFLAGS 的示例,因为 “通过在您的环境中设置变量 CFLAGS,您可以使大多数 makefile 中的所有 C 编译都使用您喜欢的编译器开关。” 例如,您可能希望在调试模式下构建多个项目,因此您可以通过 shell export CFLAGS="-g3" 简单地控制它。
    • @DarrenSmith 不确定这是否仍然被认为是好的或普遍支持的做法。许多 makefile 只是设置 CFLAGS := ... 覆盖您的环境变量。
    【解决方案2】:

    据我所知,${FOO}$(FOO) 之间没有区别,无论 FOO 的定义方式如何。

    如果您使用 GNU make,有一个函数 origin 可以让您进行区分:它将返回 command line 用于在命令行中定义的变量和 environment 用于环境导出的变量(更多信息在manual

    使用以下Makefile

    foo ?= foo
    
    default:
        @echo ${foo}, comes from $(origin foo)
    
    • make 打印 foo, comes from file
    • make foo=bla 打印 bla, comes from command line
    • (export foo=bar; make) 打印 bar, comes from environment

    【讨论】:

      【解决方案3】:

      扩展@Virgile 答案,您可以在生成文件的开头添加以下类型的检查。尽管所有这些检查都可以驻留在专用的 makefile 中,然后从主 makefile 中包含,但对于您希望检查的每个变量都需要重复很多操作

      foo ?= foo
      
      # check origin
      ifdef foo
      ifneq "$(origin foo)" "command line"
      $(error foo: must come from command line)
      endif
      else
      $(error foo not defined)
      endif
      
      default:
          @echo ${foo}, comes from $(origin foo)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-22
        • 2013-12-07
        • 1970-01-01
        相关资源
        最近更新 更多