arm-linux-gcc 4.4.4交叉编译工具链的制作

时间:2021-08-27 18:54:10

前言

由于之前从来没有接触到Linux,经过一个月的学习(主要通过上网查阅相关的资料,到CSDN论坛上面去看),通过制作交叉工具链这一项任务,将Linux系统的基本指令,Linux不同内核的版本的文件结构体系等内容有了一个系统的认识与了解。

初学交叉工具链的制作,在制作过程中fedora经过了多次的安装与卸载,交叉编译工具(如二进制工具binutilskernel内核,gcc编译器,glibc)的版本也经过了多次的选择。通过对网上资料的分析,对比,总结,最后终于制作了一个属于自己的交叉编译工具链arm-linux-gcc-4.4.4(见附件的压缩包),并且通过了测试。

    此交叉编译工具链的制作主要参考了网页:http://www.cnblogs.com/Charles-Zhang-Blog/archive/2013/02/21/2920999.html。此文中大部分内容都是准确的,只有少部分的叙述有一点问题,有问题的部分在文中已经用红色的字体标出(见下文)。

 

 

 

Linux ARM交叉编译工具链制作过程

一、下载源文件

源代码文件及其版本:

binutils-2.19.tar.bz2,       gcc-core-4.4.4.tar.bz2    gcc-g++-4.4.4.tar.bz2 Glibc-2.7.tar.bz2 Glibc-ports-2.7.tar.bz2 Gmp-4.2.tar.bz2 mpfr-2.4.0.tar.bz2mpc-1.0.1.tar.gz   Linux-2.6.25.tar.bz2 (由于我在编译出错的过程中,根据出错的信息修改了相关的C代码,故而没有下载相应的补丁)

   一般一个完整的交叉编译器涉及到多个软件,主要包括bilingualsccglibc等。其中,binutils主要生成一些辅助工具;gcc是用来生成交叉编译器,主要生成arm-linux-gcc交叉编译工具,而glibc主要提供用户程序所需要的一些基本函数库。

 

二、建立工作目录

     编译所用主机型号 fc14.i686,虚拟机选的是VM7.0Linux发行版选的是Fedora9,

     第一次编译时用的是root用户(第二次用一般用户yyz), 所有的工作目录都在/home/yyz/cross下面建立完成,首先在/home/yyz目录下建立cross目录,然后进入工作目录,查看当前目录。命令如下:

 

创建工具链文件夹:

[root@localhost  cross]# mkdir embedded-toolchains

下面在此文件夹下建立如下几个目录:

setup-dir:存放下载的压缩包;

src-dir:存放binutilsgccglibc解压之后的源文件;

Kernel:存放内核文件,对内核的配置和编译工作也在此完成;

build-dir :编译src-dir下面的源文件,这是GNU推荐的源文件目录与编译目录分离的做法;

tool-chain:交叉编译工具链的安装位;

program:存放编写程序;

doc:说明文档和脚本文件;

 下面建立目录,并拷贝源文件。

[root@localhost  cross] #cd embedded- toolchains
[root@localhost  embedded- toolchains] #mkdir setup-dir src-dir kernel build-dir tool-chain program doc
[root@localhost  embedded- toolchains] #ls
build-dir doc kernel program setup-dir src-dir tool-chain
[root@localhost  embedded- toolchains] #cd setup-dir

 拷贝源文件:
这里我们采用直接拷贝源文件的方法,首先应该修改setup-dir的权限

[root@localhost  embedded- toolchains] #chmod 777 setup-dir

然后直接拷贝/home/yyz目录下的源文件到setup-dir目录中,如下图:

 

 建立编译目录:

[root@localhost  setup-dir] #cd ../build-dir
[root@localhost  build -dir] #mkdir build-binutils build-gcc build-glibc

三、输出环境变量

输出如下的环境变量方便我们编译。

为简化操作过程。下面就建立shell命令脚本environment-variables
[root@localhost  build -dir] #cd ../doc
[root@localhost  doc] #mkdir scripts
[root@localhost  doc] #cd scripts
用编辑器vi编辑环境变量脚本envionment-variables[root@localhost  scripts] 

#vi envionment-variables  
export  PRJROOT=/home/yyz/cross/embedded-toolchains
export  TARGET=arm-linux
export  PREFIX=$PRJROOT/tool-chain
export  TARGET_PREFIX=$PREFIX/$TARGET
export  PATH=$PREFIX/bin:$PATH

截图如下:

