Ubuntu 下建立ARM交叉编译工具链(转)

Ubuntu 下建立ARM交叉编译工具链

2009-04-18 benzus   搞了一天,终于成功了。下面分享一下。
我的Ubuntu是9.04(今早刚升级的,目前还是beta版,其中gcc-4.3.3),不过8.10应该也没什么问题,其他版本的不清楚,不过如果你的Ubuntu不幸不是这两个版本,也可以试一下。另外说一句,我敢断定如果你在RedHat或Fedora下编译的话,成功率会比Ubuntu高很多!(呵呵,其实我已经试过了,看来Debian系做开发还是没有RedHat系方便啊)特别是,RedHat/Fedora对源码包版本的选择和组合比较自由,通常很随便就能编译成功,所以用RedHat/Fedora做开发是很不错的选择!

开始前的提醒:但愿你知道bash的自动补全功能,不然以下的工作中那些冗长的不断重复的路径名将让你很不愉快。

一、准备工作
     确认你的Ubuntu上已经安装了C/C++编译环境(gcc、g++、libc等等),如果没有或者你不确定,请执行下列命令来安装:
$ sudo apt-get install build-essential

      安装GNU automake:
$ sudo apt-get install automake

      安装bison、flex:
$ sudo apt-get install bison flex

      安装texinfo:
$ sudo apt-get install texinfo

       安装gawk(Ubuntu默认安装mawk,但mawk编译glibc headers会出问题):
$ sudo apt-get install gwak

       有了gawk,留着mawk也没什么意思了,卸载它吧:
$ sudo apt-get remove mawk

二、下载源码包
       为了与时俱进,我基本上全部使用当前最新的源码包。当然,Linux内核现在最新的是2.6.29.1,但内核对构建交叉工具链的影响还不算大,我们只是需要内核的头文件。这里我选择2.6.28,没什么原因,只是因为是偶数的,看着舒服。
        源码包                                           下载地址/方法
binutils-2.19.tar.gz                         ftp.gnu.org/gnu/binutils
gcc-core-4.3.3.tar.gz                     ftp.gnu.org/gnu/gcc
gcc-g++-4.3.3.tar.gz                     ftp.gnu.org/gnu/gcc
mpfr-2.4.1.tar.gz                                google
gmp-4.3.0.tar.gz                                 google
linux-2.6.28.tar.gz                        ftp.kernel.org/pub/linux/kernel
glibc-ports-2.7.tar.gz                    ftp.gnu.org/gnu/glibc
glibc-2.7.tar.gz                             ftp.gnu.org/gnu/glibc
另外还需要glibc-2.7的补丁(google一下就能下载到):
glibc-2.7-alpha_ioperm_fix-1.patch
glibc-2.7-alpha_PTR_MANGLE_fix-1.patch
glibc-2.7-branch_update-1.patch
glibc-2.7-branch_update-1A.patch
glibc-2.7-libgcc_eh-1.patch
glibc-2.7-localedef_segfault-1.patch

三、编译前的准备
        说一下,我把编译后的东西都放在登录用户目录下的armtools目录,具体步骤如下:
$ cd ~
$ mkdir armtools
        导出环境变量:
$ export PREFIX=~/armtools
$ export TARGET=arm-linux
        创建tars目录,把上面下载的源码包和补丁都放在~/tars目录下,之后创建SourceDir用来存放以后解压缩的源码包,BuildDir作为我们编译的地方:
$ mkdir ~/tars
$ mkdir ~/tars/SourceDir
$ mkdir ~/tars/BuildDir

四、编译binutils
         binutils的编译是最独立的,一般也不会有什么问题,当然,我还是遇到了编译不通过的事情但还是让我解决了,请看:
