l 前言
在嵌入式系统移植的过程中,必不可少的一样东西是交叉编译器,只有使用交叉编译器才可以把原先在宿主机(相信大多数人所使用的宿主机会是Linuxx86系统的)上所编写的程序交叉编译成开发板(如ARM系统或PPC系统)所识别的二进制形式。对于一些成熟的移植过程来说,互联网上存在已经制作好的交叉编译器,只要下载过来解压缩配置后就可以使用了。但在使用这些交叉编译器的过程中可能存在着一些问题,由于自己机子上的某些环境不一样,会导致使用这些交叉编译器编译出来的内核,bootloader存在这样或那样的问题。为了去除交叉编译器对今后的编译工作带来的错误影响,最好创建属于自己的交叉编译器。
l 配置
手动创建交叉编译器相当复杂,对于一般的嵌入式程序开发员来说,这部分知识并不是必须的。幸好我们有Dan Kegel所写的创建交叉编译器的脚本工具crosstool。从crosstool官方网站上下载crosstool的最新版本(0.43之后就再没更新过),解压缩后得到crosstool-0.43目录,查看crosstool-0.43文件夹,可以看到目录下有很多demo-*.sh脚本和*.dat配置文件。首先需要找到你要交叉编译的平台CPU所对应的demo-*.sh脚本,比如说我要交叉编译的平台是三星的S3C2440,它的CPU是ARM9T,则选用demo-arm9tdmi.sh。
如下是对该文件的说明,标红色部分表示可根据需要进行修改,这里我们保持文件默认:
#!/bin/sh
# This script has one line for each known working toolchain
# for this architecture. Uncomment the one you want.
# Generated by generate-demo.pl from buildlogs/all.dats.txt
set -ex
TARBALLS_DIR=$HOME/downloads
RESULT_TOP=/opt/crosstool
export TARBALLS_DIR RESULT_TOP
GCC_LANGUAGES=”c,c++”
export GCC_LANGUAGES
# Really, you should do the mkdir before running this,
# and chown /opt/crosstool to yourself so you don’t need to run as root.
mkdir -p $RESULT_TOP
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.5-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6.dat` sh all.sh –notest
eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.5-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.6.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.6-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.1.0-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh –notest
echo Done.
TARBALLS_DIR是指创建crosstool过程中所需要的glibc, binutils, gcc等程序的tar.bz2文件所要存放的位置,这里我把他们放在我的下载目录。Crosstool会自动的从网上下载所需的程序,但由于crosstool在下载的过程中选择的服务器会是国外的官方服务器,会比较慢,最好在build过程之前从网上把这些所需要的文件下载过来放到TARBALLS_DIR中,具体所需要的文件会在下面做介绍。
RESULT_TOP指的是编译好后所生成的交叉编译器存放的目录,一定要改到有写权限的目录,不然无法编译。
eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6-tls.dat` sh all.sh –notest
表示使用cross-tools顶层目录下的arm9tdmi.dat(根据CPU类型选择)和gcc-3.4.5-glibc-2.3.6-tls.dat(根据想要使用的gcc版本和glibc版本进行选择)来进行交叉编译器的创建。在crosstool官方网站的buildlog页面上可以看到各种CPU和GCC+Glibc版本那些已经编译成功,那些部分成功,那些彻底失败。
如果需要更改,在修改好demo-*.sh脚本后,打开所选定的arm9tdmi.dat和 gcc-3.4.5-glibc-2.3.6-tls.dat文件
首先,打开arm9tdmi.dat
KERNELCONFIG=`pwd`/arm.config
TARGET=arm-9tdmi-linux-gnu
GCC_EXTRA_CONFIG=”–with-cpu=arm9tdmi –enable-cxx-flags=-mcpu=arm9tdmi”
TARGET_CFLAGS=”-O”
TARGET表示最后生成的交叉编译工具链的名称,根据自己喜欢修改。
其次打开gcc-3.4.5-glibc-2.3.6-tls.dat
BINUTILS_DIR=binutils-2.15
GCC_DIR=gcc-3.4.5
GLIBC_DIR=glibc-2.3.6
LINUX_DIR=linux-2.6.23.8
LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0
GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.6
将这里的LINUX_DIR改成你真正想要移植的Linux版本,然后这里的binutils-2.15, gcc-3.4.5, glibc-2.3.6, linux-2.6.23.8, linux-libc-headers-2.6.12.0, glibc-linuxthreads-2.3.6就是你所要下载后放到之前提到的TARBALLS_DIR里的文件(必须是tar.bz2文件)。
l 步骤
以root登陆Ubuntu系统,创建目录/opt/crosstool/(视demo-*.sh脚本里面的变量RESULT_TOP不同而不同)并修改其owner。这是是因为此crosstool不能以root安装,而须以username安装,安装过程会读写此目录,故需要修改属主。
以用户username登陆,创建TARBALLS_DIR指定的目录,在这是系统默认的下载路径/home/username/downloads,本身已存在,不需要自己创建,但如果TARBALLS_DIR被修改过了,则要创建这个修改后的目录,这个目录将来用于自动从网上下载gcc, binutilty,glibc等。如果自己已经下载了这些软件包,也放在这个目录下,这样就不用程序自动从网上下载了。
从http://kegel.com/crosstool/下载crosstool-0.43.tar.gz到目录/opt/crosstool,,执行如下命令
cd /opt/crosstool
tar xzvf crosstool-0.43.tar.gz
进入crosstool-0.43目录执行shdemo-arm9tdmi.sh开始创建交叉编译工具,大概要经历1到2个小时
l 问题与解决方案
配置好crosstool后,运行脚本有可能得到如下错误
问题1:
. ……………….
……………….
applying patch /opt/crosstool-0.43/patches/glibc-2.3.6/arm-ctl_bus_isa.patch
getandpatch.sh: 1: patch: not found
patch /opt/crosstool-0.43/patches/glibc-2.3.6/arm-ctl_bus_isa.patch failed
解决办法:通过sudo apt-get install patch 安装patch解决这一问题
问题2:
…………………………
…………………………
/home/rookiesean/workspace/crosstool-0.43/crosstool.sh: 110: bison: not found
crosstool: You don’t have bison installed
解决办法:通过sudo apt-get install bison 安装bison解决这一问题
问题3:
…………………………
…………………………
/home/rookiesean/workspace/crosstool-0.43/crosstool.sh: 111: flex: not found
crosstool: You don’t have flex installed
解决办法:通过sudo apt-get install flex 安装flex解决这一问题
问题4:
…………………………
…………………………
configure: error:
*** These critical programs are missing or too old: as ld
*** Check the INSTALL file for required versions.
出现这种情况是因为Ubuntu默认所安装的binutils版本为binutils-2.20,当binutils太新的时候,crosstool只好将它当成太老的版本,报告说too old; as ld. 于是我们需要重新编译安装一个老版本的binutils, 2.19或者2.18都可以被crosstool所识别,这里拿binutils-2.18举例。但还有一个问题,Ubuntu10.04默认安装的gcc版本是gcc-4.4.3,跟binutils-2.20一样,太高版本的gcc对语法要求更为严格,这样会导致binutils-2.18无法轻松的编译通过,于是我们需要编译安装一个老版本的gcc,4.1的版本可以编译成功binutils-2.18。在Ubuntu10.04可以通过
解决方案:
执行sudo apt-get install gcc-4.1安装gcc-4.1,安装完成后,执行如下命令:
cd /usr/bin
sudo rm gcc
sudo ln -sf gcc-4.1 gcc
gcc -v
得到如下显示:
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v –enable-languages=c,c++ –prefix=/usr –enable-shared –with-system-zlib –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –enable-nls –with-gxx-include-dir=/usr/include/c++/4.1.3 –program-suffix=-4.1 –enable-__cxa_atexit –enable-clocale=gnu –enable-libstdcxx-debug –with-tune=generic –enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.3 20080704 (prerelease) (Ubuntu 4.1.2-27ubuntu1)
表明原先指向gcc-4.4的的符号链接已经被重新指向新安装的gcc-4.1,系统中默认的gcc版本为4.1
下载binutils-2.18,将其解压缩后,进入binutils顶层目录,运行
./configure -prefix=/home/rookiesean/temp/binutils -disable-nls
make all
make install
其中–prefix=/home/rookiesean/temp/binutils表示生成可执行文件的存放位置,可自定义。
编译成功后在/home/rookiesean/temp/binutils/bin/中就生成了ld as程序的可执行文件,到/usr/bin目录下面将系统默认的ld和as替换成2.18版本的:
#进入/usr/bin目录
cd /usr/bin/
#备份as ld为后面恢复使用
sudo cp as as.bak
sudo cp ld ld.bak
#删除原来版本的as ld
sudo rm as ld
#替换2.18版本
ln -sf /opt/crosstool/binutils/bin/ld ld
ln -sf /opt/crosstool /binutils/bin/as as
ld -v; as -v
得到如下显示:
GNU ld (GNU Binutils) 2.18
GNU assembler version 2.18 (i686-pc-linux-gnu) using BFD version (GNU Binutils) 2.18
表示系统默认的binutils版本已经变换为2.18版本。
接下来,就可以运行demo-*.sh建立属于自己的交叉编译器了。
问题5:
version.c:40: error: syntax error before string constant
make[2]: *** [/opt/crosstool/crosstool-0.43/build/arm-softfloat-linux-gnu/gcc-3.4.5-glibc-2.3.6/build-glibc/csu/version.o] Error 1
make[2]: Leaving directory `/opt/crosstool/crosstool-0.43/build/arm-softfloat-linux-gnu/gcc-3.4.5-glibc-2.3.6/glibc-2.3.6/csu'
make[1]: *** [csu/subdir_lib] Error 2
make[1]: Leaving directory `/opt/crosstool/crosstool-0.43/build/arm-softfloat-linux-gnu/gcc-3.4.5-glibc-2.3.6/glibc-2.3.6'
make: *** [lib] Error 2
解决办法:老版本的glibc在/bin/sh为dash的时候会出现这个问题,一种解决方法是把/bin/sh重定向为bash,在创建完交叉编译器后可以将/bin/sh重新改回dash,运行如下面命令修改/bin/sh:
cd /bin
sudo mv /bin/sh sh.old
sudo ln -sf bash /bin/sh
sh –version
得到如下显示:
GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
重新运行demo-*.sh建立属于自己的交叉编译器了。
l 恢复修改的系统设置
1. 恢复gcc为4.4
Sudo rm /usr/bin/gcc
Sudo ln –s /usr/bin/gcc-4.4 /usr/bin/gcc
2. 恢复sh
Cd /bin
Sudo rm sh
Sudo mv sh.old sh
3. 恢复as ld
Cd /usr/bin
Sudo rm ld
Sudo mv ld.bak ld
Sudo rm as
Sudo mv as.bak as