Ubuntu 9.10上建立ARM-Linux交叉编译环境

一、序言

学习ARM嵌入式的人都知道,要想使PC上的程序运行在ARM板,必须建立交叉编译环境来对源代码进行编译。对于交叉编译环境的基本概念这里就不多说了,网上多得是。这里主要是写我在建立交叉编译环境时的方法步骤和一些想法。

我的建立过程经历了疯狂的四天。在这四天里,我除了睡觉,吃饭,上厕所,几乎所有的时间都坐在电脑面前,只是为了最后那100多MB的文件。我终于体会到了在面对复杂的问题时的那种无助的心情。也终于知道了想当一名自由软件支持者所要具备的能力与心态(那就是怎样在困难与错误面前寻找解决办法)。

学习嵌入式Linux的道路是辛苦的,尤其是DIY。为了建立一个交叉编译的环境,我便花费了4天的努力才得到结果。就那100多MB的文件,看起来没什么,可是时间成本是巨大的。这几天时间什么都没做,课也全逃掉了,有一位同学甚至还发短信问我是不是消失了?_?嘿嘿,我当然没消失,只是躲在寝室里在电脑上编译那几个文件。这就是自由软件的麻烦之处,文件之间关系依赖很复杂繁琐,初学者根本不知道其文件见的联系是怎么样的,按着网上的步骤出现了错误也不知原因。编译中总是有那些莫名奇怪的错误,有了错误怎么办,上网查,看README文档,看标准,上各个BBS上去问,国内的网站没有,还得去国外网站上去查汗。有的错误还好,是常见的,有解决方案色;有的错误有成百上千种原因,我不可能一一去试晕;甚至有两次我还编译出了连网上都不存在的错误,我更是晕了惊恐。有时候编译总是不过,我便把全部文件删除然后重新来做,这样反反复复不知有多少次吐。怪不得有人说做交叉编译环境是要靠运气的。

不过还好,我在国外的一个网站中找到一个版本较为新的建立步骤,而且通过率很高,没什么大的错误。下面便进入正题,把我的建立过程写下来。

二、准备文件

我的电脑是装的Ubuntu 9.10 Linux,不是虚拟机。想建立交叉编译环境,首先你的电脑中得有编译环境,就是那些常见的,例如GCC等。这个我就不写了,网上也是多得是,太常见了。

然后,我们要下载建立所需要的文件。这是列表:

源代码文件及其版本与下载地址:

binutils-2.19.1.tar.bz2       http://ftp.gnu.org/gnu/binutils/
    gcc-4.3.3.tar.bz2             http://ftp.gnu.org/gnu/gcc/gcc-4.3.3/

glibc-2.11.tar.bz2            http://ftp.gnu.org/gnu/glibc/
    glibc-ports-2.11.tar.bz2      http://ftp.gnu.org/gnu/glibc/
    gmp-4.2.4.tar.bz2             http://ftp.gnu.org/pub/gnu/gmp/
    linux-2.6.30.1.tar.bz2        http://ftp.kernel.org/pub/linux/kernel/v2.6/
    mpfr-2.4.1.tar.bz2            http://www.mpfr.org/mpfr-2.4.1/
    补丁包版本及其下载地址:

binutils-2.19.1-branch_update-1.patch

http://ftp.crosslfs.org/pub/clfs/conglomeration/binutils/
    binutils-2.19.1-posix-1.patch

http://ftp.cross-lfs.org/pub/clfs/conglomeration/binutils/           
    gcc-4.3.3-branch_update-5.patch

http://ftp.lfs-matrix.net/pub/clfs/conglomeration/gcc/
    gcc-4.3.3-posix-1.patch

http://ftp.lfs-matrix.net/pub/clfs/conglomeration/gcc/
    gcc_eh.patch.cross

http://svn.exactcode.de/t2/trunk/package/base/glibc/gcc_eh.patch.cross
    mpfr-2.4.1-branch_update-1.patch

http://cross-lfs.org/files/packages/embedded-0.0.1/
    mpfr-2.4.1-branch_update-2.patch

http://cross-lfs.org/files/packages/embedded-0.0.1/

注:1.对于版本的要求:刚开始时很多人都会选用各个源代码最新的版本,其实没必要,也不好。其一,你的板子不一定支持这么新的源代码;其二,因为新的版本中会加入新的东西,当你按着原先的方法进行编译时会出错误,而你又不知道错误在哪,这是很麻烦的,我就吃了这方面的亏,所以当你是新人时,尽量选择网上成功例子的版本,这样会出错的概率会小一些。当然,如说你是高手或者对Linux下各个源代码的编译过程有所了解,那就例外了。

2.打补丁的方法:打补丁的方法很简单,首先进入你想要打补丁的文件夹,然后执行patch -p1 < path/to/your patch document(就是你的补丁文件的路径,还要注意“<”前后是有空格的),例如:

$cd binutils-2.19.1

$patch -p1 < /home/Yourname/binutils-2.19.1-branch_update-1.patch  

如果你想详细了解请看:http://www.diybl.com/course/6_system/linux/Linuxjs/2008826/137710.html

然后我们开始要建立文件目录:

/home/Yourname/ARM/--Build /*存放源代码的目录/--binutils/*二进制文件

                  |                         | --gcc/*编译器

                  |                         | --glibc/*C库文件

                  |--Linux-Kernel /*存放内核的目录

                  |--Cross-Compile /*工具安装目录

建立好了目录之后,将各个源代码文件放入对应的文件夹中,这时../Build/binutils中应该有binutils-2.19.1.tar.bz2,binutils-2.19.1-branch_update-1.patch,binutils-2.19.1-posix-1.patch。/Build/gcc中应该有 gcc-4.3.3.tar.bz2,gmp-4.2.4.tar.bz2 ,mpfr-2.4.1.tar.bz2,gcc-4.3.3-branch_update-5.patch,gcc-4.3.3-posix-1.patch,mpfr-2.4.1-branch_update-1.patch,mpfr-2.4.1-branch_update-2.patch。Build/glibc中应该有glibc-2.11.tar.bz2,glibc-ports-2.11.tar.bz2,gcc_eh.patch.cross。Linux-Kernel中应该有linux-2.6.30.1.tar.bz2

紧接着,解压缩各个文件,对应打好补丁。然后,将gmp-4.2.4改名gmp和mpfr-2.4.1改名mpfr放入gcc-4.3.3文件夹中。将glibc-ports-2.11改名为ports放入glibc-2.11中。

对于Ubuntu的用户,有一工具叫做mawk,我不知道是干什么用的,但是对于建立交叉编译环境是不利的,要换成gawk,具体方法可以google。

到目前为止,文件准备工作已全部完毕。

三、建立二进制工具(binutils)

建立环境变量:

$vim ~/.bashrc 在最先面加入如下的代码:

export PRJROOT=/home/Yourname/ARM

export PREFIX=$PRJROOT/Cross-Compile
    export $TARGET=arm-linux
    export PATH=$PREFIX/tools/bin:$PATH
    export host=i486-cross-linux-gnu

然后在终端执行

$cd /home/Youname/ARM/Build/binutils

$mkdir b

$cd b

$AR=ar AS=as ../binutils-2.19.1/configure /

--build=i486-cross-linux-gnu /

--host=i486-cross-linux-gnu /

--target=$TARGET /

--prefix=$PREFIX/tools /

--with-sysroot=$PREFIX /

--disable-nls --enable-shared --disable-multilib  --disable-werror注意:“/”不能省且前有空格

$make all

$make install

看一下$PREFIX/tools/bin 下的生成的文件都是用来干什么的

add2line - 将你要找的地址转成文件和行号,它要使用 debug 信息。

Ar-产生、修改和解开一个存档文件

As-gnu 的汇编器C++filt-C++ 和 java 中有一种重载函数,所用的重载函数最后会被编译转化成汇编的标号,c++filt 就是实现这种反向的转化,根据标号得到函数名。

Gasp-gnu 汇编器预编译器。

Ld-gnu 的连接器Nm-列出目标文件的符号和对应的地址Objcopy-将某种格式的目标文件转化成另外格式的目标文件Objdump-显示目标文件的信息

Ranlib-为一个存档文件产生一个索引,并将这个索引存入存档文件中

Readelf-显示 elf 格式的目标文件的信息

Size-显示目标文件各个节的大小和目标文件的大小

Strings-打印出目标文件中可以打印的字符串,有个默认的长度,为4

Strip-剥掉目标文件的所有的符号信息

四、建立内核头文件(Linux Kernel)

$cd $PRJROOT/Linux-Kernel/linux-2.6.30.1

$mkdir -p $PREFIX/usr/include

$make mrproper

$make ARCH=arm headers_check

$make ARCH=arm INSTALL_HDR_PATH=dest headers_install

$cp -rv dest/include/* $PREFIX/usr/include

$find $PREFIX/usr/include -name .install -or -name ..install.cmd | xargs rm -fv

五、建立初始编译器(bootstrap gcc)

$cd $PRJROOT/Build/gcc

$mkdir g

$cd g

$AR=ar LDFLAGS="-Wl,-rpath,$PREFIX/lib"/

/home/polaris/ARM/build/gcc/gcc-4.3.3/configure /

--build=i486-cross-linux-gnu /

--host=i486-cross-linux-gnu /

--target=arm-linux /

--prefix$PREFIX/tools /

--enable-languages=c /

--disable-nls --disable-shared --disable-threads /

--disable-libmudflap --disable-libssp --disable-libgomp /

--disable-decimal-float --without-headers --with-newlib /

--with-sysroot=$PREFIX

$make

$make install

我们来看看 $PREFIX/bin 里面多了哪些东西,你会发现多了 arm-linux-gcc 、arm-linux-unprotoize、cpp 和 gcov 几个文件。

Gcc-gnu 的 C 语言编译器

Unprotoize-将 ANSI C 的源码转化为 K&R C 的形式,去掉函数原型中的参数类型。

Cpp-gnu的 C 的预编译器

Gcov-gcc 的辅助测试工具,可以用它来分析和优程序。

六、建立 c 库(glibc) 

$cd $PRJROOT/Build/glibc

$mkdir g

$cd g

$echo "libc_cv_forced_unwind=yes" > config.cache /

echo "libc_cv_c_cleanup=yes" >> config.cache /

echo "libc_cv_arm_tls=yes" >> config.cache

$BUILD_CC="gcc" CC=arm-linux-gcc AR=arm-linux-ar RANLIB=arm-linux-ranlib

$$PRJROOT/build/glibc/glibc-2.11/configure /

--build=i486-cross-linux-gnu /

--host=arm-linux /

--target=arm-linux /

--prefix=$PREFIX/usr /

--with-tls --disable-profile --enable-add-ons /

--enable-kernel=2.6.0 --with-__thread /

--with-binutils=$PREFIX/tools/bin /

--with-headers=$PREFIX/usr/include /

--cache-file=config.cache

$make all

$make install

然后你还要修改 libc.so 文件,将GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a)改为
GROUP ( libc.so.6 libc_nonshared.a)这样连接程序 ld 就会在 libc.so 所在的目录查找它需要的库,因为你的机子的/lib目录可能已经装了一个相同名字的库,一个为编译可以在你的宿主机上运行的程序的库,而不是用于交叉编译的。

七、建立全套编译器(full gcc)

在建立boot-gcc 的时候,我们只支持了C。到这里,我们就要建立全套编译器,来支持C和C++。

$cd $PRJROOT/Build/gcc

$mkdir g1

$cd g1

$/home/polaris/ARM/build/gcc/gcc-4.3.3/configure /

--build=i486-cross-linux-gnu /

--host=i486-cross-linux-gnu /

--target=arm-linux /

--prefix=$PREFIX/tools /

--enable-languages=c,c++ --enable-c99 /

--enable-threads=posix --enable-long-long --enable-shared /

--enable-__cxa_atexit --disable-multilib --disable-nls --disable-libgomp /

--with-sysroot=$PREFIX

$make

$make install

我们再来看看 $PREFIX/bin 里面多了哪些东西。你会发现多了 arm-linux-g++ 、arm-linux-protoize 和 arm-linux-c++ 几个文件。

G++-gnu的 c++ 编译器。

Protoize-与Unprotoize相反,将K&R C的源码转化为ANSI C的形式,函数原型中加入参数类型。

C++-gnu 的 c++ 编译器。

至此,整个交叉编译环境就建立完成了。

八、测试(Test)

写一个Hello World程序来测试你的交叉编译环境

$vim hello.c

#include<stdio.h>

int main()

{

    printf("Hello World!/n");

    return 0;

}

$arm-linux-gcc hello.c -o hello

$file hello

hello: ELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), not stripped

上面的输出说明你编译了一个能在 arm 体系结构下运行的 helloworld,证明你的编译工具做成功了!

九、后序

以上是我的建立过程方法,因为每个人手中的电脑配置不同且Linux内部环境设置也不一样,按此步骤建立不一定能够正确建立。因此本文只作为参考,在建立过程中要多用网络来寻找解决问题的方法,这样才能建立一个完整的交叉编译环境。如若本文有错误,敬请原谅!

十、参考资料

1.《自己实验建立交叉编译工具链》http://blog.chinaunix.net/u2/60303/showart_2159276.html

2.《如何为嵌入式开发建立交叉编译环境http://www.ibm.com/developerworks/cn/linux/l-embcmpl/

 

转自新浪博客:http://blog.sina.com.cn/s/blog_44543ce90100h6ya.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值