一般在工作中,或者使用中,对于gcc的一些了解,很多都是很熟悉,但是具体一条条列出来,发现可以对gcc的一般使用会有更清晰的了解。对于初学者或者经常使用vs这类IDE的同学,可以通过这个总结对gcc使用有个直观的入门和了解。
旋风式入门
- gcc工作流程
- 预处理 -E
- 宏替换
- 头文件展开
- 注释去掉
- xxx.c->xxx.i (还是c文件)
- 编译 -S (编译最耗时间)
- xxx.i -> xxx.s
- 汇编文件
- 汇编 -c
- xxx.s->xxx.o
- 二进制文件
- 链接
- xxx.o -> xxx(可执行权限)
- 预处理 -E
gcc在整个过程中,自己做的事情就是编译,其它几步是调用其它程序完成的,预处理调用预处理器cpp,汇编调用汇编器as,链接时调用链接器ld。
gcc常用参数
- -v / –version
- -I:编译时指定头文件的路径
- -L:指定静态库的文件所在的路径
- -l:指定静态库的名字
例:静态库文件名叫libtest.a:
gcc main.c -I ./include -L ./lib -ltest -o myapp
- -c:将汇编文件生成二进制文件,得到一个.o文件
- -o: 指定生成文件的名字
- -g:gdb调试的时候需要加
- -D:指定一个宏:
gcc sum.c -D DEBUG -o app
- -Wall:显示警告信息,能改就改掉,可能就是个错误
- -On:
- 优化代码,n是级别:1,2,3 最高级别就是3
制作静态库和动态库
制作静态库
命名规则: libMyName.a
制作步骤:
生成.o
gcc -c *.c- 打包(将所有的.o文件)
ar rcs 静态库的名字 *.o
- 打包(将所有的.o文件)
ar rcs libmytest.a a.o b.o c.o
(就是一个打包.o文件的过程)ar 工具不包含在gcc中
r –> 将文件插入静态库中
c –> 创建静态库,不管库是否存在
s –> 写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。
查看库中的符号(函数、全局变量等): nm libmytest.a
使用: main.c -L -l
gcc main.c (库) -LlibPath -llibname -o app -Iinclude
注:有时静态库也需要加-fPIC生成位置无关的代码
- 这取决于你对静态库有什么用处。如果你只想把它链接到程序中,它不需要PIC代码(libtool调用一个便利库,因为你几乎可以没有它,它只是帮助你的编译过程达到合理的大小)。否则,如果你打算将共享库与它链接,则需要在静态库中使用PIC代码。
制作动态库
动态库后缀: .so – libmyname.so
- 制作步骤:
- 生成与位置无关的代码(.o)
gcc -fPIC -c *.c -Iinclude- 将.o打包生成.so文件
gcc -shared *.o -o libmytest.so
- 将.o打包生成.so文件
- 生成与位置无关的代码(.o)
- 使用 main.c lib include
gcc main.c -Llib -lmytest -Iinlude -o app
应用程序不能执行, 动态链接器连接不到自己制作的库
- 临时设置的方法:
export LD_LIARARY_PATH=./lib - 永久设置的方法:
- 找到动态链接库的配置文件: /etc/ld.so.conf
- 在该文件中添加动态库的目录(绝对路径)
- 更新: sudo ldconfig -v
- 在该文件中添加动态库的目录(绝对路径)
- 找到动态链接库的配置文件: /etc/ld.so.conf
- 制作步骤: