GCC编译过程 与 动态链接库和静态链接库

C++源文件到可执行文件过程

源程序 预处理->编译和优化->汇编->链接->可执行文件

1.预处理(Preprocessing)
读取源程序,对其中的伪指令(以#开头的指令(宏定义、条件编译指令、头文件包含指令))和特殊符号进行处理
gcc -E main.c -o main.i

2.编译阶段(Compilation)
把预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。
gcc -S main.c -o main.s

3.汇编过程(Assembly)
把汇编语言代码翻译成目标机器指令
gcc -c main.s hello.s -o hello.o

4.链接程序(Linking)
将main.o和hello.o以及一些其他必要的目标文件组合起来,包含各函数库的入口,创建可执行目标文件。
gcc main.o hello.o -o hello

GCC文件后缀名

后缀 含义
.h .hpp .hxx C/C++头文件
.c .cpp .cc .cxx C/C++源代码文件
.i .ii 预处理过的C源代码文件
.s 汇编代码
.S 经过预编译的汇编代码
.o 目标机器指令
.a(linux) .lib(Win32) 静态链接库
.so(linux) .dll(Win32) 动态链接库

库文件命名规范

在 linux 下,库文件一般放在/usr/lib和/lib下,
静态库的名字一般为libxxxx.a,其中 xxxx 是该lib的名称;
动态库的名字一般为libxxxx.so.major.minor,xxxx 是该lib的名称,major是主版本号,minor是副版本号

库比较

依据链接时期的不同,库又有静态库和动态库之分。

静态库是在链接阶段被链接的。所以生成的可执行文件就不受库的影响了。即使库被删除了,程序依旧能够成功执行。
有别于静态库,动态库的链接是在程序执行的时候被链接的。所以,即使程序编译完,库仍须保留在系统上,以供程序执行时调用,相关库删除之后程序不能正常运行。

假设多个程序链接了同一个库,则每个生成的可运行文件就都会有一个库的副本,必定会浪费系统空间。
动态库是在程序执行时被链接的,所以磁盘上仅仅须保留一份副本,因此节约了磁盘空间。

静态库可以在程序移植前将相关库链接进去,只需移植可执行文件,方便。
动态库牺牲了运行效率。

静态库

静态库,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。

可以简单看成是一组目标文件(.o/.obj文件)的集合

创建过程
编译成目标文件.o

gcc -c index.cpp -o index.o

通过ar工具将目标文件打包成.a静态库文件,生成静态库libindex.a

ar -crv libindex.a index.o

在程序中链接静态库,生成的hello.static就不再依赖libindex.a了

gcc test.c libindex.a -L ./ -o hello.static
# -L后面是 要链接的静态库地址(-Lxxx中间有没有空格都行)
或
gcc test.c -l index -L./ -static -o hello.static 
#这里-l之后紧接是库名(注意-lxxxx中间有没有空格都行,且省略后缀),但是要增加-static说明是静态库

动态库

特点

  • 动态库把对一些库函数的链接载入推迟到程序运行的时期
  • 可以实现进程之间的资源共享。(因此动态库也称为共享库)
  • 将一些程序升级变得简单。(增量更新,只需更新库)
  • 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显式调用)

创建过程
编译成目标文件.o

gcc -c index.cpp -o index.o

由.o文件创建动态库文件

gcc -shared -fPCI index.o -o libindex.so 
# 64位机要加上这个参数-fPCI   

在程序中链接动态库

gcc test.c -lindex -L./ -o test.out

常见的链接库

在编译带有线程库的函数时得在后面加-lpthread,编译使用了libevent库的文件时,得在后面加上-levent,还有编译json或异步I/O等时都得在编译时都得加上特有的链接库

你可能感兴趣的:(C++)