当前位置: 代码迷 >> 综合 >> LinuxC.动态库和静态库以及库链接
  详细解决方案

LinuxC.动态库和静态库以及库链接

热度:84   发布时间:2023-12-29 11:45:58.0

================================= 动态库和静态库 =====================================
库文件是什么?
printf -->有谁见过这个函数的内部实现?
头文件用来做什么?

举例:
你们公司做摄像头的,你卖摄像头会不会把源码卖了?
不卖源码,别人要用所以把源码打包成为库文件
camera.c —>编译成为库文件,比如 libcamera.so
camera.h —>存放相应C文件函数接口说明
只给看的到的函数文件接口说明和看不到内容的库文件

一、静态库
1)用来做什么?
2)静态库格式:libxxx.a
3)将 add.c sub.c 编译为静态库文件,操作步骤如下:

①先把.c文件生成.o文件(机器码)
gcc -c add.c -o add.o
gcc -c sub.c -o sub.o
②再把.o文件合成静态库
ar cr libstatic.a add.o sub.o

使用静态库: 原来的操作:gcc main.c add.c sub.c -o target 现在的操作:gcc main.c -o target -lstatic -L. --》头文件和库文件都在当前路径
-lstatic —>链接库 l —>link
库的格式:libxxx.a
链接库的格式:-lxxx

-L. —>告诉编译器库文件的路径

以下方式常用:
gcc main.c -o target -lstatic -L /home/gec/lib -I/home/gec/include
/home/gec/lib —>存放 libstatic.a 文件
/home/gec/include —>存放 add.h sub.h
-L —》指定库文件的路径
-I —》指定头文件的路径

