linux下静态库和动态库使用的从无到有

首先我们先列出gcc编译器的常用命令:


我们在来看看gcc的编译流程,因为我们在开发工具中玩了太久,一般都会忽略这些细节的:


好,下面我们在来谈一谈静态库和动态库

关于静态库和动态库的优点和结构实现我们就不BB了。

ar是gnu归档工具,rcs表示(replace and create),我们就是要使用这个工具来给我们封装静态库的。

#include "myprintf.h"

int main(void)
{
	myprintf("hello gcc\r\n");
}
#ifndef myprintf_h
#define myprintf_h

#include <stdio.h>

void myprintf(char* str);

#endif
#include "myprintf.h"
void myprintf(char * str)
{
	printf("%s\r\n",str);
}
#首先我们要把该文件制作成.o文件 ,然后使用ar工具将其更改为静态库
gcc -o myprintf.o -c myprintf.c

ar rcs libmyprintf.a myprintf.o
#进行静态库的连接工作
gcc -L . main.c -o main.o -lmyprintf


下面我们来说说动态库的生成与调用

我们还是以上面的几个.c文件为例

首先我们来使用共享的,与地址无关的命令来编译动态库

gcc -I ./include -shared -fPIC -o ~/lib/libmyprintf.so  ./src/myprintf.c//稍后说明为啥把生成的动态库放到~/bin中

注意我们没有加-c哦

然后我们进行动态库的连接

gcc	-I ./include  -L ~/lib ./test/main.c -o main.o -lmyprintf

好了,这样动态库的连接工作就做完了。

然后我们进行LD_LIBRARY_PATH环境变量的配置

找到用户目录下的.bashrc在最后添加如下脚本代码

# set lib so it includes user's private lib if it exists
if [ -d "$HOME/lib" ] ; then
    export LD_LIBRARY_PATH="$HOME/lib"
fi

重新启动bash,以重新加载配置文件,此时在运行main.o则不会报错,要不然会报找不到libmyprintf.so动态库。

那么这是为什么呢,这是因为我们的操作系统默认的动态库查找路径是去

/usr/lib
/lib
/lib64

这几个目录下查找,为了不发生和系统动态库的重叠问题我们在用户目录下创建lib文件夹,以存放我们自己的动态库。



还有就是当我们将我们要调用的xxx.so动态库放到了以上所说的目录中去,我们在执行ldd也是没有找到这个动态库的,这是为什么呢?


这就要牵涉到一个配置文件了,linux操作系统会默认到该配置文件中指定的路径下面查找动态库,因为我们更改了文件结构,但是linux有他自己的优化机制,所以我们得自己手动调用一个命令来时我们的文件结构生效。

sudo /sbin/ldconfig

下面我们来提一提这个配置文件是什么?

假设想往上面两个目录以外加东西的时候,我们不配置环境变量的话,一定要修改/etc/ld.so.conf,然后再调用ldconfig,不然也会找不到 比如安装了一个到/usr/local/mysql,mysql有一大堆library在/usr/local/mysql/lib下面,这时就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib,保存过后ldconfig一下,新的library才能在程序运行时被找到。

好了下面我们来整理一下动态库放置位置的几种方式

1:往/lib和/usr/lib里面加东西,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig

2:想往上面两个目录以外加东西的时候,一定要修改/etc/ld.so.conf,然后再调用ldconfig

3:如果想在这两个目录以外放lib,但是又不想在/etc/ld.so.conf中加东西(或者是没有权限加东西)。那也可以,就是export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找library。


说完这边我们就又需要思考一个问题了,那就是我们用下载的源码,通过makefile进行编译和连接,如果我们在./configure(忘了怎么拼写了,知道我的意思就行)指定我们的安装路径,此时生成的动态库就放在我们指定的路径下时,如我们置顶目录下的./lib/,但是他并没有修改我们的任何文件和环境变量,他又是怎么找到的呢?

那就不得不提到run path 这个名词,就是运行时环境,也就是我们在连接的时候使用指定的命令,这个命令会在可执行文件中写入我们给定的动态库查找路径,这样我们在运行的时候就不需要再做什么多余的操作了~~!

那么怎么实现这样的操作呢?

 gcc -o mian.out main.c -I ../include -L ../lib -lmethod -Wl,-rpath=../lib

这里又有两种概念,一种叫做编译与链接时查找路径,一种叫做运行时查找路径:

编译与链接时查找路径:就是我们指定的-I 头文件的路径 -L动态库的路径 -lmethod动态库的名称,这里的文件只在编译链接时进行参与

运行时查找路径: -rpath 就是运行时动态库的查找路径,那么你会问-Wl是什么意思呢 ,可以自行man page一下,

我简单的说 -Wl 就是一个gcc的选项,表示要调用连接器ld,-rpath 是ld的的一个选项,表示指定程序运行时库的路径。

链接器的选项还有很多我们就不一一介绍了。只要我们明白原理就ok了。





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值