允许用户覆盖 CFLAGS、CXXFLAGS 和朋友

Bee*_*ope 5 makefile build gnu-make

典型的 makefile 通常使用内置变量CFLAGS、等CXXFLAGS1来设置传递给 C、C++ 或其他编译器/工具的标志原则上,有时这甚至可以让您完全避免编写编译配方,因为各种内置规则使用这些标志。CPPFLAGS

一般来说,makefile 可能会向所需的FLAGS变量中添加内容添加内容,例如包含目录、指示要使用哪种语言标准的参数等。这些变量还可能包括“可选”或“默认”参数,例如优化级别、警告级别和其他可以有效更改或删除的设置。

由于CFLAGS和 字段是“众所周知的”变量,因此它们显然也是最终用户的配置点。例如,如果默认情况下项目在没有调试信息的情况下进行编译,则预期CFLAGS=-gmake命令行上会导致-g添加到 $(CC) 编译器命令行,从而导致生成调试信息。同样,对于最终用户可能想要控制的其他选项,例如优化级别、-marchgcc 的设置等。

然而,这两种用途对我来说似乎不兼容。如果用户覆盖,$(CFLAGS)他们将删除如上所述的任何内部“必需”标志,并且项目可能无法编译或可能编译不正确。

有处理这个问题的最佳实践吗?对于“单值”变量来说,实际上不会出现同样的问题,$(CC)因为它们通常只有一个值:在本例中,是要使用的 C 编译器。如果用户覆盖它,您就使用它们的值。原则上,诸如此类$(CFLAGS)的内容是一个值列表,其中一些是内部的,不应被覆盖,而另一些则是用户可能想要覆盖的。

直观上,解决方案似乎是$(CFLAGS)在 makefile 中将 and Friends 保留为空且未使用,更喜欢CFLAGS_INTERNAL在 makefile 中指定参数,然后将两者都放在命令行上。然而,我很好奇是否有最佳实践,或者我是否遗漏了一些明显的东西。


1对于这个问题的其余部分,我通常会简单地引用它,$(CFLAGS)并理解这只是整个众所周知的编译器标志变量系列的方便代表,例如$(CPPFLAGS)$(CXXFLAGS)等等。

Ren*_*let 0

override指令可能就是您正在寻找的:

$ cat Makefile
override CFLAGS += -foobar

all:
    $(info CFLAGS = $(CFLAGS))

$ make
CFLAGS = -foobar
make: 'all' is up to date.

$ make CFLAGS=-g
CFLAGS = -g -foobar
make: 'all' is up to date.
Run Code Online (Sandbox Code Playgroud)

请注意,您还可以使用:

$ make CFLAGS+=-g
Run Code Online (Sandbox Code Playgroud)

在命令行上,但它的行为就像:

$ make CFLAGS=-g
Run Code Online (Sandbox Code Playgroud)