一文看懂C/C++编译过程以及g++编译选项
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
前言
在linux系统下输入man g++即可以看到gcc官方文档对gcc编译选项的详细说明本文也主要是在官方文档基础上对gcc/g++编译过程和一些编译选项进行了总结和说明希望对学习这块内容的人有所帮助。
1、编译的四个阶段
一般我们使用gcc/g++将源码编译为可执行文件编译过程仔细划分的话可以分为4个阶段预处理、编译、汇编、链接。以add.cpp为源文件进行举例说明。
预处理
这一步主要是替换掉源文件中定义的宏比如替换#include包含的头文件替换define定义的宏变量等。预处理之后的文件形式上还是源码只是对源码有些地方做了替换。预处理后的文件名后缀为.ii 。
编译
将预处理的之后的源码编译为汇编代码。汇编后缀为.s
汇编
将汇编代码汇编生成目标文件。目标文件后缀为.o
链接
将一个或几个目标文件链接在一起形成一个可执行文件。
2、通过编译选项来控制编译过程
还是以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
3、一个编译案例
假如main.cpp、add.cpp和add.h位于同一个目录下面每个文件的具体内容如下
// main.cpp
#include <iostream>
#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
4、g++编译选项总结
前面提到可以编译选项-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进行调试就要加上该选项。