gcc

gcc 与 g++ 分别是 gnu 的 c & c++ 编译器 gcc/g++ 在执行编译工作的时候,总共需要4步:

  1. 预处理,生成 .i 的文件[预处理器cpp]
  2. 将预处理后的文件转换成汇编语言, 生成文件 .s [编译器egcs]
  3. 有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器as]
  4. 连接目标代码, 生成可执行程序 [链接器ld]

常用参数

-pedantic 对使用扩展语法的地方产生警告信息
-std=<标准> 指定输入源文件遵循的标
-save-temps 不删除中间文件
-E 仅作预处理,不进行编译、汇编和链接
-S 编译到汇编语言,不进行汇编和链接
-c 编译、汇编到目标代码,不进行链接
-v 打印出编译器内部编译过程的命令行信息和编译器的版本
-O 优化程序选项, 优化是编译器的一部分,它可以检查和组合编译器生成的代码,指出未达到最优的部分,并重新生成它们,从而使用户编写的程序更加完美且节省空间。在gcc编译器选项中,使用-O选项对代码进行优化。优化级别分3级,由高到低分别为:-O3、-O2、-O1

-O1(-O): 对编译出的代码进行优化
-O2: 进行比-O高一级的优化
-O3: 产生更高级别的优化
说明:
-O1(或-O)、-O2、-O3分别代表优化级别,数字越高,代表gcc的优化级别越高,高的优化级别代表着程序将运行的更快。优化级别越高则程序量越大。直接优化程序本身,性能的提高的变化更加明显

-Wall 生成所有警告信息

-Werror gcc 将所有的警告当成错误进行处理,这在使用自动编译工具(如Make等)时非常有用

-include file 包含某个代码,相当于#include<filename>

-imacros file 将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身不出现在输入文件中

-I dir 在使用#include “file”时,gcc/g++ 会先在当前目录查找你所制定的头文件, 如果没有找到, 他回到默认的头文件目录找, 如果使用 -I 制定了目录,他会先在你所制定的目录查找, 然后再按常规的顺序去找。

-C 在预处理的时候, 不删除注释信息, 一般和-E使用, 有时候分析程序,用这个很方便的。

-M 生成文件关联的信息。包含目标文件所依赖的所有源代码

-MM 显示去掉系统头文件外的依赖关系

-L dir lib所在目录, 向GCC的库文件搜索路径中添加新的目录

-l library 制定编译的时候使用的库 , 如 gcc -lm hello.c 使用libmath库编译程序, 默认以lib开头

-g 如果需要在编译时生成调试符号信息,可以使用GCC 的-g或者-ggdb选项. 可以通过在-g选项后附加数字1、2或3来指定在代码中加入调试信息的多少。默认的级别是2(-g2),此时产生的调试信息包括扩展的符号表、行号、局部或外部变量信息。使用任何一个调试选项都会使最终生成的二进制文件的大小急剧增加,同时增加程序在执行时的开销,因此调试选项通常仅在软件的开发和调试阶段使用。

-static 此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么动态连接库,就可以运行
-share 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统有动态库

-fPIC 表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码, 就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。

静态库链接时搜索路径顺序:

  1. ld会去找GCC命令中的参数-L
  2. 再找gcc的环境变量LIBRARY_PATH
  3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:

  1. 编译目标代码时指定的动态库搜索路径
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
  4. 默认的动态库搜索路径/lib
  5. 默认的动态库搜索路径/usr/lib

有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

静态库与动态库

静态库存在多份拷贝,动态库在内存中只存在一份拷贝,动态库避免了静态库浪费空间的问题。

静态链接库的生成

使用 ar csr 归档函数实现打包

gcc -c  foo.c -o foo.o
gcc -c  bar.c -o bar.o
ar csr libfoo.a foo.o
ar csr libbar.a bar.o

使用 gcc -o main main.c -L . -lbar -lfoo 表示在当前目录下搜索链接库,并将libbar 和 libfoo进行链接

动态链接库的生成

  1. gcc -fPIC -c tool.c -o tool.o
    -fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享
  2. gcc -shared -o tool.so tool.o
    两个命令合成一个 gcc -fPIC -shared -o tool.so tool.c

执行时如何定位共享文件位置:

  • 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)。
  • 对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存

如何让系统找到它:

  • export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH 这是一种通过环境变量操作的方式
  • 如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
  • 如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:
    • 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
    • 运行ldconfig ,该命令会重建/etc/ld.so.cache文件
文档更新时间: 2021-03-08 11:49   作者:周国强