【发布时间】:2011-02-19 00:59:16
【问题描述】:
我可以将变量作为命令行参数传递给 GNU Makefile 吗?换句话说,我想传递一些最终将成为 Makefile 中的变量的参数。
【问题讨论】:
标签: makefile gnu command-line-arguments
我可以将变量作为命令行参数传递给 GNU Makefile 吗?换句话说,我想传递一些最终将成为 Makefile 中的变量的参数。
【问题讨论】:
标签: makefile gnu command-line-arguments
您有几个选项可以从您的 makefile 外部设置变量:
来自环境 - 每个环境变量都转换为具有相同名称和值的 makefile 变量。
您可能还想设置-e 选项(又名--environments-override),并且您的环境变量将覆盖makefile 中的分配(除非这些分配本身使用override directive。但是,不建议这样做,它是使用?=赋值更好更灵活(条件变量赋值运算符,仅在变量尚未定义时才有效):
FOO?=default_value_if_not_set_in_environment
请注意,某些变量不是从环境继承的:
MAKE 来自脚本名称SHELL 要么在 makefile 中设置,要么默认为 /bin/sh(理由:命令在 makefile 中指定,它们是特定于 shell 的)。从命令行 - make 可以将变量赋值作为其命令行的一部分,与目标混合:
make target FOO=bar
但是makefile 中对FOO 变量的所有赋值都将被忽略,除非您在赋值中使用override directive。 (效果与环境变量-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 导出所有变量。
【讨论】:
make A='"as df"'
export PROJECT_MAKE_ARGS = CC=$(CC) CFLAGS=$(CFLAGS) 并将其作为make -C folder $(PROJECT_MAKE_FLAGS) 传递。如果有办法告诉库的 makefile 忽略环境,那将是理想的(与 -e 相反)。
make target FOO=barmake FOO=bar target?
最简单的方法是:
make foo=bar target
然后在你的makefile中你可以参考$(foo)。请注意,这不会自动传播到子品牌。
如果您使用的是子品牌,请参阅这篇文章:Communicating Variables to a Sub-make
【讨论】:
included?
假设你有一个这样的makefile:
action:
echo argument is $(argument)
然后你可以称它为make action argument=something
【讨论】:
来自manual:
make 中的变量可以来自 make 运行的环境。 make 在启动时看到的每个环境变量都会转换为具有相同名称和值的 make 变量。但是,makefile 中的显式赋值或带有命令参数的赋值会覆盖环境。
所以你可以这样做(来自 bash):
FOOBAR=1 make
在您的 Makefile 中产生一个变量 FOOBAR。
【讨论】:
好像
命令 args 覆盖环境变量
生成文件
send:
echo $(MESSAGE1) $(MESSAGE2)
运行示例
$ MESSAGE1=YES MESSAGE2=NG make send MESSAGE2=OK
echo YES OK
YES OK
【讨论】:
这里没有提到另一个选项,它包含在 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)。
【讨论】: