Library 可分成三种, static 、 shared 与 dynamically loaded 。 1. Static librariesStatic 链接库用于静态链接,简单讲是把一堆 object 檔用 ar(archiver) 包装集合起来,文件名以 `.a' 结尾。优点是执行效能通常会比后两者快,而且因为是静态链接,所以不易发生执行时找不到 library 或版本错置而无法执行的问题。缺点则是档案较大,维护度较低;例如 library 如果发现 bug 需要更新,那么就必须重新连结执行档。 1.1 编译编译方式很简单,先例用 `-c' 编出 object 檔,再用 ar 包起来即可。 ____ hello.c ____ ____ world.c ____ ____ mylib.h ____ $ gcc -c hello.c world.c /* 编出 hello.o 与 world.o */ 这样就可以建出一个档名为 libmylib.a 的檔。输出的档名其实没有硬性规定,但如果想要配合 gcc 的 '-l' 参数来连结,一定要以 `lib' 开头,中间是你要的 library 名称,然后紧接着 `.a' 结尾。 1.2 使用____ main.c ____ 使用上就像与一般的 object 档连结没有差别。 $ gcc main.c libmylib.a 也可以配合 gcc 的 `-l' 参数使用 $ gcc main.c -L. -lmylib `-Ldir' 参数用来指定要搜寻链接库的目录, `.' 表示搜寻现在所在的目录。通常默认会搜 /usr/lib 或 /lib 等目录。 $ ./a.out
2. Shared librariesShared library 会在程序执行起始时才被自动加载。因为链接库与执行档是分离的,所以维护弹性较好。有两点要注意, shared library 是在程序起始时就要被加载,而不是执行中用到才加载,而且在连结阶段需要有该链接库才能进行连结。 首先有一些名词要弄懂, soname 、 real name 与 linker name 。 soname 用来表示是一个特定 library 的名称,像是 libmylib.so.1 。前面以 `lib' 开头,接着是该 library 的名称,然后是 `.so' ,接着 real name 是实际放有 library 程序的文件名,后面会再加上 minor 版号与 一般来说,版号的改变规则是 ( 印象中在 APress-Difinitive Guide to GCC 中有提到,但目前手边没这本书 ) ,最后缀的 release 版号用于程序内容的修正,接口完全没有改变。中间的 minor 用于有新增加接口,但相旧接口没改变,所以与旧版本兼容。最前面的 version 版号用于原接口有移除或改变,与旧版不兼容时。 linker name 是用于连结时的名称,是不含版号的 soname ,如 : libmylib.so 。 2.1 编译shared library 的制作过程较复杂。 $ gcc -c -fPIC hello.c world.c 编译时要加上 -fPIC 用来产生 position-independent code 。也可以用 -fpic 参数。 ( 不太清楚差异,只知道 -fPIC 较通用于不同平台,但产生的 code 较大,而且编译速度较慢 ) 。 $ gcc -shared -Wl,-soname,libmylib.so.1 -o libmylib.so.1.0.0 \ -shared 表示要编译成 shared library 若不指定 soname 的话,在编译结连后的执行档会以连时的 library 档名为 soname ,并载入他。否则是载入 soname 指定的 library 档案。 可以利用 objdump 来看 library 的 soname 。 $ objdump -p libmylib.so | grep SONAME 若不指名 -soname 参数的话,则 library 不会有这个字段数据。 在编译后再用 ln 来建立 soname 与 linker name 两个档案。
2.2 使用与使用 static library 同。 $ gcc main.c libmylib.so 以上直接指定与 libmylib.so 连结。 或用 $ gcc main.c -L. -lmylib linker 会搜寻 libmylib.so 来进行连结。 如果目录下同时有 static 与 shared library 的话,会以 shared 为主。 $ gcc main.c -static -L. -lmylib 此时可以用 ldd 看编译出的执行档与 shared 链接库的相依性 因为编译时有指定 -soname 参数为 libmylib.so.1 的关系,所以该执行档会加载 libmylib.so.1 。否则以 libmylib.so 连结,执行档则会变成要求加载 libmylib.so $ ./a.out 因为找不到 libmylib.so.1 所以无法执行程序。 a. 把 libmylib.so.1 安装到系统的 library 目录,如 /usr/lib 下 3. Dynamically loaded librariesDynamicaaly loaded libraries 才是像 windows 所用的 DLL ,在使用到 3.1 使用方式动态加载是透过一套 dl function 来处理。 ____ dltest.c ____ #include <dlfcn.h> int main() { /* 开启之前所撰写的 libmylib.so 链接库 */ /* 取得 hello function 的 address */ 编译时要加上 -ldl 参数来与 dl library 连结 关于 dl 的详细内容请参阅 man dlopen -- Creating a shared and static library with the gnu compiler [gcc] Program Library HOWTO APress - Definitive Guide to GCC ------------------------------------------------------------------------------------------------------------------ Makefile
clean: |