1. -l选项自动给库文件名增加lib前缀和.a/.so后缀。所以如果你有一个lib叫做libusb.a,那么编译选项是-lusb。另一方面,如果你有一个文件叫做libusb.o(是目标文件而不是库文件),并希望将其作为库的形式使用,那么使用-llibusb.o。
2. pkg-config
这玩意自动给你的gcc命令行加上相关的lib和include位置选项。例如:
gcc -o test test.c ·pkg-config --libs --cflags glib-2.0·
附上pkg-config项目自己给出的介绍:
pkg-config is a helper tool used when compiling applications and libraries. It helps you insert the correct compiler options on the command line so an application can use gcc -o test test.c pkg-config --libs --cflags glib-2.0 for instance, rather than hard-coding values on where to find glib (or other libraries). It is language-agnostic, so it can be used for defining the location of documentation tools, for instance.
3. ldconfig
Linux在加载应用程序的时候,并不直接加载共享库,而是由/lib/ld.so来干这个事情。ld.so在标准路径(/lib,/usr/lib)中寻找共享库。But,如果.so在非标路径,ld.so就抓虾了。所以,我们需要将非标路径加入/etc/ld.so.conf,然后运行ldconfig生成/etc/ld.so.cache。ld.so加载共享库的时候,会从ld.so.cache查找(但不会理睬ld.so.conf!)。
4. 静态库和动态库
4.1 静态库的生成
使用gcc -c生成.o文件,然后使用ar归档为.a文件。
4.2 静态库的使用
4.2.1 直接将.a作为源代码交给gcc:
gcc x.c libmy.a -o myelf
4.2.2 通过指定库文件位置:
gcc -o myelf x.c -LYOUR_LIB_PATH -lmy
4.3 动态库的生成
gcc -o libmy.so -shared my.o [-fPIC]
所生成的.so同时用于编译和执行。
4.4 -fPIC
-fPIC选项生成位置无关代码,即.so内的代码和数据在使用时不需要重定位,但也因为此,只能通过got(global offset table)间接寻址。如果不使用-fPIC,.so在使用时必须进行重定位,为每个使用该库的进程都在物理内存中复制一份副本,因为需要修改其中的地址。
4.5 动态库的使用
4.5.1 直接将.so交给gcc
gcc x.c libmy.so -o myelf
这种方法生成的ELF文件中包含编译时so文件所在的位置,在执行时要求so文件处于相同位置。
4.5.2 使用-L和-l指定.so位置
gcc -o myelf x.c -LYOUR_LIB_PATH -lmy
4.5.3 使用dlopen在应用程序执行时加载
参考http://www.ibm.com/developerworks/cn/linux/l-dynamic-libraries/index.html
4.5.4 其他
上面我们说过,.so同时用于编译和执行,但编译和执行时的查找方式和顺序是不一样的(嗯,在历史上曾经一样过)。
编译时gcc的查找顺序:
- LIBRARY_PATH(仅对native编译器有效,对cross compiler无效)
- -L -l指定位置
- 标准位置
执行时ld.so的查找顺序:
- LD_LIBRARY_PATH
- 标准位置
- ld.so.cache指定位置
4.6 可以通过ldd查看某个应用程序需要哪些动态库