GNU makefile:从命令行参数传递额外的变量

Passing additional variables from command line to make

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


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

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

    您可能还希望将-e选项(也称为--environments-override)设置为开,并且您的环境变量将覆盖makefile中的分配(除非这些分配本身使用override指令)。但是,不建议这样做,而且使用?=赋值(条件变量赋值运算符,仅当变量尚未定义时才有效)更为方便和灵活:

    1
    FOO?=default_value_if_not_set_in_environment

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

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

    1
    make target FOO=bar

    但是,除非在赋值中使用override指令,否则makefile中对FOO变量的所有赋值都将被忽略。(效果与环境变量的-e选项相同)。

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

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

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

    1
    2
    3
    4
    5
    # Do like this
    CFLAGS=-g
    export CFLAGS
    target:
            $(MAKE) -C target

    您也可以不带参数地使用export导出所有变量。


最简单的方法是:

1
make foo=bar target

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

如果您使用的是Sub Make,请参阅本文:将变量与Sub Make通信


假设您有这样的makefile:

1
2
action:
    echo argument is $(argument)

那你就称它为make action argument=something


从手册中:

Variables in make can come from the environment in which make is run. Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value. However, an explicit assignment in the makefile, or with a command argument, overrides the environment.

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

1
FOOBAR=1 make

生成makefile中的变量FOOBAR


史泰尔曼和麦格拉思的GNU制造手册中还没有提到另一个选项(见http://www.chemie.fu berlin.de/chemnet/use/info/make/make_7.html)。它提供了示例:

1
2
3
4
5
6
7
archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
        +touch archive.a
        +ranlib -t archive.a
else
        ranlib archive.a
endif

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CXX=clang++-3.5
CXXFLAGS = -Wall -Werror -std=c++11
LDLIBS = -lpthread

SOURCES = class01 class02 class03

%: %.cxx
    $(CXX) $(CXXFLAGS) -o [email protected] $^ $(LDLIBS)
ifneq (,$(findstring r,  $(MAKEFLAGS)))
    ./[email protected]
endif

all: $(SOURCES)

.PHONY: clean

clean:
    find . -name"*.out" -delete

有了它,你会:

  • 建立并运行一个文件w/make -r class02
  • 建造所有w/MAKEmake all
  • 构建并运行所有w/make -r(假设它们都包含某种断言内容,而您只想测试所有内容)

1
export ROOT_DIR=<path/value>

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


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

例子:

1
make unittest=*

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