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的常用选项 ...
随机推荐
- linux VI命令快捷键
ctrl+f 下一页 ctrl+b 上一页 ctrl+u 上半页 ctrl+d 下半页 数字+空格键 根据当前光标移动多少个字母 0键 光标移动到第一个字母,是当前行的 $键 光标移动到最后一个字母 ...
- 帮你克服web字体选择焦虑症
1.背景 前端时间产品经理问我,移动端web默认字体有哪些,哪些字体不侵权?我当时感觉这方面的知识很匮乏,只能回答出微软雅黑和苹方简体,平常写代码时,没怎么留意过font-family设置的字体属性, ...
- 移动Web开发实践——解决position:fixed自适应BUG
在移动web中使用position:fixed,会踩到很多坑,在我之前的一篇文章<移动端web页面使用position:fixed问题总结>中已经总结了很多bug,但是在后续的开发中有关f ...
- 论文翻译:2020_FLGCNN: A novel fully convolutional neural network for end-to-end monaural speech enhancement with utterance-based objective functions
论文地址:FLGCNN:一种新颖的全卷积神经网络,用于基于话语的目标函数的端到端单耳语音增强 论文代码:https://github.com/LXP-Never/FLGCCRN(非官方复现) 引用格式 ...
- vue3知识点的自我总结
1. 我们对ref的错误理解 ref 经常去监听基本数据类型. 同时也可以去监听[数组][对象]都是可以的. ref是深度的监听.并不是大家说的那样不能去监听复杂的数据类型. 只是根据我们推荐ref去 ...
- 你管这叫代理模式(Proxy Pattern)
代理模式 代理模式即给一个真实类提供一个代理类,该代理类代替真实类完成其功能,一般还可在代理类上添加一些真实类不具有的附加功能,通俗来讲代理模式就是我们生活中常见的中介,代理模式又可分为静态代理和 ...
- 【刷题-LeetCode】215. Kth Largest Element in an Array
Kth Largest Element in an Array Find the kth largest element in an unsorted array. Note that it is t ...
- C++模板之成员模板和模板构造函数
namespace myspace6 { template<typename T1> class TC { public: template<typename T2> TC(T ...
- Ubuntu SVN 搭建
SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS.互联网上很多版本控制服务已从CVS迁移到Subversion ...
- backup archivelog all not backed up
backup archivelog all not backed up;这条命令可以用来备份没有备份过的归档日志,同时不会备份已经备份过的归档日志.下面是具体用法.第一次备份归档日志 RMAN> ...