linux如何编译静态库,linux静态库和动态库编译及使用

/**************************************************************************/

/*add.c*/

int add(int x, int y)

{

return x + y;

return 0;

}

/*************************************************************************/

然后add.h代码为:

/*add.h*/

#ifndef _ADD_H_

#define _ADD_H_

int add(int, int);

#endif

/***************************************************************************/

main函数代码:

/*main.c*/

#include

int main(void)

{

printf("2+3= %d\n", add(2,3));

return 0;

}

/**********************************************************************************/

1 静态库的编译流程

将add.c 单独的源文件编译成静态库libadd.a

gcc -c add.c  //生成 add.o

ar crv libadd.a add.o // 生成静态库libadd.a

2 静态库的使用

gcc -o main main.c  -I. -L. -ladd  (注: -I -L -l的意思在文章后面)

也可以: gcc -o main main.c -I ./libadd.a (注:这里 ./libadd.a 可以是相对地址或者绝对地址 如:./lib/libadd.a , /home/lisi/lib/lib.a)

3 动态库的编译流程

gcc -fPIC -c add.c // 生成add.o

gcc -shared -o libadd.so add.o // 或者使用 ar crv libadd.so add.o

上面可合并成一行: gcc -fPIC -shared -o libadd.so add.c

注: -fPIC 使输出的对象模块是按照可重定位地址方式生成的(即与位置无关).

-shared 指定把对应的源文件生成对应的动态链接库库文件libstr.so文件

4 动态库的使用

4.1 隐式调用

代码编写与静态库一样,不需要包含到处函数的头文件,若主函数是C++程序(即.cpp), 则需要在main.cpp中用extern "C"{} 包含被调用的函数(add.c)的头文件(这里需要包含头文件是与.cpp和.c混合编译有关,同静态\动态库无关),用g++或者用gcc(加上一个链接的参数 -lstdc++)编译.

1 )代码编写:与静态库一样

2 ) 编译main.c 生成可执行程序(动态库隐式调用的使用)

gcc -o main main.c ./libadd.so

或者 gcc -o main main.c -L. libadd.so

(

注:以上两种情况执行./main时会出现./main: error while loading shared libraries,cannot open shared object file: No such file or directory?

解决方案:

方法一: libadd.so放到/usr/lib 或 /lib 中去.

方法二: export LD_LIBRARY_PATH=$(pwd) 或者 export LD_LIBRARY_PATH=./ ,

方法三: 在/etc/ld.so.conf文件加入我们生成的库目录(只支持绝对路径),然后执行 #/sbin/ldconfig.

)

或者将libadd.so 拷贝到目录 /user/lib 或者 /lib 中,然后执行 gcc -o main main.c libadd.so  //此时不需要指定搜索路径

4.2 显示调用

4.2.1 在main.c 中增加头文件 #include 引入dlopen , dlsym , dlclose , dlerror 几个系统调用

主要介绍dlopen()系统调用

第一个参数:指定共享库的名称,将会在下面位置查找指定的共享库.

-环境变量 LD_LIBARARY_PATH列出的用冒号间隔的所有目录

-文件/etc/ld.so.cache重找到库的列表,用 ldconfig 维护

-目录/usr/lib

-目录/lib

-当前目录

第二个参数:指定打开共享库.

-RTLD_NOW:将共享库重的所有函数加载到内存

-RTLD_LAZY:会退后共享库中的函数的加载操作,知道调用dlsym()时方加载某函数

返回值:返回动态库的句柄

#include

#include

int main()

{

int (*func)(int , int );

void *dl = dlopen("./libadd.so", RTLD_LAZY);

if (dl == NULL)

return -1;

func = dlsym(dl, "add");

if (func == NULL)

return -1;

printf("2+3=%d", func(2, 3));

dlclose(dl);

return 0;

}

4.2.2 编译main.c生成可执行程序,动态库已创建

gcc -o main main.c -ldl // 注:使用libld.so库进行系统调用

5 动态库使用中遇到的问题

gcc编译文件时出现undefined reference to 'xxxx'的错误?

这是链接错误,不是编译错误,源程序代码本身没有问题,是你的编译时参数用的不对.你没有指定连接程序要用到的库,比如你的程序里用到了一些数学函数sqrt ,那么你就要在编译参数里指定程序要链接数学库,eg:gcc -o math math.c -lm.

6 gcc中一些参数的作用

6.1 -l 参数和 -L参数

-l 参数就是用来指定程序要链接的库, -l 参数紧接着就是库名, 那么库名跟真正的库文件名有什么关系呢?拿数学库来说,他的库名是m ,他的库文件名是 libm.so ,很容易看出,把库文件名的lib和尾.so 去掉就是库名了. 如第三方库名字叫做libtest.so 那么我们只需要把libtest.so 拷贝到 /usr/lib 或者 /usr/local/lib里,在编译时加上 -ltest 参数,我们就能用上libtest.so库了.

注意:要用libtest.so 库里的函数,我们还需要与libtest.so 配套的头文件.eg:gcc -o test  test.c -ltest(libtest.so 的隐式调用)

6.2 -include 和-I参数

-include 用来包含头文件,但是一般情况下包含头文件都在源码里用#include xxx 实现, -include 参数很少用. -I参数用来指定头文件目录.

/usr/include 目录一般是不用指定的,gcc 知道去那里找,但是如果头文件不在 /usr/include 里我们就要用 -I参数指定. 比如 头文件放在 /myinclude目录里,那么便以命令行就加上-I/myinclude 参数,如果不加就会得到 "xx.h: No such file or deirectory "的错误. (注-I参数也可以用相对路径,比如当前目录,可以用 -I. 来指定). 也可以通过设置环]境变量C_INCLUDE_PATH来指定头文件目录,怎样设置可参看http://www.voidcn.com/article/p-ecxrzhpz-xw.html

额外知识点:

1 Linux静态库的命名规则

static library filename =

lib + +

.a

静态库文件名中间那一部分是库的实际名称,链接器需要使用这个名称来进行链接。

2 Linux动态库命名规则

dynamic library filename =

lib +  +

.so +

动态库文件名中间那一部分是库的实际名称,链接器会在随后的构建时库文件搜索过程中使用这个名称,装在器也会在运行时库文件搜索过程中使用这个名称。

3 动态库的版本信息

dynamic library version information =

..

其中,每个助记符可能使用一个或多个数字来表示

M:主版本号

m:次版本号

p:补丁(很小的代码改动)版本号

4 动态库的soname

library

soname = lib +

name> +

.so +

major version digit(s)>

举例来说,库文件libz.so.1.2.3.4的soname则是libz.so.1

实际上只有主版本好的数字在库soname中起作用,这意味着即使库的次版本好是不同的,也可能使用同一个soname值来表示。

动态库的soname通产由链接器嵌入二进制库文件的专有ELF字段中。通常使用特定的链接器选项,将表示库soname的字符串传递给链接器。比如

$ gcc -shared -Wl, -soname, libfoo.so.1 -o libfoo.so.1.0.0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值