执行如下语句使环境变量生效:

[root@localhost scripts]# source ./environment-variables

 四、建立二进制工具(binutils

下面将分步介绍安装binutils-2.19.1的过程。

[root@localhost  script] # cd $PRJROOT/src-dir
[root@localhost  src-dir] # tar jxvf ../setup-dir/binutils-2.19.1.tar.bz2
[root@localhost  src-dir] # cd $PRJROOT/build-dir/build-binutils
创建Makefile

[root@localhost  build-binutils] #../../src-dir/binutils-2.19.1/configure --target=$TARGET --prefix=$PREFIX

   build-binutils目录下面生成Makefile文件,然后执行makemake install,此过程比较缓慢,大约需要一个15分钟左右。完成后可以在$PREFIX/bin下面看到我们的新的binutil

输入如下命令

[root@localhost  build-binutils]#ls $PREFIX/bin

可以看到如下结果

 

五、建立内核头文件

   在这里我们使用的是2.6.25的内核版本,因为交叉工具链工具链是针对特定的处理器和操作系统的(我的fedora的内核是2.6.25),因此在编译之前就需要对linux内核进行配制,可以通过“make config”“make menuconfig”命令对内核进行配制,配制完成后,在linux源文件的目录下就会生成一个.config文件,这就是我们所需要的文件。

Note我 是按照fedora内核版本来看的。

[root@localhost  embedded- toolchains] #cd kernel

[root@localhost  kernel] #tar jxvf ../setup-dir/linux-2.6.25.tar.bz2                
//[root@localhost  kernel] #bunzip2 ../setup-dir/patch-2.6.25.bz2 
[root@localhost  kernel] #cd linux-2.6.25
然后就是配置内核,第一步是修改Makefile

修改 MakefileARCH = arm  

CROSS_COMPILE = arm-linux- menuconfig  

接着使用make menuconfig进入内核配置菜单 ,出现如下的错误:    

 

  错误原因:就是在上边配置Makefile时:ARCH            ?= $(SUBARCH)这一行后边不小心加了有了空格了。去掉空格。

 

   注意在配置时一定要选择处理器的类型,我选的处理器是三星2410类型的,

配置完退出并保存。

配置完须执行make,参数如下:

[root@localhost linux-2.6.25]# make ARCH=arm CROSS_COMPILE=arm-linux- (执行过程中有错误出现也没关系,主要目的是产生头文件version.hautoconf.h

 执行完检查一下内核目录中的/kernel/linux-2.6.25/include/linux/version.hautoconf.h文件是不是生成了,这是编译glibc要用到的。version.h  autoconf.h 文件的存在,说明你生成了正确的头文件。

接下来建立工具链需要的include目录,并将内核头文件复制过去。
[root@localhost  linux-2.6.25] #cd include

[root@localhost  include] #ln -s  asm-arm asm

可以查看一下,经过编译可以自动生成。如果已经生成链接,则不必重新链接。2.6.25已自动生成)
[root@localhost  include] #cd asm
[root@localhost  asm] #ln -s arch-epxa arch  

可以查看一下,经过编译可以自动生成。如果已经生成链接,则不必重新链接。

复制头文件到交叉编译工具链的安装目录:

[root@localhost  asm] #mkdir –p $TARGET_PREFIX/include
[root@localhost asm] #cp -r $PRJROOT/kernel/linux-2.6.25/include/linux $TARGET_PREFIX/include
[root@localhost  asm] #cp -r $PRJROOT/kernel/linux-2.6.25/include/asm-arm $TARGET_PREFIX/include/asm

[root@localhost  asm] #cp -r $PRJROOT/kernel/linux-2.6.25/include/asm-generic $TARGET_PREFIX/include

// root@localhost  asm] #cp -r $PRJROOT/kernel/linux-2.6.25/arch/arm/include/asm  $TARGET_PREFIX/include/(低版本没有此路径可以选择不复制)

[root@localhost  asm] #cp -r $PRJROOT/kernel/linux-2.6.25/arch/arm/mach-s3c2410/include/mach $TARGET_PREFIX/include/asm

 六、建立初始编译器 boot strap gcc

    这一步的目的主要是建立arm-linux-gcc工具,注意这个gcc没有glibc库的支持,所以只能用于编译内核、BootLoader等不需要C库支持的程序,后面创建C库也要用到这个编译器,所以创建它主要是为创建C库做准备,如果只想编译内核和BootLoader,那么安装完这个就可以到此结束。安装过程如下:  [root@localhost  build-binutils] #cd $PRJROOT/setup-dir

