我可以将变量作为命令行参数传递给GNU Makefile吗?换句话说,我想传递一些参数,最终这些参数将成为Makefile中的变量。
我可以将变量作为命令行参数传递给GNU Makefile吗?换句话说,我想传递一些参数,最终这些参数将成为Makefile中的变量。
您有几种选项可以从外部设置变量到您的makefile中:
From environment - each environment variable is transformed into a makefile variable with the same name and value.
You may also want to set -e
option (aka --environments-override
) on, and your environment variables will override assignments made into makefile (unless these assignments themselves use the override
directive . However, it's not recommended, and it's much better and flexible to use ?=
assignment (the conditional variable assignment operator, it only has an effect if the variable is not yet defined):
FOO?=default_value_if_not_set_in_environment
Note that certain variables are not inherited from environment:
MAKE
is gotten from name of the scriptSHELL
is either set within a makefile, or defaults to /bin/sh
(rationale: commands are specified within the makefile, and they're shell-specific).From command line - make
can take variable assignments as part of his command line, mingled with targets:
make target FOO=bar
But then all assignments to FOO
variable within the makefile will be ignored unless you use the override
directive in assignment. (The effect is the same as with -e
option for environment variables).
Exporting from the parent Make - if you call Make from a Makefile, you usually shouldn't explicitly write variable assignments like this:
# Don't do this!
target:
$(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
Instead, better solution might be to export these variables. Exporting a variable makes it into the environment of every shell invocation, and Make calls from these commands pick these environment variable as specified above.
# Do like this
CFLAGS=-g
export CFLAGS
target:
$(MAKE) -C target
You can also export all variables by using export
without arguments.
最简单的方法是:
make foo=bar target
在你的makefile中,你可以引用$(foo)
。请注意,这不会自动传播到子make。
如果你正在使用子make,请参阅本文:将变量传递给子make
包含(included)
的makefile吗? - Pablo假设你有一个像这样的makefile:
action:
echo argument is $(argument)
然后你会调用它:make action argument=something
看起来命令参数会覆盖环境变量。
Makefile:
send:
echo $(MESSAGE1) $(MESSAGE2)
示例运行:
$ MESSAGE1=YES MESSAGE2=NG make send MESSAGE2=OK
echo YES OK
YES OK
根据手册的说明:
在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
来构建并运行所有内容(假设它们都包含某种特定类型的断言内容,你只想测试它们)。make unittest=*
我使用BOOST_TEST,通过给参数--run_test=$(unittest)赋予通配符, 从而可以使用正则表达式来过滤出我想要Makefile运行的测试。
export ROOT_DIR=<path/value>
然后在Makefile中使用变量$(ROOT_DIR)
。
make A='"as df"'
。注意保留原指令意思且不添加解释。 - Ciro Santilli OurBigBook.comexport PROJECT_MAKE_ARGS = CC=$(CC) CFLAGS=$(CFLAGS)
并将其作为make -C folder $(PROJECT_MAKE_FLAGS)
传递。如果有一种方法可以告诉库的Makefile忽略环境变量,那就太理想了(与-e相反)。 - R.D.