CFLAGS、CCFLAGS、CXXFLAGS - 这些变量到底控制什么?
我正在使用 GNU make 来编译我的 C++ 代码,我想了解如何使我的编译可定制。
我在不同的地方读到 CFLAGS
、CCFLAGS
和 CXXFLAGS
用于此目的。那么我应该如何使用它们呢?如果我有额外的编译器命令行参数,我应该将它们附加到 CFLAGS 还是放在前面?有通用的做法吗?
为什么是三个不同的变量?我认为 C 编译器应该获取 CFLAGS
和 CCFLAGS
,而 C++ 编译器应该获取 CFLAGS
和 CXXFLAGS
— 确实如此我理解对了吗?
人类用户应该设置这些变量吗?是否有任何自动工具(automake
、autoconf
等)设置它们?我应该使用的 Linux 系统没有定义任何这些变量——这是典型的吗?
目前我的 Makefile 看起来像这样,我觉得它有点脏:
ifdef code_coverage
GCOV_FLAG := -fprofile-arcs -ftest-coverage
else
GCOV_FLAG :=
endif
WFLAGS := -Wall
INC_FLAGS := -Istuff -Imore_stuff -Ietc
CCFLAGSINT := -O3 $(WFLAGS) $(INC_FLAGS) $(CCFLAGS)
... (somewhere in the makefile, the command-line for compilation looks like this)
$(CC) $(CCFLAGSINT) -c $< -o $@
... (somewhere in the makefile, the command-line for linking looks like this)
$(CC) $(GCOV_FLAG) $(CCFLAGSINT) $(OBJLIST) $(LDFLAGS) -o $@
我很确定这里没有错误; Makefile 工作得很好。但是是否有任何违反约定的内容(例如 CCFLAGSINT
- 我应该覆盖 CCFLAGS
吗?或者 CXXFLAGS
?FUD!)
抱歉了这么多问题;显然你不会全部回答,但我希望答案能帮助我理解这些设置背后的总体思路。
I am using GNU make to compile my C++ code, and I would like to understand how to make my compilations customizable.
I read in different places that CFLAGS
, CCFLAGS
and CXXFLAGS
are used for this purpose. So how should i use them? If I have additional command-line arguments to the compiler, should I append them to CFLAGS
or prepend them? Is there a common practice?
Why the three different variables? I suppose the C compiler should get CFLAGS
and CCFLAGS
, while the C++ compiler should get CFLAGS
and CXXFLAGS
—did I get it right?
Is the human user supposed to set these variables at all? Do any automatic tools (automake
, autoconf
, etc) set them? The Linux system that I am supposed to use doesn't define any of these variables—is this typical?
Currently my Makefile looks like this, and I feel it's a bit dirty:
ifdef code_coverage
GCOV_FLAG := -fprofile-arcs -ftest-coverage
else
GCOV_FLAG :=
endif
WFLAGS := -Wall
INC_FLAGS := -Istuff -Imore_stuff -Ietc
CCFLAGSINT := -O3 $(WFLAGS) $(INC_FLAGS) $(CCFLAGS)
... (somewhere in the makefile, the command-line for compilation looks like this)
$(CC) $(CCFLAGSINT) -c lt; -o $@
... (somewhere in the makefile, the command-line for linking looks like this)
$(CC) $(GCOV_FLAG) $(CCFLAGSINT) $(OBJLIST) $(LDFLAGS) -o $@
I am pretty sure there are no bugs here; the Makefile works very well. But is there anything that goes against conventions (like CCFLAGSINT
—should I just overwrite CCFLAGS
instead? Or CXXFLAGS
? FUD!)
Sorry for so many questions; you will obviously not answer them all, but I hope the answers will help me understand the general idea behind these settings.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
正如您所注意到的,这些是 Makefile {宏或变量},而不是编译器选项。他们实施一套约定。 (宏是它们的旧名称,仍然被一些人使用。GNU make doc 称它们为变量。)
名称重要的唯一原因是默认的 make 规则,可以通过
make -p
看到,它使用其中一些。如果您编写自己的所有规则,则可以选择所有自己的宏名称。
在普通的 gnu make 中,没有 CCFLAGS 这样的东西。有
CFLAGS
、CPPFLAGS
和CXXFLAGS
。CFLAGS
用于 C 编译器,CXXFLAGS
用于 C++,CPPFLAGS
用于两者。为什么两者中都有
CPPFLAGS
?按照惯例,它是预处理器标志(-D
、-U
)的所在地,c 和 c++ 都使用它们。现在,每个人都想要相同的 c 和 c++ 定义环境的假设可能是有问题的,但却是传统的。PS 正如 James Moore 所指出的,某些项目使用 CPPFLAGS 作为 C++ 编译器的标志,而不是 C 预处理器的标志。 Android NDK 就是一个巨大的例子。
As you noticed, these are Makefile {macros or variables}, not compiler options. They implement a set of conventions. (Macros is an old name for them, still used by some. GNU make doc calls them variables.)
The only reason that the names matter is the default make rules, visible via
make -p
, which use some of them.If you write all your own rules, you get to pick all your own macro names.
In a vanilla gnu make, there's no such thing as CCFLAGS. There are
CFLAGS
,CPPFLAGS
, andCXXFLAGS
.CFLAGS
for the C compiler,CXXFLAGS
for C++, andCPPFLAGS
for both.Why is
CPPFLAGS
in both? Conventionally, it's the home of preprocessor flags (-D
,-U
) and both c and c++ use them. Now, the assumption that everyone wants the same define environment for c and c++ is perhaps questionable, but traditional.P.S. As noted by James Moore, some projects use CPPFLAGS for flags to the C++ compiler, not flags to the C preprocessor. The Android NDK, for one huge example.
根据
GNU make
手册:src: https://www.gnu.org/software/make /manual/make.html#index-CFLAGS
注意:PP代表PreProcessor(而不是Plus Plus),即
这些变量由
make
的隐式规则使用src: https://www.gnu.org/software /make/manual/make.html#规则目录
According to the
GNU make
manual:src: https://www.gnu.org/software/make/manual/make.html#index-CFLAGS
note: PP stands for PreProcessor (and not Plus Plus), i.e.
These variables are used by the implicit rules of
make
src: https://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
最小示例
只是将Mizux所说的作为一个最小示例:
main_c.c
main_cpp。然后
,在没有任何
Makefile
的情况下:运行:
所以我们明白:
make
有隐式规则来生成main_c
和main_cpp
来自main_c.c
和main_cpp.cpp
CFLAGS 和 CPPFLAGS 被用作
.c
编译隐式规则的一部分CXXFLAGS 和 CPPFLAGS 用作
.cpp
编译的隐式规则的一部分不使用 CCFLAGS。
顺便说一句,SCons 构建系统 例如 对 C 和 C++ 通用的标志使用 CCFLAGS,这是我有时遵循的约定定制规则。
这些变量仅自动在 make 的隐式规则中使用:如果编译使用了我们自己的显式规则,那么我们必须显式地使用这些变量,如下所示:
以实现与隐式规则类似的效果。
我们也可以按照我们想要的方式命名这些变量:但是由于 Make 已经在隐式规则中神奇地对待它们,因此它们是很好的名称选择。
在 Ubuntu 16.04、GNU Make 4.1 中测试。
相关:CFLAGS 与 CPPFLAGS
Minimal example
And just to make what Mizux said as a minimal example:
main_c.c
main_cpp.cpp
Then, without any
Makefile
:runs:
So we understand that:
make
had implicit rules to makemain_c
andmain_cpp
frommain_c.c
andmain_cpp.cpp
CFLAGS and CPPFLAGS were used as part of the implicit rule for
.c
compilationCXXFLAGS and CPPFLAGS were used as part of the implicit rule for
.cpp
compilationCCFLAGS is not used.
BTW, the SCons build system for example uses CCFLAGS for flags that are common to C and C++, which is a convention I sometimes follow on my custom make rules.
Those variables are only used in make's implicit rules automatically: if compilation had used our own explicit rules, then we would have to explicitly use those variables as in:
to achieve a similar affect to the implicit rules.
We could also name those variables however we want: but since Make already treats them magically in the implicit rules, those make good name choices.
Tested in Ubuntu 16.04, GNU Make 4.1.
Related: CFLAGS vs CPPFLAGS
这是对所有现有答案的补充,这些答案主要描述了这些
make
变量如何影响编译过程。在这个答案中,我描述了使用这些变量的建议方法以及任何周围的注意事项。它的部分灵感来自类似问题的答案。编译标志有两种类型:
-I
,它告诉编译器在哪里可以找到 h 文件)。-O
,优化级别)。只有类型 2(自定义)应该进入 CCFLAGS,如果用户指定它们,它们应该覆盖
Makefile
中定义的任何内容。在Makefile
中使用?=
语法:类型 1 设置应该进入一个新的虚构变量,该变量应该将它们全部聚合起来,并且还包括标准变量,就像
CCFLAGS
:不,似乎并非如此。我上面描述的东西是一种选择,看起来不错,但它不是标准的。
是的,这些用于使用命令行指定选项。环境变量通常不存在。
不,这个
Makefile
的想法是正确的:将CCFLAGS
和其他标志附加到编译器的命令中-线;不要更新CCFLAGS
。This is an addition to all the existing answers, which mostly describe how these
make
variables affect the compilation process. In this answer, I describe a suggested way to use these variables, and any surrounding considerations. It is partly inspired by an answer to a similar question.Compilation flags are of two types:
-I
, which tells the compiler where to find h-files).-O
, optimization level).Only type 2 (customization) should go into
CCFLAGS
, and if the user specifies them, they should override whatever is defined in theMakefile
. Use?=
syntax for that in yourMakefile
:Type 1 settings should go into a new made-up variable, which should aggregate them all, and also include the standard variables, like
CCFLAGS
:No, it doesn't seem so. Stuff I described above is one option, which looks good, but it's not standard.
Yes, these are for specifying options using the command line. The environment variables usually don't exist.
No, the idea of this
Makefile
is correct: appendCCFLAGS
and other flags to the compiler's command-line; don't updateCCFLAGS
.