还有一种不建议的操作:将 相应的库文件 头文件 放入系统默认的路径 : /usr/lib /lib
gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ sudo cp ~/lib/libstatic.a /usr/lib
[sudo] password for gec:
gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ sudo cp ~/include/*.h /usr/include/
gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$
gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ gcc main.c -o target -lstatic —>当前编译不需要指定路径

还有一种办法:将库文件和头文件所在路径添加为默认路径(环境变量)

LD_LIBRARY_PATH
LIBRARY_PATH —》设置的是编译时库文件的路径
C_INCLUDE_PATH —》设置编译时头文件的路径
查看环境变量
echo $LD_LIBRARY_PATH
echo $LIBRARY_PATH
echo $C_INCLUDE_PATH

设置环境变量

export LIBRARY_PATH=path:$LIBRARY_PATH —>设置库文件路径

gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ echo $

LIBRARY_PATH

gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ export LIBRARY_PATH=/home/gec/lib:LIBRARYPATHgec@ubuntu:/mnt/hgfs/share/day03/code/staticLibLIBRARY_PATH gec@ubuntu:/mnt/hgfs/share/day03/code/staticLibLIBRARYP?ATHgec@ubuntu:/mnt/hgfs/share/day03/code/staticLib echo LIBRARYPATH/home/gec/lib:gec@ubuntu:/mnt/hgfs/share/day03/code/staticLibLIBRARY_PATH /home/gec/lib: gec@ubuntu:/mnt/hgfs/share/day03/code/staticLibLIBRARYP?ATH/home/gec/lib:gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib

export C_INCLUDE_PATH=path

gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ echo $C_INCLUDE_PATH

gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ export C_INCLUDE_PATH=/home/gec/include
gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$ echo CINCLUDEPATH/home/gec/includegec@ubuntu:/mnt/hgfs/share/day03/code/staticLibC_INCLUDE_PATH /home/gec/include gec@ubuntu:/mnt/hgfs/share/day03/code/staticLibCI?NCLUDEP?ATH/home/gec/includegec@ubuntu:/mnt/hgfs/share/day03/code/staticLib gcc main.c -o target -lstatic —>前面已经设置过头文件和库文件路径,所以不需要指定路径
gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib$
注意: 使用 静态库 一旦编译得到可执行程序之后就不需要 静态库了 ,可执行文件可以独立运行 缺点就是可执行文件太大

二、动态库 1)格式:libxxx.so 2)将 add.c sub.c 编译为动态库文件,操作步骤如下: gcc -c add.c -o add.o -fPIC gcc -c sub.c -o sub.o -fPIC
gcc -fPIC -shared add.o sub.o -o libdyname.so

编译时的第一种办法: gcc main.c -o target -ldyname -I/home/gec/include

-L/home/gec/lib —》指定动态库文件和头文件的路径
gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$ gcc main.c -o target -ldyname -I/home/gec/include -L/home/gec/lib gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$ ./target ./target: error while loading shared libraries: libdyname.so: cannot open shared object file: No such file or directory gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$

编译时的第二种办法: —》设置相应的路径为环境变量 export LIBRARY_PATH=/home/gec/lib:LIBRARYPATH???>设置库文件路径exportCINCLUDEPATH=/home/gec/includegec@ubuntu:/mnt/hgfs/share/day03/code/dyLibLIBRARY_PATH --->设置库文件路径 export C_INCLUDE_PATH=/home/gec/include gec@ubuntu:/mnt/hgfs/share/day03/code/dyLibLIBRARYP?ATH???>exportCI?NCLUDEP?ATH=/home/gec/includegec@ubuntu:/mnt/hgfs/share/day03/code/dyLib gcc main.c -o target
-ldyname —》编译时不需要指定头文件和库文件的路径 gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$ ./target ./target: error while loading shared libraries: libdyname.so: cannot open shared object file: No such file or directory —》运行时无法链接到动态库的路径 gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$

gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$ echo $LD_LIBRARY_PATH

gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$ export LD_LIBRARY_PATH=/home/gec/lib:LDLIBRARYPATH???》将动态库的路径加入环境变量gec@ubuntu:/mnt/hgfs/share/day03/code/dyLibLD_LIBRARY_PATH ---》将动态库的路径加入环境变量 gec@ubuntu:/mnt/hgfs/share/day03/code/dyLibLDL?IBRARYP?ATH???gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib echo LDLIBRARYPATH/home/gec/lib:gec@ubuntu:/mnt/hgfs/share/day03/code/dyLibLD_LIBRARY_PATH /home/gec/lib: gec@ubuntu:/mnt/hgfs/share/day03/code/dyLibLDL?IBRARYP?ATH/home/gec/lib:gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$ ./target1 sum = 11 sub = 22 gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib$

注意: 动态库编译出来的可执行文件在运行时依然需要链接动态库

三、总结
1)静态库
如何编译得到一个静态库

编译时的第一种办法:直接指定库文件和头文件路径
编译时的第二种办法:设置头文件和库文件所在路径为环境变量
使用 LIBRARY_PATH —》设置静态库所在的路径为环境变量
使用 C_INCLUDE_PATH —》设置头文件所在的路径为环境变量
要想长期有效将相应的命令设置到启动脚本文件 ,比如:~/.bashrc /etc/profile

2)动态库

如何编译得到一个动态库

编译时的第一种办法:直接指定库文件和头文件路径
编译时的第二种办法:设置头文件和库文件所在路径为环境变量
使用 LIBRARY_PATH —》设置静态库所在的路径为环境变量
使用 C_INCLUDE_PATH —》设置头文件所在的路径为环境变量
要想长期有效将相应的命令设置到启动脚本文件 ,比如:~/.bashrc /etc/profile

注意:运行时还是需要链接动态库,所以需要使用 LD_LIBRARY_PATH 设置链接路径 !!!!

3)静态库与动态库的对比

静态库:生成可执行文件后,优点是不再依赖于静态库可独立运行,缺点是库都添加到执行文件里了体积大。
动态库:生成可执行文件后,缺点是要依赖于动态库才能运行,需要使用 LD_LIBRARY_PATH 设置链接路径才可以运行,
优点是生成的文件体积小。

四、如何查询相关的环境变量
命令:export

declare -x C_INCLUDE_PATH="/home/gec/include"
declare -x HOME="/home/gec"
declare -x LD_LIBRARY_PATH="/home/gec/lib:"
declare -x LIBRARY_PATH="/home/gec/lib:"
declare -x PATH="/home/gec/bin:/home/gec/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/arm/5.4.0/usr/bin"
declare -x PWD="/mnt/hgfs/share/day03/作业/test"
declare -x SHELL="/bin/bash"