在linux系统下,输入man g++,即可以看到gcc官方文档对gcc编译选项的详细说明,本文也主要是在官方文档基础上,对gcc/g++编译过程和一些编译选项进行了总结和说明,希望对学习这块内容的人有所帮助。
一般我们使用gcc/g++将源码编译为可执行文件,编译过程仔细划分的话,可以分为4个阶段:预处理、编译、汇编、链接。以add.cpp为源文件进行举例说明。
预处理
这一步主要是替换掉源文件中定义的宏,比如替换#include包含的头文件,替换define定义的宏变量等。预处理之后的文件形式上还是源码,只是对源码有些地方做了替换。预处理后的文件名后缀为.ii 。
编译
将预处理的之后的源码编译为汇编代码。汇编后缀为.s
汇编
将汇编代码汇编生成目标文件。目标文件后缀为.o
链接
将一个或几个目标文件链接在一起,形成一个可执行文件。
还是以add.cpp为例,如果要生成各个阶段的文件,可以通过编译选项来控制。
生成预处理.ii文件
编译选项为 -E,这里一定要用-o 指定输出的文件名,不然默认是输出到屏幕。其它几个阶段可以不用指定输出文件名。
g++ add.cpp -E -o add.ii #需要指定输出文件名,得到add.ii
生成汇编.s文件
编译选项为-S,可以不用-o指定输文件名,默认为add.s,当然也可以指定。
g++ add.ii -S # 默认输出文件名为add.s
# 也可以直接一步从源文件得到.s文件
g++ add.cpp -S
生成目标.o文件
编译选项为-c,可以不用-o指定输出文件名,默认为add.o。
g++ add.s -c # 从汇编文件得到目标文件
# 也可以从源文件或与预处理后文件得到目标文件
g++ add.ii -c # 从预处理之后的文件得到目标文件
生成可执行文件
一般每个.cpp文件经过处理之后,都能得到一个目标.o文件,可以将多个目标文件链接成一个可执行文件。假如main.cpp,也生成了main.o文件,那么将main.o和add.o链接成一个可执行文件。
不需要编译选项,可以用-o指定可执行文件的文件名,如果不指定默认为a.out
g++ main.o add.o # 默认生成a.out
g++ main.o add.o -o main # 指定可以执行文件名为main
值得说明的是,编译选项只是指定编译过程的结束阶段,并未要求输入文件阶段,因此跳过中间某一个过程也是可以,比如从.cpp文件直接生成可以执行文件。涉及多个文件时,不同文件处于不同阶段也是可以的。比如一个为源文件,一个为汇编文件,然后用这个两个文件生成可执行性文件也是ok的:
g++ main.cpp add.s -o main
假如main.cpp、add.cpp和add.h位于同一个目录下面,每个文件的具体内容如下:
// main.cpp
#include
#include "add.h"
using namespace std;
int main ()
{
cout << "add result is:" << add(500, 20) << endl;
return 0;
}
// add.h
int add(int num1, int num2);
// add.cpp
#include "add.h"
int add(int num1, int num2) {
return num1 + num2;
}
linux系统下,进入到三个文件所在目录,依次执行下面3个命令:
g++ add.cpp -E -o add.ii # 生成add.ii
g++ add.ii -S # 生成add.s
g++ add.s -c # 生成add.o
会依次生成add.ii 、add.s、 add.o三个文件。此时目录文件情况为:
add.cpp add.h add.ii add.o add.s main.cpp
然后使用下面的命令,直接将main.cpp和add.o生成可以执行文件,相当与省略了main.cpp编译的中间过程。
g++ main.cpp add.o -o main
此时目录情况为:
add.cpp add.h add.ii add.o add.s main main.cpp
然后输入 ./main 可以看到打印如下,说明编译过程正确。
# add result is:520
前面提到可以编译选项-E、-S、-c来指定编译的终止阶段,如果不加编译选项,默认生成可以执行文件。其它常用的编译选项有:
-o filename 指定输出文件名
-I dir,(大写i,可理解为include首字母),将dir添加到头文件的查找路径,即如果头文件在dir可以确保查找头文件成功。
-llibrary 或 -l library(不推荐),如果需要连接库library,指定链接库library。
-L dir,为-l中指定的库添加搜索目录dir,即如果library在dir可以确定搜索到
-shared以及-fpic或-fPIC,生成动态库时需要,pic表示postion independent code,即生成与位置无关的代码。
-std=standard,执行标准,如-std=c++11。
-g,编译时产生调试信息,比如要使用gdb进行调试,就要加上该选项。