使用 GCC 进行 C/C++ 代码编译时,如果代码中使用到了库函数,需要使用 -l 选项指定该库函数所在的库。如:-lm-lrt-lpthread等。这种方式使用的是库的缩写。一个库的文件名如果是:libxxx.solibxxx.a,则可以使用 -lxxx 进行链接。这种规则很常见,但是缺点也很明显。假设在一台 Linux 机器上,同时具有 libxxx.solibxxx.a,GCC 会优先链接 libxxx.so。虽然,GCC 也提供了 -static 选项可以强制链接静态库。但是,这时候新的问题出现了,假设有两个库 xy,他们都具有静态库和动态库两个版本。假设我想要链接 libx.soliby.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.cppmain.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.solibx.ay.cpp 编译成 liby.soliby.amain.cpplibx.soliby.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.1libx.so.2 ,可以使用 -l:libx.so.1 指定版本号为 1 的库。

GCC 使用库文件名进行链接的更多相关文章

  1. 有关 GCC 及 JNA 涉及动态库/共享库时处理库文件名的问题

    动态库尤其是共享库在 Linux 环境下普遍存在库文件名包含版本号的情况,比如 Linux 环境下经常会发现一个共享库的真实文件名是 libfoo.so.1.1.0,而同时会有多个指向该真实库文件的软 ...

  2. gcc -l:手动添加链接库

    链接器把多个二进制的目标文件(object file)链接成一个单独的可执行文件.在链接过程中,它必须把符号(变量名.函数名等一些列标识符)用对应的数据的内存地址(变量地址.函数地址等)替代,以完成程 ...

  3. 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 ...

  4. GCC 静态库和动态库

    转自GCC 静态库和动态库 //hello.c #include void print_hello() { printf("HelloWorld "); } //main.c #i ...

  5. gcc与g++的编译链接的示例详解

    一.编译方式的示例详解 1. 编译C代码 代码如下:main.c /*!  ************************************************************** ...

  6. Linux GCC编译库

    本文主要解决以下几个问题 1).为什么要使用库? 2).库的分类 3).创建自己的库 为什么要使用库? 或许大家对自己初学 Linux时的情形仍记忆尤新吧.如果没有一个能较好的解决依赖关系的包管理器, ...

  7. C/C++学习笔记-gcc动态库及静态库

    gcc工作流程 1.预处理 gcc -E 2.编译 gcc -S 3.汇编 gcc -c 4.链接 没参数制作静态库: 1.命名规则:libMyName.a2.制作步骤: ①.生成.o gcc -c ...

  8. Linux GCC lib库相互引用,互相依赖(交叉引用)链接解决办法

    Linux GCC中,如果lib a依赖b,b又依赖a,链接的时候无论a放在前,还是b放在前,都会提示unrefrence. 解决办法就是: 链接的时候a链接两次,即: -la -lb -la

  9. GCC的编译过程和链接

    GCC编译过程 一个C/C++文件要经过预处理(preprocessing).编译(compilation).汇编(assembly).和连接(linking)才能变成可执行文件. gcc的常用选项 ...

随机推荐

  1. Docker之Docker Machine已弃用

    作为刚开始学习docker的新手,从网上查询文档无疑是最快的学习捷径,但是这次在docker翻车了,困扰了整整三天,特记录一下. 一般我们使用docker for windows安装,一路往下点直至安 ...

  2. Oracle update和select 关联

    Oracle update和select 关联 目录 Oracle update和select 关联 1.介绍 2.解决方法 2.1.需求 2.2.错误演示 2.3.解决方法 1.介绍 本文主要向大家 ...

  3. 【Java】反射

    文章目录 反射 概述 动态语言与非动态语言 动态语言 非动态语言 Java反射机制提供的功能 反射相关的主要API 关于java.lang.Class类的理解 类的加载过程 获取Class的实例的方式 ...

  4. day 21 C语

    (1).有以下程序: 执行后的输出结果是[A] (A).256,1 (B).1,256 (C).255,1 (D).256,0 (2).以下选项中与(!a==0)的逻辑值不等价的表达式是[B] (A) ...

  5. 【机器学习】VAE

    机器学习算法-VAE 目录 机器学习算法-VAE 1. VAE模型推导 1.1 算法引入 1.2 模型推导 1.3 损失函数 1.4 重参数技巧 2. 实现 2.1 模型定义 2.2 实验 1. VA ...

  6. thanos receiver压测结果分享

    压测环境 k8s容器环境 单核 32GB内存 thanos版本:v0.22.0 客户端发送32271959条数据,100个并发:同样的数据文件发送了两遍,取第二遍的性能数据 在thanos recei ...

  7. AXAJ基础知识学习

    AXAJ基础知识学习 博客首页 Ajax简介 ajxa全称是Asynchronous Javascript And XML ,就是异步的JS 和XML 通过Ajax可以再浏览器中向服务器发送异步请求, ...

  8. gin中的文件上传

    1. 单文件上传 package main import ( "fmt" "github.com/gin-gonic/gin" "log" ...

  9. vivo数据库与存储平台的建设和探索

    本文根据Xiao Bo老师在"2021 vivo开发者大会"现场演讲内容整理而成.公众号回复[2021VDC]获取互联网技术分会场议题相关资料. 一.数据库与存储平台建设背景 以史 ...

  10. python18day

    今日内容 ''' 用代码模拟博客园系统. 项目分析: 一.首先程序启动,页面显示下面内容供用户选择: 1.请登录 2.请注册 3.进入文章页面 4.进入评论页面 5.进入日记页面 6.进入收藏页面 7 ...