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

时间:2018-07-31 06:23:52

标签: makefile build gnu-make

典型的makefile经常使用内置变量CFLAGSCXXFLAGSCPPFLAGS 1 来设置传递给C,C ++的标志或其他编译器/工具。原则上,由于各种内置规则都使用这些标志,因此有时甚至可以避免完全编写编译配方。

通常,makefile可能会将东西添加到需要编译的代码的FLAGS变量中,例如include目录,指示使用哪种语言标准的参数等。 。这些变量还可能包含“可选”或“默认”参数,例如优化级别,警告级别和可能有效更改或删除的其他设置。

由于CFLAGS和字段是“众所周知的”变量,因此它们显然也是最终用户的配置点。例如,如果默认情况下一个项目在编译时没有调试信息,则期望CFLAGS=-g命令行上的make导致-g被添加到$(CC)编译器命令行中,并且因此导致产生调试信息。同样,对于最终用户可能希望控制的其他选项,例如优化级别,gcc上的-march设置,等等。

但是,这两种用法似乎与我不兼容。如果用户覆盖$(CFLAGS),则他们将删除如上所述的所有内部“必需”标志,并且该项目可能无法编译或编译不正确。

是否有处理此问题的最佳实践?对于像$(CC)这样的“单值”变量,实际上不会出现相同的问题,因为它们通常只有一个值:在本示例中,使用的是C编译器。如果用户覆盖它,则使用其值。诸如$(CFLAGS)之类的东西原则上是一个值列表,其中一些值是内部值,不应覆盖,而其他值则用户可能希望覆盖。

从直觉上讲,一种解决方案似乎是将$(CFLAGS)和朋友保留为空且未在您的Makefile中使用它们,而更喜欢说CFLAGS_INTERNAL作为Makefile中的参数,然后将两者都放在命令行中。但是,我很好奇,是否有最佳实践,或者是否缺少明显的东西。


1 对于此问题的其余部分,我通常会简单地参考$(CFLAGS),前提是这只是整个编译器标记变量家族的方便代表,例如$(CPPFLAGS)$(CXXFLAGS)等。

4 个答案:

答案 0 :(得分:1)

我面临着同样的问题。目前,我的解决方案是提供“ {@ 1}},OPTIMSWARNINGS之类的“非标准”标志,这些标志将在内部附加到“标准” MODENV上。

如果用户在命令行中定义CXXFLAGS,则假定他要覆盖它,如果这就是他想要的,那他应该得到:覆盖。具有讽刺意味的是,这意味着我在Makefile中使用CXXFLAGS

我不希望高级用户放弃他们的头发,因为我坚持将自己的东西添加/添加到他们的标志上,所以我认为最终的情况是这样的:

  • GOOD::要求高级用户传递复杂的自定义标志
  • 不良::要求高级用户修补Makefile

答案 1 :(得分: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.

请注意,您也可以使用:

$ make CFLAGS+=-g

在命令行上,但其行为类似于:

$ make CFLAGS=-g

答案 2 :(得分:0)

我更喜欢的方法是为这些公共变量提供合理的默认值,但让用户提供自己的值-覆盖默认值。

include $(wildcard makefile.in Makefile.in)

BUILD ?= build
CFLAGS ?= -O2 -fPIC -pedantic -Wall -Wextra -Wconversion

这可以通过环境变量,命令行参数(例如make CFLAGS=-g或永久存在于makefile.in中)完成。

我知道这并不能完全解决您在问题中描述的问题,但是我发现用例中用户希望使用非默认标志编译项目应该可以

  1. 根据需要定义这些变量
  2. 检查默认设置,最好在makefile的顶部
  3. 也许可以根据默认设置调整定义

如果某人想要使用一些特殊标志进行构建并且无法执行这些步骤,那么无论如何都会有一些更严重的问题。

当构建变得更加复杂并且默认值在较大的Makefile中设置并取决于其他条件时,这种方法将无法很好地扩展。

答案 3 :(得分:0)

在使用debuginfo软件包构建RPM时,偶然发现了相同的问题。

生成debuginfo的要求是在-g中传递CFLAGS,同时保留软件CFLAGS中包含的Makefile

因此,如果您想向CFLAGS添加一些额外的位,而又不覆盖Makefile中存在的位,则可以简单地将CFLAGS用作环境变量。但是只要有问题的Makefile使用CFLAGS += ...表示法即可。

例如,假设您拥有Makefile拥有以下软件:

CFLAGS += $(ARCH) -O3 -std=gnu11 -Wall ...

要使用所有这些标志 -g构建它,您将执行以下操作:

CFLAGS='-g' make 

请注意,将其作为make的参数传递是无效的,例如:make CFLAGS='-g'是错误的,因为它将覆盖内部CFLAGS

有关pass -g for building debuginfo packages properly

解决方案的更多信息

这里是make: appending to variables上的参考。