代码之家  ›  专栏  ›  技术社区  ›  Pablo

从命令行传递附加变量

  •  494
  • Pablo  · 技术社区  · 15 年前

    我可以将变量作为命令行参数传递给gnu makefile吗?换句话说,我想传递一些参数,这些参数最终将成为makefile中的变量。

    7 回复  |  直到 8 年前
        1
  •  615
  •   rogerdpack    11 年前

    您有几个选项可以从makefile外部设置变量:

    • 来自环境 -每个环境变量都转换为具有相同名称和值的makefile变量。

      您也可以设置 -e 选项(AKA) --environments-override )并且您的环境变量将重写生成文件中的分配(除非这些分配本身使用 override directive . 但是,不推荐使用,而且使用起来更灵活、更好 ?= 赋值(条件变量赋值运算符,仅当变量尚未定义时才有效):

      FOO?=default_value_if_not_set_in_environment
      

      请注意,某些变量不是从环境继承的:

      • MAKE 从脚本的名称中获取
      • SHELL 在生成文件中设置,或默认为 /bin/sh (理由:命令是在makefile中指定的,它们是特定于shell的)。
    • 从命令行 - make 可以将变量分配作为命令行的一部分,与目标混合:

      make target FOO=bar
      

      但是然后 所有工作分配到 FOO 将忽略makefile中的变量 除非你用 重写 指令 在作业中。(效果与 -e 环境变量的选项)。

    • 从父make导出 -如果从makefile调用make,通常不应显式地编写如下变量赋值:

      # Don't do this!
      target:
              $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
      

      相反,更好的解决方案可能是导出这些变量。导出一个变量会使它进入每个shell调用的环境中,并从这些命令中进行调用,如上面指定的那样选择这些环境变量。

      # Do like this
      CFLAGS=-g
      export CFLAGS
      target:
              $(MAKE) -C target
      

      您也可以导出 全部的 变量,通过使用 export 没有参数。

        2
  •  160
  •   Mark Byers    15 年前

    最简单的方法是:

    make foo=bar target
    

    然后在makefile中,您可以参考 $(foo) . 请注意,这不会自动传播到Sub Make。

    如果您使用的是Sub Make,请参阅本文: Communicating Variables to a Sub-make

        3
  •  55
  •   nc3b    15 年前

    假设您有这样的makefile:

    action:
        echo argument is $(argument)
    

    那你就叫它 make action argument=something

        4
  •  17
  •   Thomas    15 年前

    manual :

    make中的变量可以来自运行make的环境。make启动时看到的每个环境变量都转换为具有相同名称和值的make变量。但是,makefile中的显式赋值或带有命令参数的显式赋值会覆盖环境。

    所以你可以这样做(从bash):

    FOOBAR=1 make
    

    产生一个变量 FOOBAR 在你的makefile中。

        5
  •  2
  •   serup    11 年前

    如果您生成一个名为make file的文件,并添加一个像这样的变量$(unittest) 这样,即使使用通配符,也可以在makefile中使用该变量。

    例子:

    make unittest=*
    

    我使用boost_测试,并为参数提供通配符--run_test=$(unittest) 然后我就可以使用正则表达式过滤掉我想要的makefile测试。 运行

        6
  •  2
  •   Ciro Costa    10 年前

    还有一个选项没有在这里引用,它包含在史泰尔曼和麦格拉思的GNU手册中(见 http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_7.html )它提供了示例:

    archive.a: ...
    ifneq (,$(findstring t,$(MAKEFLAGS)))
            +touch archive.a
            +ranlib -t archive.a
    else
            ranlib archive.a
    endif
    

    它涉及验证给定参数是否出现在 MAKEFLAGS . 例如。。假设你正在学习C++ 11中的线程,你把你的学习划分成多个文件( class01 ,…, classNM )您希望:编译然后全部单独运行,或者一次编译一个,如果指定了标志,就运行它。( -r 例如)。所以,你可以想出以下方法 Makefile :

    CXX=clang++-3.5
    CXXFLAGS = -Wall -Werror -std=c++11
    LDLIBS = -lpthread
    
    SOURCES = class01 class02 class03
    
    %: %.cxx
        $(CXX) $(CXXFLAGS) -o $@.out $^ $(LDLIBS)
    ifneq (,$(findstring r,  $(MAKEFLAGS)))
        ./$@.out
    endif
    
    all: $(SOURCES)
    
    .PHONY: clean
    
    clean:
        find . -name "*.out" -delete
    

    有了它,你会:

    • 生成并运行文件w/ make -r class02 ;
    • 构建所有W// make make all ;
    • 生成并运行所有w/ make -r (假设它们都包含某种断言内容,而您只想测试它们全部)
        7
  •  2
  •   parasrish    9 年前
    export ROOT_DIR=<path/value>
    

    然后使用变量, $(ROOT_DIR) 在makefile中。