gcc/g++链接时对库的顺序要求

-LdirAdd directory dir to the list of directories to be searched for -l. -llibrary
-l librarySearch the library named library when linking. (The secondalternative with the library as a separate argument is only for POSIXcompliance and is not recommended.)It makes a difference where in the command you write this option;the linker searches and processes libraries and object files inthe order they are specified. Thus, `foo.o -lz bar.o' searcheslibrary `z' after file foo.o but before bar.o. If bar.o refers tofunctions in `z', those functions may not be loaded.The linker searches a standard list of directories for thelibrary, which is actually a file named liblibrary.a. The linkerthen uses this file as if it had been specified precisely by name.The directories searched include several standard systemdirectories plus any that you specify with -L.Normally the files found this way are library files—archive fileswhose members are object files. The linker handles an archive fileby scanning through it for members which define symbols that haveso far been referenced but not defined. But if the file that isfound is an ordinary object file, it is linked in the usualfashion. The only difference between using an -l option andspecifying a file name is that -l surrounds library with `lib' and`.a' and searches several directories.    以上来源于gcc手册

对于library的查找

查找需要连接的符号名是从前向后找,根据-L指定的路径顺序查找;不同 目录下的同名的库,只取第一个(从左向右),后面同名库被忽略;

对于符号的查找

从左向右查找,如果是主程序块和静态库,不能定位地址就报错: ‘undefined reference to: xxx’如果是链接成动态库,则假设该符号在load 的

时候地址重定位。如果找不到对应的动态库,则会在load的时候报:“undefined symbol: xxx“这样的错误。

–as-needed对链接动态库的影响

gcc-4.6默认开启ld的–as-needed选项。

--as-needed
--no-as-neededThis option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-neededoption.  Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line,regardless of whether the library is actually needed or not.  --as-needed causes a DT_NEEDED tag to only be emitted fora library that satisfies an undefined symbol reference from a regular object file or, if the library is not found inthe DT_NEEDED lists of other libraries linked up to that point, an undefined symbol reference from another dynamiclibrary.  --no-as-needed restores the default behaviour.--add-needed
--no-add-neededThese two options have been deprecated because of the similarity of their names to the --as-needed and --no-as-neededoptions.  They have been replaced by --copy-dt-needed-entries and --no-copy-dt-needed-entries.--copy-dt-needed-entries
--no-copy-dt-needed-entriesThis option affects the treatment of dynamic libraries referred to by DT_NEEDED tags inside ELF dynamic librariesmentioned on the command line.  Normally the linker won't add a DT_NEEDED tag to the output binary for each librarymentioned in a DT_NEEDED tag in an input dynamic library.  With --copy-dt-needed-entries specified on the command linehowever any dynamic libraries that follow it will have their DT_NEEDED entries added.  The default behaviour can berestored with --no-copy-dt-needed-entries.This option also has an effect on the resolution of symbols in dynamic libraries.  With --copy-dt-needed-entriesdynamic libraries mentioned on the command line will be recursively searched, following their DT_NEEDED tags to otherlibraries, in order to resolve symbols required by the output binary.  With the default setting however the searchingof dynamic libraries that follow it will stop with the dynamic library itself.  No DT_NEEDED links will be traversed toresolve symbols.--以上来源于man手册

--add-needed                Set DT_NEEDED tags for DT_NEEDED entries in   following dynamic libs
--no-add-needed             Do not set DT_NEEDED tags for DT_NEEDED entries   in following dynamic libs
--as-needed                 Only set DT_NEEDED for following dynamic libs if used
--no-as-needed              Always set DT_NEEDED for following dynamic libs

as-needed,意思大概是:只给用到的动态库设置DT_NEEDED。
例如:

g++ -shared a.o -ltest1 -lxxx -lrt -o libtest2.so

当链接生成libtest2.so的时候,如果libtest2.so里面用到了libtest1.so,但是没有用到libxxx.so。
当开启–as-needed选项的时候,就不会链接libxxx.so文件
–as-needed就是忽略链接时没有用到的动态库,只将用到的动态库set NEEDED。

常见错误

1.链接主程序模块或者是静态库的时的‘undefined reference to: xxx’

g++ -Wl,--as-needed -ltest1 -lc -lm -ldl -lpthread -L/home/ocaml/lib/ -lrt -o app main.o

假设main.o依赖libtest1.so中的东西。因为gcc对库的顺序要求(gcc编译时,由左向右)和–as-needed选项的开启(因为libtest1.so在main.o的左边,

所以gcc认为没有使用到它,–as-needed将其忽略),ld忽略libtest1.so,定位main.o的符号的时候当然会找不到符号的定义。

所以会出现‘undefined reference to’这个错误!

正确写法是:是:

g++ -Wl,--as-needed main.o -ltest1 -lc -lm -ldl -lpthread   -L/home/ocaml/lib/  -lrt -o app

2.编译动态库(shared library)的时候会导致一个比较隐晦的错误

编译出来的动态库的时候没有问题,但是加载的时候有“undefined symbol: xxx”这样的错误。假如像这也链接PyGalaxy.so

g++ -shared -Wl,--as-needed -lGalaxyParser -lc -lm -ldl -lpthread -L/home/ocaml/lib/ -lrt -o PyGalaxy.so PyGalaxy.o

load PyGalaxy.so的时候会有上面的运行时错误!

