抗压能力差适合啥职业:手工制作最新版arm-linux交叉工具链(ubuntu 9.04)

来源:百度文库 编辑:偶看新闻 时间:2024/05/06 00:01:41

手工制作最新版arm-linux交叉工具链(ubuntu 9.04)

发表于 2011 年 03 月 19 日 由 屡败屡战

特别声明:本文可以转发,但是一定要注明出处“摘自王良明的博客:非常开源www.veryopen.org”,唯独百度文库不能收录。

注意:本文是在ubuntu 9.04 desktop i386操作系统上完成的,对于在ubuntu 10.04操作系统上制作工具量的方法参见“手工制作最新版arm-linux交叉工具链(ubuntu 10.04)”

目录
———————————————————
一、交叉编译开发环境概况
1、交叉编译工具链包含的文件
2、编译配置命令configure的三个关键参数
3、制作工具链的流程图
4、目录视图
二、制作工具链
1、准备需要的软件包
2、准备工作环境
3、安装Linux内核头文件
4、编译安装binutils
5、安装Glibc 的头文件
6、编译gcc(第一阶段,生成临时arm-linux-gcc)
7、编译库文件GLIBC
8、编译gcc(第二阶段,生成最终arm-linux-gcc)
9、编译gdb+gdbserver
三、配置交叉开发环境
1、配置工作环境变量
2、配置vim的工作参数
3、配置nfs+ftp
四、常见问题及处理
———————————————————

网上关于制作交叉编译工具链的方法不多,就算有也是不全面,参照这些文档操作几乎是百分之百失败!本文算是一篇非常全面的文档了,从安装操作系统开始,直到最后交叉编译成功的整个过程都做了详细的阐述,不过涉及的命令很多,参数尤甚,在具体的操作过程中需细心,如果有哪位同仁发现有新的问题,欢迎随时联系交流,从使得本文档更加完善。

一、交叉编译开发环境概况。


【图1】交叉开发环境物理设备连接图

【图2】网络拓扑图


1、交叉编译工具链包含的文件

【图3】工具链中的文件类型


在Linux平台上,编辑工具主要是vim,其他的文件(如编译器、连接器、头文件、库文件和帮助文件)则是本文重点要讲述的。

2、编译配置命令configure的三个关键参数

在具体的编译一个程序之前,我们一般事先要做配置,常用的方法是执行源文件根目录下的configure配置脚本,这个配置脚本带有很多的命令行参数,对于交叉编译来说,最主要也是最需要搞清楚的三个参数是:–host, –build, –target。(主意:参数前面是两个减号“-”)

–host:配置后并且编译好的程序能够运行的机器类型。这里指定的机器类型的格式是:“CPU类型-机器类型-操作系统类型-描述”,比如i686-pc-linux-gnu表述X86类型CPU,个人电脑,linux操作系统,描述GNU。在Linux系统上,这个参数一般取变量MACHTYPE的值。如:- -host=${MACHTYPE}。如果不特别指定本参数,那么默认就是${MACHTYPE}。

–build:执行编译任务的机器类型。一般后续的编译命令是make,通常配置和编译工作都在同一台机器上完成(其实就是本机)。但也存在一种特殊情况,即在另一台速度更快的电脑上完成编译任务(这种情况往往是编译特大型的程序)。如果不指定本参数,那么默认就是–host指定的值。

–target:编译后的程序用来处理的那些程序能够运行的机器类型。这个参数在编译gcc时常用,比如本文编译gcc时就是通过指定–target参数的值为arm-linux,表示这样编译出来的gcc(实际程序名是arm-linux-gcc)用来编译其他程序时生成的可执行程序可以在ARM类型的CPU上跑(当然要在linux操作系统的支持下)。

举例1:
本文用到的例子因为配置和编译都在同一台电脑上进行,所以是:
–host=${MACHTYPE}  –build=${MACHTYE}  –target=arm-linx

3、制作工具链的流程图

