gcc 常见用法

gcc 与 g++ 分别是 gnu 的 c & c++ 编译器 gcc/g++ 在执行编译工作的时候,总共需要4步:

1、预处理,生成 .i 的文件 - 预处理器

2、将预处理后的文件转换成汇编语言 - 编译器egcs

3、将汇编语言汇编成目标代码(机器语言) -汇编器as

4、链接目标代码生成可执行程序 - 链接器ld

常见编译选项:

-E        预处理,这个不生成文件,可以重定向到文件
-S        预处理和编译生成 .s 文件
-c        预处理、编译、汇编成目标代码(机器语言)

-o        指定目标文件的名称

#gcc 在编译时会有 .s 汇编文件 .o 目录文件等,实际上gcc将中间文件放在了 /tmp 目录下
#并且在编译完成后会将其删除,加上此选项,可以利用管道技术来代替临时文件,从而提高编译效率(在非 gnu 汇编工具可能会出现问题)
-pipe

-N    数据段编译进代码段

-I    指定头文件搜索路径
-L    指定链接库搜索路径
-l    指定链接时的库

# -O0 表示没有优化 -O1 为默认值,-O3 优化级别最高
-O0 -O1 -O2 -O3

# 调试信息和优化在编译器工作而不是链接期
-g    产生调试信息
-g3   包含宏定义

-static     禁止使用动态库链接
-shared     尽量使用动态库

-fPIC       生成位置无关代码

#只支持 ANSI 标准的 C 语法
#这一选项将禁止 GNU C 的某些特色,例如 asm 或 typeof 关键词
-ansi

-w      不生成警告信息
-Wall   生成所有警告信息

-Wa,option    传递 option 给汇编程序,多个选项用逗号隔开
-Wl,option    传递 option 给链接程序,多个选项用逗号隔开

-Wl,-rpath=/usr/local/lib    指定运行时库搜索路径,多个路径用 : 隔开
-Wl,-rpath-link=/xxx         指定链接时库搜索路径

-s    移除符号表和重定位信息

-Wl,-e,entry_port    指定 entry_port 为程序入口点

-fPIC广泛使用于共享库,使得同一个库中的代码能够被加载到不同进程的地址空间中正常的运行,都是基于下一条指令地址(%rip)的偏移来计算跳转

位置无关相关详细选项可以参考:位置无关代码生成(重定位)选项和说明 GCC

编译成动态库

#编译位置无关代码并链接成动态库
gcc -c d1.c -o d1.o -fPIC -Iinc
gcc -c d2.c -o d2.o -fPIC -Iinc

#如果依赖其他动态库(/usr/local/lib/libxxx.so)且不在默认搜索路径
#gcc d1.o d2.o -shared -o libdl.so -L/usr/local/lib -lxxx
#gcc gcc d1.o d2.o -shared -o libdl.so /usr/local/lib/libxxx.so
gcc d1.o d2.o -shared -o libdl.so

编译成静态库

#编译
gcc -c d1.c -o d1.o -Iinc
gcc -c d2.c -o d2.o -Iinc

#打包成静态库
ar -r libdl.a d1.o d2.o


相关环境变量

LD_PRELOAD - 优先使用的动态库

LIBRARY_PATH - 链接时库搜索路径

LD_LIBRARY_PATH - 运行时库搜索路径


动态库搜索路径

1.使用 LD_LIBRARY_PATH 指定搜索路径,export LD_LIBRARY_PATH=xxxx

2.编译时使用 -Wl,-rpath=xx指定动态库的搜索路径

3.修改 /etc/ld.so.conf,添加动态库搜索路径

4.复制动态库到系统默认的路径下,如 /lib64

动态库搜索路径优先级

1.编译时指定动态库搜索路径

2.环境变量 LD_LIBRARY_PATH 中的路径

3.配置文件 /etc/ld/so.conf 中的路径

4.系统默认的路径比如 /lib64 等


LD_PRELOAD例子 

假设puts.c如下

int puts(char *str)
{
   //somecode
    return 1;
}
#编译成动态库
gcc puts.c -fPIC -shared -nostdlib -o puts.so
#设置环境变量
export LD_PRELOAD="/xxxx/puts.so"

此时,我们运行的程序里只要动态链接的调用puts的,都会调用上面的函数

但是对于已经在运行的程序,没有用

上一篇: cmake 使用例子
下一篇: linux逻辑卷管理员命令-lvm
作者邮箱: 203328517@qq.com