赞
踩
我们知道从源文件到可执行程序需要如下经历4个步骤
这里的动静态库本质上就是xxx.o文件的集合
下面用一份简单的代码来认识动静态库
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
可以通过 ldd+文件名 来查看一个可执行程序所依赖的库文件。
使用 file+文件名 可以查看文件类型
图中 libc.so.6 表示c语言动态库,在Linux中生成的可执行程序默认情况下是动态库链接。
想要让生成的可执行程序为动态链接,需要添加 -static 选项。
从图中我们发现静态生成的可执行程序比动态生成的可执行程序要大得多
查看文件类型
静态链接生成的可执行程序并不依赖其他库文件,此时当我们使用ldd 文件名命令查看该可执行程序所依赖的库文件时就会看到以下信息。
静态库:
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
优点:
缺点:
动态库:
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
优点:
缺点:
下面演示静态库的打包和使用,先创建两个源文件add.c,sub.c,再创建两个头文件add.h,sub.h。
add.h
#pragma once
extern int my_add(int x, int y);
add.c
#include "add.h"
int my_add(int x, int y)
{
return x + y;
}
sub.h
#pragma once
extern int my_sub(int x, int y);
sub.c
#include "sub.h"
int my_sub(int x, int y)
{
return x - y;
}
ar命令是gnu的归档工具,常用于将目标文件打包为静态库,下面我们使用ar命令的-r选项和-c选项进行打包。
这里可以将头文件sub.h和add.h,静态库文件libmymath.a放入新建的目录lib下,此时可以将lib给别人使用了。
下面尝试使用我们打包好的静态库文件lib
创建main.c文件
#include<stdio.h>
#include "add.h"
#include "sub.h"
int main()
{
printf("%d\n",my_add(10,20));
printf("%d\n",my_sub(10,20));
return 0;
}
现在该目录下就只有main.c和我们刚才打包好的静态库。
此时使用gcc编译main.c生成可执行程序时需要携带三个选项:
注意:
了解静态库的使用规则后,我们不禁会产生疑问,为什么之前使用gcc编译的时候没有指明过库名字?
因为我们使用gcc编译的是C语言,而gcc就是用来编译C程序的,所以gcc编译的时候默认就找的是C库,但此时我们要链接的是哪一个库编译器是不知道的,因此我们还是需要使用-l选项,指明需要链接库文件路径下的哪一个库。
实际上我们拷贝头文件和库文件到系统路径下的过程,就是安装库的过程。
我们还是用上面四个文件演示
这里我们使用Makefile文件
这里的makefile文件可以将要生成的文件一次性全部生成,如下图
注意:
再将生成的头文件和动态库(libmymath.so)打包
还是用刚才的main.c文件演示
用和静态库一样的方法生成可执行程序
运行一下,发现生成的可执行程序报错了
用ldd指令看看可执行程序所属
从图中可以看到,此时可执行程序所依赖的动态库是没有被找到的。
解决方法:
LD_LIBRARY_PATH是程序运行动态查找库时所要搜索的路径,我们只需将动态库所在的目录路径添加到LD_LIBRARY_PATH环境变量当中即可。
此时系统可以找到该可执行程序所依赖的动态库,程序也可以执行了。
/etc/ld.so.conf.d/路径下存放的全部都是以.conf为后缀的配置文件,而这些配置文件当中存放的都是路径,系统会自动在/etc/ld.so.conf.d/路径下找所有配置文件里面的路径,之后就会在每个路径下查找你所需要的库。我们若是将自己库文件的路径也放到该路径下,那么当可执行程序运行时,系统就能够找到我们的库文件了。
在/etc/ld.so.conf.d/路径下新建一个以.conf为后缀的配置文件,将动态库的路径拷贝到该文件下
此时我们用ldd命令查看可执行程序时,发现系统还是没有找到该可执行程序所依赖的动态库。
我们需要使用ldconfig命令将配置文件更新一下
此时可以正常运行文件了
方法二和方法三不推荐,会污染路径。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。