一、 头文件
1 “”中的头文件,在源文件当前目录查找
2 -I 中指定目录 -I可以在CFLAG中指定
3 gcc的环境变量 C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH
4 编译器预设路径、内定目录:
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g -3
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include
但是假如装gcc的时候,有给定的prefix的话,那么就是
/usr/include
prefix/include
prefix/xxx-xxx-xxx-gnulibc/include
prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include
此外还可用pkg-config 程序,用来在编译脚本中向编译器传递头文件包含路径或库文件路径。 Linux下那么多库,在./configure时时怎么判断它们存不存在的,难道是靠递归搜索?pkg-config这个命令和/*/lib/pkgconfig下的一些.pc文件才是主角。每个.pc文件定义了库的名字、路径、编译选项等,比如glib-2.0.pc文件:
prefix=/usr
exec_prefix=${prefix}
libdir=/usr/lib
includedir=${prefix}/include
glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums
Name: Glib
Description: C Utilitiy Library
Version: 2.14.4
Libs: -L${libdir} -lglib-2.0
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include
--cflags 参数可以给出在编译时所需要的选项,而 --libs 参数可以给出连接时的选项
configure到某个库的时候,pkg-config命令会首先去环境变量PKG_CONFIG_PATH定义好的路径下搜索库名字对应的.pc文件(库名加.pc),找到了就行了,等会儿make的时候就可以通过正则表达式取出libs和cflags的值来使用。
如configure文件中有:
pkg_XLIB_CFLAGS='$PKG_CONFIG --cflags "x11" 2>/dev/null'(还是`***`)(结果是-I的形式)
(x11表示libx11库),这些参数配置结束后写入Makefile。
配置 pkgconfig
PKG_CONFIG_PATH 的缺省设置是 /lib/pkgconfig, /usr/lib/pkgconfig 和 /usr/local/lib/pkgconfig. 这些设置都是硬编码的,所以不用另外设置它们。
二、 库文件
Ø 编译的时候动态库的搜索路径:
1 gcc会去找-L 指定的路径和 -l指定的库(指定库的路径)
2 由'-rpath-link'选项指定的搜索路径 在LDFLAGS中gcc 的参数"-Wl,-rpath-link,-Wl"指定。 '-rpath-link'比‘-L’多一功能,指定的目录还可用于搜索依赖库。
3 由'-rpath'指定的搜索路径. '-rpath'跟'-rpath_link'的不同之处在于,由'-rpath'指定的路径被包含在可执行文件中,并在运行时使用, 而'-rpath-link'选项仅仅在连接时起作用.'-rpath'比'-rpath-link'多一功能,指定路径编译进程序,当程序运行时,首先从这些目录中寻找库。
4 再找内定目录 /lib、 /usr/lib、 /usr/local/lib 这是当初compile gcc时写在程序内的
'-rpath'跟'-rpath_link'用来指定依赖库的路径
Ø 对于交叉编译,链接时库搜索路径及优先顺序如下:
1 -rpath-link 指定
2 -rpath 指定
3 –L 指定
4 连接器的默认链接目录,通常在交叉编译器目录下。
Ø 如何指定-rpath-link :在configure之前设置LDFLAGS,如
export LDFLAGS = " -Wl,-rpath-link -Wl,目录/lib"(-Wl表示用于连接器)
在configure文件中也有:
pkg_XLIB_CFLAGS='$PKG_CONFIG --libs "x11" 2>/dev/null'(还是`***`)
本人注解:
man gcc:
-Wl指示参数option是传给ld的,而option如果包含逗号,则option会以逗号切割为多个参数传递给ld-Wl,option
Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example,
-Wl,-Map,output.map' passes
-Map output.map' to the linker. When u> sing the GNU linker, you can also get the same effect with `-Wl,-Map=output.map'.
gcc -Wl,aaa,bbb,ccc
最终会变成:
ld aaa bbb ccc
你也可以这样:
gcc -Wl,aaa, -Wl,bbb -Wl,ccc
Ø 运行时动态库的搜索路径
1Ø进程启动时加载
首先 LD_PRELOAD
1、 -rpath指定目录(在编译目标代码时指定程序的动态库搜索路径"-Wl,-rpath,"指定)
2、 通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔)
3、 /etc/ld.so.cache中指定的动态库搜索路径, 由ldconfig读取配置文件/etc/ld.so.conf 生成。
4、 默认的动态库搜索路径/lib
5、 默认的动态库搜索路径/usr/lib
2Ø 运行时加载 dlopen()
第一个参数:指定共享库的名称,将会在下面位置查找指定的共享库。
-/开头,绝对路径,名字必须完全匹配。
-环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。
-文件/etc/ld.so.cache中找到的库的列表,用ldconfig维护。
-目录usr/lib。
-目录/lib。
-当前目录。
第二个参数:指定如何打开共享库。
其中flag有:RTLD_LAZY RTLD_NOW RTLD_GLOBAL,其含义分别为:
RTLD_LAZY:在dlopen返回前,对于动态库中存在的未定义的变量(如外部变量extern,也可以是函数)不执行解析,就是不解析这个变量的地址。
RTLD_NOW:与上面不同,他需要在dlopen返回前,解析出每个未定义变量的地址,如果解析不出来,在dlopen会返回NULL,错误为:
: undefined symbol: xxxx.......
RTLD_GLOBAL:它的含义是使得库中的解析的定义变量在随后的随后其它的链接库中变得可以使用。
转载子Linux操作系统的头文件和库文件搜索路径,红色部分为本人添加注释。