制作工具链是一个考验体力、智力和耐力的工作,完成一个完整工具链的制作耗费数天的时间是不足为怪的。那么从宏观上事先了解整个制作个过程是非常必要的,这样就能从全局了解和把握它。

【图4】制作工具链的流程图

根据箭头指向我们很容易知道编译的先后次序:binutils的编译是独立的,而要注意的是gcc的编译分成两个阶段,第一阶段是静态编译成arm-linux-gcc,目的是为了用它来编译交叉开发所需要的库文件和头文件,然后利用这些交叉库和头文件对gcc进行第二阶段的编译,从而生成最终的交叉编译器arm-linux-gcc,在操作过程中我们要时时注意每一次编译所用到的编译器什么,图中已经给出了答案:即,除了编译glibc使用临时的arm-linux-gcc外,其他统一采用主机上的gcc。最终生成的交叉工具arm-linux-*、交叉库/头和交叉编译器arm-linux-gcc就是我们需要的交叉工具链。

4、目录视图

在整个制作过程中,我们建立了一系列的目录(包括编译过程中建立的目录和工具链目录),如下图所示:

【图5】制作工具链过程中创建的目录

二、制作工具链

主意:下面的绿色部分表示命令,“#”之后的内容是说明,命令中非单字母参数前是两个减号“-”,由于排版问题只显示了一个“-”,比如参数–host前是两个“-”。所有的命令都是以root用户运行的。

1、准备需要的软件包

上面linux内核地址错误,应该是ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.28.tar.bz2
把这些软件包下载到目录/usr/local/arm/tars下。

2、准备工作环境

在windows上安装vmware,然后新建一个虚拟机(8G磁盘空间和512M内存,NAT网卡),在虚拟机里安装ubuntu 9.04 desktop i386版本。

1)、设置root用户登录:
(1)菜单“系统–>管理–>登录菜单–>安全”,勾选“允许本地系统管理员登录(A)”;(2)打开一个终端(菜单“应用程序–>附件–>终端”),输入命令:sudo -s,然后输入密码切换到超级用户去修改root的密码:passwd root

2)、更新安装源和加装必要的软件:
注销当前用户(鼠标点击右上角的关机图标,然后点击“退出…”),然后以root用户重新登录。
sed -i ‘s|cn.arch|tw.arch|g’ /etc/apt/sources.list #换成台湾的安装源,这样安装软件速度要快很多。
apt-get update && apt-get upgrade && reboot #对全部软件进行升级。升级之后需要重启电脑,以后登陆统一用root。菜单“系统–>系统管理–>更新管理器”会提示还有软件需要升级,然后再重启电脑。
dpkg -l|grep ^ii|awk ‘{print $2}’ > packages.orig #先记录截止目前安装的所有软件包。
rapt-get install openssh-serve # 安装远程管理服务器,这样我们可以远程登陆了。
echo “UseDNS no” >> /etc/ssh/sshd_config #关闭ssh登录时的DNS反向解析,从而加快ssh登录。

使用命令ifconfig可以查看网卡的ip地址,记下地址一遍以后远程登陆。在windows上安装一个远程登陆工具putty,从这里(http://www.veryopen.org/wp-content/downloads/putty.zip)可以下载,解压之后把里面的putty.exe放到电脑桌面上,然后直接双击即可启动(输入虚拟机的ip地址即可登陆)。

apt-get install vim #安装全功能编辑工具vim。
echo “export HISTSIZE=5000″ >> /root/.bashrc #记录最近5000条历史命令。
.  /root/.bashrc #或者:
exit #退出putty,然后再次从putty登陆虚拟机。

apt-get install patch texinfo m4 flex bison #加装这些软件包
apt-get build-dep glibc #安装编译glibc依赖的软件包。
apt-get build-dep gcc-4.2 #安装编译gcc时所依赖的软件包。

3)、设置环境变量:

