转:http://fanwei51880.blog.163.com/blog/static/3240674020111145285375/

总结如下:
1)当你在编译生成静态库的时候, 只需要相应的依赖库库的头文件即可. 只有在你想生成so,或可执行文件 时, 才需要lib库.
   对于你没有用到的lib, 但是不包含又编译失败, 那么只包含其头文件即可.
2)如果你同时使用了多个库,而库之间又相互依赖,那么在链接是,把最底层的依赖库放在最右侧.否则可能会链接失败
3)如果我已经把最底层的库放在最后边了,还是链接失败怎么办?
请检查是否依赖了同名的其他的库. 自己查看链接库的路径

对1)的说明
如果你不用该so, 那么你就不要将他的lib放在你的makefile里面! 否则运行时会依赖该so的.
案例:

我的cgi, cp到正式环境, 居然开始依赖 mysql的so, 奇怪, 我的项目中并无用到mysql. 然后,makefile中去掉mysql相关的 头文件, 以及lib, 却发现 没有mysql的头文件还编译不过去, 因为我用的另一个库tlib用到了mysql, fuck, 怎么办?

答案: 只把mysql的头文件 路径等加到 makefile里面, 这样gcc有了头文件至少可以编译过去. 然后, 在连接的时候, 由于你的代码并没有真正用到mysql, 所以不会去连接mysql相关的东东. 所以, 直接链接通过.

分析: 虽然tlib用到了mysql, 但是由于tlib是一个非常庞大的静态库, 其里面依赖的内容非常多, 而我只用到了tlib里面的一小部分功能(且不含mysql), 所以, 我只需把mysql头文件加上即可. 链接时时不会真正用到mysql的没有lib. 除非我用到tlib里面的相关mysql接口.

如果你想生成静态库:
linux下, 如果你的项目(是个静态库)的依赖某个库(不管动态库还是静态库), 当你在编译生成静态库的时候, 只需要相应的依赖库库的头文件即可.
(因为, linux的.a本身就是一堆.o的集合, .o也就是一堆cpp文件的编译结果, 并没有开始执行链接)
举例:
  libcomm.a 就是这样, 虽然依赖的很多的库, 比如html_template, mysql, MARKUPSTL, 但只需他们的头文件即可.
USED = \
       MARKUPSTL \
       NETCLIENTEX \
       HTML_TEMPLATE \
       TLIB \

INC  = \
    $(foreach i, $(USED), $(INC_$(i)))

#看到没, LIB 为空!!!
LIB  =

如果你想生成so,或可执行文件 
1)那么你必须包含上你需要的lib, 而且, 如果你 通过 -lxxx, 那么gcc默认后首先尝试链接 xxx的动态库libxxx.so.1(libxxx.so.1是libxxx.so的符号链接文件, 并不是真正的libxxx.so, 但是会指向libxxx.so), 如果找不到libxxx.so.1,然后寻找xxx的静态库libxxx.a.
2)同时, 如果你没有用到某个lib的话, 一定不要包含其lib, 如果编译不通过, 最多只需包含其头文件即可.
就像我上面的案例一样, 没有用到mysql, 却包含而来mysql的lib, 导致在运行机上找不到 mysql.so 而运行失败, 去掉mysql的lib, 只保留mysql的 头文件, 可以链接过去, 并且可以正常运行.

2)如果你同时使用了多个库,而库之间又相互依赖,那么在链接是,把最底层的依赖库放在最右侧.否则可能会链接失败
  g++ -o $(target) liba libb libc
  如果liba 依赖libb, libb依赖libc, 那么请把libc放在最后面.
  如果 g++ -o $(target) liba libc libb会导致libb的链接失败. 
  有一种情况离开,liba也依赖libc,并且依赖关系和libb对libc的依赖的接口一样, 那么把libc放在中间不会报错,但最好不要这么做.
 
3)如果我已经把最底层的库放在最后边了,还是链接失败怎么办?
   检查是否连接到了相同名字的其他的库.  我又一次就是如此,系统系统中存在多个network的库, 虽然我把正确的network库放在了最后面,但是由于其他库包含路径下也有老的同名的network库,导致我链接失败.

库依赖的查看

使用ldd命令来查看执行文件依赖于哪些库。

该命令用于判断某个可执行的 binary 档案含有什么动态函式库。
[root@test root]# ldd [-vdr] [filename]
参数说明:
--version  打印ldd的版本号
-v --verbose  打印所有信息,例如包括符号的版本信息
-d --data-relocs  执行符号重部署,并报告缺少的目标对象(只对ELF格式适用)
-r --function-relocs  对目标对象和函数执行重新部署,并报告缺少的目标对象和函数(只对ELF格式适用)
--help 用法信息。

