前言
本文浅析gcc在构建多文件项目,使用静态链接库,动态链接库中,各个编译参数的含义和常见用法。
利用参数控制gcc的编译进度
这是gcc常处理的文件类型:
- .c / .cpp:c,cpp源码
- .s:汇编源码
- .m:objective-c源码
- .i:c预处理结果文件
- .ii:cpp预处理结果文件
- .S:汇编预处理结果文件
- .h:头文件
- .o:编译后得到的目标文件
- .so:动态链接库文件(一种特殊的目标文件)
- .a:静态链接库
- .out:可执行文件。实际可执行文件没有统一的后缀,系统根据文件属性来区分可执行文件和不可执行文件。缺省情况下gcc生成的可执行文件名为a.out。
编译流程
- 预处理:生成.i或.ii文件
- 编译:将.i或.ii文件编译成为汇编语言,生成.s文件
- 汇编:将汇编语言进行汇编处理,生成目标文件,即.o文件
- 链接:将一个或多个.o文件链接,生成可执行程序文件
上述中间在用户指定分步进行时会得到保留,但在一次性完成编译时会被删除
编译选项
gcc的命令格式为"gcc [options][filenames]"。其常用编译选项有:
options取值 | 说明 | 示例 |
---|
-c | 编译并汇编指定的文件,但不进行链接。生成.o文件,通常用于编译不包含主程序的子程序文件 | gcc -c test1.c test2.c | -S | 编译指定的源文件,不进行汇编,生成.s汇编文件 | gcc -S circle.c,这将生成circle.s文件 | -E | 预处理指定的源文件,不进行编译。默认情况下预处理器的输出会被导入到标准输出流,可以通过-o选项将其导入到某个文件中 | gcc -E circle.c -o circle.i | -o filename | 指定输出文件的名称。如果不给出这个选项,gcc生成的可执行文件将名为a.out | gcc main.c func.c -o app.out | -g | 在可执行程序中包含调试信息 | | -L library_path | 在库文件的搜索路径列表中添加library_path路径 | | -llibrary | 链接时搜索指定的函数库library。gcc会默认链接libc.a或者libc.so,但是要想链接到其它库则需要手动添加 | 使用-l选项链接数学库,gcc main.c -o main.out -lm | -I head_path | 在头文件的搜索路径列表中添加head_path路径 | | -static | 进行静态编译,且链接静态库,禁止链接动态库 | | -shared | 和-fPIC配合使用 | | -fPIC | 生成使用相对地址的位置无关的目标代码 | |
创建静态链接库
创建静态链接库的技术栈相对动态链接库要简单。首先我们需要生成一批目标文件:
gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc -c test3.c -o test3.o
然后利用ar对它们进行打包:
ar src libtest.a test1.o test2.o test3.o
这将生成一个名为libtest.a的静态链接库。ar的命令格式是"ar 静态库文件名 目标文件列表"。 src参数的含义是:
- s:创建目标文件索引,这再创建较大的库时能提高速度
- r:替换库中已有的目标文件,或加入新的目标文件
- c:创建一个库,不管库是否存在,都将创建它
创建动态链接库
一种选择,从源文件生成动态链接库:
gcc -fPIC -shared test.c -o libtest.so
另一种选择,从目标文件生成动态链接库:
gcc -fPIC -c test.c -o test.o
gcc -shared test.o -o libtest.so
链接到动态库的编译:
gcc main.c libtest.so -o app.out
直接执行app.out将触发链接失败,我们有这三种方式将链接器引导至我们的动态链接库:
- 将动态库保存在标准目录下,比如/usr/lib
- 把动态库所在的路径添加到环境变量LD_LIBRARY_PATH中,在shell中输入命令"export LD_LIBRARY_PATH=libraryDIR:$LD_LIBRARY_PATH"或
- 把动态库所在的路径libraryDir添加到/etc/ld.so.conf中然后执行ldconfig或者以动态 库所在路径libraryDir为参数执行ldconfig
- 修改~/.bashrc这个配置文件,对本用户有效。该配置文件将在bash启动时被运行
需要注意的是,上面第二种方式会再重启终端后失效。另外我做了一点实验,这三条命令都可以短暂的让动态库的路径生效:
export LD_LIBRARY_PATH=libpath:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:libpath export LD_LIBRARY_PATH=libpath 它们都是可行的。
此上即通过gcc创建动/静态链接库的基本流程,和动态库链接路径的正确引导方式。
|