1、FAQ
1.1、glibc安装时.so库文件和.h头文件都安装到什么文件夹,gcc怎么能正确的找到相应的文件夹?
当我们在build gcc时设定–prefix=/path/,则gcc安装到/path/,gcc默认会在/path/lib/路径下搜寻库,在/path/include/路径下搜寻头文件。
例如,一般linux系统把gcc和glibc都安装到/usr/目录,所以gcc可执行文件在/usr/bin目录下,而glibc的库文件在/usr/lib目录下,glibc的头文件在/usr/include目录下。
当然上述的关系并不是一定的,在安装gcc和glibc的时候可以手工指定。可以使用命令“gcc -print-search-dirs”来查看gcc库的搜索路径:
可以使用以下几种方法来更改gcc默认搜寻的库路径和头文件路径:
- (1)使用 “gcc –nostdlib –Lusrlibpath”来改变gcc的默认库搜索路径,使用 “gcc –nostdinc –Iusrincpath”来改变gcc的默认头文件搜索路径。
- (2)使用“gcc –Wl, –sysroot=” 来改变gcc的默认库搜索路径。
- (3)更改gcc的specs文件来自定义gcc的任何选项。
Specs是gcc的配置文件。这种修改方法功能最强大,但是难度和风险也最大,因为gcc的spec文件比较晦涩难懂,我也暂时不会修改,只是先给大家介绍有这种方法的存在。
使用“gcc –v“命令查看gcc specs的路径:
也有些安装的gcc使用的是内置的spec,而没有外置的spec文件:
对于内置的spec,可以使用命令“gcc -dumpspecs “查看具体的spec内容:
也可以使用“gcc -specs= “来指定gcc的spec文件。
- (4) gcc默认的配置是否在build时由configure命令传入的?
使用“gcc –v“命令可以查看gcc的configure值,关于configure选项的说明在gcc-4.1.0\gcc\doc\install.texi文件中有详细描述。
1.2、程序链接时,链接库的搜寻路径有哪些?
链接时,库的搜寻路径的配置有以下方法:(具体使用可参见实例一章的描述)
- (1) 使用 “gcc –Llibpath –llibname”指定链接库搜寻路径。
- (2)使用环境变量“LIBRARY_PATH” 指定链接库搜寻路径。
- (3)使用ld连接脚本中的 “SEARCH_DIR” 指定链接库搜寻路径。
1.3、程序运行时,动态链接库的搜寻路径有哪些?
链接时,库的搜寻路径的配置有以下方法:(具体使用可参见实例一章的描述)
- (1) 编译时使用 “gcc –Wl,-rpath”指定运行时动态链接库的搜寻路径,硬编码进ELF文件 “RPATH”选项。
- (2) 编译时使用环境变量 “LD_RUN_PATH”指定运行时动态链接库的搜寻路径,硬编码进ELF文件 “RPATH”选项。
- (3)使用环境变量 “LD_LIBRARY_PATH”指定运行时动态链接库的搜寻路径。
- (4)使用配置文件“/etc/ld.so.conf”指定运行时动态链接库的搜寻路径。
- (5)使用运行时动态链接库的默认搜寻路径“/lib、/usr/lib”。
1.4、程序编译时,头文件的搜寻路径有哪些?
编译时,头文件的搜寻路径的配置有以下方法:(具体使用可参见实例一章的描述)
- (1) 编译时使用“gcc –I incpath”指定头文件搜寻路径。
- (2) 编译时使用环境变量 “C_INCLUDE_PATH”指定头文件搜寻路径。
- (3) 编译时使用gcc的默认头文件搜寻路径。
常用头文件目录的说明:
- (1)、/usr/src/linux/include:
/usr/src/linux/是内核源码路径,/usr/src/linux/include包含的是内核头文件,一般在编译模块时使用。
- (2)、/usr/include
/usr/include路径主要是glibc的头文件,是用来编译用户态文件的。但是/usr/include其中也包含内核头文件所需的linux/、asm/文件夹,但是这两个文件夹主要是用来做一些兼容性用的,真正用到内核头文件还是要用/usr/src/linux/include。
1.5、制作交叉编译器时,各项搜寻路径的配置?
制作交叉编译器时,需要关注相关四种路径的配置:编译时链接的库文件路径、编译时用到的头文件路径、编译时用到的二进制工具路径、编译时指定的动态加载器的名称路径。
- (1)、编译时链接的库文件路径:
如果不指定,应该是和安装路径相关的默认路径。如果要指定,可以在编译binutils中ld的时候,使用“LIB_PATH”选项指定:
- (2)、编译时用到的头文件路径:
- (3)、编译时用到的二进制工具路径:
默认二进制工具的路径,可以使用以下命令查看:
使用指定的二进制工具,可以使用“gcc -B”选项:
- (4)、编译时指定的动态加载器的路径和名称:
硬编码进elf的动态加载器路径和名称,由gcc spec文件指定:
2、实例操作
生成两个.c文件:
cat >say.c<<eof
#include "stdio.h"
void say()
{
printf("Say!");
}
Eof
cat >test.c <<eof
#include "stdio.h"
void say();
main(){
say();
}
eof
2.1、链接时库的搜寻路径
将say.c编译成libsay.so,再在编译test.c时来链接libsay.so,用以测试gcc链接时库的搜寻路径。
- (1)使用 “gcc –Llibpath –llibname”指定链接库搜寻路径:
(2)使用环境变量“LIBRARY_PATH” 指定链接库搜寻路径:
(3)使用ld连接脚本中的 “SEARCH_DIR” 指定链接库搜寻路径:
使用“ld –verbose”命令查看gcc的默认链接脚本中SEARCH_DIR参数,当然你也可以使用 “ld –Txxx.lds”来指定链接脚本。
拷贝libsay.so到SEARCH_DIR指定路径,并链接测试:
2.2、运行时动态加载库的搜寻位置
- (1) 编译时使用 “gcc –Wl,-rpath”指定运行时动态链接库的搜寻路径,硬编码进ELF文件 “RPATH”选项:
使用readelf文件查看elf文件中的硬编码运行时库搜寻路径:
- (2) 编译时使用环境变量 “LD_RUN_PATH”指定运行时动态链接库的搜寻路径,硬编码进ELF文件 “RPATH”选项:
- (3)使用环境变量 “LD_LIBRARY_PATH”指定运行时动态链接库的搜寻路径:
(4)使用配置文件“/etc/ld.so.conf”指定运行时动态链接库的搜寻路径:
(5)使用运行时动态链接库的默认搜寻路径“/lib、/usr/lib”:
生成一个.c文件和一个.h文件:
cat >test1.c <<eof
> #include "test1.h"
> void main()
> {
> printf("Test .h include!\n");
> }
> eof
cat >test1.h <<eof
> #include "stdio.h"
> eof
2.3、程序编译时,头文件的搜寻路径有哪些?
(1) 编译时使用“gcc –I incpath”指定头文件搜寻路径:
(2) 编译时使用环境变量 “C_INCLUDE_PATH”指定头文件搜寻路径:
- (3) 编译时使用gcc的默认头文件搜寻路径:
gcc的默认头文件搜寻路径设置方法还没弄明白。但是可以使用以下命令查看:
使用默认路径来编译: