一、编译过程
在使用gcc编译程序时,编译过程可以简要划分为4个阶段:
预处理、编译、汇编、链接
1.1 预处理(preprocessing)
这个阶段主要处理源文件中的#indef、#include和#define预处理命令;
这里主要是把一些include的头文件和一些宏定义,放到源文件中。
编译命令:gcc -E -o hello.i hello.c
1.2 编译(compilation)
将经过预处理文件(test.i)之后的程序转换成特定汇编(test.s)代码
编译命令:gcc -S -o hello.s hello.i
1.3 汇编(assembly)
汇编过程将上一步的汇编代码转换成机器码,这一步产生的文件叫做目标文件,是二进制格式
编译命令: gcc -c -o hello.o hello.s
1.4 链接(linking)
链接过程使用链接器将该目标文件与其他目标文件、库文件、启动文件等链接起来生成可执行文件。附加的目标文件包括静态连接库和动态连接库。
编译命令:gcc -o hello hello.o
二、 常用编译选项
2.1 -c
预处理、编译和汇编源文件,但是不作链接,编译器根据源文件生成 OBJ 文件。缺省情况下, GCC 通过用`.o'替换源文件名的后缀`.c', `.i', `.s'等,产生 OBJ 文件名。可以使用-o 选项选择其他名字。 GCC 忽略-c 选项后面任何无法识别的输入文件
2.2 -S
编译后即停止,不进行汇编。对于每个输入的非汇编语言文件,输出结果是汇编语言文件。缺省情况下, GCC 通过用`.s'替换源文件名后缀`.c', `.i'等等,产生汇编文件名。可以使用-o 选项选择其他名字。 GCC 忽略任何不需要汇编的输入文件
2.3 -E
预处理后即停止,不进行编译。预处理后的代码送往标准输出
2.4 -o file
指定输出文件为 file。无论是预处理、编译、汇编还是链接,这个选项都可以使用。如果没有使用`-o'选项,默认的输出结果是:可执行文件为`a.out';修改输入文件的名称是`source.suffix',则它的 OBJ 文件是`source.o',汇编文件是 `source.s',而预处理后的 C 源代码送往标准输出。
2.5 -v
显示制作 GCC 工具自身时的配置命令;同时显示编译器驱动程序、预处理器、编译器的版本号
2.6 -Wall
打开了所有需要注意的警告信息,比如没有指定类型的声明、在声明之前就使用的函数、局部变量除了声明就没再使用等
2.7 -g
以操作系统的本地格式(stabs, COFF, XCOFF,或 DWARF)产生调试信息, GDB 能够使用这些调试信息
2.8 -O、-O1、-O2、-O3
优化:对于大函数,优化编译的过程将占用稍微多的时间和相当大的内存
-O:不优化
-O1:优化一些
-O2:多优化一些
-O3:优化的更多
2.9 -llibrary
链接名为 library 的库文件。链接器在标准搜索目录中寻找这个库文件,库文件的真正名字是`liblibrary.a'
2.10 -nostartfiles
不链接系统标准启动文件,而标准库文件仍然正常使用
2.11 -nostdlib
不链接系统标准启动文件和标准库文件,只把指定的文件传递给链接器
2.12 -static
在支持动态链接(dynamic linking)的系统上,阻止链接共享库
2.13 -shared
生成一个共享 OBJ 文件,它可以和其他 OBJ 文件链接产生可执行文件
2.14 -Idir
在头文件的搜索路径列表中添加 dir 目录
2.15 -I ( i 的大写)
指定头文件路径(相对路径或绝对路径,建议相对路径)
2.16 -L
指定连接的动态库或者静态库路径(相对路径或绝对路径,建议相对路径)
2.17 -fPIC
用于生成位置无关的代码(Position-Independent-Code),可以使得动态库可以被多个程序共享
三、库的制作与使用
3.1 制作、使用动态库
1.将源文件进行汇编操作,需要使用参数 -c, 还需要添加额外参数 -fpic /-fPIC
gcc 源文件(*.c) -c -fPIC
2. 将得到的.o 文件打包成动态库,还是使用 gcc, 使用参数 -shared 指定生成动态库
gcc -shared 与位置无关的目标文件(*.o) -o 动态库(libxxx.so)
3. 编译APP
gcc -o test main.o -lsub -L /libsub.so/所在目录/
4. 使用APP
- 先把 libsub.so 放到 Ubuntu 的/lib 目录,然后就可以运行 test 程序
- 如果不想把 libsub.so 放到/lib,也可以放在某个目录比如/a,然后执行 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
./test
3.2 制作、使用静态库
1.将源文件进行汇编操作,需要使用参数 -c, 还需要添加额外参数 -fpic /-fPIC
gcc 源文件(*.c) -c -fPIC
2. 将得到的.o 文件打包成动态库,使用 ar指令生成静态库
ar crs 静态库(libxxx.so) 与位置无关的目标文件(*.o)
3. 编译APP
gcc -o test main.o -lsub -L /libsub.a/所在目录/
4. 使用APP
./test