我可以将变量作为命令行参数传递给 GNU Makefile 吗?换句话说,我想传递一些最终将成为 Makefile 中的变量的参数。
您有几个选项可以从 makefile 外部设置变量:
从环境 - 每个环境变量都转换为具有相同名称和值的 makefile 变量。您可能还想设置 -e 选项(又名 --environments-override),并且您的环境变量将覆盖 makefile 中的分配(除非这些分配本身使用 override 指令。但是,不建议这样做,而且更好灵活使用 ?= 赋值(条件变量赋值运算符,仅在变量尚未定义时才有效):FOO?=default_value_if_not_set_in_environment 注意某些变量不是从环境继承的:MAKE 是从脚本名称获得的 SHELL要么在 makefile 中设置,要么默认为 /bin/sh(基本原理:命令在 makefile 中指定,并且它们是特定于 shell 的)。
MAKE 是从脚本名称中获取的
SHELL 要么在 makefile 中设置,要么默认为 /bin/sh(基本原理:命令在 makefile 中指定,并且它们是特定于 shell 的)。
从命令行 - make 可以将变量赋值作为其命令行的一部分,与目标混合: make target FOO=bar 但是,除非您在赋值中使用覆盖指令,否则 make 文件中对 FOO 变量的所有赋值都将被忽略。 (效果与环境变量的 -e 选项相同)。
从父 Make 导出 - 如果你从 Makefile 调用 Make,你通常不应该像这样显式地写变量赋值: # 不要这样做! target: $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS) 相反,更好的解决方案可能是导出这些变量。导出一个变量会使其进入每个 shell 调用的环境,并且从这些命令中进行调用会按照上面指定的方式选择这些环境变量。 # Do like this CFLAGS=-g export CFLAGS target: $(MAKE) -C target 你也可以使用不带参数的导出来导出所有变量。
最简单的方法是:
make foo=bar target
然后在您的 makefile 中您可以参考 $(foo)
。请注意,这不会自动传播到子制作。
如果您使用的是子制作,请参阅这篇文章:Communicating Variables to a Sub-make
included
?
假设你有一个这样的生成文件:
action:
echo argument is $(argument)
然后您将其称为 make action argument=something
似乎命令 args 覆盖了环境变量。
生成文件:
send:
echo $(MESSAGE1) $(MESSAGE2)
示例运行:
$ MESSAGE1=YES MESSAGE2=NG make send MESSAGE2=OK
echo YES OK
YES OK
从 manual:
make 中的变量可以来自 make 运行的环境。 make 在启动时看到的每个环境变量都会转换为具有相同名称和值的 make 变量。但是,makefile 中的显式分配或使用命令参数会覆盖环境。
所以你可以做(来自bash):
FOOBAR=1 make
在您的 Makefile 中产生一个变量 FOOBAR
。
这里没有引用另一个选项,它包含在 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.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
有了这个,你会:
使用 make -r class02 构建并运行文件;
用 make 或 make all 建造所有东西;
使用 make -r 构建并运行所有内容(假设它们都包含某种断言内容,而您只想测试它们)
如果您创建一个名为 Makefile 的文件并添加一个类似 $(unittest) 的变量,那么即使使用通配符,您也可以在 Makefile 中使用此变量
例子 :
make unittest=*
我使用 BOOST_TEST 并通过为参数提供通配符 --run_test=$(unittest) 然后我将能够使用正则表达式过滤掉我希望我的 Makefile 运行的测试
export ROOT_DIR=<path/value>
然后使用 Makefile 中的变量 $(ROOT_DIR)
。
make A='"as df"'
export PROJECT_MAKE_ARGS = CC=$(CC) CFLAGS=$(CFLAGS)
并将其作为make -C folder $(PROJECT_MAKE_FLAGS)
传递。如果有办法告诉库的 makefile 忽略环境,那将是理想的(与 -e 相反)。make target FOO=bar
make FOO=bar target
?