使用 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. Spark案例练习-打包提交

    关注公众号:分享电脑学习回复"百度云盘" 可以免费获取所有学习文档的代码(不定期更新)云盘目录说明:tools目录是安装包res 目录是每一个课件对应的代码和资源等doc 目录是一 ...

  2. 51 Nod 1006 最长公共子序列(LCS & DP)

    原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1006 题目分析: 首先先知道LCS问题,这有两种: Long ...

  3. Android函数抽取壳的实现

    0x0 前言 函数抽取壳这个词不知道从哪起源的,但我理解的函数抽取壳是那种将dex文件中的函数代码给nop,然后在运行时再把字节码给填回dex的这么一种壳. 函数抽取前: 函数抽取后: 很早之前就想写 ...

  4. 《剑指offer》面试题47. 礼物的最大价值

    问题描述 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0).你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格.直到到达棋盘的右下角.给定一个棋盘及 ...

  5. 【刷题-LeetCode】240. Search a 2D Matrix II

    Search a 2D Matrix II Write an efficient algorithm that searches for a value in an m x n matrix. Thi ...

  6. golang gin框架中实现"Transfer-Encoding: chunked"方式的分块发送数据到浏览器端

    参考了这篇帖子: https://golangtc.com/t/570b403eb09ecc66b90002d9 golang web如何发送小包的chunked数据 以下是代码: r.GET(&qu ...

  7. 实习之bii--总体感受体验

    在bii实习了一个暑假,感受收获都不少,记录一下. 首先当时面试时其实说的比较多的是sdn,结果来了以后主要在搞DNS,介绍一下所做的工作为何吧.bii名为北京下一代互联网工程中心,由于IPV6的逐渐 ...

  8. golang中的sync

    1. Go语言中可以使用sync.WaitGroup来实现并发任务的同步 package main import ( "fmt" "sync" ) func h ...

  9. 集合框架-工具类-Arrays方法介绍

    1 package cn.itcast.p3.toolclass.arrays.demo; 2 3 import java.util.Arrays; 4 5 public class ArraysDe ...

  10. 集合框架-Map集合-LinkedHashMap及关联源码操作

    1 package cn.itcast.p9.linkedhashmap.demo; 2 3 import java.util.HashMap; 4 import java.util.Iterator ...