Linux的.a、.so和.o文件 对比 window下的dll,lib,exe文件

 连续几天终于将一个又一个问题解决了,这里说其中一个问题linux

  描述问题:使用多线程pthread的时候,(我用的IDE,CODEBOLCKS)编译后发现直接弹出窗口,程序尚未被Build。。巴拉巴拉,而后陷入了这个循环。提示有一句pthead_create未定义。c++

  发现:pthread要用到动态连接库(libpthread.a)才能使用。程序员

  解决办法:后来在setting->complies and link->link setting里面加入了系统中这个文件的地址。windows

  详细查了一下,.a与.so的区别,其实就是静态连接库与动态连接库。有一篇博文,很详细,附上连接:http://blog.csdn.net/nieyinyin/article/details/6890557缓存

  Linux下的.so是基于Linux下的动态连接,其功能和做用相似与windows下.dll文件。多线程

  下面是关于.so的介绍:eclipse

1、引言函数

  一般状况下,对函数库的连接是放在编译时期(compile time)完成的。全部相关的对象文件(object file)与牵涉到的函数库(library)被连接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,由于全部须要的函数已拷贝到本身门下。因此这些函数库被成为静态库(static libaray),一般文件名为“libxxx.a”的形式。测试


  其实,咱们也能够把对一些库函数的连接载入推迟到程序运行的时期(runtime)。这就是如雷贯耳的动态连接库(dynamic link library)技术。ui

2、动态连接库的特色与优点

  首先让咱们来看一下,把库函数推迟到程序运行时期载入的好处:

  1. 能够实现进程之间的资源共享。

  什么概念呢?就是说,某个程序的在运行中要调用某个动态连接库函数的时候,操做系统首先会查看全部正在运行的程序,看在内存里是否已有此库函数的拷 贝了。若是有,则让其共享那一个拷贝;只有没有才连接载入。这样的模式虽然会带来一些“动态连接”额外的开销,却大大的节省了系统的内存资源。C的标准库 就是动态连接库,也就是说系统中全部运行的程序共享着同一个C标准库的代码段。

  2. 将一些程序升级变得简单。用户只须要升级动态连接库,而无需从新编译连接其余原有的代码就能够完成整个程序的升级。Windows 就是一个很好的例子。

  3. 甚至能够真正坐到连接载入彻底由程序员在程序代码中控制。

  程序员在编写程序的时候,能够明确的指明何时或者什么状况下,连接载入哪一个动态连接库函数。你能够有一个至关大的软件,但每次运行的时候,因为 不一样的操做需求,只有一小部分程序被载入内存。全部的函数本着“有需求才调入”的原则,因而大大节省了系统资源。好比如今的软件一般都能打开若干种不一样类 型的文件,这些读写操做一般都用动态连接库来实现。在一次运行当中,通常只有一种类型的文件将会被打开。因此直到程序知道文件的类型之后再载入相应的读写 函数,而不是一开始就将全部的读写函数都载入,而后才发觉在整个程序中根本没有用到它们。

3、动态连接库的建立

  因为动态连接库函数的共享特性,它们不会被拷贝到可执行文件中。在编译的时候,编译器只会作一些函数名之类的检查。在程序运行的时候,被调用的动态 连接库函数被安置在内存的某个地方,全部调用它的程序将指向这个代码段。所以,这些代码必须实用相对地址,而不是绝对地址。在编译的时候,咱们须要告诉编 译器,这些对象文件是用来作动态连接库的,因此要用地址不无关代码(Position Independent Code (PIC))。

  对gcc编译器,只需添加上 -fPIC 标签,如:

  gcc -fPIC -c file1.c
  gcc -fPIC -c file2.c
  gcc -shared libxxx.so file1.o file2.o

  注意到最后一行,-shared 标签告诉编译器这是要创建动态连接库。这与静态连接库的创建很不同,后者用的是 ar 命令。也注意到,动态连接库的名字形式为 “libxxx.so” 后缀名为 “.so”

4、动态连接库的使用

