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

时间:2011-04-04 17:14:32

标签: gcc naming-conventions makefile

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

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

3 个答案:

答案 0 :(得分:74)

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

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

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

在香草牛奶制作中,没有CCFLAGS这样的东西。有CFLAGSCPPFLAGSCXXFLAGS。 C编译器为CFLAGS,C ++为CXXFLAGS,两者为CPPFLAGS

为什么两者都是CPPFLAGS?传统上,它是预处理程序标志(-D-U)的主页,c和c ++都使用它们。现在,假设每个人想要相同的c和c ++定义环境也许是有问题的,但是传统的。


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

答案 1 :(得分: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.c自动制作n.o,格式为
  ‘$(CC)$(CPPFLAGS)$(CFLAGS)-c”。

     

编译C ++程序
  由n.cc,n.cpp或n.C自动制作n.o,格式为
  ‘$(CXX)$(CPPFLAGS)$(CXXFLAGS)-c”。
  我们建议您为C ++源文件使用后缀“ .cc”,而不是“ .C”。

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

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

因此我们了解到:

  • make具有隐式规则,可根据main_cmain_cpp来制作main_c.cmain_cpp.cpp
  • CFLAGS和CPPFLAGS用作.c编译隐式规则的一部分
  • CXXFLAGS和CPPFLAGS用作.cpp编译隐式规则的一部分

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

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

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

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

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

在Ubuntu 16.04,GNU Make 4.1中进行了测试。