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

问题描述 投票:60回答:2

我正在使用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!)

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

gcc naming-conventions makefile
2个回答
74
投票

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

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

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

在香草gnu make中,没有CCFLAGS这样的东西。有CFLAGSCPPFLAGSCXXFLAGS。用于C编译器的CFLAGS,用于C ++的CXXFLAGS和用于两者的CPPFLAGS

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


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


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的隐式规则使用

编译C程序 n.o是从n.c自动生成的,带有表格的配方 '$(CC)$(CPPFLAGS)$(CFLAGS)-c'。

编译C ++程序 n.o是从n.cc,n.cpp或n.C自动生成的,具有表格的配方 '$(CXX)$(CPPFLAGS)$(CXXFLAGS)-c'。 我们建议您对C ++源文件使用后缀“.cc”而不是“.C”。

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


0
投票

而只是为了使Mizux said作为一个最小的例子:

main_c.c

#include <stdio.h>

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

main_cpp.cpp

#include <iostream>

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

然后,没有任何Makefile

make CFLAGS='-g -O3' CXXFLAGS='-ggdb3 -O0' CPPFLAGS='-DX=1 -DY=2' 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

所以我们理解:

  • qazxsw poi有来自makemain_c的qazxsw poi和qazxsw poi的隐含规则
  • CFLAGS和CPPFLAGS被用作main_cpp编译的隐式规则的一部分
  • CXXFLAGS和CPPFLAGS被用作main_c.c编译的隐式规则的一部分

这些变量仅自动用于make的隐式规则:如果编译使用了我们自己的显式规则,那么我们必须明确地使用这些变量,如:

main_cpp.cpp

实现类似于隐式规则的影响。

我们也可以根据需要命名这些变量:但是由于Make已经在隐式规则中对它们进行了神奇的处理,因此可以选择好的名称。

在Ubuntu 16.04中测试,GNU Make 4.1。

© www.soinside.com 2019 - 2024. All rights reserved.