a.gcc工作流程
预处理: 宏定义替换, 头文件展开, 去掉注释, 条件编译不会进行语法检查, C文件->C文件 xxx.i 命令: gcc -E
编译: 语法检查, 生成汇编文件 xxx.s 命令: gcc -S (用时最长)
汇编: 将汇编文件生成二进制文件 xxx.o 命令: gcc -c
链接: 将二进制文件插入启动代码生成可执行文件 命令: gcc 默认生成a.out
b.gcc常用参数
-v/-version 查看版本号
-l 编译的时候指定头文件目录. include "head.h" 默认是在当前目录中找, 如果头文件不在当前目录,则需要-l来指定头文件的目录
-E 预处理, 生成xxx.i; -S 编译, 生成xxx.s; -c 汇编, 生成xxx.o; -o 指定生成的文件名字
-g 生成可执行程序中添加调试信息(有源码, 方便调试, 文件一般比较大)
-D 编译的时候指定宏, 一般用在调试时, 假如宏做命令的参数
-Wall 添加警告信息, 可理解为严格编译, n = 0, 1, 2, 3 一般默认为O1
-On 设置代码的优先级别
c.gcc--动态库静态库 -- 二进制文件
静态库: (不过一般使用在makefile中)
命名规则: libxxx.a
制作步骤:
1:生成对应的.o文件 gcc -c *.c(将所有的.c文件编译成.o文件)
2:将.o打包成静态库 ar rcs libxxx.a *.o
参数r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其 他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置 参数c:创建一个库。不管库是否存在,都将创建 参数s:创建目标文件索引,这在创建较大的库时能加快时间。(补充:如果不需要创建索引,可改成大写S参数;如果。a文件缺少索引,可以使用ranlib命令添加)
3:使用 gcc main.c -l 头文件路径 -L 库的路径 -l 库的名字(xxx)
动态库:
命名规则: libxxx.so
制作步骤:
1: 生成.o文件 gcc -c -fpic(fPIC) *.c
2: 将.o文件打包 gcc -shared *.o -o libxxx.so
3: 使用 gcc main.c -l 头文件路径 -L 库的路径 -l 库的名字(xxx)
此时是无法运行的(ldd 可执行程序(查看链接)), 因为静态库也称之为共享库, 并且是在程序使用时编译进去, 所以编译时会检测有没有包含动态库
如果有的话, 虽然使用时指定了库的名字, 但是还要指定其路径, 此时就需要系统动态载入器(dynamic linker/loader)
对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段 — 环境变量LD_LIBRARY_PATH — /etc/ld.so.cache 文件列表 — /lib/, /usr/lib目录找到库文件后将其载入内存
解决:
1. 拷贝自己制作的共享库到/lib或者/usr/lib
2. 临时设置(环境变量)LD_LIBRARY_PATH命令: LD_LIBRARY_PATH=目录:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径 永久设置,把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,设置到∼/.bashrc或者 /etc/profile文件中, 然后source(.) ~/.bashrc/etc/profile 对所有用户生效, ~/.bashrc 对当前用户有效
3. 将其添加到 /etc/ld.so.cache文件中 编辑/etc/ld.so.conf文件 : sudo vi ld.so.conf加入库文件所在目录的绝对路径 /home/guofu/code.....
运行sudo ldconfig -v ,该命令会重建/etc/ld.so.cache文件其他方法: dlopen/dlsys/dlclose
- 动态库静态库总结:
- 静态库: 在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。 动态库:在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
但是如果对库进行更改, 静态库则需要重新编译, 而动态库则不需要.