GCC简介
GCC = GUN Compiler Collection(GNU编译器套件)
GCC包含了C、C++、Objective-C、Fortran、Java、Ada和Go等语言编译器以及这些语言的标准库(glibc, libstdc++)
GCC的功能:将人为刻度的源代码转化为目标硬件可执行机器指令序列
GCC工作流程
编译器工作流程:
- 预处理(preprocessing)
- 编译(compiling)
- 汇编(assembling)
- 链接(linking)
- 预处理
- 移除注释
- 组合跨越多行的代码
- 头文件展开
- 条件编译
- 宏定义替换
- 编译
源文件转化为汇编文件 - 链接
将多个目标文件/库文件组合为一个文件
G/G++编译器的输入必须为一个C/C++源文件,每一个源文件被称为一个编译单元(Translation Unit)。编译单元为编译器处理编译任务的最小单位。
- 编译源文件,生成目标二进制文件
g++ -o main main.cpp - 查看预编译步骤输出
g++ -E -o main.i main.cpp - 查看编译步骤输出
g++ -S -o main.s main.cpp - 查看汇编步骤输出
g++ -c -o main.o main.cpp
gcc常用编译选项
-E: 只执行预处理流程
-S: 只执行编译流程
-C: 只执行汇编流程
-o file: 输出文件
-g: 产出物包含标准调试信息
-l dir: 头文件搜索路径
-isystem dir: 系统头文件搜索路径
-L dir: 库文件搜索路径
-l<library>: 链接库文件
-O<n>: 编译器优化等级
-D<name=value>: 添加编译器宏定义
-std=<version>: 语言版本 eg -std=c++14
-shared: 生成动态库
-fPIC: 生成位置无关代码
g++ -o <executable> -I <include_dirs> -L <library_dirs> <src_files/obj_files> -l <libbrary>
使用-o参数指定输出可行文件名称
使用-I参数定义头文件搜索路径
使用-L参数定义链接库搜索路径,仅针对使用库名称链接的情况
最后可以指定多个源文件/目标文件
使用-l指定链接库, -l参数应在源文件后
gcc编译动态库 & 静态库
动态库
g++ -fPIC -shared -o libxxx.so <src_files>
使用-fPIC参数指定生成位置无关代码
使用-shared参数指定生成动态库
静态库
g++ -o xxx.o -c xxx.cpp
生成obj文件
ar -rc -o libxxx.a <obj_files>
- 使用gcc将所有源文件编译为目标文件
- 使用ar工具将所有目标文件打包为静态库
编译完成后,使用
第一种方法
g++ -o main main.cpp ./libxxx.a
将所有的库输入进去
第二种方法
g++ -o main -L ./ main.cpp -lhello
第二种方法的静态库是可以正常执行的,但是动态库不行,需要设置环境变量,readelf -d main | less 读取到依赖于链接库,而静态库并不需要
添加 LD_LIBRARY_PATH=$PWD 然后执行文件即可
Makefile的使用
工具简介
使用gcc命令的局限性
- 一个规模很大的工程,可能包含数百个甚至数千个源文件
- 每一个源文件可能都有不同的编译参数
- 一个工程可能有多个二进制文件产出物
对于大型工程,使用gcc命令编译各个源文件几乎是不可能完成的工作。
gcc虽然可以将源文件编译为目标二进制文件,但是却不能帮助我们管理大型的c/c++源代码工程
Makefile可以狭义的理解为一个工程文件的编译规则,它描述了整个工程的编译参数,依赖关系,链接规则等。
Makefile可以使得我们的项目工程的编译变得自动化,不需要每次都输入一堆源文件和参数。
基本语法
默认文件名称:Makefile
Makefile结构:
[目标名称]:[依赖条件] [执行指令]
使用Makefile管理工程
- 每一个源文件生成的目标文件定义为一个target
- 产出文件路径与target名称一致
- 增加名为clean的target,用于清空编译产出物
痛点:
- 编写Makefile比较麻烦,对于大型工程Makefile的开发量较大
- 灵活性不足,不方便根据编译环境的变化而调整编译行为
- 可维护不足,Makefile只对指令和依赖关系进行了结构化排布,可读性不强
CMake的使用
CMake工具简介
针对Makefile的管理大型项目的痛点,出现了很多工具来弥补Makefile的不足。一些典型的工具有:
- GNU automake
- CMake
等等
这些工具设计思想大同小异
- 用介于人类自然语言的语法描述工程结构
- 通过工具将工程结构描述文件转化为Makefile
- 通过Makefile编译工程
CMake基本语法
cmake使用名为CMakeLists.txt文件来管理工程
CMakeLists.txt文件中主要用到如下命令
- cmake_minimum_requred: 定义cmake脚本最低兼容版本
- project: 定义工程名称
- set: 定义变量
- add_executable: 定义可执行程序目标
- add_libarary: 定义库文件目标
- target_include_directories: 定义目标的头文件搜索路径
- target_link_directories: 定义目标的库文件搜索路径
- target_link_libraries: 定义目标的链接库
- add_subdirectory: 添加工程结构子文件夹
流程控制
- if
- foreach