重命名:
[root@localhost  setup-dir] #mv gcc-core-4.4.4.tar.bz2  gcc-4.4.4.tar.bz2 

[root@localhost  setup-dir] #cd $PRJROOT/src-dir
[root@localhost  src-dir] #tar jxvf ../setup-dir/gcc-4.4.4.tar.bz2  

    从 GCC-4.3起,安装GCC将依赖于GMP-4.1以上版本和MPFR-2.3.2以上版本。如果将这两个软件包分别解压到GCC源码树的根目录下,并分别命名为"gmp""mpfr",那么GCC的编译程序将自动将两者与GCC一起编译。建议尽可能使用最新的GMPMPFR版本。

[root@localhost src-dir]# tar jxvf ../setup-dir/mpfr-2.4.0.tar.bz2

[root@localhost src-dir]# tar jxvf ../setup-dir/gmp-4.2.tar.bz2

[root@localhost src-dir]# tar xvzf ../setup-dir/mpc-1.0.1.tar.gz

[root@localhost src-dir]# mv mpfr-2.4.0 gcc-4.4.4/mpfr

[root@localhost src-dir]# mv gmp-4.2  gcc-4.4.4/gmp

[root@localhost src-dir]# mv mpc-1.0.1  gcc-4.4.4/mpc

 

 

    同样,由于第一次安装ARM交叉编译工具,那么支持的l.ibc库的头文件也没有,src-dir/gcc-4.4.4/gcc/config/arm/t-linux文件,在TARGET_LIBGCC2_CFLAGS中添加两个定义:-Dinhibit_libc  –D__gthr_posix_h

原文:  TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer –fPIC

改后: TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h

编译:
[root@localhost  src-dir] #cd $PRJROOT/build-dir/build-gcc

[root@localhost build-gcc]# ../../src-dir/gcc-4.4.4/configure --target=$TARGET --prefix=$PREFIX --without-headers --enable-languages=c --disable-shared --disable-threads --disable-decimal-float --disable-libmudflap --disable-lipssp

 [root@localhost build-gcc]# make all-gcc           //1个小时左右时间

 [root@localhost build-gcc]# make install-gcc

 [root@localhost build-gcc]# make all-target-libgcc

 [root@localhost build-gcc]# make install-target-libgcc

glibc的编译中,还需要libgcc_eh.a(否则出现错误:-lgcc_eh没有找到……bin/ld: cannot find -lgcc_eh),使用了--disable-shared的选项,将不会生成libgcc_eh.a,可以通过对libgcc.a的链接来实现。

[root@localhost build-gcc]#  ln -vs libgcc.a `arm-linux-gcc -print-libgcc-file-name | sed 's/libgcc/&_eh/'`

  Notearm-linux-gcc-print-libgcc-file-name之间有一个空格  

 运行报告:

“/workspace/wei/mywork/moblin/tools/bin/../lib/gcc/i586-linux/4.3.3/libgcc_eh.a” -> “libgcc.a”

装完成后,查看结果:

[root@localhost  build-gcc] #ls $PREFIX/bin  

下面arm-linux-gcc等工具已经生成,表示boot trap gcc工具已经安装成功

 

七、编译glibc 

   这一步是最为繁琐的过程,目标板必须靠它来执行或者是开发大部分的应用程序。glibc套件常被称为C链接库,但是glibc实际产生很多链接库,其中之一是C链接库libc。因为嵌入式系统的限制,标准GNU C链接库显得太大,不适合应用在目标板上。所以需要寻找C链接库的替代品,在这里现以标准GNU C为例建立工具链。

[root@localhost  build-gcc] #cd $PRJROOT/src-dir
[root@localhost  src-dir] # tar jxvf ../setup-dir/glibc-2.7.tar.bz2
[root@localhost  src-dir] # tar jxvf ../setup-dir/glibc-ports-2.7.tar.bz2

[root@localhost  src-dir] # mv –v glibc-ports-2.7 glibc-2.7/ports

[root@localhost  src-dir] # cd glibc-2.7

接下来对glibc-2.7configure文件打补丁

[root@localhost  glibc-2.7] #>sed -i -e "/ccheaders=/s@\`\(\$CC.*include\)\`@\"& -isystem \`\1-fixed\`\"@" configure

此外将asm文件夹下的__deprecated改成如下所示的:

 

 

