欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

组装SDK之arm交叉编译器的制作

程序员文章站 2022-07-12 09:43:47
...

组装SDK之arm交叉编译器的制作#

闲来无事,打扫出了积灰了N年的一块arm9 samsung2416的开发板,来做点事情,从组装一个SDK开始吧。 首先来制作交叉编译器。 制作交叉编译器的方法有很多,比如用buildroot,cross-ng,不过这里是手工搭建一个可以转移到不同目录或Ubuntu 64PC上的arm交叉编译器。制作的过程中搜集了很多资料,下面的每一步都经过实验。
##简介##
GCC不仅仅是一个编译器,它是一个能够构建多种编译器的开源工程。本文将说明如何编译一个arm 交叉编译器。所需要的是带有gcc的Linux的机器。本文中我的build机器是Ubuntu x86_64(buid system, BS=X86_64), 制作的是用于arm (target system, TS=arm)的c/c++ 交叉编译器(host system compiler running on, HS=x86_64)。 用这个交叉编译器编译uboot 和kernel,验证它确实可用。
组装SDK之arm交叉编译器的制作
在开始制作之前需要分清几个路径,源码目录,编译目录,安装目录,最后是sysroot。 sysroot是编译得到的可执行档认为的目标系统根目录。 sysroot中有完整的库和头文件,包含标准的Linux执行时的目录层次。

##需要的软件包##

$ sudo apt-get install g++ make gawk

需要相应的源码包,新建一个目录,将下列需要的源码下载下来。

$ wget http://ftpmirror.gnu.org/binutils/binutils-2.24.tar.gz
$ wget http://ftpmirror.gnu.org/gcc/gcc-4.9.2/gcc-4.9.2.tar.gz
$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.10.27.tar.xz
$ wget http://ftpmirror.gnu.org/glibc/glibc-2.20.tar.xz
$ wget http://ftpmirror.gnu.org/mpfr/mpfr-3.1.2.tar.xz
$ wget http://ftpmirror.gnu.org/gmp/gmp-6.0.0a.tar.xz
$ wget http://ftpmirror.gnu.org/mpc/mpc-1.0.2.tar.gz
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.12.2.tar.bz2
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-0.18.1.tar.gz

开头的四个源码包是最主要的,binutils 二进制工具集(ld,as,objdump), gcc, kernel, glibc。剩下的是编译gcc需要的库源码包。
##这些组件如何组织在一起##
完成以后我们将会获得如下图所示的一些库。我们会首先编译左边的部分,最后编译生成右边的部分。
组装SDK之arm交叉编译器的制作
左边部分当中,我们会首先从binutils中生成目标平台的汇编器arm-linux-as,链接器arm-linux-ld等,然后编译gcc获得交叉编译器gcc和g++。mpfr,gmp,mpc等库会被链接到交叉编译器中。
图的右边部分是一个使用交叉编译器编译的可执行程序。它使用了标准c++库的接口,还可能使用到libgcc库,标准c++库,标准c库都是glibc提供,c++库依赖c库。libgcc从gcc编译得到,libgcc会依赖c库。libc需要内核的头文件,它使用标准系统调用访问kernel。
##构建工具链的步骤##
解压下载的源码包

$ for f in *.tar*; do tar xf $f; done

在GCC目录下创建依赖库目录的符号链接,创建完成后,执行GCC编译脚本时,会自动处理相关的库。

$ cd gcc-4.9.2
$ ln -s ../mpfr-3.1.2 mpfr
$ ln -s ../gmp-6.0.0 gmp
$ ln -s ../mpc-1.0.2 mpc
$ ln -s ../isl-0.12.2 isl
$ ln -s ../cloog-0.18.1 cloog
$ cd ..

创建一个安装目录,并保证对目录有读写权限。

$ mkdir -p /home/nkd/cross/bin
$ mkdir -p /home/nkd/cross/arm-none-linux-gnueabi/libc

创建cross目录,cross目录是安装目录,libc是gcc和libc的sysroot目录,使其成为cross的子目录,可以构建可移动交叉工具链,gcc在链接c库时会从相对路径中去找。
在bashrc中添加

 export PATH=/home/nkd/cross/bin:$PATH
 export prefix=/home/nkd/cross
 export sysroot=/home/nkd/cross/arm-none-linux-gnueabi/libc

###1.Binutils###
第一步,编译binutils生成交叉汇编器,交叉链接器等工具。