如果命令行中给定的库名字包含'/',这个程序的libc5版本将使用它作为库名字;否则它将在标准位置搜索库。运行一个当前目录下的共享库,加前缀"./"。

linux 下 奇怪的 动态库 依赖问题的更多相关文章

  1. ffmpeg学习笔记-Linux下编译Android动态库

    Android平台要使用ffmpeg就需要编译生成动态库,这里采用Ubuntu编译Android动态库 文件准备 要编译生成Android需要以下文件 NDK ffmpeg源代码 NDK下载 NDK可 ...

  2. Linux程序编译链接动态库版本号的问题

    不同版本号的动态库可能会不兼容,假设程序在编译时指定动态库是某个低版本号.执行是用的一个高版本号,可能会导致无法执行. Linux上对动态库的命名採用libxxx.so.a.b.c的格式.当中a代表大 ...

  3. Linux下Qt创建共享库与链接共享库详解

    随着程序写的逐渐变多,或多或少的我们都会使用别人写好的库:或者我们不想让别人看到我们的一些核心程序,可以将核心程序封装成库.本次和大家分享的是在Ubuntu下使用Qt生成共享库以及在Qt中链接共享库的 ...

  4. linux下编译安装boost库

    linux下编译安装boost库 linux下编译安装boost库 1.下载并解压boost 1.58 源代码 下载 解压 2.运行bootstrap.sh 3.使用b2进行构建 构建成功的提示 4. ...

  5. Golang调用windows下的dll动态库中的函数

    Golang调用windows下的dll动态库中的函数 使用syscall调用. package main import ( "fmt" "syscall" & ...

  6. LINUX学习笔记——LINUX下EXP命令全库备份数据库文件

    LINUX下EXP命令全库备份数据库文件 1)建立备份目录,目录操作权限授权给Oracle用户 mkdir /backup  --创建backup文件夹 cd  /   --进入cd语句 ls  -l ...

  7. Golang调用windows下的dll动态库中的函数 Golang 编译成 DLL 文件

    Golang调用windows下的dll动态库中的函数 package main import ( "fmt" "syscall" "time&quo ...

  8. linux下如何查询未知库所依赖的包

    经常会遇到linux下安装软件时提示少文件,如何知道所缺少的文件属于哪个包?用什么命令查看? 例如:/lib/ld-linux.so.2: bad ELF interpreter: 没有那个文件或目录 ...

  9. Linux下编译使用boost库:

    Boost是什么不多说, 下面说说怎样在Linux下编译使用Boost的所有模块. 1. 先去Boost官网下载最新的Boost版本, 我下载的是boost_1_56_0版本, 解压. 2. 进入解压 ...

随机推荐

  1. html5 拖放到购物车

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  2. gpgcheck

    warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY Public key for co ...

  3. KMP算法——Javascript实现

    腾讯和阿里的笔试刚过去了,里面有很多题都很值得玩味的.之前Blog积累的很多东西,还要平时看的书,都有很大的帮助.这个深有体会啊! 例如,腾讯有一道算法题是吃香蕉(好邪恶的赶脚..),一次吃一根或者两 ...

  4. 读取proc信息的可扩展实现

    需求 1. 将内存.线程数等信息注册到zk上进行监控 2. 统计信息,为下一步做负载均衡做准备. 实现 本文只解决问题1. 从网上查询了下,这些信息可以从proc文件系统中获取,如果不知道proc的, ...

  5. hibernate search例子

    [TOC] 1. 概念介绍 1.1. Hibernate Search Hibernate Search是Hibernate的子项目,把数据库全文检索能力引入到项目中,并通过"透明" ...

  6. 巧解Tomcat中JVM内存溢出问题

    你对Tomcat 的JVM内存溢出问题的解决方法是否了解,这里和大家分享一下,相信本文介绍一定会让你有所收获. tomcat 的JVM内存溢出问题的解决 最近在熟悉一个开发了有几年的项目,需要把数据库 ...

  7. ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)

    ZOJ 3597 题意是说有n把枪,有m个靶子,每把枪只有一发子弹(也就是说一把枪最多只能打一个靶子), 告诉你第 i 把枪可以打到第j个靶, 现在等概率的出现一个连续的P把枪,在知道这P把枪之后,你 ...

  8. .net 学习资源(转)

      名称:快速入门地址:http://chs.gotdotnet.com/quickstart/描述:本站点是微软.NET技术的快速入门网站,我们不必再安装.NET Framework中的快速入门示例 ...

  9. springMVC使用注解方式进行页面跳转

    <!--控制层-->package cn.org.spartacus.spring; import org.springframework.beans.factory.annotation ...

  10. OC: Block回调的使用demo

    Block 的用法 对于类的继承问题,子类在实现的时候,一般是自下而上,先看看下面的实现没有,没实现就向上找方法去实现. // // main.m #import <Foundation/Fou ...