(1)解压缩:
$ cd ~/tars/SourceDir
$ tar -zvxf ../
binutils-2.19.tar.gz
(2)编译:
$ cd ~/tars/BuildDir
$ mkdir binutils
$ cd binutils
$ ../../SourceDir/binutils-2.19/configure --target=$TARGET --prefix=$PREFIX
$ make
$ make all install
注:在make这一步中,可能会在编译
SourceDir/binutils-2.19/gas/config/tc-arm.c 出现gcc把警告当成错误的错误,其原因在于编译该文件时使用了-Werror选项,解决办法是修改 SourceDir/binutils-2.19/gas/configure文件第10624行,把ERROR_ON_WARNING=yes改为ERROR_ON_WARNING=no,保存退出,重新执行make即可。
(3) 导出binutils的路径:
$ export PATH=$PREFIX/bin:$PATH


五、编译gcc(第一遍)

       第一次编译gcc只是为了产生针对target用的编译工具,因此不需要头文件和特别注意的,当然要注意满足target的要求。
(1)解压缩:
$ cd ~/tars/SourceDir
$ tar -zvxf ../gcc-core-4.3.3.tar.gz
       从 GCC-4.3起,安装GCC将依赖于GMP-4.1以上版本和MPFR-2.3.2以上版本。如果将这两个软件包分别解压到GCC源码树的根目录下,并分别命名为"gmp"和"mpfr",那么GCC的编译程序将自动将两者与GCC一起编译。建议尽可能使用最新的GMP和MPFR版本。
$ tar -zvxf ../
mpfr-2.4.1.tar.gz
$ tar -zvxf ../
gmp-4.3.0.tar.gz
$ mv mpfr-2.4.1 gcc-4.3.3/mpfr
$ mv gmp-4.3.0 gcc-4.3.3/gmp
      既然是第一次安装ARM交叉编译工具,那么本机的glibc支持的应该是本机的编译工具库,而不是ARM交叉编译工具库。并且支持ARM交叉编译工具的其它 支持语言(比如:C++、java)的libc库(最终的gcc生成的二进制代码联接需要该库支持)我们也没有,所以,要增加编译开关:
--enable-languages=c --disable-threads --disable-shared
同样,由于第一次安装ARM交叉编译工具,那么支持的libc库的头文件也没有!所以我们征用Dinhibit_libc来解决这个问题。操作如下:
$ cd gcc-4.3.3/gcc/config/arm
$ mv t-linux t-linux-orig
$ sed 's/TARGET_LIBGCC2_CFLAGS =/TARGET_LIBGCC2_CFLAGS = -D__gthr_posix_h -Dinhibit_libc/' < t-linux-orig > t-linux-core
$ cp t-linux-core t-linux

(2)编译:
$ cd ~/tars/BuildDir
$ mkdir gcc-core
$ cd gcc-core
$ ../../SourceDir/gcc-4.3.3/configure /
--target=$TARGET /
--prefix=$PREFIX /
--enable-languages=c /
--disable-shared /
--disable-threads /
--disable-libmudflap /
--disable-libssp
注: 由于没有arm的glibc,需要使用--disable-libmudflap --disable-libssp,禁止两个边界检查使用的库。
$ make all-gcc
(如果有错则忽略之,不过我编译时没有出错,注意是all-gcc,不是all)
$ make install-gcc

六、创建 linux-kernel 头文件
(1)解压并初步配置内核:
$ cd ~/tars/SourceDir
$ tar -zvxf ../linux-2.6.28.tar.gz
$ cd linux-2.6.8
$ make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
在menuconfig里面load一个的s3c2410的配置然后退出并保存。
$ make ARCH=arm CROSS_COMPILE=arm-linux- #这个不用等编译结束,开始一两分钟就用Ctrl+C中止。即使报错也别管它。

(2)复制内核头文件到目标目录:
$ mkdir $PREFIX/$TARGET/include
$ cp -a include/linux    $PREFIX/$TARGET/include/linux
$ cp -a include/asm-arm   $PREFIX/$TARGET/include/asm
$ cp -a include/asm-generic   $PREFIX/$TARGET/include/asm-generic
$ cp -a arch/arm/include/asm   $PREFIX/$TARGET/include
$ cp -a arch/arm/mach-s3c2410/include/mach   $PREFIX/$TARGET/include/asm

