.o 就相当于Windows里的obj文件 
.a 是好多个.o合在一起,用于静态连接 
.so 是shared object,用于动态连接的,和dll差不多

.o文件是链接文件,.a是静态库文件,靠.o文件生成,作为一个库为外部程序提供函数,接口。

生成.o文件:
gcc -c test.o test.c

生成.a文件:
ar cqs test.a test.o

o: 编译的目标文件
a: 静态库,其实就是把若干o文件打了个包
so: 动态链接库(共享库)

lo: 使用libtool编译出的目标文件,其实就是在o文件中添加了一些信息
la: 使用libtool编译出的库文件,其实是个文本文件,记录同名动态库和静态库的相关信息

1 libtool的工作原理
libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中;使用libtool的标准方法,可以在不同平台上创建并调用动态库。可以认为libtool是gcc的一个抽象,其包装了gcc(或者其他的编译器),用户无需知道细节,只要告诉libtool需要编译哪些库即可,libtool将处理库的依赖等细节。libtool只与后缀名为lo、la为的libtool文件打交道。

libtool主要的一个作用是在编译大型软件的过程中解决了库的依赖问题;将繁重的库依赖关系的维护工作承担下来,从而释放了程序员的人力资源。libtool提供统一的接口,隐藏了不同平台间库的名称的差异等细节,生成一个抽象的后缀名为la高层库libxx.la(其实是个文本文件),并将该库对其它库的依赖关系,都写在该la的文件中。该文件中的dependency_libs记录该库依赖的所有库(其中有些是以.la文件的形式加入的);libdir则指出了库的安装位置;library_names记录了共享库的名字;old_library记录了静态库的名字。

当编译过程到link阶段的时候,如果有下面的命令:
$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la

libtool会到/usr/lib路径下去寻找liba.la,然后从中读取实际的共享库的名字(library_names中记录了该名字,比如liba.so)和路径(lib_dir中记录了,比如libdir=’/usr/lib’),返回诸如/usr/lib/liba.so的参数给激发出的gcc命令行。

如果liba.so依赖于库/usr/lib/libb.so,则在liba.la中将会有dependency_libs=’-L/usr/lib -lb’或者dependency_libs=’/usr/lib/libb.la’的行,如果是前者,其将直接把“-L/usr/lib –lb”当作参数传给gcc命令行;如果是后者,libtool将从/usr/lib/libb.la中读取实际的libb.so的库名称和路径,然后组合成参数“/usr/lib/libb.so”传递给gcc命令行。

当要生成的文件是诸如libmylib.la的时候,比如:
$libtool --mode=link gcc -o libmylib.la -rpath /usr/lib –L/usr/lib –la

其依赖的库的搜索基本类似,只是在这个时候会根据相应的规则生成相应的共享库和静态库。

注意:libtool在链接的时候只会涉及到后缀名为la的libtool文件;实际的库文件名称和库安装路径以及依赖关系是从该文件中读取的。

2 为何使用 -Wl,–rpath-link -Wl,DIR?
使用libtool解决编译问题看上去没什么问题:库的名称、路径、依赖都得到了很好的解决。但下结论不要那么着急,一个显而易见的问题就是:并不是所有的库都是用libtool编译的。

比如上面那个例子,
$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la

如果liba.so不是使用libtool工具生成的,则libtool此时根本找不到liba.la文件(不存在该文件)。这种情况下,libtool只会把“–L/usr/lib –la”当作参数传递给gcc命令行。

考虑以下情况:要从myprog.o文件编译生成myprog,其依赖于库liba.so(使用libtool生成),liba.so又依赖于libb.so(libb.so的生成不使用libtool),而且由于某种原因,a对b的依赖并没有写入到liba.la中,那么如果用以下命令编译:
$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la

激发出的gcc命令行类似于下面:
gcc –o myprog /usr/lib/liba.so

由于liba.so依赖于libb.so(这种依赖可以用readelf读liba.so的ELF文件看到),而上面的命令行中,并没有出现libb.so,于是,可能会出现问题。

