================================= 动态库和静态库 =====================================
库文件是什么?
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: L I B R A R Y P A T H g e c @ u b u n t u : / m n t / h g f s / s h a r e / d a y 03 / c o d e / s t a t i c L i b LIBRARY_PATH gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib LIBRARYPATHgec@ubuntu:/mnt/hgfs/share/day03/code/staticLib echo L I B R A R Y P A T H / h o m e / g e c / l i b : g e c @ u b u n t u : / m n t / h g f s / s h a r e / d a y 03 / c o d e / s t a t i c L i b LIBRARY_PATH /home/gec/lib: gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib LIBRARYPATH/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
C
I
N
C
L
U
D
E
P
A
T
H
/
h
o
m
e
/
g
e
c
/
i
n
c
l
u
d
e
g
e
c
@
u
b
u
n
t
u
:
/
m
n
t
/
h
g
f
s
/
s
h
a
r
e
/
d
a
y
03
/
c
o
d
e
/
s
t
a
t
i
c
L
i
b
C_INCLUDE_PATH /home/gec/include gec@ubuntu:/mnt/hgfs/share/day03/code/staticLib
CINCLUDEPATH/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:
L
I
B
R
A
R
Y
P
A
T
H
−
−
−
>
设
置
库
文
件
路
径
e
x
p
o
r
t
C
I
N
C
L
U
D
E
P
A
T
H
=
/
h
o
m
e
/
g
e
c
/
i
n
c
l
u
d
e
g
e
c
@
u
b
u
n
t
u
:
/
m
n
t
/
h
g
f
s
/
s
h
a
r
e
/
d
a
y
03
/
c
o
d
e
/
d
y
L
i
b
LIBRARY_PATH --->设置库文件路径 export C_INCLUDE_PATH=/home/gec/include gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib
LIBRARYPATH−−−>设置库文件路径exportCINCLUDEPATH=/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: L D L I B R A R Y P A T H − − − 》 将 动 态 库 的 路 径 加 入 环 境 变 量 g e c @ u b u n t u : / m n t / h g f s / s h a r e / d a y 03 / c o d e / d y L i b LD_LIBRARY_PATH ---》将动态库的路径加入环境变量 gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib LDLIBRARYPATH−−−》将动态库的路径加入环境变量gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib echo L D L I B R A R Y P A T H / h o m e / g e c / l i b : g e c @ u b u n t u : / m n t / h g f s / s h a r e / d a y 03 / c o d e / d y L i b LD_LIBRARY_PATH /home/gec/lib: gec@ubuntu:/mnt/hgfs/share/day03/code/dyLib LDLIBRARYPATH/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"