七、编译glibc
(1)解压缩:
$ cd ~/tars/SourceDir
$ tar -zvxf ../glibc-2.7.tar.gz
$ tar -zvxf ../glibc-ports-2.7.tar.gz
$ mv -v glibc-ports-2.7 glibc-2.7/ports
$ cd glibc-2.7
(2)打补丁和修正:
$ patch -Np1 -i ../../glibc-2.7-alpha_ioperm_fix-1.patch
$ patch -Np1 -i ../../glibc-2.7-alpha_PTR_MANGLE_fix-1.patch
$ patch -Np1 -i ../../glibc-2.7-branch_update-1.patch
$ patch -Np1 -i ../../glibc-2.7-branch_update-1A.patch
$ patch -Np1 -i ../../glibc-2.7-libgcc_eh-1.patch
$ patch -Np1 -i ../../glibc-2.7-localedef_segfault-1.patch

接着做以下动作
      原来从gcc4.3开始将一部分头文件放到另一个文件夹中,导致glibc找不到,对glibc的configure做补丁(至于原因可以参见configure文件里的注释):
$ sed -i -e "/ccheaders=/s@/`/(/$CC.*include/)/`@/"& -isystem /`/1-fixed/`/"@" configure

     还有就是为了编译通过修改的文件
$ sed -i 's/# define UNDOCARGS_5/tUNDOCARGS_4/&/n/n# define DOCARGS_6/tDOCARGS_5/n# define UNDOCARGS_6/tUNDOCARGS_5/' ports/sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h

操作内核文件前先备份:
$ cp
../linux-2.6.28/arch/arm/include/asm/memory.h ../linux-2.6.28/arch/arm/include/asm/memory.h.bak

$ sed -i 's/__deprecated/__attribute__((deprecated))/' ../linux-2.6.28/arch/arm/include/asm/memory.h

       1. 在上面的文件memory.h里,增加宏CONFIG_DRAM_BASE和CONFIG_DRAM_SIZE的定义(随便定义即可)
       2. 把这一句“#include ”改为“#include
       3. 把上面修改过的内核头文件memory.h复制到目标目录
$PREFIX/$TARGET/include覆盖掉旧的。即:
$ cp
../linux-2.6.28/arch/arm/include/asm/memory.h $PREFIX/$TARGET/include/asm
       4. 在文件ports/sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h,增加这一句 #include
(3)编译:
$ cd ~/tars/BuildDir
$ mkdir glibc
$ cd glibc
$ CC=arm-linux-gcc AR=arm-linux-ar RANLIB=arm-linux-ranlib /
../../SourceDir/glibc-2.7/configure /
--host=arm-linux /
--prefix=$PREFIX/$TARGET /
--enable-add-ons /
--with-headers=$PREFIX/$TARGET/include /
libc_cv_forced_unwind=yes /
libc_cv_c_cleanup=yes
$ make
$ make install
注:按照上面的方法,编译是能通过的。我们终于有库了,现在可以重新编译gcc了,因为第一遍编译时是没有库的,是不完整的。


八、编译gcc(第二遍)
(1)恢复先前的t-linux文件:
$ cd ~/tars/SourceDir
$ cd gcc-4.3.3/gcc/config/arm
$ mv t-linux t-linux.bak
$ mv t-linux-orig t-liinux
(2)解压缩 c++ 编译器源码包:
$ cd ~/tars/SourceDir
$ tar -zvxf ../gcc-g++-4.3.3.tar.gz
(3)编译c、c++编译器:
先清理一下:
$ cd ~/tars/BuildDir/gcc-core
$ make clean
$ make distclean

$ ../../SourceDir/gcc-4.3.3/configure /
--target=$TARGET /
--prefix=$PREFIX /
--enable-languages=c,c++ /
--enable-threads=posix /
--enable-shared /
--enable-__cxa_atexit /
--with-local-prefix=$PREFIX

$ make all
$ make install

好,编译结束了,试试自己做的arm-gcc工具吧!可以开始用它来编译内核了。
来自: http://hi.baidu.com/benzus/blog/item/2f4b849b31382dbdc9eaf4ef.html

你可能感兴趣的:(Ubuntu 下建立ARM交叉编译工具链(转))