在Ubuntu10.04中建立ARM交叉编译环境

Ubuntu10.04中建立ARM交叉编译环境

 

Linux中建立整个ARM交叉编译环境的整体过程为:

1、  下载源文件

2、  Linux中建立编译目录并设置环境变量

3、  建立内核头文件

4、  建立二进制工具(binutils

5、  建立初始编译器(bootstrap gcc

6、  建立glibc

7、  建立全套编译器(full gcc

8、  验证编译器

 

 

一、下载源文件

GNU的所有源码文件都可以到这个地址下载:http://ftp.gnu.org/gnu/

Linux Kernel源代码可以去这里下载:http://www.kernel.org

mpc可以去这里下载:http://www.multiprecision.org

我所下载的源码包如下:

binutils-2.21.1.tar.bz2

gcc-4.6.1.tar.gz

glibc-2.14.tar.gz

glibc-linuxthreads-2.5.tar.bz2

glibc-ports-2.13.tar.gz

gmp-5.0.2.tar.bz2

linux-2.6.32.45.tar.gz

mpc-0.9.tar.gz

mpfr-2.4.2.tar.gz

注:mpfr不建议使用3.0.0版本。mpfr-3.0.0Bug,会导致gcc编译不过。

 

 

二、在Linux中建立编译目录并设置环境变量

选定自己的工作目录,如我选择/home/embedded作为自己的工作目录。然后再embedded中建立build-toolskerneltools三个文件夹。实例:

root@ubuntu:/home/huchao# cd /home/

root@ubuntu:/home# mkdir embedded

root@ubuntu:/home# cd embedded/

root@ubuntu:/home/embedded# mkdir build-tools kernel tools

root@ubuntu:/home/embedded# cd build-tools/

root@ubuntu:/home/embedded/build-tools# mkdir build-binutils build-boot-gcc build-glibc build-gcc

各文件夹的作用如下:

/home/embedded:交叉编译环境的主目录

/home/embedded/build-tools:存放binutilsgccglibcGNU源码和用来编译这些源代码的目录

/home/embedded/kernel:用来存放Linux内核源代码

/home/embedded/tools:用来存放编译好的交叉编译工具和库文件

/home/embedded/build-tools/build-binutils:编译binutils的目录

/home/embedded/build-tools/build-boot-gcc:编译gcc启动部分的目录

/home/embedded/build-tools/build-glibc:编译glibc的目录

/home/embedded/build-tools/build-gcc:编译整个gcc的目录

 

建立好编译目录之后便是设置环境变量(建议直接在~/.bashrc中修改,注意修改之后要重新运行Terminal)。如下:

export PRJROOT=/home/embedded

export TARGET=arm-linux

export PREFIX=$PRJROOT/tools

export TARGET_PREFIX=$PREFIX/$TARGET

export PATH=$PREFIX/bin:$PATH

各个环境变量的意义如下:

PRJROOT:整个交叉编译环境的根目录

TARGET:目标文件对应的architecturearm-linux表示编译出来的target只能在arm architecture中运行

PREFIX:目标文件夹的路径前缀

TARGET_PREFIX:目标文件夹的路径前缀路径

PATH:可执行文件路径,这里主要指定编译工具等

 

 

三、建立内核头文件

Linux内核源码解压至$PRJROOT/kernel目录,然后建立几个文件的符号链接,最后生成version.h文件。实例:

首先解压Linux内核源文件

root@ubuntu:/home/embedded/kernel# cp /mnt/hgfs/VMwareShare_Ubuntux64/linux-2.6.32.45.tar.gz .

root@ubuntu:/home/embedded/kernel# tar -xvf linux-2.6.32.45.tar.gz

root@ubuntu:/home/embedded/kernel# mkdir /home/embedded/tools/arm-linux

root@ubuntu:/home/embedded/kernel# mkdir /home/embedded/tools/arm-linux/include

root@ubuntu:/home/embedded/kernel# ln -s /home/embedded/kernel/linux-2.6.32.45/include/linux /home/embedded/tools/arm-linux/include/linux

root@ubuntu:/home/embedded/kernel# ln -s /home/embedded/kernel/linux-2.6.32.45/include/asm-generic /home/embedded/tools/arm-linux/include/asm-generic

root@ubuntu:/home/embedded/kernel# ln -s /home/embedded/kernel/linux-2.6.32.45/arch/arm/include/asm /home/embedded/tools/arm-linux/include/asm

下面检查上面创建的符号链接是否正确。实例:

root@ubuntu:/home/embedded/kernel# cd /home/embedded/tools/arm-linux/include/

root@ubuntu:/home/embedded/tools/arm-linux/include# ll

总用量 8

drwxr-xr-x 2 root root 4096 2011-09-29 05:12 ./

drwxr-xr-x 3 root root 4096 2011-09-29 05:07 ../

lrwxrwxrwx 1 root root   58 2011-09-29 05:12 asm -> /home/embedded/kernel/linux-2.6.32.45/arch/arm/include/asm/

lrwxrwxrwx 1 root root   57 2011-09-29 05:10 asm-generic -> /home/embedded/kernel/linux-2.6.32.45/include/asm-generic/

lrwxrwxrwx 1 root root   51 2011-09-29 05:09 linux -> /home/embedded/kernel/linux-2.6.32.45/include/linux/

看到如上结果表示符号链接创建正确。

 

最后生成version.h文件。实例:

root@ubuntu:/home/embedded/kernel/linux-2.6.32.45# cd /home/embedded/kernel/linux-2.6.32.45/

root@ubuntu:/home/embedded/kernel/linux-2.6.32.45# make include/linux/version.h

  CHK     include/linux/version.h

  UPD     include/linux/version.h

下面查看version.h文件是否建立成功。实例:

root@ubuntu:/home/embedded/kernel/linux-2.6.32.45# cd /home/embedded/kernel/linux-2.6.32.45/include/linux/

root@ubuntu:/home/embedded/kernel/linux-2.6.32.45/include/linux# ll | grep version.h

-rw-r--r--  1 root root     97 2011-09-29 05:14 version.h

看到如上结果表示version.h文件建立成功。

 

 

四、建立二进制工具(binutils

Binutils是一些二进制工具集合,其中包含了常用的一些命令。首先将binutils-2.21.1.tar.bz2解压至build-tools,然后进入build-binutils目录,配置并编译binutils,最后使用make install进行安装。实例:

root@ubuntu:/home/embedded/build-tools# cd /home/embedded/build-tools/

root@ubuntu:/home/embedded/build-tools# cp /mnt/hgfs/VMwareShare_Ubuntux64/binutils-2.21.1.tar.bz2 .

root@ubuntu:/home/embedded/build-tools# tar -xjf binutils-2.21.1.tar.bz2

root@ubuntu:/home/embedded/build-tools# cd build-binutils/

root@ubuntu:/home/embedded/build-tools/build-binutils# ../binutils-2.21.1/configure --target=$TARGET --prefix=$PREFIX

root@ubuntu:/home/embedded/build-tools/build-binutils# make

root@ubuntu:/home/embedded/build-tools/build-binutils# make install

完成后,去$PREFIX中检查一下生成的工具。实例:

root@ubuntu:/home/embedded/build-tools/build-binutils# cd /home/embedded/tools/bin

root@ubuntu:/home/embedded/tools/bin# ll

总用量 49988

drwxr-xr-x 2 root root    4096 2011-09-29 05:30 ./

drwxr-xr-x 6 root root    4096 2011-09-29 05:30 ../

-rwxr-xr-x 1 root root 3009029 2011-09-29 05:30 arm-linux-addr2line*

-rwxr-xr-x 2 root root 3161667 2011-09-29 05:30 arm-linux-ar*

-rwxr-xr-x 2 root root 4789065 2011-09-29 05:30 arm-linux-as*

-rwxr-xr-x 1 root root 2981965 2011-09-29 05:30 arm-linux-c++filt*

-rwxr-xr-x 1 root root   77829 2011-09-29 05:30 arm-linux-elfedit*

-rwxr-xr-x 1 root root 3456392 2011-09-29 05:30 arm-linux-gprof*

-rwxr-xr-x 4 root root 4502054 2011-09-29 05:30 arm-linux-ld*

-rwxr-xr-x 4 root root 4502054 2011-09-29 05:30 arm-linux-ld.bfd*

-rwxr-xr-x 2 root root 3048986 2011-09-29 05:30 arm-linux-nm*

-rwxr-xr-x 2 root root 3710926 2011-09-29 05:30 arm-linux-objcopy*

-rwxr-xr-x 2 root root 4176150 2011-09-29 05:30 arm-linux-objdump*

-rwxr-xr-x 2 root root 3161666 2011-09-29 05:30 arm-linux-ranlib*

-rwxr-xr-x 1 root root  807601 2011-09-29 05:30 arm-linux-readelf*

-rwxr-xr-x 1 root root 3036038 2011-09-29 05:30 arm-linux-size*

-rwxr-xr-x 1 root root 3010718 2011-09-29 05:30 arm-linux-strings*

-rwxr-xr-x 2 root root 3710917 2011-09-29 05:30 arm-linux-strip*

 

这些生成的文件的作用分别为:

arm-linux-addr2line:将你要找的地址转成文件和行号,它要使用 debug 信息

arm-linux-ar:产生、修改和解开一个存档文件

arm-linux-asGNU的汇编器

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

arm-linux-elfedit:用途暂时未知

arm-linux-gprofGNU汇编器预编译器

arm-linux-ldGNU的连接器

arm-linux-ld.bfd:用途暂时未知

arm-linux-nm:列出目标文件的符号和对应的地址

arm-linux-objcopy:将某种格式的目标文件转化成另外格式的目标文件

arm-linux-objdump:显示目标文件的信息

arm-linux-ranlib:为一个存档文件产生一个索引,并将这个索引存入存档文件中

arm-linux-readelf:显示 elf 格式的目标文件的信息

arm-linux-size:显示目标文件各个节的大小和目标文件的大小

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

arm-linux-strip:剥掉目标文件的所有的符号信息

 

 

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

Gcc是最主要的编译器。首先将gcc-4.6.1.tar.gz解压至build-tools,然后将gmp-5.0.2.tar.bz2mpfr-2.4.2.tar.gzmpc-0.9.tar.gz分别解压至gcc源码所在目录,并将目录重命名为gmpmpfrmpc,然后进入build-boot-gcc目录,进行编译配置,然后make all-gcc并安装,最后make all-target-gcc并安装。实例:

root@ubuntu:/home/embedded/build-tools# cd /home/embedded/build-tools/

root@ubuntu:/home/embedded/build-tools# cp /mnt/hgfs/VMwareShare_Ubuntux64/gcc-4.6.1.tar.gz .

root@ubuntu:/home/embedded/build-tools# tar -xvf gcc-4.6.1.tar.gz

root@ubuntu:/home/embedded/build-tools# cd gcc-4.6.1/

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# cp /mnt/hgfs/VMwareShare_Ubuntux64/mpfr-2.4.2.tar.gz .

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# cp /mnt/hgfs/VMwareShare_Ubuntux64/gmp-5.0.2.tar.bz2 .

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# cp /mnt/hgfs/VMwareShare_Ubuntux64/mpc-0.9.tar.gz .

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# tar -xvf mpfr-2.4.2.tar.gz

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# mv mpfr-2.4.2/ mpfr

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# tar -xjf gmp-5.0.2.tar.bz2

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# mv gmp-5.0.2/ gmp

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# tar -xvf mpc-0.9.tar.gz

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# mv mpc-0.9 mpc

 

这里需要修改一下编译配置文件:/home/embedded/build-tools/gcc-4.6.1/gcc/config/arm/t-linux

将“TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer –fPIC”改为“TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h”。

然后便可以切换到目录build-boot-gcc进行编译了,实例:

root@ubuntu:/home/embedded/build-tools/gcc-4.6.1# cd /home/embedded/build-tools/build-boot-gcc/

root@ubuntu:/home/embedded/build-tools/build-boot-gcc# ../gcc-4.6.1/configure --target=$TARGET --prefix=$PREFIX --without-headers --enable-languages=c --disable-threads --with-newlib --disable-shared --disable-libmudflap --disable-libssp

root@ubuntu:/home/embedded/build-tools/build-boot-gcc# make all-gcc

root@ubuntu:/home/embedded/build-tools/build-boot-gcc# make install-gcc

root@ubuntu:/home/embedded/build-tools/build-boot-gcc# make all-target-libgcc

root@ubuntu:/home/embedded/build-tools/build-boot-gcc# make install-target-libgcc

 

完成之后,$PREFIX/bin下又多了几个文件:

-rwxr-xr-x 1 root root  864105 2011-09-29 06:32 arm-linux-cpp*

-rwxr-xr-x 2 root root  854850 2011-09-29 06:32 arm-linux-gcc*

-rwxr-xr-x 2 root root  854850 2011-09-29 06:32 arm-linux-gcc-4.6.1*

-rwxr-xr-x 1 root root  126539 2011-09-29 06:32 arm-linux-gcov*

这些生成的文件的作用分别为:

arm-linux-cppGNUC的预编译器

arm-linux-gccGNUC语言编译器

arm-linux-gcc-4.6.1GNUC语言编译器,其实和arm-linux-gcc是一样的

arm-linux-gcovgcc 的辅助测试工具,用来分析和优化程序

 

 

六、建立glic

Glibc是交叉编译环境的运行库。首先将glibc-2.14.tar.gz解压至build-tools,然后将glibc-linuxthreads-2.5.tar.bz2解压至glibc源码所在目录,将glibc-ports-2.13.tar.gz解压至glibc源码所在目录,并重命名为ports。进入build-glibc文件夹,建立用于配置glibcconfig.cache文件,然后配置并编译glibc,安装glibc,最后修改libc.so。实例:

root@ubuntu:/home/embedded/build-tools# cd /home/embedded/build-tools/

root@ubuntu:/home/embedded/build-tools# cp /mnt/hgfs/VMwareShare_Ubuntux64/glibc-2.14.tar.gz .

root@ubuntu:/home/embedded/build-tools# tar -xvf glibc-2.14.tar.gz

root@ubuntu:/home/embedded/build-tools# cd glibc-2.14/

root@ubuntu:/home/embedded/build-tools/glibc-2.14# cp /mnt/hgfs/VMwareShare_Ubuntux64/glibc-linuxthreads-2.5.tar.bz2 .

root@ubuntu:/home/embedded/build-tools/glibc-2.14# tar -xjf glibc-linuxthreads-2.5.tar.bz2

root@ubuntu:/home/embedded/build-tools/glibc-2.14# cp /mnt/hgfs/VMwareShare_Ubuntux64/glibc-ports-2.13.tar.gz .

root@ubuntu:/home/embedded/build-tools/glibc-2.14# tar -xvf glibc-ports-2.13.tar.gz

root@ubuntu:/home/embedded/build-tools/glibc-2.14# mv glibc-ports-2.13/ ports

root@ubuntu:/home/embedded/build-tools/glibc-2.14# cd ../build-glibc/

建立用于配置glibcconfig.cache文件,文件内容为:

libc_cv_forced_unwind=yes

libc_cv_c_cleanup=yes

libc_cv_arm_tls=yes

 

建立完成之后,便可以开始配置并编译glibc了,实例:

root@ubuntu:/home/embedded/build-tools/build-glibc# BUILD_CC="gcc" CC=$TARGET-gcc ../glibc-2.14/configure --host=$TARGET --target=$TARGET --prefix=/usr --enable-add-ons --disable-profile --cache-file=config.cache --with-binutils=$PREFIX/bin/ --with-headers=$TARGET_PREFIX/include/

root@ubuntu:/home/embedded/build-tools/build-glibc# make

编译出错:

../ports/sysdeps/unix/sysv/linux/arm/sigrestorer.S:30: Error: previous CFI entry not closed (missing .cfi_endproc)

解决方法:

root@ubuntu:/home/embedded/build-tools/build-glibc# vi ../glibc-2.14/ports/sysdeps/unix/sysv/linux/arm/sigrestorer.S

找到如下行:

ENTRY(__default_sa_restorer)

在其下添加:

END(__default_sa_restorer)

找到如下行:

ENTRY(__default_rt_sa_restorer)

在其下添加:

END(__default_rt_sa_restorer)

继续make编译

root@ubuntu:/home/embedded/build-tools/build-glibc# make

编译出错:

../sysdeps/unix/syscall-template.S:82: Error: CFI instruction used without previous .cfi_startproc

解决方法:

root@ubuntu:/home/embedded/build-tools/build-glibc# vi ../glibc-2.14/sysdeps/unix/syscall-template.S

找到如下行:

#define T_PSEUDO(SYMBOL, NAME, N)                PSEUDO (SYMBOL, NAME, N)

在其上添加:

#define PSEUDO(name, syscall_name, args)   \

  .text;                                \

  ENTRY (name);                        \

    DO_CALL (syscall_name, args);         \

    cmn r0, $4096;

继续make编译

root@ubuntu:/home/embedded/build-tools/build-glibc# make

编译出错:

allocatestack.c:247:33: 错误:‘TLS_DTV_UNALLOCATED’未声明(在此函数内第一次使用)

解决方法:

root@ubuntu:/home/embedded/build-tools/build-glibc# vi ../glibc-2.14/nptl/allocatestack.c

root@ubuntu:/home/embedded/build-tools/build-glibc# vi ../glibc-2.14/elf/dl-tls.c

分别在文件中的include后面添加:

#define TLS_DTV_UNALLOCATED      ((void *) -1l)

继续make编译

root@ubuntu:/home/embedded/build-tools/build-glibc# make

编译出错:

/home/embedded/tools/lib/gcc/arm-linux/4.6.1/../../../../arm-linux/bin/ld: cannot find -lgcc_eh

解决方法:

root@ubuntu:/home/embedded/build-tools/build-glibc# ln -s /home/embedded/tools/lib/gcc/arm-linux/4.6.1/libgcc.a /home/embedded/tools/lib/gcc/arm-linux/4.6.1/libgcc_eh.a

继续make编译

root@ubuntu:/home/embedded/build-tools/build-glibc# make

编译出错:

../sysdeps/ieee754/dbl-64/s_fma.c:152:15: 错误:‘FE_TOWARDZERO’未声明(在此函数内第一次使用)

解决方法:

root@ubuntu:/home/embedded/build-tools/build-glibc# vi ../glibc-2.14/sysdeps/ieee754/dbl-64/s_fma.c

在文件中的include后面添加:

#define FE_TOWARDZERO 0xc00000

#define FE_INEXACT 16

继续make编译

root@ubuntu:/home/embedded/build-tools/build-glibc# make

编译出错:

../sysdeps/ieee754/dbl-64/s_fmaf.c:39:15: 错误:‘FE_TOWARDZERO’未声明(在此函数内第一次使用)

解决方法:

root@ubuntu:/home/embedded/build-tools/build-glibc# vi ../glibc-2.14/sysdeps/ieee754/dbl-64/s_fmaf.c

在文件中的include后面添加:

#define FE_TOWARDZERO 0xc00000

#define FE_INEXACT 16

继续make编译

root@ubuntu:/home/embedded/build-tools/build-glibc# make

root@ubuntu:/home/embedded/build-tools/build-glibc# make install_root=$TARGET_PREFIX prefix="" install

 

最后,修改libc.so便完成此步骤

root@ubuntu:/home/embedded/build-tools/build-glibc# vi ../../tools/arm-linux/lib/libc.so

找到如下行:

GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux.so.2 ) )

将其改为:

GROUP ( libc.so.6 libc_nonshared.a )

 

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

首先进入build-gcc目录,然后配置并编译full gcc,最后安装就完成了。实例:

root@ubuntu:/home/embedded/build-tools/build-glibc# cd /home/embedded/build-tools/build-gcc/

root@ubuntu:/home/embedded/build-tools/build-gcc# ../gcc-4.6.1/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --disable-libgomp

root@ubuntu:/home/embedded/build-tools/build-gcc# make

root@ubuntu:/home/embedded/build-tools/build-gcc# make install

完成之后,$PREFIX/bin下又多了几个文件:

-rwxr-xr-x 2 root root  869603 2011-09-29 19:25 arm-linux-c++*

-rwxr-xr-x 2 root root  869603 2011-09-29 19:25 arm-linux-g++*

这些生成的文件的作用分别为:

arm-linux-g++GNUc++编译器

arm-linux-c++:等同于arm-linux-g++

 

 

八、验证编译器

使用vim写下如下代码,并保存为main.c文件:

#include <stdio.h>

int main(void)

{

         printf("hello world\n");

         return 0;

}

然后执行编译命令。实例:

root@ubuntu:/home/embedded/tmp# arm-linux-gcc -static main.c –o helloworld

编译完成后验证最终编译出的文件。实例:

root@ubuntu:/home/embedded/tmp# file helloworld

helloworld: ELF 32-bit LSB executable, ARM, version 1, statically linked, for GNU/Linux 2.0.0, not stripped

有如上输出表示编译ARM版本程序成功。

 

 
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值