gcc杂谈

时间:2022-02-09 10:20:44

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查看某个应用程序需要哪些动态库