export TOP=/usr/local/arm #设置目标工具链目录的顶成目录。
export TAR=${TOP}/tars    #设置源文件压缩包的存放目录路径。
export CLFS=${TOP}/clfs #设置编译过程工作目录。
export SYSROOT=${TOP}/4.2.1 #设置目标工具链的工作目录。
export TARGET_PREFIX=${TOP}/4.2.1 #设置目标工具链的安装目录。
export LINUX_VERSION=2.6.28 #设置 Linux 的版本号
export BINUTILS_VERSION=2.18 #设置 binutils 的版本号
export GLIBC_VERSION=2.6.1 #设置 glibc 的版本号
export GCC_VERSION=4.2.1 #设置 目标工具链的版本号。
export CLFS_TARGET=”arm-linux” #设置目标交叉编译工具链的编译器(arm-linux-gcc)的路径,因为在完成第一阶段arm-linux-gcc的编译后,我们将会把它安装到这里,并且使用它来编译出第二阶段 arm-linux-gcc 制作所依赖的动态链接库 glibc。
export PATH=${TARGET_PREFIX}/bin:$PATH
unset CFLAGS #禁用两个环境变量,因为可能导致编译过程出错
unset CXXFLAGS #默认情况下这两个环境变量为空,但随不同的Linux 平台的不同,或者用户自己之前的使用过程中设置了这两个变量设置目标工具链的目标体系,Gcc编译器会根据这个变量来确定目标交叉编译工具链是为那个目标体系的cpu编译程序的。

为了使得每次登陆后自动设置这些环境变量,可以把上述内容加到文件/root/.bashrc的末尾。

3、安装Linux内核头文件

install -dv ${SYSROOT}/usr/include #建立Linux头文件安装目录
install -dv ${TOP}/source #建立源码解压目录
cd ${TOP}/source #进入源码解压目录
tar -xjf  ${TAR}/linux-${LINUX_VERSION}.tar.bz2 #解压解包 Linux 内核源码包
cd linux-${LINUX_VERSION} #进入Linux 内核源码目录
make mainstone_defconfig ARCH=arm #设置 Linux 内核源码匹配的cpu 体系,我们用的是PXA270
make include/linux/version.h #生成Linux 版本头文件。

#复制制作目标交叉编译工具链所要的Linux头文件
cp -a include/{asm-generic,linux,mtd,scsi,sound}  ${SYSROOT}/usr/include
cp -a include/asm-arm  ${SYSROOT}/usr/include/asm

4、编译安装binutils

mkdir -p ${TARGET_PREFIX} #建立目标交叉编译工具链安装目录
cd ${TOP}/source #进入源码解压目录
tar -jxf ${TAR}/binutils-${BINUTILS_VERSION}.tar.bz2 #解压binutils 源码包到此目录
cd binutils-${BINUTILS_VERSION} #进入 binutils 的源码目录
patch -Np1 -i ${TAR}/binutils-${BINUTILS_VERSION}-posix-1.patch #给binutils打补丁
mkdir -p ${TOP}/source/BUILD/binutils-${BINUTILS_VERSION} #建立 binutils 的编译目录
cd ${TOP}/source/BUILD/binutils-${BINUTILS_VERSION} #进入 binutils 的编译目录

#设立汇编器的环境变量
export AR=ar     #注意:这里定义的两个环境变量是临时性的,重启机器后没有了,那么下次再来执行下面的命令前还要定义这两个环境变量。
export AS=as
#对 binutils 进行配置
${TOP}/source/binutils-${BINUTILS_VERSION}/configure–prefix=${TARGET_PREFIX} –target=${CLFS_TARGET}–with-sysroot=${SYSROOT} –disable-nls –enable-shared –disable-multilib–enable-werror=no
make configure-host #编译 binutils
注意:做下面的步骤之前请参考文后的“问题1”处理
make
make install #安装 binutils

#复制后续编译所要的 binutils 的头文件
cp -v ${TOP}/source/binutils-${BINUTILS_VERSION}/include/libiberty.h ${SYSROOT}/usr/include

5、安装Glibc 的头文件

cd ${TOP}/source #进入源码解压目录
tar -jxf ${TAR}/glibc-${GLIBC_VERSION}.tar.bz2 #解压 Glibc 的源码包到此目录

#改变源码目录名,为了标识这份源码是为安装头文件而解压、配置、补丁的。这里采用改变目录名的方式来实现,目的在于保留这些编译、设置过的源码,以后可以直接用这些编译过的内容直接安装,不需要再次编译。因为编译是很耗时的事情。
mv glibc-${GLIBC_VERSION}  glibc-${GLIBC_VERSION}-headers-build
cd glibc-${GLIBC_VERSION}-headers-build #进入glibc头文件安装源码目录

#下面两行是为了消除在配置glibc时 gcc 对glibc的依赖。因为这里只是为了安装头文件,并不是要配置、编译、安装 Glibc。
cp configure{,.orig}
sed -e ‘s/3.4/3.[0-9]/g’ configure.orig > configure
#解压glibc 的cpu体系支持源码包到glibc 头文件安装源码目录,因为glibc 默认是没有ARM cpu支持的,GNU组织专门加入了此源码包来解决此问题。
tar -jxf ${TAR}/glibc-ports-${GLIBC_VERSION}.tar.bz2
#改变cpu 体系支持源码目录为 ports ,因为glibc对所有加入的而外支持包的默认搜索目录为 ports。
mv glibc-ports-${GLIBC_VERSION}  ports
#建立glibc头文件配置、安装的工作目录
mkdir -p ${TOP}/source/BUILD/glibc-${GLIBC_VERSION}-headers-build
#进入glibc头文件配置、安装的工作目录
cd ${TOP}/source/BUILD/glibc-${GLIBC_VERSION}-headers-build
#以下三步是为了把glibc头文件配置成支持 NPTL(linux 的新线程标准)而设立的必须条件,并把这些条件写入缓存文件(可以从下面的配置选项 –cache-file=config.cache看出)
echo “libc_cv_forced_unwind=yes” > config.cache
echo “libc_cv_c_cleanup=yes” >> config.cache
echo “libc_cv_arm_tls=yes” >> config.cache
export CC=gcc #指定配置使用的编译器

#配置glibc
${TOP}/source/glibc-${GLIBC_VERSION}-headers-build/configure–prefix=/usr –host=${CLFS_TARGET} –with-headers=${SYSROOT}/usr/include–cache-file=config.cache
make install-headers install_root=${SYSROOT} #安装 glibc头文件
cp -v bits/stdio_lim.h ${SYSROOT}/usr/include/bits #复制编译后续编译所要的头文件
#建立必要的地头文件,内容为空,因为这个头文件在第一阶段Gcc 编译安装时要被 check 到,但这是后面编译安装目标机的glibc时才被生成安装的。
touch ${SYSROOT}/usr/include/gnu/stubs.h

#拷贝建立支持NPTL编译器所必须的头文件
cp -f${TOP}/source/glibc-${GLIBC_VERSION}-headers-     build/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h   ${SYSROOT}/usr/include/bits

6、编译gcc(第一阶段,生成临时arm-linux-gcc)

export CC=gcc #指定配置使用的编译器
cd ${TOP}/source #进入源码解压目录
tar -jxf ${TAR}/gcc-${GCC_VERSION}.tar.bz2 #解压gcc源码
#改变源码目录,为了标识这是第一阶段用的gcc源码,目的前面说过了。
mv gcc-${GCC_VERSION} gcc-${GCC_VERSION}-stage1
cd gcc-${GCC_VERSION}-stage1 #进入第一阶段源码目录

