1. 库的介绍
库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。 windows上对应的是.lib .dll linux上对应的是.a .so
2、静态库
静态库:在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。静态库与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。Linux创建静态库过程如下:
[1] 首先,将代码文件编译成目标文件.o(StaticMath.o)g++ -c StaticMath.cpp。
[2] 然后,通过ar工具将目标文件打包成.a静态库文件注意带参数-c,否则直接编译为可执行文件ar -crv libstaticmath.a StaticMath.o(c:创建一个库,r:插入模块若存在同名则替换,v: 程序执行时显示详细的信息)
3、动态库
在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题 ,动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp。
动态库特点总结:
[1] 动态库把对一些库函数的链接载入推迟到程序运行的时期。
[2] 可以实现进程之间的资源共享。(因此动态库也称为共享库)。
[3] 将一些程序升级变得简单。
[4] 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。
4、库文件的链接处理
一个编译单元是指一个.cpp文件以及它所#include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里。链接器之库文件处理:其实链接真正的输入只有两类,一类是目标文件,另一类是库文件(包括通常以.a结束的静态库和以so结束的动态库),当然还有链接脚本输入以及响应文件输入等信息。但是事实上一个库文件也是一个所有目标文件以某种形式组成的打包文件。就好像windows下的winrar或者linux下的tar文件,它都是为了把一个操作系统相关的文件夹表示的文件树结构压缩入一个文件,从而便于传输,因为很多工具都是不支持文件夹传递了(因为文件目录结构是操作系统相关组织形式),例如我们常见的ftp协议以及大部分的IM软件。
所以对于链接器来说,它就执行了对目标文件打包相反的操作,也就是把文件中的符号还原为一些目标文件的组合。但是为了便于链接器更快的知道这个库文件中包含了哪些文件,库文件使用了自己特殊的格式来组织符号,从而可以让链接器尽可能快的确定这个库中的某些文件是否需要。所以库文件的开始列出了自己包含的所有符号的信息(准确的说是已定义符号),在链接器读入库文件的时候,它会决定读取这些信息,决定这个库中符号是否需要。如果当前未定义符号在库文件中有定义,那么就把这个符号所在的目标文件整个作为链接器的目标文件输入。这相当于一个CPU的cache算法,如果有一个cache字节命中,那么整个cache line都被从内存读入CPU cache。
实例
GCC_PATH=`which mips-linux-gnu-gcc`
MIPS_SDK=`dirname $GCC_PATH`/../
echo "$MIPS_SDK"
LINK_LIBS="-lpush -lwlink -lwserver -lrecorder -lwanyee -lm -lrt -lpthread \
-lprotobuf-lite -lzrt_sta -lwywifi -lIOTCAPIs -lAVAPIs -lsCHL -lmp4record \
-lmp4v2 -lfdk-aac -lzlink \
-limp -lalog"
if [ ! -e out ];then
mkdir out
fi
rm out/*
rm libs/libwlink.a
生成.o文件,为制作静态库做准备。 gcc -c的时候 只需要指出inculde
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/tutk -Iinclude/protobuf -I${MIPS_SDK}/include -o out/wlink.o src/wlink/wlink.cpp
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/tutk -Iinclude/protobuf -I${MIPS_SDK}/include -o out/p2p.o src/wlink/p2p.cpp
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/tutk -Iinclude/protobuf -I${MIPS_SDK}/include -o out/ota.o src/wlink/ota.cpp
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/tutk -Iinclude/protobuf -I${MIPS_SDK}/include -o out/test.o src/test.cpp
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/tutk -Iinclude/protobuf -I${MIPS_SDK}/include -o out/aes256.o src/wlink/aes256.cpp
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/tutk -Iinclude/protobuf -I${MIPS_SDK}/include -o out/led.o src/wlink/led.cpp
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/tutk -Iinclude/protobuf -I${MIPS_SDK}/include -o out/key.o src/wlink/key.cpp
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Ijz_oss/include -Iinclude -Iinclude/wanyee -Iinclude/protobuf -I${MIPS_SDK}/include -o out/audio.o src/wlink/audio.cpp
所有的.c 都生成了.o 然后制作.a
mips-linux-uclibc-gnu-ar -cr libs/libwlink.a out/wlink.o out/ota.o out/test.o out/aes256.o out/p2p.o out/audio.o out/led.o out/key.o
mips-linux-uclibc-gnu-gcc -c -fvisibility=hidden -O3 -Iinclude -Iinclude/wanyee -Iinclude/protobuf -I${MIPS_SDK}/include -o out/wyapp.cpp.o wyapp.cpp
这一步要用.o .a .so生成可执行文件,这一步要指出-l(要连接的动/静态库名字) 和-L(库的位置)
mips-linux-uclibc-gnu-g++ -o out/wyapp out/wyapp.cpp.o -Llibs -Llibs/tutk -Llibs/mp4 -Llibs/protobuf -Ljz_oss/lib/uclibc -Wl,-rpath=$ORIGIN -s -fvisibility=hidden -L${MIPS_SDK}/lib ${LINK_LIBS}