说“可能”,是因为如果在本地编译的情况下,gcc在命令行中找不到一个库(比如上面的liba.so)依赖的其它库(比如libb.so),链接器会按照某种策略到某些路径下面去寻找需要的共享库:

  1. 所有由’-rpath-link’选项指定的搜索路径.
  2. 所有由’-rpath’指定的搜索路径. ‘-rpath’跟’-rpath_link’的不同之处在于,由’-rpath’指定的路径被包含在可执行文件中,并在运行时使用, 而’-rpath-link’选项仅仅在连接时起作用.
  3. 在一个ELF系统中, 如果’-rpath’和’rpath-link’选项没有被使用, 会搜索环境变量’LD_RUN_PATH’的内容.它也只对本地连接器起作用.
  4. 在SunOS上, ‘-rpath’选项不使用, 只搜索所有由’-L’指定的目录.
  5. 对于一个本地连接器,环境变量’LD_LIBRARY_PATH’的内容被搜索.
  6. 对于一个本地ELF连接器,共享库中的DT_RUNPATH'和DT_RPATH’操作符会被需要它的共享库搜索. 如果’DT_RUNPATH’存在了, 那’DT_RPATH’就会被忽略.
  7. 缺省目录, 常规的,如’/lib’和’/usr/lib’.
  8. 对于ELF系统上的本地连接器, 如果文件’/etc/ld.so.conf’存在, 这个文件中有的目录会被搜索.

    从以上可以看出,在使用本地工具链进行本地编译情况下,只要库存在于某个位置,gcc总能通过如上策略找到需要的共享库。但在交叉编译下,上述八种策略,可以使用的仅仅有两个:-rpath-link,-rpath。这两个选项在上述八种策略当中优先级最高,当指定这两个选项时,如果链接需要的共享库找不到,链接器会优先到这两个选项指定的路径下去搜索需要的共享库。通过上面的描述可以看到:-rpath指定的路径将被写到可执行文件中;-rpath-link则不会;我们当然不希望交叉编译情况下使用的路径信息被写进最终的可执行文件,所以我们选择使用选项-rpath-link。

    gcc的选项“-Wl,–rpath-link –Wl,DIR”会把-rpath-link选项及路径信息传递给链接器。回到上面那个例子,如果命令行中没有出现libb.so,但gcc指定了“-Wl,–rpath-link –Wl,DIR”,则链接器找不到libb.so的时候,会首先到后面-rpath-link指定的路径去寻找其依赖的库。此处我们使用的编译命令的示例是使用unicore平台的工具链。
    $ unicore32-linux-gcc –o myprog /usr/lib/liba.so
    -Wl,–rpath-link -Wl,/home/UNITY_float/install/usr/lib

    这样,编译器会首先到“/home/UNITY_float/install/usr/lib”下面去搜索libb.so

    libtool如何把选项“-Wl,–rpath-link –Wl,DIR”传递给gcc?libtool中有一个变量“hardcode_libdir_flag_spec”,该变量本来是传递“-rpath”选项的,但我们可以修改它,添加我们需要的路径,传递给unicore32-linux-gcc。

    “hardcode_libdir_flag_spec”原来的定义如下:
    hardcode_libdir_flag_spec="${wl}–rpath ${wl}$libdir"

    我们修改后的定义如下:
    hardcode_libdir_flag_spec="${wl}—rpath-link ${wl}$libdir
    -Wl,–rpath-link -Wl,/home/UNITY_float/install/usr/lib
    -Wl,–rpath-link -Wl,/home/UNITY_float/install/usr/X11R6/lib "

    这样,当libtool在“–mode=link”的模式下,就会把选项“-Wl,–rpath-link –Wl,DIR”传递给gcc编译器了。

