1.编译器的编译链接步骤
在学习常用的gcc/g++编译器的命令行参数前,先了解编译器的编译链接过程
- 预处理(预编译):将源文件和头文件输入预处理器cpp,输出后缀名为
.i
或者.ii
的文件。预编译过程主要包含这些处理:- 进行宏替换
- 处理所有条件编译指令,比如说
#ifdef
、#if
、#endif
、#elif
、#else
- 处理预编译指令
#include
- 删除所有的注释
- 保留
#pragma once
指令,因为这个指令编译器需要使用 - 添加行号和文件名标识
- 编译:将第一步骤的输出作为cc1plus或者cc1编译器的输入,输出后缀名为
.s
的汇编代码文件。编译过程主要包含:- 词法分析
- 语法分析
- 语义分析
- 优化
- 汇编:将汇编代码由汇编器as处理转换成机器可以执行的指令,通常输出为后缀名为
.o
或者.obj
的文件 - 链接:由链接器ld链接上一步产生的目标文件和库,生成可执行程序
note:不指定具体的编译器如cc1plus、cc1的时候,编译器指的是包含预处理器、编译器、汇编器、链接器。
2.gcc/g++编译器的常用命令参数
- -E:执行到预处理
//预编译,结果为main.i文件
gcc main.c -E -o main.i
- -S:执行源代码到汇编代码的转换
//汇编,结果为main.s
gcc main.c -S
- -c:指定编译器的输入
// 指定输入为main.c
gcc -c main.c -o main.o
// 指定输入为main.s
gcc -c main.s -o main.o
- -o:指定编译器的输出目标
//目标:生成qq.exe可执行程序(windows下)
gcc main.c -o qq
//目标:生成.i文件
gcc -E test.c -o test.i //.i文件
- -g或者-ggdb:生成供调试用的可执行文件
gcc main.c -g
- -O:编译器对代码进行自动优化编译,输出效率更高的可执行文件
//-O后面还可以跟上数字指定优化级别,常用的数字0-3.
//O0表示不做优化,O1为默认优化
gcc main.c -O2
- -W:在编译中开启一些额外的警告(warning)信息
- -Werror:要求gcc将所有的警告信息当成错误进行处理.
- -Wall:将所有的警告信息全公开
- -Wno-deprecated:使用语言废弃的特性,编译器不输出warning
- -Wno-strict-aliasing
gcc main.c -W // -Wall:将所有的警告信息全公开 gcc main.c -Wall
- -w:关闭所有警告信息
- -v/--version:查看编译器版本
- -I:编译时指定头文件路径
//main.c文件内容如下:
#include <stdio.h>
#include "log.h"
int main()
{
printf("logNum:%d\n",logNum);
return 0;
}
//log.h文件的内容如下
#ifndef _LOG_H_
#define _LOG_H_
const int logNum = 10;
#endif
//main.c与comon文件夹位于同级目录下
//-I指明head.h所在的目录,-o指定生成可执行程序的名称
gcc main.c -I ./comon/ -o qq
- -L dirname:指明链接过程中链接程序ld到指定的目录中寻找。
//-L dirname:确定库文件(.so和.a的集合)所在的目录
- -lname:链接时装载名为libname.a的函数库。Linux下的库文件在命名时有一个约定,就是应该以 lib 这3个字母开头,由于所有的库文件都遵循了同样的规范,因此在用 -l 选项指定链接的库文件名时可以省去 lib 这3个字母。
例如:-lm 表示链接名为 libm.a 的数学函数库。
- -pedantic:当gcc在编译不符合ANSI/ISO C 语言标准的源代码时,将产生相应的警告信息。
//main.c文件内容如下:
#include <stdio.h>
void main(void)
{
printf("HelloWorld");
return;
}
//将产生警告信息
gcc main.c -o qq -pedantic
- -static:默认情况下,gcc 在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库。
如果需要的话,可以在编译时加上-static
选项,强制使用静态链接库。 - -shared:创建后缀名为
.so
的共享对象文件的时候使用 - -save-temps:保存编译过程中生成的一些列中间文件
# gcc test.c -o test -save-temps
除了生成执行文件test之外,还保存了test.i 和 test.s,test.o中间文件,供用户查询调试。
- -D选项:在使用gcc或者g++编译器定义宏,语法如下
gcc -D宏名称[=宏值],不指定宏的值则默认为1
- -fPIC:编译生成地址无关代码。PIC全称Position-independent Code,编译后缀名为
.so
的动态库的时候使用这个选项 - -pipe:使用管道而不是临时文件
- -std:指定项目工程按照什么标准进行后续的处理。例如
-std=c++17
- -rdynamic
-rdynamic和-Wno-strict-aliasing命令行参数后续补充