背景
Barrelfish是微软开发的一个开源操作系统。为了研究该系统目前基础设施的完善程度,需要移植一些Linux下的用户空间工具。本文介绍了使用chroot来搭建cross compile环境的过程。
方法比较
为了编译Barrelfish平台上的应用,有两种方法。
使用Hakefile
模仿Barrelfish的其他系统组件,把应用的所有源文件和库依赖都写在Hakefile中,利用Barrelfish的构建系统Hake来生成编译命令。
- 优点
Hake会自动添加必要的编译选项,如果每个C文件都可以编译通过,只要Hakefile中的库依赖填写正确,那么链接过程基本不会出错。
另外,当库的源代码发生变化后,执行make命令就可以自动重新构建应用。
- 缺点
一些较大的工具源码文件比较多,依赖关系错综复杂,有的还需要通过宏定义来对功能进行定制。只有搞清楚所有依赖和需要的宏定义才可以写出正确的Hakefile。
在configure过程中提供所有的编译选项
autoconf是linux下应用的常用构建方式,这类应用编译时分为configure和make两个步骤。在configure步骤时,在CFLAGS环境变量中加入-nostdlib和-nostdinc等参数来定义头文件和库文件的搜索位置,从而实现在make时只使用Barrelfish的头文件和库。
- 优点
不用分析源码间的依赖关系,使用configure可以自动分析系统内可用的库函数和头文件,并生成正确的config.h。一般来说configure步骤通过之后,make步骤是很容易通过的。如果缺少必要的库函数或者头文件,那么configure步骤就会失败并有提示。
- 缺点
与宿主系统的环境混合在一起,
若应用中掺杂了一些自定义的编译步骤,不仅configure步骤有可能无法正确识别环境,生成错误的config.h,也有可能会导致目标文件中链接到宿主系统的代码,使得程序无法再Barrelfish中正确运行。
使用chroot构建编译环境
使用chroot可以切换到一个空的根目录,根目录中的所有文件都是可控的,因此,编译时一定不会被宿主系统污染,也可以通过设置环境变量使得gcc在编译所有程序时,都使用Barrelfish的库和头文件。消除了第二种方法的缺点。
步骤
假设新的根目录位于/my/root目录中。为了方便说明,把该目录导出到环境变量中。
export root=/my/root
挂载必要的文件系统
命令如下mkdir -p $root/sys $root/proc $root/dev sudo mount --bind /sys $root/sys sudo mount --bind /sys $root/proc sudo mount --bind /sys $root/dev
复制必要的程序
此时该根目录中没有任何可用的程序,如果直接使用chroot命令进入目录会有如下错误。> sudo chroot /my/root /bin/bash chroot: failed to run command ‘/bin/bash’: No such file or directory
即使把/bin/bash复制到
/my/myroot/bin
中,依然会有该提示。不过注意,虽然提示相同,但是产生的原因却不同,前者是/bin/bash文件不存在,后者是bash运行所需要的动态链接库文件不存在。因此还需要复制运行时需要的动态链接库。> cp /bin/bash /my/root/bash > ldd /bin/bash linux-vdso.so.1 (0x00007ffd4d7cd000) #对该项的说明见https://en.wikipedia.org/wiki/VDSO libreadline.so.7 => /usr/lib/libreadline.so.7 (0x00007f8d2bbe9000) libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f8d2b9e5000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f8d2b640000) libncursesw.so.