Makefile学习⑦:编译动态库和静态库

编译链接动态库

动态链接库名词解释:
动态:运行时才去加载,动态加载
链接:指库文件和二进制程序分离,用某种特殊手段维护两者之间的关系
:库文件(window下为.dll文件,Linux下为.so文件)

使用动态链接库的好处是程序可以和库文件分离,可以分别发版,然后库文件可以被多处共享

动态链接库:不会把代码编译到二进制文件中,而是运行时才去加载,所以只需要维护一个地址

-fPIC 		产生位置无关的代码
-share 		编译成共享库
-l(小写L)	指定动态库
-I(大写I)	指定头文件目录,默认为当前目录
-L(大写L)	手动指定库文件搜索目录,默认只链接共享目录

随便写个加法函数,将其编译成动态库
add.h

#ifndef _ADD_H_
#define _ADD_H_

#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>

int add(int num1,int num2);

#ifdef __cplusplus
}
#endif
#endif

add.c

#include <stdio.h>
#include <stdlib.h>
#include "add.h"
int add(int num1,int num2)
{
    int ret = 0;

    ret = num1 + num2 ;
    return ret;
}

使用如下编译命令将add.c编译为libadd.so动态库文件

 gcc -shared -fPIC add.c -o libadd.so

在这里插入图片描述
随后再通过链接动态库的方式编译main函数
main.c

#include <stdio.h>
#include <stdlib.h>
#include "add.h"
int main(void)
{
    int a = 1;
    int b = 2;
    int addRet = 0;

    addRet = add(a, b);
    
    printf("a + b = %d\n",addRet);
 
    return 0;
}

编译命令

gcc -o main main.c -L./ -ladd

执行完编译命令后会生成可执行文件main,但是在执行该文件的时候可能会出现报错。
在这里插入图片描述
原因是因为该默认链接的动态库路径未找到libadd.so文件
解决办法有2种
一:将libadd.so拷贝到默认链接的动态库路径下(Linux系统下路径一般为/usr/lib或者)

sudo cp libadd.so /usr/lib/ 

拷贝完毕后再次执行该文件则成功
在这里插入图片描述
二:运行时手动指定动态库的目录
具体命令如下:

export LD_LIBRARY_PATH=(你的动态库所在的路径) 

若无法确定完整路径可直接在动态库当前目录输入pwd命令查看当前路径,直接复制即可
在这里插入图片描述
此方法仅限于当前shell命令窗口和当前用户使用,若退出或者新建shell窗口则无效,属于临时的方法。

编写Makefile实现编译链接动态库

注意在编写Makefile的时候不要忘记了把链接动态库的路径加上,可参考前两种方法。
此处博主采用临时环境变量的方法,因为第一种直接拷贝的方法,针对于无root权限的用户来说无法使用会报错。
在这里插入图片描述

编译静态库

静态链接库:会把库中的代码编译到二进制文件中,当程序编译完成后,该库文件可以删除。

Linux系统中的静态库为.a文件,Windows系统中的静态库为.lib文件

区别于动态链接库:
①动态链接库必须与程序同时部署,还要保障程序能加载的到库文件
②静态库可以不用部署(已经被加载到程序里面了),而且运行时速度更快(因为不用去加载),但是会导致程序的体积更大,并且库中的内容如果有更新,则需要重新编译生成程序。

举个例子:
你要远行,在路上走三天三夜。
动态库就相当于,你背了一袋粮食路上吃,饿的时候才拿出来吃。
静态库就相当于,你在出发前先吃饱,吃饱了在上路,不带粮食。

仍然沿用编译动态库时所创建的的.c文件,采用不同的编译方式将其编译成静态库。
编译顺序如下:

首先将add.c文件编译成add.o文件
再通过命令 ar -r libadd.a add.o
将add.o文件编译生成libadd.a静态库文件

在这里插入图片描述
生成静态库后,再执行编译main.c链接静态库生成main程序
在这里插入图片描述
使用Makefile进行整合优化
代码如下:

TARGET=main
LDFLAGS=-L./
LIBS=libadd.a

$(TARGET):
	$(CC) main.c -o $(TARGET) $(LDFLAGS) -static $(LIBS)
	
clean:
	$(RM) $(TARGET)

在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