定制工具链ToolChain for ARM

  • 1、 ToolChain 简介

          ToolChain 包含许多部件:主要之一是GCC,它可以是本机编译工具或交叉编译工具,GCC由Binuitls工具支持,Binutils是二进制代码维护工具,这些部件是编译程序的必要工具,同时他们也需要C库(glibc)支持。认真考虑一下:定制一套编译工具并不是想像中的易事!如果你还想继续看下去,必须具备如下技能:
           熟悉Linux环境
           熟悉Linux的必要命令和工具的使用
           知道如何配置、编译核心和应用程序

           以下章节将介绍怎样定制ARM交叉编译工具集,但对于大多数ARM开发者来说,没有必要亲自做这件事,完全可以用现成的工具集。除非现成的工具集不满足你的使用要求,或者你想提高开发应用的能力。总之,我们强烈建议你使用现成稳定的工具集来做应用开发!

    2、 定制ToolChain


        首先来看看工作的大至步骤:
        决定目标的名称
        决定目标的存放位置
        编译、安装Binutils
        编译、安装GCC
        编译、安装GLIBC
        让交叉编译工具支持更多编译语言
        测试定制的交叉编译工具

    2.1、决定目标的名称


           本机编译工具集编译的代码只适用本机(大多数PC是X86)运行,对于ARM开发者来说,需要一个能在本机编译、但编译却生成ARM运行代码的一套交叉编译工具集。
           因此,选择一个与本机工具集相异的特定含义的目标名称是非常有必要的。
    arm-linux:是个比较受欢迎的名称,支持ELF格式(ARMLinux标准)。除Acorn用户使用老的a.out格式外。
    arm-linuxaout:选择a.out格式,ARMLinux基本不支持它了。
    arm-aout、arm-coff、arm-elf、arm-thumb:其它的格式名。

           你也可以在其中插入版本信息,比如:

    armv2:ARMV2核,支持26bit模式。

    armv3l、armv3b:ARMV3核,小字节(l)或大字节(b)模式。

    armv4l、armv4b:ARMV4核,如:StrongARM、ARM7TDMI、ARM8、ARM9。同样也支持小字节(l)或大字节(b)模式。

    armv5l、armv5b:ARMV5核,如:XScale核ARM10。同样也支持小字节(l)或大字节(b)模式。

           选择什么名称对定制ARM交叉编译工具集没太大的影响,但用大家常用的名称会比较好些。

    2.2、决定目标的存放位置


           既然是定制ARM交叉编译工具集,那么就不能覆盖本机的编译工具集(否则,本机将不能再编译本机运行代码!),同时还要考虑本机Linux环境的多用户、多任务特征。因此,选择一个与本机编译工具集不同的多用户共享位置是必要的。

           ARM交叉编译工具集的存放位置:在本文中,我们让它等于/usr/local/arm (本机编译工具集的存放位置通常在/usr或/usr/local)

           ARM交叉编译工具集的名称:在本文中,我们让它等于 arm-pc-linux,表示在本 地pc上编译,生成的是ARM指令代码(详细规则见glibc的README文件)。 (本机编译工具集名称通常是: i686-pc-linux-gnu,表示在本地pc上编译, 生成的是i686指令代码)
           ARM核心文件位置:本文中我们让它等于 ~/armlinux 。不过,~/armlinux在这里仅 是个联接而已,它指向真正ARM核心源代码位置(见2.4.1描述)。 (本机核心存放位置通常在/usr/src/linux)

    2.3、编译、安装Binutils

          它是GNU(ftp://ftp.gnu.org)工具之一,主要是二进制代码的处理维护工具。

    2.3.1、Binutils工具部件简介
    add2line:将地址转换成文件名或行号对,以便调试程序。

    ar:从体系文件中创建、修改、扩展程序代码。

    as:生成汇编程序代码。

    c++filt:建立低级语言和用户级语言的名称符号联接,并保持它们的相互关系。

    gasp:汇编宏处理器。

    ld:目标代码联接,联接各目标代码块,它是生成可执行代码的最终步骤。

    nm:从目标代码文件中枚举所有调试符号名。

    objcopy:使用GNU BSD库,把目标代码从一文件格试拷贝成另一种格试。

    objdump:显示目标文件信息。

    readelf:显示elf文件信息。

    ranlib:生成索引以加快对归档文件的访问。

    size:列出目标模块或文件的代码尺寸。

    strings:打印可打印的目标代码字符(至少4个字符),打印字符多少可以控制。对 于其它格试的文件,打印字符串。

    strip:放弃所有符号联接。

    2.3.2、Binutils的配置和编译安装
    tar -jxvf binutils-2.16.1.tar.bz2 -C ~
    cd ~/binutils-2.16.1

    make clean
    make distclean

    ./configure --target=arm-pc-linux   --prefix=/usr/local/arm

    make
    make install

           如果安装成功(通常都不会有问题),进入下一步:GCC

    2.4、编译、安装GCC

           它是GNU(ftp://ftp.gnu.org)工具之一,是主要的编译处理工具。

    2.4.1 ARM核心头文件
           对于本机的编译工具集,通常核心头文件已经安装在/usr/src/linux/include,或被gcc拷贝到搜寻路径内。但对于ARM交叉编译工具集,可能还没有(除非在此前已经安装过),由其是第一次定制。所以,我们需要提取ARM核心头文件。这里我们使用面向AT91RM9200的核心文件 linux-2.4.27-vrs1.tar.bz2 (如果是通用核心,那么你需要面向ARM的补丁文件)

    tar -jxvf linux-2.4.27-vrs1.tar.bz2 -C ~
    cd ~
    ln -s linux-2.4.27-vrs1-ATMEL armlinux

           好了,我们建立了:~/armlinux 联接

    cd ~/armlinux
    vim Makefile

           检查ARCH := 的行,如果不是arm,请把它改成ARCH := arm,保存退出。 (检查CROSS_COMPILE := /usr/local/arm/bin/arm-pc-linux-,如果不同,修改它)

    make clean
    make distclean

    make menuconfig

           配置核心(选择ARM为AT91RM9200和其它相关配置),保存退出。

    make dep

          (如遇错误终止,看第3部份是否有解答!)

           肯定有错误发生而终止!当然,我们并不是想现在编译这个核心,只是理顺核心文件间的关系,以便下面拷贝操作顺利进行......

    mkdir /usr/local/arm/arm-pc-linux/sys-include

    cp -dR ~/armlinux/include/asm-arm         /usr/local/arm/arm-pc-linux/sys-include/asm

    cp -dR ~/armlinux/include/linux         /usr/local/arm/arm-pc-linux/sys-include/linux

             好了,我们现在有ARM交叉编译的公用核心头文件了。

    2.4.2、gcc配置、编译和安装

          阅读gcc源代码INSTALL目录下的文件,获得更多的配置和编译安装帮助。
          为了使用前面编译好的Binutils工具,添加路径。
    export PATH=$PATH:/usr/local/arm/bin
          (如果/usr/local/arm/bin已经包含在PATH,此步骤省略)

    tar -jxvf gcc-3.4.5.tar.bz2 -C ~

    cd ~/gcc-3.4.5

    2.4.3、第一次安装ARM交叉编译工具gcc
          (阅读gcc源代码INSTALL目录下的文件,获得更多的配置、编译和安装帮助)
           通常都会遇到问题而使整个过程不能完成,因为以下要素必须考虑:
           既然是第一次安装ARM交叉编译工具,那么本机的glibc支持的应该是本机的编译工具库,而不是ARM交叉编译工具库。并且支持ARM交叉编译工具的其它支持语言(比如:C++、java)的libc库(最终的gcc生成的二进制代码联接需要该库支持)我们也没有,所以,要增加编译开关:
    --enable-languages=c --disable-threads --disable-shared
           同理,由于第一次安装ARM交叉编译工具,那么支持的libc库的头文件也没有!所以我们征用Dinhibit_libc来hack(这个词只可意会,不可言传)这个问题。操作如下:
    cp ~/gcc-3.4.5/gcc/config/arm/t-linux     ~/gcc-3.4.5/gcc/config/arm/t-linux.orig
    vim ~/gcc-3.4.5/gcc/config/arm/t-linux
           给TARGET_LIBGCC2_CFLAGS = 增加操作参数
    -Dinhibit_libc -D__gthr_posix_h
           保存退出。
           让我们来重新配置、编译它......
    export PATH=$PATH:/usr/local/arm/bin
          (如果/usr/local/arm/bin已经包含在PATH,此步骤省略)

    cd ~/gcc-3.4.5

    make clean
    make distclean

    ./configure --target=arm-pc-linux --prefix=/usr/local/arm              --disable-threads --disable- shared                        --enable-languages=c

           (由于上面我们把交叉编译头文件拷贝到了gcc的默认sys-include目录,因此不需要定义--with-headers参数。实际测试中,定义--with-headers反而不能make通过,不知道是否bug)

    make
           (痛苦的除bug过程!)
          (如遇错误终止,看第3部份是否有解答,并且强烈建议你从make clean开始!)
    make install
           如果安装成功,我们就有了能编译C语言的ARM交叉编译工具gcc了。如果你只是用ARM交叉编译工具编译ARM核心,OK!你可以就此打住。如果想编译用户级代码,继续进入下阶段......

    2.5、编译、安装GLIBC

           glibc 是个C库,几乎所有的应用程序都需要共享它提供的功能(除了kernel、bootload、和其它完全不用C库的功能代码),因此glibc的存在有利益小系统或嵌入系统缩减系统总代码尺寸与存放空间(尽管单个的glibc库是比较大的)。所以,最后的工作就是:构造ARM交叉编译系统的glibc库。
    2.5.1、解压源代码
           首先解压glibc代码,再解压linuxthreads代码到glibc代码的源码目录下......
    tar -jxvf glibc-2.3.6.tar.bz2 -C ~
    tar -jxvf glibc-linuxthreads-2.3.6.tar.bz2 -C ~/glibc-2.3.6
    2.5.2、glibc配置、编译、安装
          阅读glibc源代码下的文件:README、FAQ和INSTALL,获得更多的配置、编译和安装帮助。
    export PATH=$PATH:/usr/local/arm/bin
         (如果/usr/local/arm/bin已经包含在PATH,此步骤省略)
    export CC=arm-pc-linux-gcc
        (定义用刚生成的ARM交叉编译工具编译。否则,生成的glibc库是本地机代码库,而不是ARM指令集代码库!!!)

         警告:不能在源代码目录下操作(为什麽?问GNU吧,我也不知道!)......

    mkdir ~/temp
    cd ~/temp

    make clean
    make distclean

    ~/glibc-2.3.6/configure --host=arm-pc-linux                                                --build=i686-pc-linux-gnu                            --with-headers=/usr/local/arm/arm-pc-linux/sys-include             --enable-add-ons=linuxthreads   --enable-shared                    --prefix=/usr/local/arm/arm-pc-linux

          (你可能注意到glibc的--prefix值与gcc的配置不一样!是的,你必须这样定义,否则,后面gcc的make过程将因找不到glibc的公用头文件或库而错误终止!)

    make
         (痛苦的除bug过程!)
         (如遇错误终止,看第3部份是否有解答,并且强烈建议你从make clean开始!)

    make install

    2.6、让交叉编译工具支持更多编译语言


          以上虽然完成了交叉编译工具的C编译器,但还不能编译ada、c++、 f77、 java、 objc等语言的程序。
    2.6.1、用现有的交叉编译工具重新构造gcc
          由于我们现在已经有了基本的C交叉编译工具,将不受2.4.3描述的条件限制。让我们重新构造gcc......
    export PATH=$PATH:/usr/local/arm/bin
          (如果/usr/local/arm/bin已经包含在PATH,此步骤省略)
    export -n CC
         (清出CC环境变量,选用本机默认编译器。否则,重新生成的交叉编译工具gcc不能在本机运行!!!)
          恢复先前(2.4.3步骤)修改的t-linux文件:
    cp ~/gcc-3.4.5/gcc/config/arm/t-linux.orig     ~/gcc-3.4.5/gcc/config/arm/t-linux
    cd ~/gcc-3.4.5

    make clean
    make distclean

           如果需要支持gcc允许的所有编程语言(牛吧),用下面这个配置:
    ./configure --target=arm-pc-linux --prefix=/usr/local/arm             --host=i686-pc-linux-gnu                                  --enable-threads=posix
           如果仅需要gcc支持C和C++编程语言(简少占用空间),用下面这个配置:
    ./configure --target=arm-pc-linux -- prefix=/usr/local/arm             --host=i686-pc-linux-gnu                                  --enable-threads=posix                                    --enable-languages=c,c++

    make
            (烧水、泡茶、耐心等待!)

    make install

    2.6.2、用完整的交叉编译工具重新构造glibc
              重复2.5.2的步骤,简单!(继续喝茶!)

    2.7、测试定制的交叉编译工具

            自己写段Hello Word!的C程序(你不会写不来吧)...比如:hello.c
    export PATH=$PATH:/usr/local/arm/bin
           (如果/usr/local/arm/bin已经包含在PATH,此步骤省略)
    arm-pc-linux-gcc -O2   -o   hello-c.arm   hello.c
           运行编译好的程序:
    ./hello-c.arm
          错误提示:cannot execute binary file

          哦!忘了,它要在ARM系统环境运行......把文件拷贝到U盘,挂接在AT91RM9200系统板上(系统板运行的是Linux,可别是什么WinCE之类的$money系统呀!),
         运行hello-c.arm,超级终端---终于看见久违的:
    Hello Word!

    (恭喜:你已经迈入制器殿堂!一代宗师指日可待......)

    ***********************************************************************

    3、遇到问题怎么办


           以下是本人操作上面步骤时遇到的问题,供以后参考。记录如下:

    =======================================================================
    Q: 用make dep(或make)ARM核心时,错误提示如下:
        cc1: error: invalid option `short-load-bytes'

    A: 参照http://gcc.gnu.org/ml/gcc-patches/1999-11n/msg00649.html
    gcc-3.x.x不支持-mshort-load-bytes,而用-malignment-traps代替。

    cp ~/armlinux/arch/arm/Makefile ~/armlinux/arch/arm/Makefile.orig

    修改ARM核文件arch/arm/Makefile,用-malignment-traps代替-mshort-load-bytes

    =======================================================================

    Q:编译glibc提示:核心版本太老,低于2.0.10

    A:如果确定你拷贝到sys-include的头文件是从高于2.0.10核中来,比如:本文中用的是2.4.27-vrs1,也提示这个错误,

    cp /usr/local/arm/arm-pc-linux/sys-include/linux/version.h     /usr/local/arm/arm-pc-linux/sys-include/linux/version.h.orig

    修改文件versions.h,替换#define UTS_RELEASE "2.4.27-vrs1"用
    #define UTS_RELEASE "2.4.27"

    =======================================================================
    Q:glibc编译错误如下:
       error: `BUS_ISA' undeclared

    A:参照http://www.ussg.iu.edu/hypermail/linux/kernel/0311.0/0529.html
    kernel-2.4.23以上的核心用CTL_BUS_ISA代替BUS_ISA,

    cp ~/glibc-2.3.6/sysdeps/unix/sysv/linux/arm/ioperm.c    ~/glibc-2.3.6/sysdeps/unix/sysv/linux/arm/ioperm.c.orig

    所以修改glibc源代码下的文件sysdeps/unix/sysv/linux/arm/ioperm.c 用CTL_BUS_ISA替换BUS_ISA

    =======================================================================
    Q:glibc编译错误如下:
       ld: cannot find -lgcc_eh

    A:参照http://kegel.com/crosstool/crosstool-0.38/patches/glibc-20040822/glibc-2.3.3-libeh-kludge.patch

    cp ~/glibc-2.3.6/Makeconfig ~/glibc-2.3.6/Makeconfig.orig

    修改glibc源代码下的文件Makeconfig

    #gnulib := -lgcc $(libgcc_eh)#static-gnulib := -lgcc -lgcc_eh $(libunwind)
    修改为:gnulib := -lgccstatic-gnulib := -lgcc
    =======================================================================
    Q: glibc编译错误如下:
    ../sysdeps/generic/s_fmax.c:28: internal compiler error: in elim_reg_cond, at flow.c:3273

    A:参照http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/flow.c.diff?cvsroot=gcc& amp;only_with_tag=csl-arm-branch&r1=1.563.4.2&r2=1.563.4.3
    问题来自gcc的内部,cp ~/gcc-3.4.5/gcc/flow.c ~/gcc-3.4.5/gcc/flow.c.orig
    修改gcc源代码下 ~/gcc-3.4.5/gcc/flow.c 文件,重新编译安装arm-pc-linux-gcc (重新开始2.4.3步骤,狂晕!)


    2010-03-12             

    注:源自原百度博客“至美心"

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值