**************************************************************************
编写:王卫无,北京讯业互联科技有限公司
版本号:V1.1
日期:2005年12月31日
联系:wolver@21com.com
更新记录:1)改动glibc配置參数  2)填加CC环境变量的设置
**************************************************************************

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&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步骤,狂晕!)

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

定制ToolChain for ARM的更多相关文章

  1. Linux内核配置:定制配置选项

    很多嵌入式开发人员都需要在Linux内核中添加一些特性,以支持特别的定制硬件. ARM架构的顶层Kconfig文件中,可以看到一个名为System Type的菜单项.在ARM system type提 ...

  2. arm交叉编译 扫盲贴

    ARM交叉编译工具链 为什么要用交叉编译器? 交叉编译通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序, 比如在PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平 ...

  3. 如何在 arm 官网上找到合适的手册

    http://infocenter.arm.com/help/advanced/help.jsp 在这里输入合适的版号即可 这样就可以不用去 CSDN 了 100000_0000_00_EN - AR ...

  4. Buildroot 用户手册 (中文)

    文章目录 I. Getting started 1. About Buildroot 2. System requirements 2.1. Mandatory packages 2.2. Optio ...

  5. 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计

    本帖最后由 xinxincaijq 于 2013-1-9 10:27 编辑 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计 转自博客:http:// ...

  6. Using QEMU for Embedded Systems Development

    http://www.opensourceforu.com/2011/06/qemu-for-embedded-systems-development-part-1/ http://www.opens ...

  7. [异常解决] Make nRF51 DFU Project Appear "fatal error: uECC.h: No such file or directory"

    What's the problem When I make the nRF51's DFU project appear "no uECC.h" error: And then ...

  8. Buildroot阅读笔记

    之前有写一篇文章:http://www.cnblogs.com/tfanalysis/p/3625430.html理清如何make menuconfig的问题,现在今天在无意间多注意了一下buildr ...

  9. 采用busybox 代替android 自带的shell

    折腾了几天,被Android那点儿少得可怜的shell命令折磨的死去活来,终于下定了革命的决心.看一下怎么把渺小的toolbox替换成伟大的busybox吧.先大致描述一下Android系统中的she ...

随机推荐

  1. Maven java项目管理工具

    Maven java项目管理工具 1.安装maven 下载最新的maven 下载地址 http://maven.apache.org/download.cgi 传到要安装的目录 例如/opt/下 # ...

  2. Log4net 自定义字段到数据库(二)

    这种方法比第一种方法麻烦些 Log4Net.config <?xml version="1.0" encoding="utf-8" ?> <c ...

  3. hdu 4888 Redraw Beautiful Drawings 网络流

    题目链接 一个n*m的方格, 里面有<=k的数, 给出每一行所有数的和, 每一列所有数的和, 问你能否还原这个图, 如果能, 是否唯一, 如果唯一, 输出还原后的图. 首先对行列建边, 源点向行 ...

  4. “use strict”对js的影响

    一:全局变量显示声明 在正常模式下,如果一个变量没有声明就赋值,默认是全局变量,严格模式禁止用这种方法.全局变量必须显示声明. ; i++) { function f2() { } // 语法错误 } ...

  5. 【LeetCode题意分析&解答】37. Sudoku Solver

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  6. 改变QTreeView项高的方法(改变Delegate行高,或者::data取数据的时候,根据Qt::SizeHintRole进行判断)

    很久之前写过一篇关于QTreeView快速显示超过千万条数据项的方法,如果说那篇文章讲的是QTreeView的内功的话,今天这篇是讲QTreeView的外功,有时我们想改变视图的数据项的行高,那怎么办 ...

  7. HDU 5893 List wants to travel(树链剖分)

    [题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5893 [题目大意] 给出一棵树,每条边上都有一个边权,现在有两个操作,操作一要求将x到y路径上所有边 ...

  8. ArcMAp对线要素进行平滑处(打断)

    一:工具简单介绍 -- ArcMAp10.1的高级编辑工具中提供了对线/面要素进行概括/平滑处理的工具. 概括工具.平滑工具分别例如以下:(首先得开启编辑状态 --- 才干够对要素的属性进行更改).选 ...

  9. Zoie Merge Policy

    Zoie有一个ZoieMergePolicy如若价格值不是特别的.这是为lucene早期的版本号merge在不考虑删除doc会计并加以改进,和LogMergePolicy只是做同样的也合并相邻节段,而 ...

  10. CodeForces 160D - Distance in Tree 树型DP

    题目给了512MB的空间....用dp[k][i]代表以k为起点...往下面走(走直的不打岔)i步能有多少方案....在更新dp[k][i]过程中同时统计答案.. Program: #include& ...