目录

GCC 命令

gcc 编译流程

GCC 编译器编译一个 C 语言程序分为四个阶段:

  1. 预处理阶段(Pre-Processing):将头文件内容添加到程序里面,生成 .i 文件
  2. 编译阶段(Compiling):将 .i 文件编译成汇编语言,生成 .s 文件
  3. 汇编阶段(Assembling):将 .s 文件编译成机器指令,生成目标文件 .o 文件
  4. 链接阶段(Linking):将各个模块的 .o 文件链接起来生成一个可执行目标文件

gcc 命令

gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o
gcc hello.o -o hello

gcc 常用选项

选项意义
-c预处理、编译、汇编指定源文件,不进行链接,生成 .o 的 obj 文件
-S预处理、编译指定源文件,生成 .s 的汇编文件
-E只进行预处理,不生成文件,需要 -o 指定或者重定向生成 .i 文件
-o [file1] [file2]将文件 file2 编译成可执行文件 file1
-C在预处理的时候, 不删除注释信息, 一般和-E使用, 有助于分析程序
-g-g选项可生成能被 gdb 调试器所使用的调试信息。只有使用了该选项后生成的可执行文件,才带有程序中引用的符号表。这时 gdb 调试程序才能对该可执行程序进行调试
-O0 、-O1 、-O2 、-O3编译器的优化选项的 4 个级别,-O0 表示没有优化, -O1为 缺省值,-O3 优化级别最高。
-shared生成共享目标文件。通常用在建立共享库时
-static禁止使用共享连接
-w不生成任何警告信息
-W生成所有警告信息
-fPIC作用于编译阶段,告诉编译器产生与位置无关的代码(Position-Independent Code)
-l[lib]指定程序要链接的库,lib 是库名,数学库的文件名是 libm.so,那么 -lm 就代表链接数学库,同理 -ldl 代表链接加载动态库的 libdl.so 库

gcc 生成动态链接库

从源文件生成动态链接库:

gcc -fPIC -shared func.c -o libfunc.so

从目标文件生成动态链接库:

gcc -fPIC -c func.c -o func.o gcc -shared func.o -o libfunc.so

-fPIC 选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。产生的代码全部使用相对地址,这样代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

gcc 将动态链接库链接到可执行文件

如果希望将一个动态链接库链接到可执行文件,那么需要在命令行中列出动态链接库的名称,具体方式和普通的源文件、目标文件一样。

gcc main.c libfunc.so -o app.out

将 main.c 和 libfunc.so 一起编译成 app.out,当 app.out 运行时,会动态地加载链接库 libfunc.so。

当然,必须要确保程序在运行时可以找到这个动态链接库。你可以将链接库放到标准目录下,例如 /usr/lib,或者设置一个合适的环境变量,例如 LIBRARY_PATH。不同系统,具有不同的加载链接库的方法。