[root@localhost  glibc-2.7] # cd $PRJROOT/build-dir/build-glibc

[root@localhost build-glibc] # CC=arm-linux-gcc AR=arm-linux-ar RANLIB=arm-linux-ranlib  ../../src-dir/glibc-2.7/configure  --host=arm-linux  --prefix=$PREFIX/$TARGET/ --with-tls --disable-profile  --enable-add-ons --with-headers=$PREFIX/$TARGET/include libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes libc_cv_arm_tls=yes

 

运行成功后的截图如下:

 

 

接着再编译,安装,此过程大约需要30分钟左右时间

 [root@localhost build-glibc] # make

 [root@localhost build-glibc] # make install

运行成功截图:

   注:以上完成后,请查看一下$TARGET_PREFIX/lib目录下的文件libc.so,看看GROUP的内容是否指定到可以用于交叉编译的库,如果不是请修改,如下  libc.so 文件(所在目录是$TARGET_PREFIX/lib),将GROUP (/lib/libc.so.6 /lib/libc_nonshared.a)改为GROUP ( libc.so.6 libc_nonshared.a)这样连接程序 ld 就会在 libc.so 所在的目录查找它需要的库,因为你的机子的/lib目录可能已经装了一个相同名字的库,一个为编译可以在你的宿主机上运行的程序的库,而不是用于交叉编译的。

我的libc.so文件里面的内容如下:

 

由于没有按照要求改过来,后面出现了如下的错误:

 

八、建立全套编译器 full gcc

[root@localhost src-dir]# tar jxvf ../setup-dir/gcc-g++-4.4.4.tar.bz2

解压之后会自动覆盖原来gcc-4.4.4部分加以C++部分。

[root@localhost src-dir]#cd gcc-4.4.4/gcc/config/arm

[root@localhost arm]#vi t-linux

TARGET_LIBGCC2_CFLAGS去掉两个定义:-Dinhibit_libc  –D__gthr_posix_h

还原t-linux文件

[root@localhost arm]#cd ../../../../../build-dir/build-gcc

[root@localhost  build-gcc] #../../src-dir/gcc-4.4.4/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --enable-threads=posix  --enable-shared --enable-__cxa_atexit  --with-local-prefix=$PREFIX/$TEGET

 

结果如下图:

 

[root@localhost  build-gcc] #make all

[root@localhost  build-gcc] #make install

经过将近1个小时的编译的过程,我们可以得到完整的编译器:

 我们可以看到 $PREFIX/bin 里面多了 arm-linux-g++ 、和 arm-linux-c++ 几个文件,G++-gnu c++ 编译器。至此,整个交叉编译环境就建立完成了。

九、完成工具链的设置

 [root@localhost  build-gcc] # cd $TARGET_PREFIX/bin

查看文件是否为二进制文件:
[root@localhost  bin] # file as ar gcc ld nm ranlib strip   

查看缺省的搜寻路径:
[root@localhost  bin] #arm-linux-gcc -print-search-dirs  

  十、测试和验证交叉编译工具

下面编写一个简单的C程序,使用建立的工具链。、
[root@localhost  bin] #cd $PRJROOT/program
[root@localhost  program] #vi hello.c
#include <stdio.h>

int main(void)

{

printf("hello ,my name is arm-linux-gcc-4.4.4!\n");

return 0;

}  

[root@localhost  program]#arm-linux-gcc hello.c -o hello 

     最后将生成hello可执行文件,使用file命令可以检查你生成的hello可执行文件是否为ARM体系和格式版本,能在开发板上正常运行的可执行文件输出为:

最后可以下结论:arm-linux-gcc-4.4.4制作成功。

 

参考网站

[1]http://ftp.gnu.org/gnu/binutils/

[2]http://mirrors.kernel.org/gnu/gcc/gcc-4.4.4/

[3]http://ftp.gnu.org/gnu/glibc/

[4]http://ftp.gnu.org/gnu/gmp/

[5]http://ftp.gnu.org/gnu/mpfr/

[6]http://www.kernel.org/pub/linux/kernel/v2.6/

[7] http://www.cnblogs.com/Charles-Zhang-Blog/archive/2013/02/21/2920999.html

版权说明:

本文中的所有文字,图片,代码的版权都是属于作者和博客园共同所有。欢迎转载,但是务必注明作者与出处。任何未经允许的剽窃以及爬虫抓取都属于侵权,作者和博客园保留所有权利。