#打上支持posix 标准的补丁,新的线程标准NPTL是符合posix标准的。
patch -Np1 -i ${TAR}/gcc-${GCC_VERSION}-posix-1.patch
#打上交叉编译gcc搜索头文件路径的补丁
patch -Np1 -i ${TAR}/gcc-${GCC_VERSION}-cross_search_paths-1.patch
cd ${TOP}/source #进入源码解压目录
mkdir -p BUILD/gcc-${GCC_VERSION}-stage1 #建立编译第一阶段gcc的工作目录
cd BUILD/gcc-${GCC_VERSION}-stage1 #进入编译第一阶段gcc 的工作目录
#配置第一阶段gcc。
${TOP}/source/gcc-${GCC_VERSION}-stage1/configure–prefix=${TARGET_PREFIX} –host=${MACHTYPE} –target=${CLFS_TARGET}–disable-multilib –with-sysroot=${SYSROOT} –disable-nls –disable-shared–enable-languages=c
#注意配置选项–enable-languages=c 和–disable-shared!因为这一阶段的gcc制作时,还没有生成其给目标机编译程序时所依赖的动态库,所以要—disable-shared,因此第一阶段的gcc是个静态的arm-linux-gcc。之所以只用了–enable-languages=c,而后面生成第二阶段的arm-linux-gcc却用了–enable-languages=c,c++,是因为我们这一阶段的arm-linux-gcc是为了生成制作第二阶段arm-linux-gcc所依赖的glibc动态函数库而制作,编译glibc只需要arm-linux-gcc,并不需要arm-linux-g++。加上c++也是没错的。

主意:如果下面一步报错,请参考文后的“问题2”处理,然后再执行下面的步骤

make all-gcc #编译第一阶段gcc
make install-gcc #安装第一阶段gcc

7、编译库文件GLIBC

cd ${TOP}/source
tar -jxf ${TAR}/glibc-${GLIBC_VERSION}.tar.bz2 #解压glibc源码
cd glibc-${GLIBC_VERSION} #进入源码目录
#解压glibc 的cpu体系支持源码包到glibc 头文件安装源码目录,因为glibc 默认是没有ARM cpu支持的,GNU组织专门加入了此源码包来解决此问题。
tar -jxf ${TAR}/glibc-ports-${GLIBC_VERSION}.tar.bz2
#改变cpu 体系支持源码目录为 ports ,因为glibc对所有加入的而外支持包的默认搜索目录为 ports。
mv glibc-ports-${GLIBC_VERSION}  ports
#以下四步均为给glibc打补丁。
patch -Np1 -i ${TAR}/glibc-2.6.1-libgcc_eh-1.patch
patch -Np1 -i ${TAR}/glibc-2.6.1-localedef_segfault-1.patch
patch -Np1 -i ${TAR}/glibc-2.6.1-cross_hacks-1.patch
patch -Np1 -i ${TAR}/glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch
mkdir -p ${TOP}/source/BUILD/glibc-${GLIBC_VERSION} #建立配置、编译、安装glibc的工作目录
cd ${TOP}/source/BUILD/glibc-${GLIBC_VERSION} #进入配置、编译、安装glibc的工作目录
#以下三步是为了把glibc头文件配置成支持 NPTL(linux 的新线程标准)而设立的必须条件,并把这些条件写入缓存文件(可以从下面的配置选项 –cache-file=config.cache看出)
echo “libc_cv_forced_unwind=yes” > config.cache
echo “libc_cv_c_cleanup=yes” >> config.cache
echo “libc_cv_arm_tls=yes” >> config.cache

#指定配置使用的编译器为gcc,即本机的gcc
export BUILD_CC=”gcc”
#指定编译glibc时使用第一阶段的交叉gcc,即上面生成的arm-linux-gcc
export CC=”${CLFS_TARGET}-gcc”
#指定汇编glibc时使用的汇编器为arm-linux-ar,即在制作binutils 时生成的交叉汇编器
export AR=”${CLFS_TARGET}-ar”
export RANLIB=”${CLFS_TARGET}-ranlib”
#配置交叉编译工具链所依赖的动态库glibc
${TOP}/source/glibc-${GLIBC_VERSION}/configure–prefix=/usr –libexecdir=/usr/lib/glibc –host=${CLFS_TARGET}–build=${MACHTYPE} –disable-profile –enable-add-ons –with-tls–enable-kernel=2.6.0 –with-__thread –with-binutils=${TARGET_PREFIX}/bin–with-headers=${SYSROOT}/usr/include –cache-file=config.cache

