前言
我们在Linux平台进行源码安装的时候,经常会遇到.so
、.o
文件的输出信息。这些文件的输出信息我们一般来说只需要大概看一眼,不需要深入探索。但是如果我们需要亲自编写源码,手动进行编译的时候,就需要对这些信息进行深度了解了。
文件解释
在linux中这些.so
、.o
、.a
文件,其实和Windows中的obj
、lib
、dll
、exe
等文件的关系是对应的。在解释linux这些文件之前,我们先来说下windows中这些文件的作用。
windows下obj、lib、dll、exe的关系
exe是我们平常所知道的可执行程序的后缀,而obj、lib、dll则是构成运行程序的关键文件。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的链接失败。
obj里存的是编译后的代码跟数据,并且有名称,所以在连接时有时会出现未解决的外部符号的问题。当连成exe后便不存在名称的概念了,只有地址。lib就是一堆obj的组合。
理论上可以连接obj文件来引用其他工程(可以认为一个obj文件等价于编译生成它的cpp文件,可以引用obj来替换cpp,也可以添加cpp来替换obj ),但实际中通常用lib来实现工程间相互引用。
编译器会默认链接一些常用的库,其它的需要你自己指定。
lib和dll的区别
lib
是编译时需要的,dll
是运行时需要的。如果要完成源代码的编译,有lib就够了。如果也使动态连接的程序运行起来,有dll
就够了。在开发和调试阶段,当然最好都有。
一般的动态库程序有lib
文件和dll
文件。lib
文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll
文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll
文件中。如果只有lib
文件,那么这个lib
文件是静态编译出来的,索引和实现都在其中。
静态编译的lib
文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。
在动态库的情况下,有两个文件,一个是引入库(.LIB)文件(实际上也算是一个静态库,只是在链接时只能把函数在dll的入口链接到exe中,而不像真正静态链接库那样将函数体真正链接到exe中 ,通过lib进行的动态链接实际上也使用了静态链接来实现 ),一个是dll文件,引入库文件包含被dll导出的函数的名称和位置,dll包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的dll文件,库中的函数和数据并不复制到可执行文件中.
因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是dll中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,dll和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。
dll内的函数分为两种:
- dll导出函数,可供应用程序调用;
- dll内部函数,只能在dll程序使用,应用程序无法调用它们
linux下 .o、.a、.so文件的的区别
- .o,是目标文件,相当于windows中的.obj文件。
- .so 为共享库,是shared object,用于动态连接的,相当于windows下的dll,是Linux中的可执行文件。
- .a为静态库,说白了就是一堆.o合在一起,用于静态连接,效果和.o是一样的。
静态函数库
- 特点:实际上是简单的普通目标文件的集合,在程序执行前就加入到目标程序中。
- 优点:可以用以前某些程序兼容;描述简单;允许程序员把程序link起来而不用重新编译代码,也就数不需要外部函数的支持,节省了重新编译代码的时间(该优势目前已不明显);开发者还可以对源代码保密。
- 这类库的名字一般是libxxx.a.利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中。
- 缺点:如果静态函数库改变了,那么你的程序必须重新编译。
共享函数库
- 共享函数库在可执行程序启动的时候加载,所有程序重新运行时都可自动加载共享函数库中的函数。相对于静态函数库,共享函数库在编译的时候 并没有被编译进目标代码中。
- 当程序执行到相关函数时才调用共享函数库里相应的函数,因此共享函数库所产生的可执行文件比较小.由于共享函数库没有被整合进你的程序,而是在程序运行时动态地申请并调用,所以程序的运行环境中必须提供相应的库.
- 共享函数库的改变并不影响你的程序,所以共享函数库的升级比较方便.
相关文章
关于gcc、cmake、make区别:https://oldpan.me/archives/gcc-make-cmake-clang-tell