从命令行传递附加变量以使

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

769725 次浏览

最简单的方法是:

make foo=bar target

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

如果您正在使用sub-make,请参阅本文:将变量传递给子制造商

假设你有一个这样的makefile:

action:echo argument is $(argument)

你可以叫它make action argument=something

手册

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

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

FOOBAR=1 make

在您的Makefile中生成变量FOOBAR

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

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

    您可能还想设置-e选项(又名--environments-override),您的环境变量将覆盖在makefile中的赋值(除非这些赋值本身使用#2指令。但是,不推荐这样做,并且使用?=赋值(条件变量赋值操作符,只有在变量尚未定义时才会生效)更好和更灵活:

    FOO?=default_value_if_not_set_in_environment

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

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

    make target FOO=bar

    然后makefile中#0变量的所有赋值都将被忽略,除非你在赋值中使用#1指令。(效果与环境变量的-e选项相同)。

  • 从父Make导出-如果您从Makefile调用Make,您通常不应该像这样显式编写变量赋值:

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

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

    # Do like thisCFLAGS=-gexport CFLAGStarget:$(MAKE) -C target

    您还可以通过使用不带参数的export导出所有变量。

如果您创建一个名为Makefile的文件并添加一个像这样的变量$(unittest)然后,即使使用通配符,您也可以在Makefile中使用此变量

例子:

make unittest=*

我使用BOOST_TEST并为参数run_test=$(unittest)提供通配符然后我将能够使用正则表达式过滤掉我想要的Makefile测试运行

这里没有引用另一个选项,它包含在Stallman和McGrath的GNU Make书中(参见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.aelseranlib archive.aendif

它涉及验证给定参数是否出现在MAKEFLAGS中。例如…假设你正在研究c++11中的线程,并且你已经将研究划分为多个文件(class01,…,classNM),并且你想要:编译所有文件并单独运行,或者一次编译一个并在指定标志的情况下运行它(例如-r)。所以,你可以想出以下Makefile

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

有了这个,你会:

  • 构建并运行一个文件w/make -r class02
  • 构建所有w/makemake all
  • 构建并运行所有w/make -r(假设它们都包含某种断言内容,您只想测试它们)
export ROOT_DIR=<path/value>

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

似乎命令参数覆盖了环境变量。

创建文件:

send:echo $(MESSAGE1) $(MESSAGE2)

示例运行:

$ MESSAGE1=YES MESSAGE2=NG  make send MESSAGE2=OKecho YES OKYES OK