主意:下面一步会报错,请参考文后的“问题3”处理,然后再执行下面的步骤

make #编译交叉编译工具链所依赖的动态库glibc
make install install_root=${SYSROOT} #安装交叉编译工具链所依赖的动态库

8、编译gcc(第二阶段,生成最终arm-linux-gcc)

export CC=gcc
cd ${TOP}/source #进入源码解压目录
tar -jxf ${TAR}/gcc-${GCC_VERSION}.tar.bz2 #解压gcc源代码
#改名源码目录,为了标识这是编译第二阶段的gcc 所用的源码
mv gcc-${GCC_VERSION} gcc-${GCC_VERSION}-stage2
cd gcc-${GCC_VERSION}-stage2 #进入源码目录

#打上支持posix 标准的补丁,新的线程标准NPTL是符合posix标准的。
patch -Np1 -i ${TAR}/gcc-${GCC_VERSION}-posix-1.patch
#打上交叉编译gcc搜索头文件路径的补丁
patch -Np1 -i ${TAR}/gcc-${GCC_VERSION}-cross_search_paths-1.patch
cd ${TOP}/source #进入源码解压目录
mkdir -p BUILD/gcc-${GCC_VERSION}-stage2 #建立第二阶段gcc的编译工作目录
cd BUILD/gcc-${GCC_VERSION}-stage2 #进入第二阶段gcc的编译工作目录

#配置第二阶段交叉编译工具链
${TOP}/source/gcc-${GCC_VERSION}-stage2/configure–prefix=${TARGET_PREFIX} –host=${MACHTYPE} –target=${CLFS_TARGET}–disable-multilib –with-sysroot=${SYSROOT} –disable-nls –enable-shared–enable-languages=c,c++ –enable-__cxa_atexit –enable-c99–enable-long-long –enable-threads=posix
make all-gcc #编译第二阶段交叉编译工具链
make install-gcc install_root=${TARGET_PREFIX} #安装交叉编译工具链

9、编译gdb

基于arm的交叉嵌入式开发往往采用gdb/gdbserver进行远程调试,gdbserver连同被调试的程序在开发板上跑,而gdb和被调试程序的源程序在电脑上,可以用如下的图形表示:

【图6】远程调试拓扑图

【图7】程序的错误类型和处理工具

1)、准备源码:
wget http://ftp.gnu.org/gnu/gdb/gdb-7.0.tar.bz2
tar -jxf gdb-7.0.tar.bz2
apt-get install libncurses5-dev
2)、编译GDB客户端:
cd gdb-7.0
./configure –target=${CLFS_TARGET}  –prefix=${TARGET_PREFIX}
make && make install
3)、编译GDB服务器:
cd gdb/gdbserver
export CC=arm-linux-gcc #指定配置使用的编译器
./configure –target=${CLFS_TARGET}  –host=${CLFS_TARGET}
sed -i  ‘s|#define HAVE_SYS_REG_H|//#define HAVE_SYS_REG_H|g’  config.h
make CC=arm-linux-gcc
cp gdbserver ${TARGET_PREFIX}/bin #把编译后的程序暂时保存到目录${TARGET_PREFIX}/bin中,等以后制作好了嵌入式根文件系统后在拷贝到嵌入式根文件系统的/bin目录下。

4)、举例说明远程调试方法
arm-linux-gcc -g hello.c -o hello #交叉编译
cp hello /srv/rootfs/bin #主意:目录/srv/rootfs/bin以nfs类型被目标板mount到根目录上。
#通过minicom链接到开发板,并启动调试器:
/root # gdbserver 192.168.0.100:1234 /bin/hello

