Building armlinux toolchain for ARM/XScaleiWMMXt(new ABI)

Building armlinux toolchain for ARM/XScaleiWMMXt(new ABI)
Aaron Wong aaronwong@engineer.com


0 Preface
两个月前,笔者在ChinaUnix BLOG 上发表了一篇日志Building arm-linux
toolchain for ARM/XSCALE,详细介绍了手工建立ARM-linux的交叉编译工具链的全过程,
但这种方法越来越体现出局限性和落后性,主要表现在:
(1)使用的软件包版本较老;
(2)使用linux-threads而非新的NPTL(Native POSIX Threading Library)线程模型;
(3)所建立的toolchain遵循旧的ABI标准,而非新的 ARM AB I 标准 ;
(4)对目标系统采用了旧的根文件系统的布局方式,所有的目标库文件都放在/lib目
录下;
(5)并没有实现真正意义上为某一处理器特性(例如PXA27x系列的iWMMX技术)进行量
身定制toolchain的目标。
此外,手工建立toolchain的过程非常繁琐,虽然可以对建立的过程进行全程控制,
但稍有疏忽就会导致失败,因此是非常耗时耗力的。
本文分析了crosstool 工具的工作机制,并以PXA27x处理器的cross toolchain建
立过程为例,介绍了使用crosstool工具自动建立交叉编译工具链的方法。新的cross
toolchain的特点在于:
(1)使用最新版本的软件包和内核(gcc-4.2.1/glibc-2.6.1/kernel-2.6.22);
(2)支持新的NPTL(Native POSIX Threading Library)线程模型;
(3)所建立的toolchain遵循新的 ARM AB I 标准 ;
(4)对目标系统采用了新的根文件系统的布局方式,库文件分开放置在/lib和
/usr/lib目录下;
(5)针对PXA27x处理器的特性( iWMMX 技术 ),对toolchain进行了量身定制。
笔者建立交叉编译工具链的主机环境:
2.6.20-1.2962.fc6,binutils-2.17.50,gcc-4.1.1,make 3.81。
更多相关问题的说明见文后附录,包括一些具有实际参考价值的链接。
1 Choose and Download Source Packages
本文所选用的软件包及补丁如下:
①binutils-2.18.tar.bz2
②gcc-4.2.1.tar.bz2
③glibc-2.6.1.tar.bz2
④linux-headers-2.6.22.6-09032007.tar.bz2
⑤binutils-2.18-posix-1.patch
⑥gcc-4.2.1-cross_search_paths-1.patch
⑦gcc-4.2.1-posix-1.patch
⑧glibc-ports-2.6.1.tar.bz2
⑨glibc-2.6.1-libgcc_eh-1.patch
⑩glibc-2.6.1-localedef_segfault-1.patch
⑪glibc-2.6.1-cross_hacks-1.patch
⑫glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch
上述软件包的选择依据来自Cross-Compiled Linux From Scratch-Sysroot(Version
SVN-0.0.1-20070915-ARM)。
将这些软件包下载到特定的目录下(根据你自己的喜好和对crosstool的修改而定,
本文下载到/home/aaronwong/crosstool/build/arm-iwmmxt-linux-gnueabi/gcc-4.2.1-
glibc-2.6.1目录下,用crosstool中的变量表示就是$BUILD_DIR),手工解压缩并打好补丁。
以glibc为例:
[说明] 事实上,crosstool可以自动为我们下载指定的软件包及相应版本的补丁,
并自动解压缩和打补丁,这通过getandpatch.sh脚本来实现。由于本文不需要其他补丁和
软件包,而且所需补丁的下载地址并不在getandpatch.sh的搜索范围内,所以这里采用手
工下载软件包,解压并打补丁的方式,并修改crosstool的相关脚本以禁止调用
getandpatch.sh。
2 Custom crosstool
2.1 Crosstool Intro
Crosstool 是Dan Kegel等人开发的一套自动建立linux交叉编译工具链的自由软件,
支持多种处理器体系结构,目前最新版本是crosstool-0.43。不过,“原始的”crosstool
建立的toolchain遵循的是old ABI,不支持新的ARM EABI。
Martin Gu y 为 crosstool-0.4 2 提供了一个 patch ,使得它可建立符合ARM EABI标准
的toolchain。鉴于此,本文使用crosstool-0.42.tar.gz 和crosstool-0.42-mg2.patch 来建
立toolchain。
在对crosstool进行修改和配置之前,强烈推荐阅读crosstool-howto 和Crosstool
variables;若有能力则还可以通读crosstool的几个核心脚本,弄清楚变量的定义、用途
以及传递方式(在此过程中您可能需要参考 CLFS-Sysroot Par t Ⅲ . Make the CrossCompile
Tools 或其他文档来了解建立toolchain的基本过程以及各软件包的configure选
项的用途)。
2.2 Crosstool Mechanism
这里简单介绍crosstool工具自动建立toolchain的机制。Crosstool有如下几个核
心文件:
① cpu.dat:指定如下参数(仅列出所关心的几个):
KERNELCONFIG 指定linux内核的配置文件,用于产生glibc所需的内核头文件;
若已有“纯净的”内核头文件,则不需要设置此参数。
TARGET 目标名,指定要建立的交叉编译工具为何种系统产生代码。例如
arm-unknow-linux-gnu。
TARGET_CFLAGS 通常指定为”-O”,也可以不指定。
GCC_EXTRA_CONFIG 在建立gcc-core和gcc时,传递额外参数给gcc的configure脚本,
主要用于指定处理器特性和对相应库的设置,例如:
--with-cpu=iwmmxt --enable-cxx-flags=-mcpu=iwmmxt
GLIBC_EXTRA_CONFIG 在建立glibc时,传递额外参数给glibc的configure脚本,例如
目标处理器没有硬件浮点运算单元时,可以指定--without-fp
USE_SYSROOT 若留空,目标系统根目录采用传统方式布局(所有库文件都放在
/lib目录下);若为1(非空),采用新的布局方式(库文件分开放置
在/lib和/usr/lib目录下)。
② gcc-glibc.dat:指定所用软件包解压之后的目录名,通常附带版本号。一个典
型的例子如下:
需要指出,LINUX_SANITIZED_HEADER_DIR指的是“纯净的”内核头文件的目录名。
另外,如果使用的gcc-core软件包与gcc软件包版本不同,还要指定GCC_CORE_DIR;如
果要编译GDB,则还要指定GDB_DIR。
③ demo-*.sh(例如demo-arm-iwmmxt.sh):设置源码包的下载目录TARBALLS_DIR,
以及toolchain的安装的顶层目录RESULT_TOP,还设置最终的cross-compiler的程序语言
支持(GCC_LANGUAGES,默认为c,c++),然后将cpu.dat和gcc-glibc.dat中定义的参数传递
给all.sh脚本,开始自动建立toolchain的过程。
④ all.sh检查所接收到的参数值,并设置内部变量的值(值得注意的是BUILD_DIR
和SRC_DIR, PREFIX, GCC_HOST等变量,下文会再说明),检查要下载、解压缩和打补丁、
BINUTILS_DIR=binutils-2.18
GCC_DIR=gcc-4.2.1
LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.22.6
GLIBC_DIR=glibc-2.6.1
GLIBCPORTS_FILENAME=glibc-ports-2.6.1
GLIBC_ADDON_OPTIONS=ports,nptl
以及要编译的软件包,清除和建立相关目录,调用getandpatch.sh脚本自动下载所需的软
件包到$BUILD_DIR并打补丁,然后调用crosstool.sh脚本自动建立toolchain,建立完毕
再视用户传递过来的参数判断是否要编译gdb,是否要测试编译linux内核等。
⑤ getandpatch.sh:被all.sh调用,用于自动下载软件包,打补丁。
⑥ crosstool.sh:被all.sh调用,是建立toolchain的核心脚本文件。
其他脚本就不作介绍了。
另外,在crosstool目录下还有两个小程序。一是config.guess脚本,如果不指定
BUILD变量的值,则在crosstool.sh脚本中,会把config.guess的运行结果作为BUILD的值;
在笔者的主机上运行结果为i686-pc-linux-gnu。二是fix-embedded-paths.c,在完成
toolchain的建立之后,crosstool.sh脚本会把它编译为一个可执行文件,可以用来手动调
整toolchain的安放位置。
其他说明:
(1)BUILD,GCC_HOST,GCC_BUILD:在crosstool.sh中。
缺省情况下,$GCC_BUILD=$GCC_HOST=$BUILD=`./config.guess`。GCC_HOST和
GCC_BUILD相同表示不是”Canadian cross”方式(所谓Canadian cross ,是指建立
toolchain的机器平台GCC_BUILD与运行toolchain的机器平台GCC_HOST不同),而一般情
况下我们建立toolchain的机器就是运行toolchain编译目标平台代码的机器。这样,
$GCC_HOST就可作为参数传递给gcc的configure脚本的—host选项,即--host=i686-pclinux-
gnu,表示最后编译出来的cross-compiler所运行的主机类型。$BUILD则作为参数
传递给glibc的configure脚本的--build选项。
(2)SHARED_MODE:在crosstool.sh中。缺省情况下为—enable-shared。
(3)什么是gcc-core?通俗的说,就是用来编译glibc的compiler,亦即gcc
stage_1,或说是bootstrap gcc。
2.3 Custom our own Crosstool
2.3.1 下载crosstool0.42
并打补丁
下载crosstool-0.42.tar.gz 和crosstool-0.42-mg2.patch,解压缩并打补丁。
2.3.2 定制自己的crosstool
(1) 建立自己的crosstool目录,并拷贝必要的文件。
(2) 编辑cpu.dat和gcc-glibc.dat文件。
显然我们还缺少这两个核心文件来传递必要的参数,我们将这两个文件分别命名为
arm-iwmmxt-eabi.dat和latest.dat。编辑arm-iwmmxt-eabi.dat文件如下:
注意,TARGET的名字并不是随意的,必须以arm开头而不能是pxa27x等其他字符
串开头,因为crosstool会根据TARGET的名字来解析$ARCH的值。gcc的configure文件
也要根据TARGET名字来进行裁决,如果要编译新的ARM EABI标准的toolchain,TARGET
名字应该以arm*-*-linux-gnueabi形式出现。这里设置USE_SYSROOT是要按新的组织形式
来安排目标系统根目录的库文件。
编辑latest.dat如下:
(3) 将demo-arm-iwmmxt.sh重命名为arm-iwmmxt-eabi.sh,并编辑如下:
TARGET=arm-iwmmxt-linux-gnueabi
TARGET_CFLAGS="-O"
GCC_EXTRA_CONFIG="--with-float=soft --with-cpu=iwmmxt --witharch=
iwmmxt --enable-cxx-flags=-msoft-float"
GLIBC_EXTRA_CONFIG="--without-fp --disable-libunwind-exceptions"
GLIBC_EXTRA_CC_ARGS="-finline-limit=10000"
USE_SYSROOT=1
BINUTILS_DIR=binutils-2.18
GCC_DIR=gcc-4.2.1
LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.22.6
GLIBC_DIR=glibc-2.6.1
GLIBCPORTS_FILENAME=glibc-ports-2.6.1
GLIBC_ADDON_OPTIONS=ports,nptl
(4) 修改all.sh。
① 注释掉getandpatch.sh的调用部分。因为我们是手工下载源码包并打补丁的,
只要把处理好的源代码放到相应目录下即可,不需要getandpatch.sh自动下载源码包。
② 根据个人喜好修改PREFIX的值:
设置“PREFIX=$RESULT_TOP=/opt/crosstool”可使目标系统的根目录更“浅”,
这是因为crosstool.sh中设置了SYSROOT=${PREFIX}/${TARGET}/sys-root,于是相当于有
$SYSROOT=/opt/crosstool/arm-iwmmxt-linux-gnueabi/sys-root。
③ 禁止自动进行目录清理:
由于arm-iwmmxt-eabi.sh中调用all.sh时没有传递--nobuild参数,因此上面被注
释掉的语句会清除旧的$BUILD_DIR,建立一个新的干净的$BUILD_DIR,然后再调用
crosstool.sh建立toolchain。
另一方面,由于我们是要手工将源码包处理好放到SRC_DIR的,又因为没有给出
SRC_DIR的值,all.sh认为SRC_DIR=$BUILD_DIR,这样实际上要求我们把源码包放到
BUILD_DIR下,于是上面的语句恰好把我们的SRC_DIR连同其中处理好的源码包一起删除
了。所以要把上面的语句注释掉。
[说明]另外一种简单解决方法是,在arm-iwmmxt-eabi.sh中调用all.sh时传递—
nobuild参数,然后把手工处理好的源码包都放到SRC_DIR(实际上也就是相同的
BUILD_DIR下),这样就不必注释掉上面的语句了。
④ 其他注释:
(5) 修改crosstool.sh。
① 修正内核头文件的安装。
按照原来的脚本,会漏拷include/asm-generic目录,导致编译时找不到头文件而
报错退出。
② 禁止修改GCC_HOST。
本来有GCC_HOST=`./config.guess`=i686-pc-linux-gnu,上面的语句会将其更改为
GCC_HOST=i686-host_pc-linux-gnu,导致在编译时找不到主机的CC而出错。
2.3.3 源码包处理与目录组织
接下来要按上面脚本中的目录设置来组织源码包并建立相应目录。
(1) 必须手动建立的目录:RESULT_TOP=/opt/crosstool(见arm-iwmmxt-eabi.dat),
以及BUILD_DIR=`pwd`/build/$TARGET/$TOOLCOMBO (见all.sh) =
~/crosstool/build/arm-iwmmxt-linux-gnueabi/gcc-4.2.1-glibc-2.6.1。
注意,用root用户建立交叉编译工具是不安全的,应该用普通用户登录;因此必须
要改变安装目录/opt/crosstool的所有者,以让普通用户(笔者是aaronwong)拥有该目录
的读写权限。
(2) 源码包处理:将所有的源码包放到$BUILD_DIR目录下,并解压缩,打补丁。最
后的各源码包目录名应该与latest.dat中设定的一致。以linux內核头文件安装为例:
2.3.4 开始自动安装
经过前面的定制之后,只要在终端下输入命令”sh arm-iwmmxt-eabi.sh”,计算机
就开始自动编译安装toolchain,大约40 – 90分钟便可完成(视主机系统的配置而定)。
[提示] 2.3节仅是笔者根据需要对crosstool所作的定制,采用手动下载源码包并打
补丁的方法,建立支持PXA27x处理器iWMMX技术的符合ARM EABI标准的toolchain。读
者可以在理解crosstool工作机制的前提下,根据自己的实际情况作相应的定制。
3 Install and Test Toolchain
3.1 自动安装及路径设置
其实上面一节已经介绍了执行脚本(arm-iwmmxt-eabi.sh)进行自动安装的步骤,这
里重提仅是为了章节的连续性~ ^_^
自动安装完毕还应该将toolchain的路径添加到环境变量PATH中去,这样只需用可
执行文件名便可调用toolchain,而不必使用绝对路径。
用vim编辑~/.bash_profile,加入下面一行:
PATH=/opt/crosstool/bin:$PATH
保存退出,执行”source ~/.bash_profile”,使刚才的修改生效(仅对当前终端有
效,若要全局有效则需要注销或重启)。
3.2 Toolchain测试
最简单和最基本的测试如下:
对于所建立的交叉编译工具链的测试,更严格有效的测试是对目标系统的内核进行
编译,并在构建好目标系统后,能编译出在目标平台上正常运行的应用程序。
Appendix A. About ARM EABI
ARM Ltd.于2003年12月发布了ARM ABI(v1),于2005年第一季度发布了ARM ABI
(v2),官方主页是Application Binary Interface (ABI) for the ARM Architecture。
“The Application Binary Interface (ABI) for the ARM® Architecture is a collection of standards, some
open and some specific to the ARM architecture. The standards regulate the interoperation
of binary
code, development tools, and a spectrum of ARM corebased
execution environments from bare metal
to platform operating systems such as ARM Linux.
Version 1.0 of the base standard was principally concerned with governing interoperation
between
relocatable files. This release version
2.0 also
sets standards for executable files.”
——from ARM Ltd. ABI page
“ABI for the ARM Architecture
Question: What is the ABI for the ARM Architecture? Is it the same as the ARM EABI?
Answer: The ABI for the ARM Architecture is a standard developed by ARM and its partners (including
CodeSourcery) that explains how compilers, assemblers, linkers, and other similar tools should generate
object files and executable files. Tools that correctly implement the ABI for the ARM Architecture can
interoperate; i.e., objects files built with one toolchain can be combined with object files built with another
toolchain if both compilers use the ABI for the ARM Architecture. The "ARM EABI" is an informal name
for the ABI for the ARM Architecture.
GNU/Linux ABI Name
Question: Why is the configuration name for GNU/Linux armnonelinuxgnueabi
instead of just armnonelinuxeabi?
Is there a GNU variant of the EABI?
Answer: The Free Software Foundation prefers that configuration names for GNU/Linux contain both the
string linux and the string gnu.The configuration armnonelinuxgnu
refers to the legacy ARM ABI for
GNU/Linux. Some tools depends on the fact that configuration names have at most three hyphens, so
gnu and eabi were combined into a single word.
The ABI used on GNU/Linux is not a special GNU variant of the EABI; it is just the EABI.
Mixed ABI and nonEABI
Systems
Question: Is it possible to run both EABI and nonEABI
binaries on the same system?
Answer: Yes, it is possible. However, running a dualABI
system requires care. If you have an oldABI
system, and want to run EABI binaries, you have several choices. One option is to link your programs
statically, using the static
option. However, linking dynamically is generally a superior approach.
CodeSourcery's toolchains use a different dynamic loader (ld.so.3), so it is possible for oldABI
and EABI
binaries to coexist. However, you will have to ensure that when you install the EABI libraries you do not
overwrite existing libraries, and you will have to set LD_LIBRARY_PATH so that the dynamic loader can
find them.
ARM GNU/Linux ABI Supplement ”
——from CodeSourcery ARM FAQ
另外,Debian Wiki上也有关于 ARM EAB I 的专题 ,非常精彩。
Russell King也曾有关于 Linux kernel AB I 与 ARM EAB I 的论述。
Appendix B. LinuxThreads and NPTL
“LinuxThreads项目最初将多线程的概念引入了Linux,但LinuxThreads并
不遵守POSIX线程标准。”
“LinuxThreads项目使用这个调用(笔者注:指clone()系统调用)来完成在用
户空间模拟对线程的支持。……这种方法有一些缺点,尤其是在信号处理、调度和
进程间同步原语方面都存在问题。另外,这个线程模型也不符合POSIX的要求。”
“NPTL,或称为Native POSIX Thread Library是Linux线程的一个新实现,
它克服了LinuxThreads的缺点,同时也符合POSIX的需求。与LinuxThreads相比,
它在性能和稳定性方面都提供了重大的改进。”
——摘自: Linux 线程模型的比较: LinuxThread s 和 NPTL (Vikaram Shukla )
Appendix C. About Linux kenerl version and headers
1. Linux内核头文件
编译Glibc必须要有linux内核头文件。最初人们直接使用内核源码包中的头文件
(/usr/include目录下),后来由于内核开发者强烈反对这种做法,于是出现了linux-libcheaders
项目,以为Linux头文件维护一个稳定版本的API。最近该项目已经停止发展(该
项目提供的最新版本的“纯净的”头文件版本是2.6.12.0);从2.6.18版本开始,内核开发组
负责维护一份统一的、“纯净的”内核头文件,获取编译glibc所需的头文件只需要使用
命令”make headers_install”即可。
您也许会对 CLF S 对头文件的说明 以及 [ 八卦故事 ] 内核头文件传奇 感兴趣。
2. Linux内核版本选择
为目标系统选择一个Linux内核版本,除了要考虑实际应用的需求之外,还要考虑
到与交叉编译工具链的匹配、内核新特性等诸多方面。
以本文为例,建立交叉编译工具链时使用2.6.22.6版本的内核头文件来编译Glibc,
那么使用这个Glibc编译得到的应用程序可以用于2.6.22.6以及以前版本的linux系统,这
是其向后兼容(backwards compatability)特性决定的——那么最早可以用于哪个版本的
Linux系统呢?这是在编译Glibc时使用—enable-kernel选项传递给configure脚本来限
制的,例如--enable-kernel=2.6.14,就表示运行应用程序的Linux系统内核版本至少要求
为2.6.14。这个应用程序可否用于2.6.22.6以上版本的Linux系统呢?原则上也是可以的,
只要更高版本的Linux系统配置为向后兼容,不过,即使这个应用程序可以运行在高版本
的内核系统上,也不会支持高版本系统的新特性。
那么目标系统的Linux内核版本与交叉编译工具的匹配要考虑哪些方面呢?这其实
没有一个公认的标准,其匹配性也受错综复杂的内在因素的影响。一般而言,内核没有发
生重大变化的条件下,可以使用建立toolchain所用内核版本(2.6.22.6)及其之前的一些版
本,也可能可用于后续的几个版本(没有保证)——这是因为随着内核版本的更新,会有越
来越多的新特性添加进来,甚至会丢弃一些旧的特性。例如,ARM EABI就需要内核本身
对它的支持,另外,本文所编译的Glibc也需要NPTL的内核支持;而Linux 2.6.16是第一
个具有上述所有特性的内核发行版,因此,与本文的toolchain匹配性较好的内核版本应
该是介于2.6.16和2.6.22.6之间。
若要使用2.6.14版本的内核,则至少需要打上EABI和NPTL的相关补丁(3101/1,
3102/1, 3103/1, 3104/1, 3105/4, 3106/2, 3107/3, 3108/2, 3109/1, 3110/2, 3111/2, 3112/1,
3205/1, 3210/1, 3270/1, 3271/1, 3339/1, 3477/1, 3484/1, 3495/1, 3524/1, 3626/1, 3729/3,
3750/3)。
Referece: ARM Linux Kernel Versions for Sourcery G++ 4.1/4.2
Appendix D. References
这里仅列出主要参考资料,文中已给出链接的部分参考资料不再列出。
[1] Building and Testing gcc/glic cross toolchains, crosstool main page。
[2] Marin's crosstool bits, crosstool-0.42 patch and Crosstool variables Reference。
[3] Cross-Compiled Linux From Scratch - Sysroot, CLFS。
[4] Cross-Compiled Linux From Scratch - Embedded, CLFS。
[5] Debian Wiki - ARM EABI。
[6] CodeSourcery ARM FAQ。
[7] ARM ABI, ARM Ltd.。
[8] Intel XScale® Technology。
[9] PXA27x-Linux Project (Old ABI)。
[10] Installing GCC: Configuration。
[11] Building a GNU/Linux ARM Toolchain (from scratch), Old ABI。
[12] LinuxDevTools web, Linux on ARM Wiki。
[13] Glibc Binutils GCC 配置选项简介 ,金步国。
[14] CLFS 2.0 原理分析 , youbest ( 冲天飞豹 ) 。
[15] 换个角度看 LFS—— 反向分析 LFS , youbest ( 冲天飞豹 ) 。
[16] Building arm-linux toolchain for ARM/XSCALE (Old ABI),Aaron Wong。
About the author
Aaron Wong (黄振华), received the B.S.degree in Electronic Engineering from Fudan
University in 2005, and now study for the M.S. degree of Communication & Information
System in East China Normal University.
[注]纰漏之处,恳请指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值