linux下编译.so 和.a 可能出现的问题 ?

1. 静态函数库

    这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

2. 动态函数库

    这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。 
linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。

编译静态库和动态库 :

无论是静态库还是动态库 ,都是由.o文件组成。因此我们可以先编译出.o文件 。
下面提供两个小程序 :
sum.h

#ifndef SUM_H_
#define SUM_H_

int add (int ,int ) ;

#endif 

sum.cpp 

#include <iostream>
#include "auth.h"

int add (int x ,int y ) 
{
	int sum = x + y ;
	return sum  ;
}

#include "sum.h"
#include<iostream>
int main()
{
	int k = add(8,10);
	std::cout<<"k= "<< k<<std::endl;
	return 0 ;
}

linux32位系统下 :
首先编译.o文件:
g++ -c sum.cpp    ------>生成.o文件
  
编译.so 文件 :
g++ -shared -fPIC -o libsum.so sum.o       ------>生成libsum.so文件

编译.a 文件 :
ar rcs libsum.a sum.o   - ----> 生成libsum.a 文件 

编译测试文件并测试 :
g++ -c test.cpp 
g++ -o test test.o -lauth -L./ 
ok,测试结果显示k = 18 ;

然而 在linux64位的系统中,这个问题就出来了 。
如果依然按照上面的命令进行编译 ,会出现以下错误 :
      /usr/bin/ld: sum.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
auth.o: could not read symbols: Bad value。
碰到这个错误 ,你可以去检查下,对应的文件在编译的时候是不是用了-fPIC这个参数哦 。

 -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

在生成.o文件的时候 加上参数 -fPIC ,这个错误就可以搞定了 ,在编译动态库时,必须指定这个参数 ,主要是因为代码的重定向的问题 。如果没有这个参数 ,编译的代码加载的时候不能够重定向。
 g++ -fPIC -c sum.cpp 

那么,如果我希望指定执行文件链接静态库怎么办呢 ??
默认情况下,如果在某个目录下.so 和.a 同时存在的时 ,gcc会优先选择.so 。
我们一般通过 -I引入包含文件 ,-L引入库目录 ,-l指定依赖的库文件。当在静态库和动态库同时存在时,gcc选择.so ,如果你在能够将. so和.a分开的情况下 ,使用-lname (name为lib的名字)来指定库文件(无论静态库还是动态库都可以),如果静态库和动态库在同一目录下 ,可以使用 path/libname.a  来指定依赖的库文件 。
Linux下约定所有库都以前缀lib开始静态库以.a结尾,动态库以.so结尾。再编译程式时,无需带上前缀和后缀

在编译过程中,-L指定的路径是编译路径 ,而在运行时需要动态的搜索库文件 ,这两个路径不是一个概念 。因此经常会出现这样的问题 :
”明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过“-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你 要作的就是通过修改LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题 了。













Android系统的.so文件和Linux系统的.so文件在一定程度上是相似的,因为Android系统是基于Linux内核进行开发的。.so文件是共享对象文件,也被称为动态链接库。它们包含了一组可执行的二进制代码和函数,可以在运行时被程序调用,以实现特定功能。 首先,Android版本的.so和Linux版本的.so具有相同的文件格式,它们都采用了ELF(可执行和可链接格式)文件格式。这意味着它们都具有相似的结构和元数据信息。 其次,它们都具有相同的编译和链接要求。无论是Android版本的.so还是Linux版本的.so,都需要使用相应的编译器和链接器进行处理。例如,在Android开发中,使用的编译工具链包括GCC和Clang等。 然而,尽管在一些方面相似,Android版本的.so和Linux版本的.so也存在一些差异。这是因为Android系统在基于Linux内核的基础上进行了定制和优化。这种定制主要涉及Android运行时环境(ART/Dalvik虚拟机)、Android软件框架和一些其他特定的Android库。 由于这些差异,Android版本的.so文件只能在Android系统上运行,而Linux版本的.so文件则可以在各种基于Linux内核的操作系统上运行。 在实际开发中,开发者需要根据目标平台和系统需求选择合适的.so文件。例如,如果开发一个Android应用程序,就需要使用Android版本的.so文件,以确保应用可以正常运行并与Android系统框架进行良好的集成。而如果在普通的Linux系统上开发,就需要使用Linux版本的.so文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值