GCC 使用库文件名进行链接
使用 GCC 进行 C/C++ 代码编译时,如果代码中使用到了库函数,需要使用 -l 选项指定该库函数所在的库。如:-lm、-lrt、-lpthread等。这种方式使用的是库的缩写。一个库的文件名如果是:libxxx.so 或 libxxx.a,则可以使用 -lxxx 进行链接。这种规则很常见,但是缺点也很明显。假设在一台 Linux 机器上,同时具有 libxxx.so 和 libxxx.a,GCC 会优先链接 libxxx.so。虽然,GCC 也提供了 -static 选项可以强制链接静态库。但是,这时候新的问题出现了,假设有两个库 x 和 y,他们都具有静态库和动态库两个版本。假设我想要链接 libx.so 和 liby.a,使用 -static 选项无法满足这个要求。我需要更加精细的控制,最好是直接根据文件名直接指定链接哪个版本的库文件,就没有任何歧义。
GCC 文档的关于 -l 选项的描述没有告诉我如何直接使用一个库文件名。于是翻看 ld 的文档。在关于 -l 选项的描述中,有这样一段话:
If namespec is of the form ‘:filename’, ld will search the library path for a file called filename, otherwise it will search the library path for a file called ‘libnamespec.a’.
也就是说可以使用 -l:filename 的形式直接指定库文件名。这个只是 ld 的选项,GCC 能不能直接使用还需要验证。设计三个 .cpp 文件,分为 x.cpp y.cpp 和 main.cpp。
// x.cpp
#include <iostream>
void print_x()
{
std::cout << "x" << std::endl;
}
// y.cpp
#include <iostream>
void print_y()
{
std::cout << "y" << std::endl;
}
// main.cpp
void print_x();
void print_y();
int main()
{
print_x();
print_y();
}
使用如下 Makefile 进行编译。x.cpp 编译成 libx.so 和 libx.a,y.cpp 编译成 liby.so 和 liby.a。main.cpp 与 libx.so 和 liby.a 编译连接成 main.out。
all : main
x :
gcc -o libx.so -shared -fPIC x.cpp
gcc -o x.o -c x.cpp
ar crs libx.a x.o
y :
gcc -o liby.so -shared -fPIC y.cpp
gcc -o y.o -c y.cpp
ar crs liby.a y.o
clean :
rm -f *.out *.o *.so *.a
main : x y
gcc -o main.out main.cpp -Wl,-rpath=./ -lstdc++ -L. -l:libx.so -l:liby.a
能直接通过编译,使用 ldd main.out 查看一下动态库依赖:
linux-vdso.so.1 (0x00007ffe71ace000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f1bdea54000)
libx.so => ./libx.so (0x00007f1bdea4f000)
libc.so.6 => /lib64/libc.so.6 (0x00007f1bde845000)
libm.so.6 => /lib64/libm.so.6 (0x00007f1bde769000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1bdec7b000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f1bde74e000)
可以看到 libx.so 被动态链接,而 liby.a 被静态链接,没有显示。执行 main.out,输出结果也符合预期。
x
y
由此可见,-l:filename 能直接用于 GCC。这种方法除了控制链接的库是静态的还是动态的之外,还能用于控制库的版本号。例如 libx.so 同时存在两个版本 libx.so.1 和 libx.so.2 ,可以使用 -l:libx.so.1 指定版本号为 1 的库。
GCC 使用库文件名进行链接的更多相关文章
- 有关 GCC 及 JNA 涉及动态库/共享库时处理库文件名的问题
动态库尤其是共享库在 Linux 环境下普遍存在库文件名包含版本号的情况,比如 Linux 环境下经常会发现一个共享库的真实文件名是 libfoo.so.1.1.0,而同时会有多个指向该真实库文件的软 ...
- gcc -l:手动添加链接库
链接器把多个二进制的目标文件(object file)链接成一个单独的可执行文件.在链接过程中,它必须把符号(变量名.函数名等一些列标识符)用对应的数据的内存地址(变量地址.函数地址等)替代,以完成程 ...
- mingw qt(可以去掉mingwm10.dll、libgcc_s_dw2-1.dll、libstdc++-6.dll的依赖,mingw默认都是动态链接gcc的库而TDM是静态链接gcc库,tdm版本更好用。用aspack压缩没有问题。qt本身不使用异常处理)good
原文地址:mingw qt作者:孙1东 不使用Qt SDK,使用mingw编译qt源代码所遇问题及解决方法: configure -fast -release -no-exceptions -no-r ...
- GCC 静态库和动态库
转自GCC 静态库和动态库 //hello.c #include void print_hello() { printf("HelloWorld "); } //main.c #i ...
- gcc与g++的编译链接的示例详解
一.编译方式的示例详解 1. 编译C代码 代码如下:main.c /*! ************************************************************** ...
- Linux GCC编译库
本文主要解决以下几个问题 1).为什么要使用库? 2).库的分类 3).创建自己的库 为什么要使用库? 或许大家对自己初学 Linux时的情形仍记忆尤新吧.如果没有一个能较好的解决依赖关系的包管理器, ...
- C/C++学习笔记-gcc动态库及静态库
gcc工作流程 1.预处理 gcc -E 2.编译 gcc -S 3.汇编 gcc -c 4.链接 没参数制作静态库: 1.命名规则:libMyName.a2.制作步骤: ①.生成.o gcc -c ...
- Linux GCC lib库相互引用,互相依赖(交叉引用)链接解决办法
Linux GCC中,如果lib a依赖b,b又依赖a,链接的时候无论a放在前,还是b放在前,都会提示unrefrence. 解决办法就是: 链接的时候a链接两次,即: -la -lb -la
- GCC的编译过程和链接
GCC编译过程 一个C/C++文件要经过预处理(preprocessing).编译(compilation).汇编(assembly).和连接(linking)才能变成可执行文件. gcc的常用选项 ...
随机推荐
- Servlet初级学习加入数据库操作(二)
源代码地址:https://url56.ctfile.com/f/34653256-527822631-2e255a(访问密码:7567) 将页面中的数据逐步替换为数据库管理 准备一个连接数据库的类 ...
- Standalone集群搭建和Spark应用监控
注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6815920501530034696/ 承接上一篇文档<Spark词频前十的统计练习> Spark on ...
- vmware快速扩容虚拟磁盘
在使用vmware进行虚拟化的时候,会遇到虚拟磁盘不够用的情况,以前的办法都是使用lvm进行管理扩容,目前在linux上可以实现快速扩容了,具体方法如下: 该方法参考阿里云在线扩容文档:文档地址 其中 ...
- 我选择了MySQL和SpringData JPA
我是3y,一年CRUD经验用十年的markdown程序员常年被誉为优质八股文选手 今天想跟大家聊聊数据库层面上的事,austin项目继续更新(注:今天聊的数据库都特指关系型数据库) 01.数据库选择 ...
- Java中生成一个唯一值的方式
现总结几种生成一个唯一值的方式 第一种:采用nanoTime() // 理论上存在重复的可能,可以在后面再加上一个随机字符串 Random r = new Random(); for (int i = ...
- 触发器中获取sql
CREATE trigger 触发器名 on 表名 for update,delete as set nocount on create table #t(EvebtType varchar(60), ...
- 【刷题-LeetCode】123 Best Time to Buy and Sell Stock III
Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of ...
- LINUX系统机器人
简介 在2016年,国内的软硬件尚不能有效支撑我们制造智能机器人,我们无法有效在Linux进行语音唤醒,只能使用斯坦福大学狮身人面像语音开源项目来进行英文识别我们对RIMA的呼唤,抗干扰性为0,意味着 ...
- golang中的pair
package main import "fmt" type Reader interface { ReadBook() } type Writer interface { Wri ...
- Servlet-请求转发
Servlet-请求转发 请求转发:服务器收到请求后,从一个资源跳转到另一个资源的操作叫请求转发 请求转发特点: 1,浏览器地址栏没有变化 2,他们是一次请求 3,他们共享Request域中的数据 4 ...