arm-linux-gdb #电脑主机上启动调试器客户端
(gdb) target remote 192.168.0.100:1234 #假定开发板的ip地址是192.168.0.100
(gdb) symbol -file /path/to/hello #指定程序源码文件的目录
……     #此后就像调试本地程序一样进行调试了。

5)、gdb的调试命令:
(gdb) list n,m #显示从n行到m行的源代码,如“list 10,30”列出10至30行的源代码
(gdb) break 9 #在第9行设置一个中断点
(gdb) run #在gdb里运行被调试程序
(gdb) print i #显示变量i的值
(gdb) info locals #显示全部的本地变量值
(gdb) help #显示全部的可用gdb命令, 用户“help <命令> ”显示具体的命令的用法。
(gdb) whatis i # 显示变量i的类型,比如“整型、结构体、字符型”等。
(gdb) print x=100 #给变量x赋值100
(gdb) step #开始单步运行
(gdb) n #单步执行一条语句
(gdb) display i,j,p #同时显示三个变量i,j,p的值
(gdb) bt #显示整个调用堆栈(比如main函数调用abc函数,abc函数有调用了fun函数调用路径会打印出来)。
(gdb) info break #列出已定义的全部断点
(gdb) delete breakpoints   9 #删除第9行的中断点
(gdb) continue #继续执行被调试程序
(gdb)  quit #退出调试

gdb的调试命令非常丰富,想要深入研究的同仁可以参考操作手册gdb.pdf

三、配置交叉开发环境

1、配置工作环境变量

这样配置好的工具链就可以打包拷贝到其他的X86机器上运行,只要把目录/usr/local/arm/4.2.1/bin加到PATH环境变量里,比如:
export PATH=/usr/local/arm/4.2.1/bin:$PATH

arm-linux-gcc -v 显示如下结果:
Using built-in specs.
Target: arm-linux
Configured with: /usr/local/arm/source/gcc-4.2.1-stage2/configure–prefix=/usr/local/arm/4.2.1 –host=i486-pc-linux-gnu –target=arm-linux–disable-multilib –with-sysroot=/usr/local/arm/4.2.1 –disable-nls–enable-shared –enable-languages=c,c++ –enable-__cxa_atexit –enable-c99–enable-long-long –enable-threads=posix
Thread model: posix
gcc version 4.2.1

主意上面的几个关键字:
1)、目录主机(Target)是arm-linux ;
2)、 运行主机(–host)是i486-pc-linux-gnu;
3)、系统根(sysroot)是/usr/local/arm/4.2.1,这个目录下有交叉编译库文件和头文件;
4)、能编译的语言有c\c++;
5)、线程兼容posix。

最后做一番测试:
cat > cross.c <#include
main(){printf(“Hello CrossTool !”);}

EOF

arm-linux-gcc cross.c -o cross #交叉编译;
file cross #查看程序类型
cross: ELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), for GNU/Linux 2.6.0, not stripped
主意上面的几个关键字:arm, dynamically linked,表示运行于arm平台,且是动态链接的。

2、配置vim的工作参数

