我正在使用GNU make来编译我的C ++代码,我想了解如何使我的编译可以自定义。
我在不同地方读到,CFLAGS
,CCFLAGS
和CXXFLAGS
用于此目的。那我该怎么用呢?如果我有额外的命令行参数给编译器,我应该将它们附加到CFLAGS
还是先添加它们?有通用做法吗?
为什么三个不同的变量?我想C编译器应该得到CFLAGS
和CCFLAGS
,而C ++编译器应该得到CFLAGS
和CXXFLAGS
- 我做得对吗?
人类用户是否应该设置这些变量?是否有任何自动工具(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 $@
我很确定这里没有错误; Makefile工作得很好。但有没有违反惯例的内容(例如CCFLAGSINT
- 我应该改为覆盖CCFLAGS
吗?或CXXFLAGS
?FUD!)
抱歉这么多问题;你显然不会全部回答,但我希望这些答案能帮助我理解这些设置背后的一般理念。
答案 0 :(得分:74)
正如您所注意到的,这些是Makefile {宏或变量},而不是编译器选项。它们实现了一组约定。 (宏是他们的旧名称,仍然被一些人使用.GNU make doc称他们为变量。)
名称重要的唯一原因是默认的制作规则,通过make -p
可见,它们使用其中一些规则。
如果您编写了所有自己的规则,则可以选择所有自己的宏名称。
在香草牛奶制作中,没有CCFLAGS这样的东西。有CFLAGS
,CPPFLAGS
和CXXFLAGS
。 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_c
和main_cpp
来制作main_c.c
和main_cpp.cpp
.c
编译隐式规则的一部分.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中进行了测试。