$ mkdir build-binutils
$ cd build-binutils
$ ../binutils-2.24/configure --prefix=$(prefix) --target=arm-none-linux-gnueabi --with-sysroot=$(sysroot) --disable-multilib
$ make -j4
$ make install
$ cd ..
  • 我们给出的目标系统参数是arm-none-linux-gnueabi,配置脚本会识别这个参数。编译时会生成arm目标系统的汇编器和链接器,并在cross目录下生成arm-none-linux-gnueabi目录。编译出来的工具会被安装到cross/bin/目录下,会带有arm-none-linux-gnueabi前缀。
    ###2.编译stage1 crossgcc###
    在下载的源码目录下执行
$ mkdir -p build-gcc
$ cd build-gcc
$ ../gcc-4.9.2/configure --prefix=$(prefix) --target=arm-none-linux-guneabi --enable-languages=c,c++ --disable-multilib --with-gnu-ld --with-gnu-as
$ make -j4 all-gcc
$ make install-gcc
$ cd ..

执行完毕后,会在prefix/bin目录下生成arm-none-linux-gnueabi-gcc,这是第一阶段的交叉编译器。不带有libgcc交叉编译器,因为libgcc需要libc,libc又需要交叉编译的gcc。
###3.安装linux 内核头文件###
安装内核头文件

$ cd linux-3.10.27
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi INSTALL_HDR_PATH=$(sysroot)/usr headers_install
$ cd ..

剩下的就是编译glibc和gcc的后两阶段编译。编译过程中gcc和glibc内的相关组件会相互依赖,下图展示了组件的编译顺序。其中某些组件是不能被被单独编译的,按照图的编译顺序,各组件才能找到所依赖的组件最后顺利编译出来。
组装SDK之arm交叉编译器的制作
另外一种过程图
组装SDK之arm交叉编译器的制作
###4.安装glibc头文件和最初用到库###

$ mkdir -p build-glibc
$ cd build-glibc
$ ../glibc-2.20/configure --prefix=/usr --build=x86_64  --target=arm-none-linux-gnueabi --with-headers=$(sysroot)/usr/include --disable-multilib libc_cv_forced_unwind=yes
$ make install_root=$(sysroot) install-bootstrap-headers=yes install-headers
$ make -j4 csu/subdir_lib
$ install csu/crt1.o csu/crti.o csu/crtn.o $(sysroot)/usr/lib
$ arm-none-linux-gnueabi-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $(sysroot)/usr/lib/libc.so
$ touch $(sysroot)/usr/include/gnu/stubs.h
$ cd ..

首先安装头文件,编译启动和清理相关的链接库。创建空的libc库, 创建占位用的必须的stubs.h文件。
在配置glibc时,prefix必须是/usr,它是基于install_root目录的,所以install_root也必须要有。
###5. 编译stage2 crossgcc2###

$ cd build-gcc
$ rm -rf *
$ ../gcc-4.9.2/configure --prefix=$(prefix) --target=arm-none-linux-guneabi --enable-languages=c,c++ --disable-multilib --with-gnu-ld --with-gnu-as --with-sysroot=$(sysroot)
$ make -j4 all-target-libgcc
$ make install-target-libgcc
$ cd ..

注意一定要带–with-sysroot参数。
###6.编译完整的glibc库###

$ cd build-glibc
$ rm -rf *
$ ../glibc-2.20/configure --prefix=/usr --build=x86_64  --target=arm-none-linux-gnueabi --with-headers=$(sysroot)/usr/include --disable-multilib
$ make -j4
$ make install_root=$(sysroot) install
$ cd ..

###7. 编译完整的crossgcc###

$ cd build-gcc
$ rm -rf *
$ ../gcc-4.9.2/configure --prefix=$(prefix) --target=arm-none-linux-guneabi --enable-languages=c,c++ --disable-multilib --with-gnu-ld --with-gnu-as --with-sysroot=$(sysroot)
//将生成的config.status中的target_os参数改为linux-gnu
$ make -j4
$ make install
$ cp -d $(prefix)/arm-none-linux-gnueabi/lib/libgcc_s.so* $(sysroot)/lib
$ cp -d $(prefix)/arm-none-linux-gnueabi/lib/libstdc++.so* $(sysroot)/usr/lib

到此为止就已经在prefix下得到了交叉编译器,在sysroot下得到安装好的c库。 以prefix为最顶层目录,整个toolchain可以移动到任何的路径下执行(已经设置好了PATH)。
###8. 测试###
将这个toolchain安装到buildroot中,可以正确编译uboot,kernel, uboot,kernel能在板子上正常运行。

相关标签: toolchain