gcc同时使用动态和静态链接

本文详细介绍了GCC编译器中的链接器选项-Wl,-Bstatic和-Wl,-Bdynamic的具体用法,解释了如何在Makefile中混合使用静态库和动态库,并避免链接错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近因为项目的makefile同时使用了静态动态的连接库,所以,就要同事的链接进去

我们知道gcc的-static选项可以使链接器执行静态链接。但简单地使用-static显得有些’暴力’,因为他会把命令行中-static后面的所有-l指明的库都静态链接,更主要的是,有些库可能并没有提供静态库(.a),而只提供了动态库(.so)。这样的话,使用-static就会造成链接错误。

之前的链接选项大致是这样的,

1 CORE_LIBS="$CORE_LIBS -L/usr/lib64/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto"

修改过是这样的,

1 2 CORE_LIBS="$CORE_LIBS -L/usr/lib64/mysql -Wl,-Bstatic -lmysqlclient -Wl,-Bdynamic -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto"

  其中用到的两个选项:-Wl,-Bstatic和-Wl,-Bdynamic。这两个选项是gcc的特殊选项,它会将选项的参数传递给链接器,作为链接器的选项。比如-Wl,-Bstatic告诉链接器使用-Bstatic选项,该选项是告诉链接器,对接下来的-l选项使用静态链接;-Wl,-Bdynamic就是告诉链接器对接下来的-l选项使用动态链接。下面是man gcc对-Wl,option的描述,

-Wl,option Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example, -Wl,-Map,output.map passes -Map output.map to the linker. When using the GNU linker, you can also get the same effect with -Wl,-Map=output.map.

下面是man ld分别对-Bstatic和-Bdynamic的描述,

-Bdynamic -dy -call_shared Link against dynamic libraries. You may use this option multiple times on the command line: it affects library searching for -l options which follow it. -Bstatic -dn -non_shared -static Do not link against shared libraries. You may use this option multiple times on the command line: it affects library searching for -l options which follow it. This option also implies --unresolved-symbols=report-all. This option can be used with -shared. Doing so means that a shared library is being created but that all of the library's external references must be resolved by pulling in entries from static libraries.

  值得注意的是对-static的描述:-static和-shared可以同时存在,这样会创建共享库,但该共享库引用的其他库会静态地链接到该共享库中。




### GCC动态链接库与静态链接库的区别及用法 #### 一、基本概念 动态链接库(Dynamic Link Library, DLL)静态链接库(Static Link Library, SLL)是两种不同的库文件形式。 - **静态链接库**是在编译阶段将目标代码嵌入到最终的可执行文件中的方式,生成的二进制文件独立于外部依赖项[^1]。 - **动态链接库**则是指在程序运行时加载并链接的目标代码,通常以共享对象的形式存在,在 Linux 下扩展名为 `.so`。 #### 二、主要区别 | 特性 | 静态链接库 | 动态链接库 | |---------------------|------------------------------------|------------------------------------| | 文件大小 | 较大 | 较小 | | 运行性能 | 更高 | 略低 | | 更新维护 | 不方便 | 方便 | | 加载时机 | 编译时完成 | 运行时加载 | 动态链接库虽然牺牲了一定的运行效率[^2],但由于其节省内存空间以及便于更新的特点,在现代软件开发中更为常见。 --- #### 三、使用方法对比 ##### (1)静态链接库的创建与使用 以下是创建使用静态链接库的一个简单示例: ###### 创建静态链接库 假设有一个简单的函数 `add.c`: ```c // add.c int add(int a, int b) { return a + b; } ``` 将其编译为目标文件,并打包成静态库: ```bash gcc -c add.c -o add.o ar rcs libadd.a add.o ``` ###### 使用静态链接库 编写主程序 `main.c` 并链接静态库: ```c // main.c #include <stdio.h> extern int add(int a, int b); int main() { printf("%d\n", add(3, 5)); return 0; } ``` 编译命令如下: ```bash gcc main.c -L. -ladd -static -o static_main ``` 这里 `-static` 参数确保只使用静态库进行链接--- ##### (2)动态链接库的创建与使用 下面是创建使用动态链接库的过程: ###### 创建动态链接库 同样基于上述 `add.c` 文件,可以按照以下步骤构建动态库: ```bash gcc -fPIC -shared add.c -o libadd.so ``` 其中 `-fPIC` 表示生成位置无关代码,而 `-shared` 则用于指示生成共享库[^3]。 ###### 使用动态链接库 修改 `main.c` 的编译指令为: ```bash gcc main.c -L. -ladd -o dynamic_main export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./dynamic_main ``` 注意:为了使程序能够找到动态库,需设置环境变量 `LD_LIBRARY_PATH` 或者将动态库复制至标准路径如 `/usr/lib/`[^4]。 --- #### 四、总结 无论是静态还是动态链接库都有各自的适用场景。当追求更高的运行效率或希望减少对外部资源的依赖时可以选择静态链接;而在注重灵活性、节约存储空间的情况下,则更倾向于采用动态链接的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值