Makefile 从命令行传递附加变量以使
我可以将变量作为命令行参数传递给GNU Makefile吗?换句话说,我想传递一些参数,这些参数最终将成为Makefile中的变量。最简单的方法是:Makefile 从命令行传递附加变量以使,makefile,gnu,command-line-arguments,Makefile,Gnu,Command Line Arguments,我可以将变量作为命令行参数传递给GNU Makefile吗?换句话说,我想传递一些参数,这些参数最终将成为Makefile中的变量。最简单的方法是: make foo=bar target 然后在makefile中,您可以参考$(foo)。请注意,这不会自动传播到子品牌 如果您使用的是sub Make,请参阅本文:假设您有这样一个Make文件: action: echo argument is $(argument) # Don't do this! target:
make foo=bar target
然后在makefile中,您可以参考
$(foo)
。请注意,这不会自动传播到子品牌
如果您使用的是sub Make,请参阅本文:假设您有这样一个Make文件:
action:
echo argument is $(argument)
# Don't do this!
target:
$(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
然后,您可以从以下位置将其称为make action argument=something
:
make中的变量可以来自运行make的环境。make启动时看到的每个环境变量都被转换为具有相同名称和值的make变量。但是,makefile中的显式赋值或带有命令参数的显式赋值会覆盖环境
因此,您可以(从bash)执行以下操作:
在您的Makefile中生成一个变量
FOOBAR
。您可以从Makefile外部设置变量:
- 来自环境-每个环境变量都转换为具有相同名称和值的makefile变量
您可能还想将
选项(也称为-e
)设置为on,您的环境变量将覆盖在makefile中的赋值(除非这些赋值本身使用。但是,不建议这样做,并且使用--environments override
赋值更好、更灵活(条件变量赋值运算符,仅在尚未定义变量时有效): 请注意,某些变量不是从环境继承的:?=
来自脚本的名称MAKE
要么在makefile中设置,要么默认为SHELL
(基本原理:命令在makefile中指定,并且它们是特定于SHELL的)/bin/sh
- 从命令行-
可以将变量赋值作为其命令行的一部分,并与目标混合:make
但是,除非使用in赋值,否则makefile中对make target FOO=bar
变量的所有赋值都将被忽略。(效果与环境变量的FOO
选项相同)-e
- 从父Make导出-如果从Makefile调用Make,通常不应该这样显式地编写变量赋值:
action: echo argument is $(argument)
相反,更好的解决方案可能是导出这些变量。导出一个变量会使它进入每个shell调用的环境中,并从这些命令中进行调用,如上文所述选择这些环境变量# Don't do this! target: $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
您还可以使用不带参数的# Do like this CFLAGS=-g export CFLAGS target: $(MAKE) -C target
导出所有变量export
make unittest=*
我使用BOOST_-TEST,并为参数--run_-TEST=$(unittest)提供一个通配符
然后,我将能够使用正则表达式过滤掉我想要的Makefile测试
要运行还有一个选项未在此处引用,它包含在Stallman和McGrath的GNU Make书中(请参阅)。它提供了以下示例:
archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
+touch archive.a
+ranlib -t archive.a
else
ranlib archive.a
endif
它涉及到验证给定参数是否出现在MAKEFLAGS
中。例如..假设您正在学习c++11中的线程,并且您已经将您的学习划分到多个文件(class01
,…,classNM
)您希望:先编译所有文件,然后单独运行,或者一次编译一个文件,如果指定了标志(例如,-r
),则运行它
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
有了这些,你会:
- 构建并运行一个文件w/
make-r class02
- 构建所有w/
或生成
生成所有
- 构建并运行所有的w/
(假设它们都包含某种断言内容,您只想测试它们)make-r
导出根目录=
然后在Makefile中使用变量$(ROOT\u DIR)
。看起来
命令args覆盖环境变量
生成文件
send:
echo $(MESSAGE1) $(MESSAGE2)
运行示例
$ MESSAGE1=YES MESSAGE2=NG make send MESSAGE2=OK
echo YES OK
YES OK
因此,目标和参数可以在位置上互换?@Michael:是的(请参阅Mark Byers的答案),sub使你指的是主makefile中包含的makefiles
吗?@Michael:这意味着从makefile内部再次调用make。我更新了我的答案,因为你似乎对这个细节感兴趣。请注意,这不会自动传播到sub makes。“不真实!”默认情况下,只有来自环境或命令行的变量才会传递给递归调用。您可以使用export指令传递其他变量。“在几乎所有情况下,另一种方法确实更好。为了完整起见,我将把它留在这里。这是唯一一个在同一行上显示make命令之前的变量赋值的答案-值得知道的是,这不是语法错误。要从命令行传递带有空格的somthing domake a='”作为df”“
如果你关心环境变量,你似乎是在自找麻烦。首先,如果它在a位置工作而不是在B位置工作,那就是一场调试噩梦,仅仅因为它们有不同的环境。仅仅根据经验,导出CFLAGS之类的东西对于大型项目来说是一场噩梦。大型项目通常都有第三方仅使用给定标志集编译的参与方库(没有人费心修复)。如果导出CFLAGS,项目的CFLAGS将覆盖第三方库并触发编译错误。另一种方法可能是定义export project\u MAKE\u ARGS=CC=$(CC)CFLAGS=$(CFLAGS)
并将其作为make-C folder$(PROJECT\u make\u FLAGS)
传递
$ MESSAGE1=YES MESSAGE2=NG make send MESSAGE2=OK
echo YES OK
YES OK