a.隐式调用 (静态库与此相同的方式)

  使用动态连接库,首先须要在编译期间让编译器检查一些语法与定义。

  这与静态库的实用基本同样,用的是 -Lpath 和 -lxxx 标签。如:

  gcc file1.o file2.o -Lpath -lxxx -o program.exe

  编译器会先在path文件夹下搜索libxxx.so文件,若是没有找到,继续搜索libxxx.a(静态库)。

  在程序运行期间,也须要告诉系统去哪里找你的动态连接库文件。在UNIX下是经过定义名为 LD_LIBRARY_PATH 的环境变量来实现的。只需将path赋值给此变量便可。csh 命令为:

  setenv LD_LIBRARY_PATH   your/full/path/to/dll

  一切安排稳当后,你能够用 ldd 命令检查是否链接正常。

  ldd program.exe

动态连接库*.so的编译与使用

b.显示调用:

  这种方式更加灵活。在代码中须要调用的地方使用 #include <dlfcn.h>这个头文件中的如下函数来调用:

 

void  *dlopen(const char *, int); void *dlsym(void *, const char *); int dlclose(void *); char *dlerror(void);

 

在说明Linux的.a、.so和.o文件关系以前,先来看看windows下obj,lib,dll,exe的关系

 

windows下obj,lib,dll,exe的关系

    lib是和dll对应的。lib是静态连接库的库文件,dll是动态连接库的库文件。
    所谓静态就是link的时候把里面须要的东西抽取出来安排到你的exe文件中,之后运行你的exe的时候再也不须要lib。
    所谓动态就是exe运行的时候依赖于dll里面提供的功能,没有这个dll,你的exe没法运行。
   
    lib,dll,exe都算是最终的目标文件,是最终产物。而c/c++属于源代码。源代码和最终目标文件中过渡的就是中间代码obj,实际上之因此须要中间代码,是你不可能一次获得目标文件。好比说一个exe须要不少的cpp文件生成。而编译器一次只能编译一个cpp文件。这样编译器编译好一个cpp之后会将其编译成obj,当全部必需要的cpp都编译成obj之后,再统一link成所须要的exe,应该说缺乏任意一个obj都会致使exe的连接失败。
   
    1.obj里存的是编译后的代码跟数据,而且有名称,因此在链接时有时会出现未解决的外部符号的问题。当连成exe后便不存在名称的概念了,只有地址。lib就是一堆obj的组合。
    2.理论上能够链接obj文件来引用其余工程(能够认为一个obj文件等价于编译生成它的cpp文件,能够引用obj来替换cpp,也能够添加cpp来替换obj ),但实际中一般用lib来实现工程间相互引用。
    3.编译器会默认连接一些经常使用的库,其它的须要你本身指定。
   
lib和DLL的区别

    (1)lib是编译时须要的,dll是运行时须要的。若是要完成源代码的编译,有lib就够了。若是也使动态链接的程序运行起来,有dll就够了。在开发和调试阶段,固然最好都有。
    (2) 通常的动态库程序有lib文件和dll文件。lib文件是必须在编译期就链接到应用程序中的,而dll文件是运行期才会被调用的。若是有dll文件,那么对应的lib文件通常是一些索引信息,具体的实如今dll文件中。若是只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。 静态编译的lib文件有好处:给用户安装时就不须要再挂动态库了。但也有缺点,就是致使应用程序比较大,并且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。
    (3)在动态库的状况下,有两个文件,一个是引入库(.LIB)文件(实际上也算是一个静态库,只是在连接时只能把函数在DLL的入口连接到exe中,而不像真正静态连接库那样将函数体真正连接到exe中 ,经过lib进行的动态连接实际上也使用了静态连接来实现 ),一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件连接到所须要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,所以在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码连接起来,从而节省了内存资源。从上面的说明能够看出,DLL和.LIB文件必须随应用程序一块儿发行,不然应用程序将会产生错误。

DLL内的函数分为两种:
    (1)DLL导出函数,可供应用程序调用;
    (2)DLL内部函数,只能在DLL程序使用,应用程序没法调用它们

