从命令行传递附加变量到 make

发布于 2024-09-01 06:11:37 字数 77 浏览 7 评论 0 原文

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

Can I pass variables to a GNU Makefile as command line arguments? In other words, I want to pass some arguments which will eventually become variables in the Makefile.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

太阳哥哥 2024-09-08 06:11:37

您可以通过多种方式从 makefile 外部设置变量:

  • 从环境 - 每个环境变量都会转换为具有相同名称和值的 makefile 变量。

    您可能还想设置 -e 选项(又名 --environments-override),并且您的环境变量将覆盖 makefile 中的分配(除非这些分配他们自己使用 override 指令 但是,不建议这样做,使用 ?= 赋值(条件变量赋值运算符,只有在变量尚未定义时才有效)要好得多、更灵活:

    FOO?=default_value_if_not_set_in_environment
    

    请注意,某些变量不是从环境继承的:

    • MAKE 从脚本名称中获取
    • SHELL 要么在 makefile 中设置,要么默认为 /bin/sh (基本原理:命令在 makefile 中指定,并且它们是特定于 shell 的) .
  • 从命令行 - make 可以将变量赋值作为命令行的一部分,与目标混合:

    使目标 FOO=bar
    

    但是makefile中对FOO变量的所有赋值都将被忽略,除非您使用override 指令 赋值。 (效果与环境变量的 -e 选项相同)。

  • 从父 Make 导出 - 如果从 Makefile 调用 Make,通常不应显式编写如下变量赋值:

    # 不要这样做!
    目标:
            $(MAKE) -C 目标 CC=$(CC) CFLAGS=$(CFLAGS)
    

    相反,更好的解决方案可能是导出这些变量。导出变量会使其进入每个 shell 调用的环境中,并且从这些命令中进行调用会选择上面指定的这些环境变量。

    # 这样做
    CFLAGS=-g
    导出CFLAGS
    目标:
            $(MAKE) -C 目标
    

    您还可以使用不带参数的 export 导出所有变量。

You have several options to set up variables from outside your 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 script
    • SHELL 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.

書生途 2024-09-08 06:11:37

最简单的方法是:

make foo=bar target

然后在你的makefile中你可以引用$(foo)。请注意,这不会自动传播到子品牌。

如果您使用子品牌,请参阅本文:将变量传递给子品牌-制作

The simplest way is:

make foo=bar target

Then in your makefile you can refer to $(foo). Note that this won't propagate to sub-makes automatically.

If you are using sub-makes, see this article: Communicating Variables to a Sub-make

枉心 2024-09-08 06:11:37

假设您有一个如下所示的 makefile:

action:
    echo argument is $(argument)

然后您可以将其命名为 make action argument=something

Say you have a makefile like this:

action:
    echo argument is $(argument)

You would then call it make action argument=something

那支青花 2024-09-08 06:11:37

看来命令参数覆盖了环境变量。

Makefile:

send:
    echo $(MESSAGE1) $(MESSAGE2)

示例运行:

$ MESSAGE1=YES MESSAGE2=NG  make send MESSAGE2=OK
echo YES OK
YES OK

It seems command args overwrite environment variable.

Makefile:

send:
    echo $(MESSAGE1) $(MESSAGE2)

Example run:

$ MESSAGE1=YES MESSAGE2=NG  make send MESSAGE2=OK
echo YES OK
YES OK
心在旅行 2024-09-08 06:11:37

来自手册

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

所以你可以(从bash):

FOOBAR=1 make

在你的Makefile中产生一个变量FOOBAR

From the manual:

Variables in make can come from the environment in which make is run. Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value. However, an explicit assignment in the makefile, or with a command argument, overrides the environment.

So you can do (from bash):

FOOBAR=1 make

resulting in a variable FOOBAR in your Makefile.

风为裳 2024-09-08 06:11:37

这里没有引用另一个选项,它包含在 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 [email protected] $^ $(LDLIBS)
ifneq (,$(findstring r,  $(MAKEFLAGS)))
    ./[email protected]
endif

all: $(SOURCES)

.PHONY: clean

clean:
    find . -name "*.out" -delete

有了它,您就可以: 使用

  • make -r class02 构建并运行一个文件;
  • 使用 makemake all 构建所有内容;
  • 使用 make -r 构建并运行所有内容(假设它们都包含某种特定类型的断言内容,并且您只想测试它们)

There's another option not cited here which is included in the GNU Make book by Stallman and McGrath (see http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_7.html). It provides the example:

archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
        +touch archive.a
        +ranlib -t archive.a
else
        ranlib archive.a
endif

It involves verifying if a given parameter appears in MAKEFLAGS. For example .. suppose that you're studying about threads in c++11 and you've divided your study across multiple files (class01, ... , classNM) and you want to: compile then all and run individually or compile one at a time and run it if a flag is specified (-r, for instance). So, you could come up with the following Makefile:

CXX=clang++-3.5
CXXFLAGS = -Wall -Werror -std=c++11
LDLIBS = -lpthread

SOURCES = class01 class02 class03

%: %.cxx
    $(CXX) $(CXXFLAGS) -o [email protected] $^ $(LDLIBS)
ifneq (,$(findstring r,  $(MAKEFLAGS)))
    ./[email protected]
endif

all: $(SOURCES)

.PHONY: clean

clean:
    find . -name "*.out" -delete

Having that, you'd:

  • build and run a file w/ make -r class02;
  • build all w/ make or make all;
  • build and run all w/ make -r (suppose that all of them contain some certain kind of assert stuff and you just want to test them all)
最终幸福 2024-09-08 06:11:37

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

示例:

make unittest=*

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

If you make a file called Makefile and add a variable like this $(unittest)
then you will be able to use this variable inside the Makefile even with wildcards

example :

make unittest=*

I use BOOST_TEST and by giving a wildcard to parameter --run_test=$(unittest)
then I will be able to use regular expression to filter out the test I want my Makefile
to run

哀由 2024-09-08 06:11:37
export ROOT_DIR=<path/value>

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

export ROOT_DIR=<path/value>

Then use the variable, $(ROOT_DIR) in the Makefile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文