简单分析原因:因为libGalaxyParser.so在mutex.o的左边,所以gcc认为没 有用到它,–as-needed将其忽略。但是前面说的动态库符号解析的特点导 致ld认为某些符号是加载的时候才去地址重定位的。但是 libGalaxyParser.so已经被忽略了。所以就算你写上了依赖的库,load的时 候也会找不到符号。但是为什么没有-Wl–as-needed的时候是正确的呢?没 有的话,ld会set NEEDED libGalaxyParser.so(用前面提到的查看动态库 依赖关系的办法可以验证)。load的时候还是可以找到符号的,所以正确。

正确的链接方式是:

g++ -shared -Wl,--as-needed PyGalaxy.o -lGalaxyParser -lc -lm -ldl -lpthread -L/home/ocaml/lib/ -lrt -o PyGalaxy.so

解决方案

在项目开发过层中尽量让lib是垂直关系,避免循环依赖;越是底层的库,越是往后面写!
例如:
g++ ... obj($?) -l(上层逻辑lib) -l(中间封装lib) -l(基础lib) -l(系统lib) -o $@
这样写可以避免很多问题,这个是在搭建项目的构建环境的过程中需要考虑清楚地,在编译和链接上浪费太多的生命不值得!

转载于:https://www.cnblogs.com/zhanggaofeng/p/9255668.html

Linux gcc/g++链接编译顺序详解相关推荐

  1. linux编译安装含义,linux源码包编译安装详解

    linux下安装软件包有两种方法:源文件编译安装(source)和 rpm 安装. 1.源文件包安装的通用方法. 一般安装源代码的程序你得要看它的README,一般在它的目录下都有的. 01.配置: ...

  2. gcc/g++等编译器 编译原理: 预处理,编译,汇编,链接各步骤详解

    例子:由多个源文件组成的C程序,经过编辑.预处理.编译.链接等阶段才能生成最终的可执行程序.此过程中,在__c__阶段可以发现被调用的函数未定义. A. 编辑和预处理 B. 预处理 C. 编译 D. ...

  3. gcc/g++链接时.o文件及库的顺序问题

    折腾gcc/g++链接时.o文件及库的顺序问题 链接静态库的顺序问题 GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结 交叉编译静态库的链接顺序 问题: 1.当lib1. ...

  4. gcc/g++ 链接库的编译与链接

          程序编译一般需要经预处理.编译.汇编和链接几个步骤.在实际应用中,有些公共代码需要反复使用,就把这些代码编译成为"库"文件.在链接步骤中,连接器将从库文件取得所需的代码 ...

  5. 【转】gcc/g++ 链接库的编译与链接

    转自:gcc/g++ 链接库的编译与链接_Surge-CSDN博客_g++ 链接 gcc/g++ 链接库的编译与链接 surgewong@gmail.com Surge_surgewong_CSDN博 ...

  6. 非常好的Linux编译内核详解 - -

    转载: http://blog.chinaunix.net/uid-263488-id-2138150.html 非常好的Linux编译内核详解 - - 一.内核简介  内核,是一个操作系统的核心.它 ...

  7. Linux卸载安装bind,Bind编译安装详解

    Bind编译安装详解 Bind是一款开放源码的DNS服务器软件,由美国加州大学Berkeley分校开发和维护的,全名为Berkeley Internet Name Domain它是目前世界上使用最为广 ...

  8. linux编译安装jpeg,Linux下jpeglib库的安装详解

    Linux下jpeglib库的安装详解 首先要下载所需的库压缩包:jpegsrc.v6b.tar.gz或 jpegsrc.v8b.tar.gz 然后将下载的压缩包随便放在和解压到你喜欢的地方. # t ...

  9. Linux系统常用命令及其使用详解大全

    Linux系统常用命令及其使用详解大全 整理了linux常用的命令,最长常用的也就几十个,cd,ls ,vi等等,有些容易忘记,经常拿出来看看. 其他的可以推荐一个网站,https://www.lin ...

最新文章

  1. 五. python的日历模块
  2. 2018牛客暑假多校三 E(KMP运用)
  3. mysql 调试分析利器_使用systemtap调试工具分析MySQL的性能
  4. wallfall瀑布流的jq实现
  5. Nginx代理概述及环境准备
  6. UNIX(多线程):26---悲观锁和乐观锁
  7. 一个计算两个日期间隔的算法
  8. mac nginx映射ip和端口_步骤四、nginx反向代理
  9. scala Set入门到熟悉
  10. vue个人学习(三)----组件
  11. Photoshop CS2序列号大全 官方免费密钥
  12. 全国首款网页版(web)真3D商城
  13. mysql类exadata功能_查看Exadata的版本
  14. php中医处方系统简介
  15. MySQL 8.0.17的安装与图形管理软件介绍
  16. android app 图片资源,Android App 瘦身总结 第一章 图片资源的优化处理
  17. php中rand函数怎么用,php rand函数用法是什么
  18. 类与对象的属性与应用
  19. JetBrains全家桶软件
  20. 【Nordic蓝牙模块justwork模式配置】

热门文章

  1. SQL Server代理(4/12):配置数据库邮件
  2. 计算机科学家Erik Meijer眼中的Hacker Way工作方式
  3. learn go anonymous function
  4. SAP MIGO的界面中Document Overview部分,可以不让一些单据在这里显示。
  5. 【java设计模式】迭代子模式
  6. POJ 1861 Network
  7. 如何取消IE“已限制此网页运行可以访问计算机的脚本或ActiveX控件”(小技巧)...
  8. 【拯救赵明】全面防护网络***服务器负载及安全解决方案
  9. 打开terminal后conda出现ERROR REPORT
  10. apt-get update时卡在 waiting for headers(转)