C/C++ 生态工具链——gcc/g++ 编译器使用指南
一,关于 GCC
GCC 的全称是 GNU Compiler Collection,是 GNU 工具链中的一种。GCC 不仅支持 C/C++语言,还支持 Fortran/Ada/Java 等语言的编译。
GCC 和 gcc 是两个概念,GCC 是工具链的集合,里面除了 gcc/g++还包含了 ccl,cclplus 等组件。gcc/g++只是 GCC 工具链的一个子集。
二,g++和 gcc 的区别
gcc 可以判断出目标程序所使用编程语言的类别,会把 xxx.c 文件当作 C 语言编译,把 xxx.cpp 文件当作 C++语言编译。而 g++只把 xxx.c 和 xxx.cpp 一律都当作 C++语言来编译。
在编译 C++文件的时候,g++会自动链接一些标准库或基础库,而 gcc 不会。当正在编译的 C++代码文件依赖 STL 标准库的时候,为了使用 STL,gcc 命令需要增加参数–lstdc++。因此,虽然 gcc 和 g++都可以编译 C++语言程序,但是使用 g++会更方便一些。
三,常见代码文件后缀名
(1)目标文件:
xxx.o, 操作系统:Linux, Mac
xxx.obj, 操作系统:windows
(2)二进制文件:
xxx(没有后缀名), 操作系统:Linux, Mac, FreeBSD,
xxx.exe, 操作系统:windows
xxx.hex,操作系统:嵌入式系统
(3)共享库文件,也叫动态库文件:
xxx.dll, 操作系统:windows
xxx.so, 操作系统:Linux
xxx.dylib, 操作系统:Mac
(4)静态库文件
xxx.a
四,C/C++语言的编译过程
1.预处理
预处理命令声明了编译时需要的各种头文件和宏,比如包含哪些头文件、宏定义的扩展、在哪个代码段做条件编译等。涉及预处理的语法有:#define,#include,#ifdef...#endif
2.编译
首先检查代码的规范性和语法错误等,检查完毕后把代码翻译成汇编语言,生成汇编语言文件
3.汇编
基于汇编语言文件生成二进制格式的目标文件
3.链接
将目标代码与所依赖的库文件进行关联或者组装,合成一个可执行文件
具体过程如图:
拿 g++举例
1.样例代码:
2.g++的编译过程:
1.预处理--将 xx.cpp 源文件预处理成 xx.i 文件
2.编译--将 xx.i 文件编译为 xx.s 的汇编文件。此时只进行编译生成汇编代码,而不对代码以汇编的方式调试
3.汇编--将 xx.s 文件汇编成 xx.o 的二进制目标文件
4.链接--将 xx.o 二进制文件进行链接,最终生成可执行程序
五,静态链接和动态链接的区别
静态库:
与目标程序合并,成为目标程序的一部分。
创建静态库的时候,需要使用"gcc/g++ -c"先将 xxx.c 源文件编译为目标文件 xxx.o,然后使用 ar 指令将 xxx.o 打包成 xxxx.a 静态库。
目标程序与静态库链接时,目标程序代码调用的任何外部函数的代码都会从静态库中复制到最终的可执行文件中。
GCC 在链接时优先使用动态库,只有当动态库不存在时才开始使用静态库,如果要强制使用静态库,编译时加上-static 参数。
使用-Wl,-Bstatic 告诉链接器优先使用静态库。
动态库:
不包含在目标程序中,但是与目标程序相关联。
创建动态库的时候,可以传-shared 和-fPIC 参数,-fPIC 参数用于编译阶段,用来生成位置无关的代码。使用“gcc -shared -fPIC”可以直接用 xxx.c 源文件生成 xxx.so 动态库。
目标程序与动态库链接时,可执行文件仅包含它所需的一个小函数表,而不是来自库文件的完整机器代码。在可执行文件开始运行之前,动态库的代码被操作系统复制到内存中进行共享。
动态库之所以叫共享库,可能是由于动态库的代码副本可以在多个程序之间共享。正因为这种链接方式,共享库每次被更新时,都不需要重新编译正在使用共享库的目标程序。
使用-Wl,-Bdynamic 告诉链接器优先使用动态库。
有关的环境变量:
LIBRARY_PATH:使用于编译期间,目标程序链接时搜索动态库的路径。
LD_LIBRARY_PATH:使用于目标程序生成后,目标程序运行时搜索动态库的路径。
静态库链接时,搜索库文件路径的顺序:
1. ld 会去找 GCC 命令中的参数-L
2. gcc 的环境变量 LIBRARY_PATH
3. /lib,/usr/lib,/usr/local/lib 等写在程序内的路径
动态库链接时,搜索库文件路径的顺序:
1. 编译目标代码时指定的动态库搜索路径
2. gcc 的环境变量 LD_LIBRARY_PATH
3. 配置文件/etc/ld.so.conf 中指定的动态库搜索路径
4. 默认的动态库搜索路径/lib
5. 默认的动态库搜索路径/usr/lib
实用程序:ldd 和 nm
ldd:列出依赖的动态库
nm:查看动态库/静态库中的函数
六,gcc/g++命令常见参数
命令格式
在 linux 环境使用:man g++可以查看 g++命令常用参数
常见参数如下(注意大小写):
编译和路径参数
预处理参数
警告与报错参数
调试参数
编码配置参数
优化参数
七,参考阅读
https://gcc.gnu.org/onlinedocs/gcc/
版权声明: 本文为 InfoQ 作者【Revolution_z】的原创文章。
原文链接:【http://xie.infoq.cn/article/7ef2500ca920b61c181b060a0】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论