建立静态连接库和建立动态连接库

    VC6中建立[Win32 Dynamic-Link Library]工程即可以建立出一个空的DLL工程.

    VC6中建立[Win32 Static Library]工程即可以建立出一个空的LIB工程(静态连接库工程,仅生成一个lib文件).

添加lib文件的经常使用办法有二个:
    一、把*.lib放在VC的Lib目录中
    二、修改project setting的Link->Input中的Addtional library path,加入你的目录dll:是可实际运行的二进制代码,有定位代码的!

    三、也能够在object/library中直接写上lib文件路径.(这里其实是能够写上任意obj文件或者lib文件的).

 

 

 

linux .o,.a,.so
        .o,是目标文件,至关于windows中的.obj文件 

  .so 为共享库,是shared object,用于动态链接的,至关于windows下的dll 

  .a为静态库,是好多个.o合在一块儿,用于静态链接 

 

静态函数库
特色:其实是简单的普通目标文件的集合,在程序执行前就加入到目标程序中。
优势:能够用之前某些程序兼容;描述简单;容许程序员把程序link起来而不用从新编译代码,节省了从新编译代码的时间(该优点目前已不明显);开发者能够对源代码保密;理论上使用ELF格式的静态库函数生成的代码能够比使用共享或动态函数库的程序运行速度快(大概1%-5%)
生成:使用ar程序(archiver的缩写)。ar rcs my_lib.a f1.o f2.o是把目标代码f1.o和f2.o加入到my_lib.a这个函数库文件中(若是my_lib.a不存在则建立)
使用:用gcc生成可执行代码时,使用-l参数指定要加入的库函数。也能够用ld命令的-l和-L参数。
 
共享函数库
    共享函数库在可执行程序启动的时候加载,全部程序从新运行时均可自动加载共享函数库中的函数。.so文件感受很复杂,光是命名规则就已经看得我很晕了~整理一下,共享库须要:soname、real name,另外编译的时候名字也有说法。依次解释下:
soname:必须的格式:lib+函数库名+.so+版本号信息(可是记住,很是底层的C库函数都不是以lib开头命名的)。例子:/usr/lib/libreadline.so.3
real name:顾名思义是真正的名字啦,有主版本号和发行版本号。可是没找到实例……
编译器编译的时候须要的函数库的名字就是不包含版本号信息的soname,例如上面的例子把最后的.3去掉就能够了。
位置:共享函数库文件必须放在特定目录,对于开放源码来讲,GNU标准建议全部的函数库文件都放在/usr/local/lib目录下,并且建议命令、可执行程序都放在/usr/local/bin目录下。不过这个只是习惯啦,能够改变,具体的位置信息能够看/etc/ld.so.conf里面的配置信息。固然,也能够修改这个文件,加入本身的一些特殊的路径要求。
建立:在网上找到了gcc方式和easyeclipse环境下两种建立方式。
gcc方式:
    首先建立object文件,这个文件将加入经过gcc –fPIC 参数命令加入到共享函数库里面,标准格式:gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list(说实话这个标准格式看起来好复杂,我找了个实例,可是好像和那个标准格式稍有不一样:gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so)
在easyeclipse环境下生成.so文件:
        1.选择新建工程,创建一个c++工程
        2.在工程类型选项里选择 Shared Library,而后填入工程名字PXXX点击完成便可。
        3.编写程序,而后编译就会在debug或者release里生成一个libPXXX.so文件,若是不要lib的起头标记点击project菜单的Properties选项,而后在弹出的界面的右边点击Build artifact页面,将Output prefix选项的内容清空便可。
        4.若是是C++程序,注意在接口函数的前面加上extern "C"标记,在头文件加上以下标记:
#ifdef   __cplusplus 
#extern   "C"{ 
#endif 
  
头文件主体 
  
#ifdef   __cplusplus 

#endif 
     若是不加以上标记,通过编译后,so里的函数名并不是你编写程序时设定的函数名,在开发环境左侧的工程文件列表中点开debug项里的PXXX.o能够看到so文件里的函数名都是在你设定的函数名后面加了一个__Fi标记,好比你用的设定的函数名称是Func(), 而so里的函数名则为Func__Fi()或者其余的名称。