执行下述命令把vim的配置参数加到用户家目录下的.vimrc中即可:
cat >$HOME/.vimrc  <set autoindent
set cindent
set cinoptions={0,1s,t0,n-2,p2s,(03s,=.5s,>1s,=1s,:1s
set nowrap
syntax enable
set ts=4
set hlsearch
set ruler
set showcmd
set nu

EOF

–这样以后用vi或者vim编辑程序时会高亮语法显示、自动缩进等等,非常方便。

vim使用技巧:
删除 DOS 回车符 ^M::%s/\r//g
删除行尾空格:%s= *==g
删除行尾空格和 DOS 回车符:%s#\s*\r\?$##
压缩多行空行为一行:%s/^\n\+/\r/
普通替换:%s/fred/joe/igc
删除所有的空行:光标移到首行,一次输入!Ggrep -v “^$”
整理杂乱的c语言代码:gg=G
整理{}内的代码:=a{

3、配置NFS+TFTP+BOOTP

需要NFS的目的是建立网络文件系统,开发箱通过它把嵌入式根文件系统“安装”过来,另外开发箱通过tftp协议把内核下载下来,通过BOOTP自动配置网卡参数。

1)、开发板内核启用NFS支持:
(1)打开嵌入式内核中的NFS配置
make menuconfig –> File systems –> Network File Systems –> Root file system NFS
(2)修改嵌入式内核中的内核启动命令串:
make menuconfig –> Bootconsole=ttyS0,115200 mem=64M rw root=/dev/nfs init=/sbin/initnfsroot=210.210.200.2:/srv/rootfsip=210.210.200.1:210.210.200.2:210.210.200.2:255.255.255.252::eth0:off

主意:上述内核启动命令串中的参数ip的格式如下:
ip=<本地网卡ip>::<网关>:<网络掩码>:<主机名>:<网卡名>:<是否自动配置>
然后要重新编译嵌入式内核。

2)、电脑上安装NFS+TFTP+BOOTP
apt-get install nfs-kernel-server tftpd bootp openbsd-inetd
# 编辑/etc/exports,在末尾加入下面一行:
/srv/rootfs  *(rw,rsync,no_subtree_check,no_root_squash)
/etc/init.d/nfs-kernel-server restart #启动NFS服务
#修改文件/etc/inetd.conf,加入如下一行:
bootps          dgram   udp     wait    root    /usr/sbin/bootpd        bootpd -i -t 120
tftp            dgram   udp     wait    nobody  /usr/sbin/tcpd  /usr/sbin/in.tftpd /srv/tftpboot

#修改文件/etc/bootptab,内容如下:
CrossBox11:ht=1: ha=0x123456789A00: ip=210.210.200.1: sm=255.255.255.252
主意:上述行中的“0x123456789A00”指开发箱的网卡物理地址(MAC),在具体操作过程中要替换成你的开发箱的网卡物理地址。

#重启inetd,从而监听bootp和tftp服务:
/etc/init.d/openbsd-inetd restart

四、常见问题及处理

问题1:在编译binutils时报错:WARNING: `makeinfo’ is missing onyour system. You should only need it if you modified a `.texi’ or`.texinfo’ file,…处理:由电脑上安装的texinfo软件包版本太新导致。编辑源代码根目录下(/usr/local/arm/source/binutils-2.18/)的configure程序,在configure里找到以下语句:’texinfo[^0-9]*([1-3][0-9]|4\.[4-9]|[5-9])’把它改为:’texinfo[^0-9]*([1-3][0-9]|4\.[4-9]|4\.[1-9][0-9]*|[5-9])’

可以用下列的命令改掉:
sed -i  ’s%[0-9]|4\.[4-9]|[5-9]%[0-9]|4\.[4-9]|4\.[1-9][0-9]*|[5-9]%g’  /usr/local/arm/source/binutils-2.18/configure

问题2:在第一阶段编译gcc的时候报如下错/usr/local/arm/4.2.1/arm-linux/bin/ld: crti.o: No such file: No such file ordirectory处理:在运行配置configure命令的时候添加参数–disable-shared。比如我当时经过长时间的检查发现虽然加了这个参数,但是这个参数与后面的参数连在一起了,中间少了一个空格。

问题3:在编译glibc库的时候报错:undefined reference to `charmap_hash’和undefined reference to `locfile_hash’。处理:
vim ${TOP}/source/glibc-${GLIBC_VERSION}/locale/programs/locfile.c在头文件包含语句下面增加一行:
const struct keyword_t * locfile_hash (register const char *str, register unsigned int len);
vim ${TOP}/source/glibc-${GLIBC_VERSION}/locale/programs/charmap.c在头文件包含语句下面增加一行:
const struct keyword_t * charmap_hash (register const char *str, register unsigned int len);