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

ana*_*lyg 64 gcc makefile naming-conventions

我正在使用GNU make来编译我的C++代码,我想了解如何使我的编译可以自定义.

我在不同的地方阅读CFLAGS,CCFLAGSCXXFLAGS用于此目的.那我该怎么用呢?如果我有额外的命令行参数编译器,我应该将它们附加CFLAGS或前置它们吗?有共同的做法吗?

为什么三个不同的变量?我想C编译器应该得到CFLAGSCCFLAGS,而C++编译器应该得到CFLAGSCXXFLAGS-我有没有得到它吗?

人类用户是否应该设置这些变量?做任何自动化工具(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 $@
Run Code Online (Sandbox Code Playgroud)

我很确定这里没有错误; Makefile工作得很好.但是有没有违反惯例的事情(比如CCFLAGSINT- 我应该改写CCFLAGS吗?或者CXXFLAGS?FUD!)

抱歉这么多问题; 你显然不会全部回答,但我希望这些答案能帮助我理解这些设置背后的一般理念.

bma*_*ies 76

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

名称重要的唯一原因是默认的make规则,可见make -p,使用其中的一些.

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

在香草gnu make中,没有CCFLAGS这样的东西.还有CFLAGS,CPPFLAGSCXXFLAGS.CFLAGS用于C编译器,CXXFLAGS用于C++,以及CPPFLAGS用于两者.

为什么CPPFLAGS两者兼而有之?通常,它是预处理程序标志(-D,-U)的主页,c和c ++都使用它们.现在,假设每个人都想要相同的c和c ++定义环境,这可能是值得怀疑的,但却是传统的.


PS正如James Moore所指出的,有些项目使用CPPFLAGS作为C++编译器的标志,而不是C预处理器的标志.Android NDK,这是一个很好的例子.

  • 我贬低你是因为有点不对劲,但你已经足够接近,以至于不值得我做出完全独立的答案.`$(CPPFLAGS)`是预处理器的标志.他们在`$(CC)`和`$(CXX)`的调用中使用的事实是偶然的.而且,它们是Makefile变量,而不是宏. (7认同)
  • 我已经彻底被带到了学校.多谢你们. (4认同)
  • @Jack 在 1982 年我遇到 make 他们称它们为宏。 (3认同)
  • @Jack:GNU Make调用变量; 其他几个来源,包括Single Unix Specification对_make_的描述,称它们为宏.一样. (2认同)
  • @Jack,不,不,不.我不是想给你上学,只是为了解释我的特殊观点.事实上,注意编辑...... (2认同)

Miz*_*zux 8

根据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


使用
"$(CC)$(CPPFLAGS)$(CFLAGS)-c" 形式的配方从nc自动编译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#Catalogue-of-Rules


Cir*_*四事件 5

最小的例子

只是为了让Mizux 所说的作为一个最小的例子:

main_c.c

#include <stdio.h>

int main(void) {
    puts("hello");
}
Run Code Online (Sandbox Code Playgroud)

main_cpp.cpp

#include <iostream>

int main(void) {
    std::cout << "hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

然后,没有任何Makefile

make CFLAGS='-g -O3' \
     CXXFLAGS='-ggdb3 -O0' \
     CPPFLAGS='-DX=1 -DY=2' \
     CCFLAGS='--asdf' \
     main_c \
     main_cpp
Run Code Online (Sandbox Code Playgroud)

运行:

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
Run Code Online (Sandbox Code Playgroud)

所以我们明白:

  • make有隐含的规则,使main_cmain_cppmain_c.cmain_cpp.cpp

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

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

  • 不使用 CCFLAGS。

    顺便说一句,例如,SCons 构建系统使用 CCFLAGS 作为 C 和 C++ 通用的标志,这是我有时在自定义生成规则上遵循的约定。

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

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

main_cpp: main_c.c
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
Run Code Online (Sandbox Code Playgroud)

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

我们也可以随意命名这些变量:但是由于 Make 已经在隐式规则中神奇地对待它们,因此它们是很好的名称选择。

在 Ubuntu 16.04、GNU Make 4.1 中测试。

相关:CFLAGS 与 CPPFLAGS