据我所知,CFLAGS(或CXXFLAGS for C ++)适用于编译器,而CPPFLAGS则由预处理器使用。
但我仍然不明白其中的区别。
我需要为#include包含的头文件指定一个包含路径 - 因为#include是一个预处理器指令,是我唯一关心的预处理器(CPPFLAGS)吗?
在什么情况下我需要给编译器一个额外的包含路径?
通常,如果预处理器找到并包含所需的头文件,为什么需要告知额外的包含目录? CFLAGS有什么用?
(在我的情况下,我实际上发现 BOTH 这些允许我编译我的程序,这增加了混乱...我可以使用CFLAGS OR CPPFLAGS来实现我的目标(至少在autoconf环境中)。给出了什么?)
答案 0 :(得分:141)
编译C程序的隐式make规则是
%.o:%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
$()
语法扩展变量。由于在编译器调用中使用CPPFLAGS
和CFLAGS
,因此用于定义包含路径的是个人品味问题。例如,如果foo.c
是当前目录中的文件
make foo.o CPPFLAGS="-I/usr/include"
make foo.o CFLAGS="-I/usr/include"
将以完全相同的方式调用编译器,即
gcc -I/usr/include -c -o foo.o foo.c
当您有多种语言需要相同的包含路径时,两者之间的区别就会发挥作用,例如,如果您有bar.cpp
则尝试
make bar.o CPPFLAGS="-I/usr/include"
make bar.o CFLAGS="-I/usr/include"
然后编译将是
g++ -I/usr/include -c -o bar.o bar.cpp
g++ -c -o bar.o bar.cpp
因为C ++隐式规则也使用CPPFLAGS
变量。
这种差异为您提供了一个很好的指南供您使用 - 如果您希望将标记用于所有语言,请将其放在CPPFLAGS
中,如果是特定语言将其放入CFLAGS
, CXXFLAGS
等。后一种类型的示例包括标准合规性或警告标志 - 您不希望将-std=c99
传递给C ++编译器!
然后你可能会在你的makefile
中得到这样的结果CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++
答案 1 :(得分:10)
CPPFLAGS
宏是用于指定#include
目录的宏。
CPPFLAGS
和CFLAGS
都适用于您的情况,因为make
(1)规则在一个命令中结合了预处理和编译(因此在命令中使用了两个宏)。 / p>
如果您使用.
表单,则无需将#include "..."
指定为包含目录。您也不需要指定标准编译器包含目录。您需要指定所有其他包含目录。
答案 2 :(得分:4)
你在implicit make rules之后。
答案 3 :(得分:0)
要添加到提到隐式规则的人中,最好使用以下命令查看make隐式定义的内容以及为您的环境定义的内容:
make -p
例如:
%.o: %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
展开
COMPILE.c = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
这还将打印# environment
数据。在这里,您会发现GCC的包含路径以及其他有用信息。
C_INCLUDE_PATH=/usr/include
在制造中,当涉及搜索时,路径很多,光线是一个……或类似的东西。
C_INCLUDE_PATH
是系统范围的,请在您的Shell的*.rc
中进行设置。$(CPPFLAGS)
用于预处理器包含路径。VPATH = my_dir_to_search
...甚至更具体
vpath %.c src
vpath %.h include
make使用VPATH作为常规搜索路径,因此请谨慎使用。如果文件在VPATH中列出的多个位置中存在,则make将以列表中的第一个出现。