安装:拷贝共享库文件到指定的标准的目录,而后运行ldconfig。若是没有权限这样作,那么就只好经过修改环境变量来实现这些函数库的使用了。方法再也不说了,很复杂。
查看:能够经过运行ldd来看某个程序使用的共享函数库。例如ldd /bin/ls。查看.so文件使用nm命令,如nm libXXX.so。(注意,nm对于静态的函数库和共享的函数库都起做用)
关于覆盖:若是想用本身的函数覆盖某个库中的一些函数,同时保留该库中其余的函数的话,能够在/etc/ld.so.preload中加入要替换的库(.o结尾的文件),这些preloading的库函数将有优先加载的权利。
关于更新:每次新增长动态加载的函数库、删除某个函数库或者修改某个函数库的路径时,都要从新运行ldconfig来更新缓存文件/etc/ld.so.cache,此文件保存已排好序的动态连接库名字列表

(在Linux下,共享库的加载是由/lib/ld.so完成的,ld.so加载共享库时,会从ld.so.cache查找)

 

 

 

 

咱们一般把一些公用函数制做成函数库,供其它程序使用。函数库分为静态库和动态库两
种。静态库在程序编译时会被链接到目标代码中,程序运行时将再也不须要该静态库。动态
库在程序编译时并不会被链接到目标代码中,而是在程序运行是才被载入,所以在程序运
行时还须要动态库存在。本文主要经过举例来讲明在Linux中如何建立静态库和动态库,以
及使用它们。

在建立函数库前,咱们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。


第1步:编辑获得举例的程序--hello.h、hello.c和main.c;

hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"
Hello XXX!"。hello.h(见程序1)为该函数库的头文件。main.c(见程序3)为测试库文件的
主程序,在主程序中调用了公用函数hello。

程序1: hello.h

#ifndef HELLO_H
#define HELLO_H

void hello(const char *name);

#endif //HELLO_H

 

程序2: hello.c

#include <stdio.h>

void hello(const char *name)
{
printf("Hello %s!\n", name);
}

程序3: main.c

#include "hello.h"

int main()
{
hello("everyone");
return 0;
}

第2步:将hello.c编译成.o文件;

不管静态库,仍是动态库,都是由.o文件建立的。所以,咱们必须将源程序hello.c经过g
cc先编译成.o文件。

在系统提示符下键入如下命令获得hello.o文件。

# gcc -c hello.c

#

咱们运行ls命令看看是否生存了hello.o文件。

# ls

hello.c hello.h hello.o main.c

#


在ls命令结果中,咱们看到了hello.o文件,本步操做完成。

下面咱们先来看看如何建立静态库,以及使用它。

第3步:由.o文件建立静态库;

静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:咱们将
建立的静态库名为myhello,则静态库文件名就是libmyhello.a。在建立和使用静态库时,
须要注意这点。建立静态库用ar命令。

在系统提示符下键入如下命令将建立静态库文件libmyhello.a。

# ar -cr libmyhello.a hello.o

#

咱们一样运行ls命令查看结果:

# ls

hello.c hello.h hello.o libmyhello.a main.c

#

ls命令结果中有libmyhello.a。

第4步:在程序中使用静态库;

静态库制做完了,如何使用它内部的函数呢?只须要在使用到这些公用函数的源程序中包
含这些公用函数的原型声明,而后在用gcc命令生成目标文件时指明静态库名,gcc将会从
静态库中将公用函数链接到目标文件中。注意,gcc会在静态库名前加上前缀lib,而后追
加扩展名.a获得的静态库文件名来查找静态库文件。

在程序3:main.c中,咱们包含了静态库的头文件hello.h,而后在主程序main中直接调用公
用函数hello。下面先生成目标程序hello,而后运行hello程序看看结果如何。

法一 # gcc -o hello main.c -L. –lmyhello,或gcc  main.c -L. –lmyhello -o hello自定义的库时,main.c还可放在-L.和 –lmyhello之间,可是不能放在它俩以后,不然会提示myhello没定义,可是是系统的库时,如g++ -o main(-L/usr/lib) -lpthread main.cpp就不出错。

