在交叉编译过程中无法使用切换运行环境的方式,因为目标系统不能在当前系统中运行。采用的制作方式是将目标系统存放在当前系统的某个目录,编译链接在该目录下。
程序链接时候需要指定链接函数库的路径,默认情况下链接时的路径与程序运行时的路径是一致的,当程序运行是不能在原路径下找到链接函数库文件就会导致程序无法运行。
在交叉编译过程中必须使用一个非根目录来存放目标系统,如果采用常规的链接,则目标系统运行时候会因为函数库目录位置发生了变化而无法运行。为了解决该问题,在交叉编译过程中引入了sysroot参数。
1、目标系统制作和运行之间的矛盾
在制作本地linux的时候,gcc默认在/usr/include 下查找头文件,binutils在/libs,/usr/lib,LD_LIBRARY_PATH,/etc/ld.so.conf目录中查找共享库。在交叉编译中不能直接为目标系统链接/lib等,因为这些都是主系统的函数库。
制作目标系统和运行目标系统之间的矛盾在于一个路径,该路径在制作过程中需要而在运行的时候不需要,该路径在主系统中用于存放目标系统。
路径的矛盾主要体现在目标系统和主系统运行时根目录结构相同,不能直接在主系统的根目录中完成制作目标系统,这会导致主系统招到破坏。
2、临时系统解决方案
根目录的矛盾在本地系统制作过程中使用临时系统作为过度系统,这样在制作目标系统时候不是由主系统而是临时系统来制作的,临时系统不占用主系统的根目录。
通过做一个能自我编译的临时环境,使其中的命令链接到/tools/lib目录中的函数库,这样避免了和主系统的冲突。然后调整gcc和binutils链接到/tools/lib下。
这样编译出来的程序必须从/tools/lib中查找库文件,这样就不符合lsb的规范。因此临时系统是不能作为目标系统的。使用chroot命令切换到临时系统环境中,此时因为临时系统的所有命令都是链接到/tools/lib的,所以就为我们最后目标系统让出了根目录。从而避免了根目录冲突。
临时系统方案,最关键的就是切换临时系统,但是切换的基础是临时系统必须可以在本地平台运行。交叉编译的临时系统是不能在本地系统运行的,所以不能采用这个办法。
3、sysroot方案
简单理解:编译和链接的默认路径都是${sysroot}/usr,${sysroot}/lib,${sysroot}/usr/include等,默认情况下${sysroot}/是空,如果指定了sysroot=/cross 编译的时候就会去指定目录下查找。
sysroot表示的目录不会用于目标系统的实际运行,仅仅在编译和链接的时候使用,因此只要sysroot设置为目标系统的安装目录就可以解决制作和运行时的矛盾。
sysroot解决了制作和运行时候的矛盾,制作目标系统时候不需要临时系统来过度,直接利用主系统的命令工具来制作目标系统的辅助命令,形成了交叉编译环境。
在sysroot解决方案中,sysroot概念只存在于制作目标系统的相关软件包中,如gcc,binutils,shadow这样的包,这些软件包运行在主系统中,完成整个目标系统的制作后不再参与目标系统的运行。
目标系统中包括binutils和gcc在内的各种软件包都是由交叉编译环境完成的,在整个过程中不会参与制作,因此不需要sysroot的支持。他们是sysroot处理的对象。
4、sysroot的使用
sysroot仅在binutils,gcc以及一些特殊的工具命令中使用。
a、
binutils和gcc由官方支持的。
gcc中的Makefile.in文件中有:
NATIVE_SYSTEM_HEADER_DIR=/usr/include
CROSS_SYSTEM_HEADER_DIR=@CROSS_SYSTEM_HEADER_DIR@
其中CROSS_SYSTEM_HEADER_DIR表示了交叉编译过程中如何查找头文件。该变量在configure中:
CROSS_SYSTEM_HEADER_DIR='$(TARGET_SYSTEM_ROOT)$(NATIVE_SYSTEM_HEADER_DIR)'
其中TARGET_SYSTEM_ROOT在configure中进行了赋值:
TARGET_SYSTEM_ROOT=$with_sysroot
$with_sysroot通过--with-sysroot参数设置传递给configure。
由此可知交叉编译默认支持--with-sysroot ,本地编译不支持。
b、
某些程序也需要处理目标系统中的文件,如shadow设置用户密码,这些工具命令没有提供设置基础目录的方式,也不支持sysroot,无法直接处理目标系统中的相关文件。可以:修改源代码,将默认处理文件的位置前加入目标系统存放路径;或者修改源代码以支持sysroot。
5、sysroot和其他目录参数的关系
与sysroot有关的还有prefix,sysconfdir等设置。prefix和sysconfdir这些参数通常设置的目录之间影哟功能到生成的代码中。sysroot仅仅在编译和链接的时候使用。当使用sysroot方式来制作目标系统的时候,各个软件包不需要考虑目标系统在制作过程中所存放的目录,编译和链接时候会自动按照sysroot设置的目录进行处理。
sysroot目录的设置影响最大的是软件包的安装过程,常见的安装过程中,安装程序会使用prefix设置的目录进行安装。使用sysroot设置目录会导致软件包案prefix设置路径进行安装,如/usr,这样的路径会导致软件包安装到主系统中,这又出现了目录冲突的问题
解决的办法使用一般软件包中自带的DESTDIR参数,该参数设置软件包的安装基础目录。
当设置DESTDIR后会在prefix设置的目录下加上该路径。
通常软件包安装命令:
make install
使用DESTDIR:
make DESTDIR=/cross install
会安装到/cross/usr目录下。