关于makefile:CFLAGS与CPPFLAGS

CFLAGS vs CPPFLAGS

我知道CFLAGS(或C ++的CXXFLAGS)用于编译器,而CPPFLAGS由预处理器使用。

但是我仍然不明白区别。

我需要为#include包含的头文件指定一个include路径-因为#include是预处理器指令,所以预处理器(CPPFLAGS)是我唯一关心的吗?

在什么情况下需要给编译器额外的包含路径?

通常,如果预处理程序找到并包含所需的头文件,为什么还需要告知它额外的包含目录? CFLAGS到底有什么用?

(就我而言,我实际上发现这两者都允许我编译程序,这增加了混乱……我可以使用CFLAGS或CPPFLAGS来实现我的目标(至少在autoconf上下文中。这有什么用?)


编译C程序的隐式make规则是

1
2
%.o:%.c
    $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

$()语法在其中扩展变量。由于在编译器调用中同时使用了CPPFLAGSCFLAGS,因此您用来定义包含路径的问题取决于个人喜好。例如,如果foo.c是当前目录中的文件

1
2
make foo.o CPPFLAGS="-I/usr/include"
make foo.o CFLAGS="-I/usr/include"

都将以完全相同的方式调用编译器,即

1
gcc -I/usr/include -c -o foo.o foo.c

当您使用多种语言需要相同的包含路径时,这两者之间的区别就会发挥作用,例如,如果您使用bar.cpp,则尝试

1
2
make bar.o CPPFLAGS="-I/usr/include"
make bar.o CFLAGS="-I/usr/include"

那么汇编将是

1
2
g++ -I/usr/include -c -o bar.o bar.cpp
g++ -c -o bar.o bar.cpp

因为C ++隐式规则也使用CPPFLAGS变量。

这种差异为您提供了一个很好的使用指南-如果您希望将标志用于所有语言,请将其放在CPPFLAGS中,如果要用于特定语言,则将其放在CFLAGSCXXFLAGS等中。后一种类型包括标准符合性或警告标志-您不想将-std=c99传递给C ++编译器!

然后,您可能会在makefile中得到类似这样的结果

1
2
3
CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++


CPPFLAGS宏是用于指定#include目录的宏。

CPPFLAGSCFLAGS都适用于您的情况,因为make(1)规则将预处理和编译结合在一个命令中(因此命令中同时使用了两个宏)。

如果使用格式#include"...",则无需将.指定为包含目录。您也不需要指定标准的编译器包含目录。您确实需要指定所有其他包含目录。


您遵循隐式make规则。