法二 #gcc main.c libmyhello.a -o hello或gcc  -o hello main.c libmyhello.a

法三:先生成main.o:gcc -c main.c ,再生成可执行文件:gcc -o hello main.o libmyhello.a或gccmain.o libmyhello.a -o hello ,动态库链接时也能够这样作。

 

# ./hello

Hello everyone!

#

咱们删除静态库文件试试公用函数hello是否真的链接到目标文件 hello中了。

# rm libmyhello.a

rm: remove regular file `libmyhello.a'? y

# ./hello

Hello everyone!

#

程序照常运行,静态库中的公用函数已经链接到目标文件中了。

咱们继续看看如何在Linux中建立动态库。咱们仍是从.o文件开始。

第5步:由.o文件建立动态库文件;

动态库文件名命名规范和静态库文件名命名规范相似,也是在动态库名增长前缀lib,但其
文件扩展名为.so。例如:咱们将建立的动态库名为myhello,则动态库文件名就是libmyh
ello.so。用gcc来建立动态库。

在系统提示符下键入如下命令获得动态库文件libmyhello.so。

 

# gcc -shared -fPIC -o libmyhello.so hello.o (-o不可少)

#

咱们照样使用ls命令看看动态库文件是否生成。

# ls

hello.c hello.h hello.o libmyhello.so main.c

#

第6步:在程序中使用动态库;

在程序中使用动态库和使用静态库彻底同样,也是在使用到这些公用函数的源程序中包含
这些公用函数的原型声明,而后在用gcc命令生成目标文件时指明动态库名进行编译。咱们
先运行gcc命令生成目标文件,再运行它看看结果。

# gcc -o hello main.c -L. -lmyhello

 

(或 #gcc main.c libmyhello.so -o hello 不会出错(没有libmyhello.so的话,会出错),可是接下来./hello 会提示出错,由于虽然链接时用的是当前目录的动态库,可是运行时,是到/usr/lib中找库文件的,将文件libmyhello.so复制到目录/usr/lib中就OK了)

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shar
ed object file: No such file or directory

#

哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,
会在/usr/lib和/lib等目录中查找须要的动态库文件。若找到,则载入动态库,不然将提
示相似上述错误而终止程序运行。咱们将文件libmyhello.so复制到目录/usr/lib中,再试
试。

# mv libmyhello.so /usr/lib

# ./hello

Hello everyone!

#

成功了。这也进一步说明了动态库在程序运行时是须要的。

咱们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令彻底同样,
那当静态库和动态库同名时,gcc命令会使用哪一个库文件呢?抱着对问题必究到底的心情,
来试试看。

先删除除.c和.h外的全部文件,恢复成咱们刚刚编辑完举例程序状态。

# rm -f hello hello.o /usr/lib/libmyhello.so

# ls

hello.c hello.h main.c

#

在来建立静态库文件libmyhello.a和动态库文件libmyhello.so。

在生成动态库时,须要使用-fPIC,这样才能生成位置无关的代码,达到代码段和数据段共享的目的

# gcc -c -fpic hello.c  //编译hello.c时也须要加上-fpic选项,不然rodata' can not be used when making a shared object; recompile with -fPIC

# ar -cr libmyhello.a hello.o (或-cvr )

# gcc -shared -fPIC -o libmyhello.so hello.o

# ls

hello.c hello.h hello.o libmyhello.a libmyhello.so main.c

#

经过上述最后一条ls命令,能够发现静态库文件libmyhello.a和动态库文件libmyhello.s
o都已经生成,并都在当前目录中。而后,咱们运行gcc命令来使用函数库myhello生成目标
文件hello,并运行程序 hello。

# gcc -o hello main.c -L. –lmyhello (动态库和静态库同时存在时,优先使用动态库, 固然,直接#gcc main.c libmyhello.a -o hello的话,就是指定为静态库了)

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shar
ed object file: No such file or directory

#

从程序hello运行的结果中很容易知道,当静态库和动态库同名时,gcc命令将优先使用动态库,默认去连/usr/lib和/lib等目录中的动态库,将文件libmyhello.so复制到目录/usr/lib中便可。

Note:
编译参数解析
最主要的是GCC命令行的一个选项:
-shared 该选项指定生成动态链接库(让链接器生成T类型的导出符号表,有时候也生成弱链接W类型的导出符号),不用该标志外部程序没法链接。至关于一个可执行文件


-fPIC 做用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code)。那么在产生的代码中,没有绝对地址,所有使用相对地址,故而代码能够被加载器加载到内存的任意位置,均可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

若是不加fPIC,则编译出来的代码在加载时须要根据加载到的位置进行重定位(由于它里面的代码并非位置无关代码),若是被多个应用程序共同使用,那么它们必须每一个程序维护一份so的代码副本了.(由于so被每一个程序加载的位置都不一样,显然这些重定位后的代码也不一样,固然不能共享)。

不用此选项的话编译后的代码是位置相关的,因此动态载入时是经过代码拷贝的方式来知足不一样进程的须要,而不能达到真正代码段共享的目的。

-L. 表示要链接的库在当前目录中;(多个库:在编译命令行中,将使用的静态库文件放在源文件后面就能够了。好比:gcc -L/usr/lib myprop.c libtest.a libX11.a libpthread.a -o myprop
其中-L/usr/lib指定库文件的查找路径。编译器默认在当前目录下先查找指定的库文件,如前面的“法二 #gccmain.c libmyhello.a-o hello”)


-lmyhello 编译器查找动态链接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so或.a来肯定库的名称libmyhello.so或libmyhello.a。
LD_LIBRARY_PATH这个环境变量指示动态链接器能够装载动态库的路径。
固然若是有root权限的话,能够修改/etc/ld.so.conf文件,而后调用 /sbin/ldconfig来达到一样的目的,不过若是没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

调用动态库的时候有几个问题会常常碰到,有时,明明已经将库的头文件所在目录 经过 “-I” include进来了,库所在文件经过 “-L”参数引导,并指定了“-l”的库名,但经过ldd命令察看时,就是死活找不到你指定连接的so文件,这时你要做的就是经过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。一般这样作就能够解决库没法连接的问题了。

 

 

静态库连接时搜索路径顺序:

1. ld(GNU linker)会去找GCC命令中的参数-L

   编译过程是分为四个阶段:预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和链接(link)  【连接】
2. 再找gcc的环境变量LIBRARY_PATH
3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态连接时、执行时搜索路径顺序:

1. 编译目标代码时指定的动态库搜索路径
2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
4. 默认的动态库搜索路径/lib
5. 默认的动态库搜索路径/usr/lib

有关环境变量:
LIBRARY_PATH环境变量:指定程序静态连接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态连接库文件搜索路径

 


另:

从上述可知,如何找到生成的动态库有3种方式:

(1)把库拷贝到/usr/lib和/lib目录下。

(2)在LD_LIBRARY_PATH环境变量中加上库所在路径。

例如动态库libhello.so在/home/example/lib目录下:

export LD_LIBRARY_PATH=LD_LIBRARY_PATH:/home/example/lib

(3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾(直接写在文件末尾,不要在路径前加include),并执行ldconfig刷新(ldconfig 命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态连接库(格式如前介绍,lib*.so*),进而建立出动态装入程序(ld.so)所需的链接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态连接库名字列表.)。这样,加入的目录下的全部库文件均可见。

附:像下面这样指定路径去链接系统的静态库,会报错说要链接的库找不到:

g++ -o main main.cpp -L/usr/lib libpthread.a 

必须这样g++ -o main main.cpp -L/usr/lib -lpthread才正确 。

自定义的库考到/usr/lib 下时,

g++ -o main main.cpp -L/usr/lib libpthread.a libthread.a libclass.a会出错,可是这样g++ -o main main.cpp -L/usr/lib -lpthread -lthread -lclass就正确了。

相关文章
相关标签/搜索