GCC 之动态连接库

GCC

上面是 GCC 进行编译时的过程,分别进行了预处理、编译、汇编和链接四个阶段,在 gcc 的命令中也有相应的参数对应:

  • E:只预处理,不进行编译、汇编和连接
  • S:只编译,不进行汇编和连接
  • c:编译和汇编,不进行链接
  • o:在各个阶段,生成指定的输出文件名称

相应的调用命令如下

# 预处理
gcc -E hello.c -o hello.i
# 编译,把代码将预处理生成的 .i 文件翻译为汇编代码
gcc -S hello.i -o hello.s
# 汇编,将汇编代码翻译成一定格式的机器代码,在 linux 系统上一般表现为 ELF 目标文件
gcc -c hello.s -o hello.o
# 链接,将汇编产生的目标文件与库文件链接起来,生成可执行代码
gcc -o hello hello.o

在汇编的过程中,会产生 .o 文件,但是还没有进行链接,使用的是 -c 选项,这个可以将每一个源文件编译成对应的目标文件,目标文件是一种中间文件或者临时文件,如果不设置该选项,gcc 一般不会保留目标文件,在可执行文件生成完成之后就自动删除了。

编译多个源代码文件时会生成多个目标文件,每个目标文件都包含了一个源文件的机器码和相关的数据。

由于 gcc 支持多种扩展文件类型,如:.cc、.cpp、.c++ 等,建议使用 -x 选项来说明 -x file_type 来指示 gcc 应该如何对待这些文件。
file_type 必须是下面其中之一:c、c-header、cpp-output、assembler、assembler-with-cpp 或者 none

在 Linux 中动态链接库(shared object file,共享对象文件)的文件后缀为 .so,它是一种特殊的目标文件,可以在程序运行时被加载(链接)进来,好处是程序的可执行文件更小,便于程序的模块化以及更新,同时,有效内存的使用效率更高。

产生动态链接库用到了两个参数:-shared-fPIC,其中 -fPCI 选项的选项作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),这样产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载器加载到内存的任意位置都可以正确执行。

# 从源文件生成动态链接库
gcc -fPCI -shared func.c -o libfunc.so
# 从目标文件生成动态链接库
gcc -fPCI -c func.c -o func.o
gcc -shared func.o -o libfunc.so
之后就可以将动态连接库连接到可执行文件了,这个可执行的文件在执行的过程中要保证它可以找到这个动态链接库
gcc main.c libfunc.so -o app

之后可以使用 ldd 命令查看一下这个可执行文件的依赖情况。

找不到的话,可以将链接库放到标准目录下,如:/usr/lib ,或者设置 LIBRARY_PATH 环境变量

ldd