CFLAGS、CCFLAGS、CXXFLAGS - 这些变量到底控制什么?

发布于 2024-10-30 06:44:19 字数 1189 浏览 2 评论 0原文

我正在使用 GNU make 来编译我的 C++ 代码,我想了解如何使我的编译可定制。

我在不同的地方读到 CFLAGSCCFLAGSCXXFLAGS 用于此目的。那么我应该如何使用它们呢?如果我有额外的编译器命令行参数,我应该将它们附加到 CFLAGS 还是放在前面?有通用的做法吗?

为什么是三个不同的变量?我认为 C 编译器应该获取 CFLAGSCCFLAGS,而 C++ 编译器应该获取 CFLAGSCXXFLAGS — 确实如此我理解对了吗?

人类用户应该设置这些变量吗?是否有任何自动工具(automakeautoconf 等)设置它们?我应该使用的 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 技术交流群。

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

发布评论

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

评论(4

眼前雾蒙蒙 2024-11-06 06:44:19

正如您所注意到的,这些是 Makefile {宏或变量},而不是编译器选项。他们实施一套约定。 (宏是它们的旧名称,仍然被一些人使用。GNU make doc 称它们为变量。)

名称重要的唯一原因是默认的 make 规则,可以通过 make -p 看到,它使用其中一些。

如果您编写自己的所有规则,则可以选择所有自己的宏名称。

在普通的 gnu make 中,没有 CCFLAGS 这样的东西。有 CFLAGSCPPFLAGSCXXFLAGSCFLAGS 用于 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, and CXXFLAGS. CFLAGS for the C compiler, CXXFLAGS for C++, and CPPFLAGS 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.

○闲身 2024-11-06 06:44:19

根据GNU make手册:

CFLAGS:提供给 C 编译器的额外标志。
CXXFLAGS:提供给 C++ 编译器的额外标志。
CPPFLAGS:提供给 C 预处理器和使用它的程序(C 和 Fortran 编译器)的额外标志。

src: https://www.gnu.org/software/make /manual/make.html#index-CFLAGS
注意:PP代表PreProcessor(而不是Plus Plus),即

CPP:运行C预处理器的程序,并将结果输出到标准输出;默认'$(CC) -E'。

这些变量由 make 的隐式规则使用

编译C程序
no 是由 nc 自动制作的,配方如下
'$(CC) $(CPPFLAGS) $(CFLAGS) -c'。

编译C++程序
no 是从 n.cc、n.cpp 或 nC 自动生成的,配方格式为
'$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c'。
我们鼓励您对 C++ 源文件使用后缀“.cc”,而不是“.C”。

src: https://www.gnu.org/software /make/manual/make.html#规则目录

According to the GNU make manual:

CFLAGS: Extra flags to give to the C compiler.
CXXFLAGS: Extra flags to give to the C++ compiler.
CPPFLAGS: Extra flags to give to the C preprocessor and programs that use it (the C and Fortran compilers).

src: https://www.gnu.org/software/make/manual/make.html#index-CFLAGS
note: PP stands for PreProcessor (and not Plus Plus), i.e.

CPP: Program for running the C preprocessor, with results to standard output; default ‘$(CC) -E’.

These variables are used by the implicit rules of make

Compiling C programs
n.o is made automatically from n.c with a recipe of the form
‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.

Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form
‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’.
We encourage you to use the suffix ‘.cc’ for C++ source files instead of ‘.C’.

src: https://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules

赢得她心 2024-11-06 06:44:19

最小示例

只是将Mizux所说的作为一个最小示例:

main_c.c

#include <stdio.h>

int main(void) {
    puts("hello");
}

main_cpp。然后

#include <iostream>

int main(void) {
    std::cout << "hello" << std::endl;
}

,在没有任何 Makefile 的情况下:

make CFLAGS='-g -O3' \
     CXXFLAGS='-ggdb3 -O0' \
     CPPFLAGS='-DX=1 -DY=2' \
     CCFLAGS='--asdf' \
     main_c \
     main_cpp

运行:

cc -g -O3 -DX=1 -DY=2   main_c.c   -o main_c
g++ -ggdb3 -O0 -DX=1 -DY=2   main_cpp.cpp   -o main_cpp

所以我们明白:

  • make 有隐式规则来生成 main_cmain_cpp 来自 main_c.cmain_cpp.cpp

  • CFLAGS 和 CPPFLAGS 被用作 .c 编译隐式规则的一部分

  • CXXFLAGS 和 CPPFLAGS 用作 .cpp 编译的隐式规则的一部分

  • 不使用 CCFLAGS。

    顺便说一句,SCons 构建系统 例如 对 C 和 C++ 通用的标志使用 CCFLAGS,这是我有时遵循的约定定制规则。

这些变量仅自动在 make 的隐式规则中使用:如果编译使用了我们自己的显式规则,那么我们必须显式地使用这些变量,如下所示:

main_c: main_c.c
    $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ 
lt;

main_cpp: main_c.c
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ 
lt;

以实现与隐式规则类似的效果。

我们也可以按照我们想要的方式命名这些变量:但是由于 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

#include <stdio.h>

int main(void) {
    puts("hello");
}

main_cpp.cpp

#include <iostream>

int main(void) {
    std::cout << "hello" << std::endl;
}

Then, without any Makefile:

make CFLAGS='-g -O3' \
     CXXFLAGS='-ggdb3 -O0' \
     CPPFLAGS='-DX=1 -DY=2' \
     CCFLAGS='--asdf' \
     main_c \
     main_cpp

runs:

cc -g -O3 -DX=1 -DY=2   main_c.c   -o main_c
g++ -ggdb3 -O0 -DX=1 -DY=2   main_cpp.cpp   -o main_cpp

So we understand that:

  • make had implicit rules to make main_c and main_cpp from main_c.c and main_cpp.cpp

  • CFLAGS and CPPFLAGS were used as part of the implicit rule for .c compilation

  • CXXFLAGS and CPPFLAGS were used as part of the implicit rule for .cpp compilation

  • CCFLAGS 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:

main_c: main_c.c
    $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ 
lt;

main_cpp: main_c.c
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ 
lt;

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

禾厶谷欠 2024-11-06 06:44:19

这是对所有现有答案的补充,这些答案主要描述了这些 make 变量如何影响编译过程。在这个答案中,我描述了使用这些变量的建议方法以及任何周围的注意事项。它的部分灵感来自类似问题的答案

我应该如何使用它们?我应该追加还是前置?

编译标志有两种类型:

  1. 编译工作所需的标志(例如:-I,它告诉编译器在哪里可以找到 h 文件)。
  2. 那些自定义编译的(例如:-O,优化级别)。

只有类型 2(自定义)应该进入 CCFLAGS,如果用户指定它们,它们应该覆盖 Makefile 中定义的任何内容。在 Makefile 中使用 ?= 语法:

CCFLAGS ?= -O3

类型 1 设置应该进入一个新的虚构变量,该变量应该将它们全部聚合起来,并且还包括标准变量,就像CCFLAGS

INC_FLAGS := -Istuff -Imore_stuff -Ietc

CCFLAGS_INTERNAL := $(INC_FLAGS) $(CCFLAGS)

有常见的做法吗?

不,似乎并非如此。我上面描述的东西是一种选择,看起来不错,但它不是标准的。

人类用户应该设置这些变量吗?我使用的 Linux 系统没有定义任何这些变量 - 这是典型的吗?

是的,这些用于使用命令行指定选项。环境变量通常不存在。

有什么违背惯例的事情吗? (就像CCFLAGSINT - 我应该覆盖CCFLAGS吗?或者CXXFLAGS?FUD!)

不,这个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.

How should I use them? Should I append or prepend?

Compilation flags are of two types:

  1. Those which are required to make the compilation work (example: -I, which tells the compiler where to find h-files).
  2. Those which customize the compilation (example: -O, optimization level).

Only type 2 (customization) should go into CCFLAGS, and if the user specifies them, they should override whatever is defined in the Makefile. Use ?= syntax for that in your Makefile:

CCFLAGS ?= -O3

Type 1 settings should go into a new made-up variable, which should aggregate them all, and also include the standard variables, like CCFLAGS:

INC_FLAGS := -Istuff -Imore_stuff -Ietc

CCFLAGS_INTERNAL := $(INC_FLAGS) $(CCFLAGS)

Is there a common practice?

No, it doesn't seem so. Stuff I described above is one option, which looks good, but it's not standard.

Is the human user supposed to set these variables at all? The linux system that I use doesn't define any of these variables - is this typical?

Yes, these are for specifying options using the command line. The environment variables usually don't exist.

Is there anything that goes against conventions? (like CCFLAGSINT - should I just overwrite CCFLAGS instead? Or CXXFLAGS? FUD!)

No, the idea of this Makefile is correct: append CCFLAGS and other flags to the compiler's command-line; don't update CCFLAGS.

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