从命令行传递其他变量来制作

时间:2010-05-13 10:31:51

标签: makefile gnu command-line-arguments

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

8 个答案:

答案 0 :(得分:643)

您可以从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
    

    但是除非你在赋值中使用override directive,否则将忽略生成文件中FOO变量的所有赋值。 (效果与环境变量的-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无参数导出所有变量。

答案 1 :(得分:169)

最简单的方法是:

make foo=bar target

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

如果您使用的是子品牌,请参阅此文章:Communicating Variables to a Sub-make

答案 2 :(得分:58)

假设你有一个这样的makefile:

action:
    echo argument is $(argument)

然后您将其称为make action argument=something

答案 3 :(得分:18)

来自manual

  

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

所以你可以(来自bash):

FOOBAR=1 make

在Makefile中生成变量FOOBAR

答案 4 :(得分:4)

此处未引用的另一个选项包含在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的文件;
  • 构建所有w / makemake all;
  • 构建并运行所有w / make -r(假设所有这些都包含某些类型的断言,你只想测试它们)

答案 5 :(得分:3)

如果你创建一个名为Makefile的文件并添加一个像这样的变量$(unittest) 那么即使使用通配符

,你也可以在Makefile中使用这个变量

示例:

make unittest=*

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

答案 6 :(得分:3)

export ROOT_DIR=<path/value>

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

答案 7 :(得分:0)

似乎

命令args覆盖环境变量

Makefile

f

运行示例

send:
    echo $(MESSAGE1) $(MESSAGE2)