Linux .a文件.o文件.la文件.lo文件和.so文件相关推荐

  1. linux中.la是什么文件,linux下的so、o、lo、a、la文件有什么区别?

    linux下的so.o.lo.a.la文件有什么区别? o: 编译的目标文件 a: 静态库,其实就是把若干o文件打了个包 so: 动态链接库(共享库) lo: 使用libtool编译出的目标文件,其实 ...

  2. Linux下.o,.so,.a,.la文件

    Linux下文件的类型是不依赖于其后缀名的,但一般来讲:     .o,是目标文件,相当于windows中的.obj文件     .so 为共享库,是shared object,用于动态连接的,和dl ...

  3. 2019-8-20 [Linux] 6.Shell的基本操作 查看 改变 列出 阅读开头/结尾 循环查看 阅读工具less 查找文件内容 文本分析工具AWK 文本编辑工具SED文件find 帮助man

    文章目录 6.linuxShell的基本操作 6.1 查看目录和文件 6.1.1 显示当前目录:pwd 6.1.2 改变目录:cd 6.1.3 列出目录内容:ls 1) 查看列表信息 以及详细信息 2 ...

  4. Linux怎么让文件按大小排序,linuxsortlinux系统下,按文件的大小进行排序的命令...

    怎样用sort 命令以 GPA作为关键字排序文件 Linux可以使用ls命令实现这一功能. ls命令是一个非常有用的查看文件与目录的命令,list之意,它的参数非常多. ls命令默认是按照文件名的字母 ...

  5. Linux环境编程:fork系统调用及其陷阱 - 内存复用,文件不复用

    Table of Contents 内存呢?是重复的 CoW(写时复制) 文件在fork上不重复 使用fork创建任务 亲子代号不同 例如:2个使用管道进行通信的进程: 推荐阅读 要在Linux / ...

  6. linux添加py自启动脚本_PyInstaller详解:将.py文件打包成exe文件

    1. 安装 本人系统是:Ubuntu16.04,python3.7. 安装的pyinstaller==3.5, UPX==upx-3.95-amd64_linux.tar.xz.不安装对应版本的pyi ...

  7. linux系统空间不足,lsof看到异常的delete状态的文件。

    linux系统空间不足,lsof看到异常的delete状态的文件. 参考文章: (1)linux系统空间不足,lsof看到异常的delete状态的文件. (2)https://www.cnblogs. ...

  8. Unix/Linux环境C编程入门教程(41) C语言库函数的文件操作详解

     上一篇博客我们讲解了如何使用Linux提供的文件操作函数,本文主要讲解使用C语言提供的文件操作的库函数. 1.函数介绍 fopen(打开文件) 相关函数 open,fclose 表头文件 #in ...

  9. more 目录linux,linux(二)目录结构、文件基本操作cat\more\less、环境变量、文件搜索...

    linux 目录结构及文件基本操作 linux文件结构: FHS(英文:Filesystem Hierarchy Standard 中文:文件系统层次结构标准),多数 Linux 版本采用这种文件组织 ...

  10. xshell下载mysql到本地文件_在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹)-Go语言中文社区...

    在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹) 1 列出所有需要copy的sh文件 -bash-4.1$ ll /mysqllog/osw/*.sh ...

最新文章

  1. 探测服务器操作系统,探测服务器操作系统工具
  2. ajax传递数组:属性traditional设置
  3. vi中跳到文件的第一行和最后一行
  4. win10系统下载文件、解压缩文件时文件名称乱码的问题解决方法
  5. 第十八篇_Class文件
  6. android音频切换到蓝牙耳机,在Android上将音频路由到蓝牙耳机(非A2DP)
  7. VBA多工作簿中多工作表分类汇总
  8. java.lang.IllegalStateException: Fragment already added
  9. Python:启程 数据分析-牛客网在线编程-中级函数12-23
  10. CPU个数、CPU物理核数、CPU逻辑核数、vCPU数之间的区别
  11. 小程序授权头像昵称改为头像昵称填写能力详解
  12. wd移动硬盘插电脑没反应_西部数据移动硬盘插电脑上不显示?
  13. DBI、DPI、DSI LCD 接口简介
  14. 海森矩阵和雅克比矩阵的区别
  15. 视频教程-JSON基础入门实战讲解-JavaScript
  16. 腾讯家低调开发的良心工具?目前无任何付费机制还挺好用~
  17. 心理学人后来怎么样了?|心理学人聊心理学
  18. 使用canvas画布实现高斯模糊效果
  19. 利用python将文件夹中子文件夹中的图片数目大于小于指定的数目分类
  20. 【云原生之Docker实战】使用Docker部署LibrePhotos照片管理系统

热门文章

  1. c语言递归求最大公约数
  2. PHP使用CURL抓取网页
  3. 半角空格 全角空格 不间断空格 通过过滤器解决
  4. 网络安全之如何保护手机支付安全
  5. Bug处理之数据库导入Warning: 1366, Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...' for column
  6. 实测 (四)NVIDIA Xavier NX + D435i / 奥比中光Astrapro 相机+ ORB-SLAM 2 + 3 稠密回环建图
  7. GBase 8a trace 日志
  8. hadoop-fs.defaultFS
  9. 排他平方数(使用C语言基础)
  10. java基础-简单的抽奖程序