Linux编译器gcc/g++的使用

库的概念

1.库的定义

  本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。

2.库的分类

  linux 下的库有两种:静态库和共享库(动态库)。 二者的不同点在于代码被载入的时刻不同。 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。

  共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,可以节省系统开销,因此代码体积较小。不同的程序调用相同库时,内存中只需有一份该动态库的实例即可。

3.在Linux下库文件的产生

静态库(后缀是.a):

  • 由源文件编译生成一堆.o,每个.o 里都包含这个编译单元的符号表

  • ar 命令将很多.o 转换成.a,成为静态库

  • 如:ar rcs libmyhello.a hello.o ,再编译:gcc add.c -static -L. -lmyhello -o hello,执行可执行文件:./hello
    描述

  • 此时发现执行gcc main.c -static -L. -lmyhello -o hello后报了一个错误,原因是你的系统中没有安装静态库
    描述

安装静态库后执行发现结果正确:

描述

删除静态库文件发现程序照常运行,原因是静态库中的公用函数已经连接到目标文件中

描述

动态库(后缀是.so):

  • gcc hello.c -shared -fPIC -o libmyhello.so
    描述
    -PIC:表示 GCC 产生的代码不要包含对函数和变量具体内存位置的引用,即编译为位置独立的代码
    -shared:表示生成动态库

  • gcc add.c -L. -lmyhello -o hello
    -L.:表示告诉 GCC 函数库可能位于当前目录

  • 若直接执行./hello会发现编译器报错,原因是GNU连接器会查找标准系统函数目录,先后搜索:①elf 文件的 DT_RPATH 段—>②境变量LD _LIBRARY _PATH(此环境变量指示动态连接器可以装载动态库的路径)—>③/etc/ld.so.cache 文件列表—>④/lib/或/usr/lib 目录找到库文件后将其载入内存。但这里生成的库并没有加载到这四个路径中的任何一条,所以编译器会报错。
    描述

  • 解决方法:①将文件 libmyhello.so 复制到目录/usr/lib 中,再执行./hello
         ②先执行:export LD_ LIBRARY_PATH=$(pwd),再执行:./hello
         ③执行ldconfig /usr/zhsoft/lib,此命令的功能在于让 ldconfig 将指定目录下的
        动态链接库被系统共享起来,会重建/etc/ld.so.cache 文件
    描述

注:当静态库与动态库同名时,gcc命令会优先使用动态库

4.库文件的命名

  • 在 linux 下,库文件一般放在/usr/lib 和/lib 下

  • 静态库的名字一般为 libxxx.a,其中 xxx 是该 lib 的名称。如:libc.a

  • 动态库的名字一般为 libxxx.so.major.minor,其中xxx 是该 lib 的名称,major 是主版本号,minor 是副版本号。如:libc.so.6

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

  1. ld 会去找 gcc 命令中的参数-L

  2. 再找 gcc 的环境变量 LIBRARY_PATH(该环境变量指定静态链接库文件搜索路径)

  3. 再找内定目录 /lib 或/usr/lib 或/usr/local/lib

动态库链接时搜索路径顺序

  1. 编译目标代码时指定的动态库搜索路径

  2. 环境变量 LD_ LIBRARY_PATH 指定的动态库搜索路径(该环境变量指定动态链接库文件搜索路径)

  3. 配置文件/etc/ld.so.conf 中指定的动态库搜索路径

  4. 默认的动态库搜索路径/lib

  5. 默认的动态库搜索路径/usr/lib

gcc 编译

 gcc编译会有以下四个步骤:

  • 预处理(宏替换、条件编译、头文件展开、去注释)
    实例:gcc -E test.c -o test.i
    描述

  • 编译(生成汇编)
    实例:gcc -S test.c -o test.s
    描述

  • 汇编(生成机器可执行代码)
    实例:gcc -c test.c -o test.o
    描述

  • 链接(生成可执行文件或库文件)
    实例:gcc test.c -o test 或 gcc test.o -o test
    描述

 选项:

  • -o:指定生成的输出文件名字

  • -E:仅执行编译预处理

  • -S:将C代码转换为汇编代码

  • -O0:编译器优化级别(0表示没有优化,1为编译器默认值,3优化级别最高)

特殊记忆法:esc、iso

猜你喜欢

转载自blog.csdn.net/adorable_/article/details/79782163