arm-none-linux-gnueabi-gcc 移植,建立ARM交叉编译环境 (arm-none-linux-gnueabi-gcc with EABI)

昨天终于把交叉编译环境、移植内核和制作root文件系统在arm开发板上顺利跑通了。期间有的步骤很顺利,但更多的是被诸多问题困扰,比如最后一个不起眼的小问题导致文件系统无法加载,郁闷了我一个星期,最终通过分析慢慢发现了这个bug。还有各源码包版本的问题,而且网上很多介绍都是基于旧版本的。我这里全部用最新或较新的版本,当然,至于新旧版本到底哪个更好更合适,这是个智者见智的论题,不在本文讨论之列。我坚信很多人也遇到过或者即将遇到我曾经历过的错误和问题,因此我觉得把我过去两周做过的相关工作,详细地写下来,希望对大家有所帮助!

首先是平台和环境 ,我过去两周都是基于vmware 中ubuntu 10.04的,但是我发现ubuntu这个很火的桌面linux发行版本并不适合进行嵌入式开发,典型的麻烦就是系统缺少很多库、服务等等,需要自己手动安装,增加了不少额外的工作,和我以前用的SuSe 9比麻烦不少。不过所以现在我干脆全新装了一个SUSE 11.2 Enterprise Server 32bit,把过去的工作重复一遍,边编译边纪录,力求不遗漏细节!

过程预览:1,准备工作,包括下载源码包、补丁、建立文件夹和设置环境变量等

2,建立内核头文件

3,建立binutils

4,建立bootstrap gcc

5,建立glibc

6,建立完整版本gcc

7,测试hello world

现在就让我们开始吧!

1 准备工作

我使用的源码包和补丁 如下:

linux-2.6.34.tar.bz2

binutils-2.20.tar.gz

gcc-4.3.5.tar.bz2

glibc-2.11.tar.gz

glibc-linuxthreads-2.5.tar.bz2

glibc-ports-2.11.tar.bz2

glibc-2.11.2-gcc_fix-1.patch

至于怎么得到这些源码包,找google吧!

建立工作目录自己选一个合适的地方,建立一个总文件夹Embedded,并且在其下建立 build-tools、kernel和tools三个子文件夹、我们以后的操作就都在这里进行了。$ mkdir Embedded$ cd Embedded$ mkdir build-tools    kernel     tool$ lsbuild-tools    kernel     tool

各文件夹作用如下:

build-tools : 保存binutils、gcc 和 glibc的源代码和用来编译这些源代码的目录。

kernel        : 保存内核源代码和补丁。

tools          : 保存编译好的交叉编译工具和库文件。

然后在build-tools文件夹中建立如下子文件夹:

$ cdbuild-tools$ mkdirbuild-binutilsbuild-boot-gccbuild-glibcbuild-gcc

build-binutils    :编译binutils的目录

build-boot-gcc : 编译gcc 启动部分的目录

build-glibc        :编译glibc的目录

build-gcc          :编译完整gcc的目录

设置环境变量:

这里设置环境变量只是为了方便,因为每个工具的config都需要输入类似的变量,不如放在环境变量里。

在命令行下打开vi  ~/.bashrc,在文档最后输入下面几行,然后注销当前用户,重新登录

export PRJROOT=/home/jinglelong/MySoftware/Embedded

export TARGET=arm-none-linux-gnueabi

export PREFIX=$PRJROOT/tools

export TARGET_PREFIX=$PREFIX/$TARGET

export PATH=$PREFIX/bin:$PATH

各变量的具体意义如下:

PRJROOT                     : 整个工程的根目录,这里当然是Embeded了

TARGET                       : 目标文件对应的体系结构,arm-linux代表编译出来的target只能在arm体系结构中运行

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

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

PATH                           : 添加可执行文件的路径,这里主要是只中间编译工具等

2 建立内核include文件

$ ln -s  /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6.34/include/linux  $TARGET_PREFIX/include/linux

$ ln -s  /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6.34/include/asm-generic/      $TARGET_PREFIX/include/asm-generic

$ ln -s  /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6.34/arch/arm/include/asm/  $TARGET_PREFIX/include/asm

编译生成version头文件

这个是编译glibc时必须的,使用命令:make include/linux/version.h

3 建立binutils

解压binutils源码到文件夹: $PRJROOT/build-tools/binutils-2.20

配置:

cd $PRJROOT/build-tools/build-binutils$ ../binutils-2.20/configure --target=$TARGET --prefix=$PREFIX

编译:make出错:../../binutils-2.20/gas/config/tc-arm.c: In function ‘make_mapping_symbol’:

../../binutils-2.20/gas/config/tc-arm.c:2489: error: suggest braces around empty body in an ‘if’ statement

打开文件binutils-2.20/gas/config/tc-arm.c,把2490行的语句,用一对大括号括起来就可以了

安装: make install完成后检查一下$PREFIX文件夹,是不是多了三个子文件夹,bin, lib, share? 打开bin,发现里面生成了14个可执行文件:

[root@localhost bin]# ls

arm-none-linux-gnueabi-addr2line  arm-none-linux-gnueabi-as   arm-none-linux-gnueabi-gprof  arm-none-linux-gnueabi-nm       arm-none-linux-gnueabi-objdump  arm-none-linux-gnueabi-readelf  arm-none-linux-gnueabi-strings arm-none-linux-gnueabi-ar         arm-none-linux-gnueabi-c++filt  arm-none-linux-gnueabi-ld     arm-none-linux-gnueabi-objcopy  arm-none-linux-gnueabi-ranlib   arm-none-linux-gnueabi-size     arm-none-linux-gnueabi-strip

他们的功能分别是:

add2line         :将你要找的地址转成文件和行号,它要使用 debug 信息。ar                  :产生、修改和解开一个存档文件as                  :gnu的汇编器c++filt            :C++ 和 java 中有一种重载函数,所用的重载函数最后会被编译转化成汇编的标,c++filt 就是实现这种反向的转化,根据标号得到函数名。gprof              :gnu 汇编器预编译器。ld                   :gnu 的连接器nm                 :列出目标文件的符号和对应的地址objcopy           :将某种格式的目标文件转化成另外格式的目标文件objdump          :显示目标文件的信息ranlib              :为一个存档文件产生一个索引,并将这个索引存入存档文件中readelf            :显示 elf 格式的目标文件的信息size                :显示目标文件各个节的大小和目标文件的大小strings            :打印出目标文件中可以打印的字符串,有个默认的长度,为4strip                :剥掉目标文件的所有的符号信息

4 建立bootstrap gcc

首先,我们为什么要建立bootstrap gcc,而不能一次性成功?原因有两点:

一是由于平台本身的gcc编译器和我们要建立的gcc版本不同,第一次用平台本身的编译器去build目标版本的gcc编译器的时候,新生成的目标编译器(相当于初始编译器编译链接生成的可执行文件)必然带有初始编译器的特征。而当我们用新生成的编译器再次编译自身时,便可去掉这种差异性。

二是因为gcc编译器依赖于glibc,而当前我们的glibc是基于本机的,所以我们首先要build基于arm体系结构的glibc,再在glibc的基础上生成基于arm体系结构的gcc。

这一步是最容易出错的,对每一步都必须谨慎,不要犯粗心之类的低级错误。

解压源码解压gcc源码到build-tool文件夹下

修改源码:gcc-4.3.5CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC -Dinhibit_libc -D__gthr_posix_h确保本机已经安装了mpc, mpfr, gmp, 如果没有,则在yast里面安装好再往后走。

配置:../gcc-4.3.5/configure --target=$TARGET --prefix=$PREFIX --without-headers --enable-languages=c --disable-threads --with-newlib --disable-shared --disable-libmudflap --disable-libssp

编译:make all-gcc安装gcc: make install再编译安装libgcc,这个是后面编译glibc必须的。编译:make all-target-libgcc安装libgcc: make install-target-libgcc

我看到网上很多文章在这一步有很多错误,一种是直接用make命令编译gcc下所有内容,这个是没有必要的,而且容易出错。我在ubuntu和suse下都无法完成编译,而在fedora下通过了;第二种情况是没有编译libgcc,这会导致后面编译glibc无法通过。

安装完成后,在$PREFIX/bin下又多了几个文件,arm-none-linux-gnueabi-cpp         : gnu的 C 的预编译器arm-none-linux-gnueabi-gcc         : gnu的 C 语言编译器arm-none-linux-gnueabi-gcc-4.3.5 : gnu的 C 语言编译器,其实和arm-linux-gcc是一样的arm-none-linux-gnueabi-gccbug    :  一个可执行脚本,具体作用未知。arm-none-linux-gnueabi-gcov        : gcc 的辅助测试工具,用来分析和优化程序

5 建立glibc解压源码:

把glibc源码解压到build-tool下,把glibc-linuxthreads-2.5.tar.bz2解压到glibc根目录下,把glibc-ports-2.11.tar.bz2解压到glibc根目录下,并且命名为ports

进入文件夹build-glibc,创建config.cache文件,并且在文件中输入以下内容

libc_cv_forced_unwind=yeslibc_cv_c_cleanup=yeslibc_cv_arm_tls=yes

配置:

BUILD_CC="gcc" CC=$TARGET-gcc ../glibc-2.11/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/

编译:make出错:/arm-linux/bin/ld: cannot find -lgcc_eh打开glibc根目录下Makeconfig文件,去掉第541,546行中的-lgcc_eh,重新make

安装:

make install_root=$TARGET_PREFIX prefix="" install

修改libc.so:

用vi或gedit打开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 )保存后退出

6 建立完整版gcc

有了前面的经验,现在就简单多了,进入目录build-gcc,

配置:

../gcc-4.3.5/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --disable-libgomp

编译:make all

安装:make install

安装完成后,在$PREFIX/bin下多了gnu的c++编译器:arm-none-linux-gnueabi-gccarm-none-linux-gnueabi-c++

7 验证工具链创建,编译生成一个hello world程序helloworld, 查看elf文件信息:$  arm-none-linux-gnueabi-readelf  -d helloworld是不是看到了ARM的信息?更直接的,就是把这个helloworld和相关依赖的动态库拷到开发板上,看它是不是真的能helloworld!

8 总结这次在SUSE 11.2上编译安装工具链,整个过程非常顺利,其实我相信只要环境,配置等正确,常见linux发行版上都会比较顺利。不过我还是建议直接下在编译好的工具链,省下了不少麻烦,而且可靠性也能保证。最后,希望本教程对大家有所帮助,如果有什么遗漏或错误之处,希望大家能批评指正!

参考文献:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: arm-none-linux-gnueabi-gcc 4.8.3 是一个用于编译运行在 ARM 架构的 Linux 系统上的交叉编译器。 gccGNU 编译器套件中的一个重要组件,它用于编译多种编程语言,包括 C、C++ 和 Fortran。arm-none-linux-gnueabi-gccgcc 的特定版本,用于交叉编译 ARM 架构上的应用程序。交叉编译是指在一种操作系统上生成适用于另一种操作系统或硬件平台上运行的可执行文件。 在 arm-none-linux-gnueabi-gcc 中,"arm" 表示该编译器是为 ARM 架构提供支持的,"none" 表示该编译器不针对特定的操作系统,"linux" 表示该编译器用于编译 Linux 操作系统上的应用程序,"gnueabi" 表示该编译器使用 GNU 工具链和 ELF 文件格式来生成应用程序。 版本号 4.8.3 表示该编译器的主要版本号是 4,次要版本号是 8,修订版本号是 3。版本号的升级通常意味着增加了新的功能、修复了已知的问题或提高了性能。 使用 arm-none-linux-gnueabi-gcc 4.8.3 编译应用程序时,我们可以通过相应的命令行选项指定编译目标以及其他所需的参数。由于它是一个交叉编译器,因此我们可以使用它在不同的操作系统上(如 Windows 或 macOS)编写并编译 ARM 架构的应用程序。编译完成后,生成的可执行文件可以在 ARM 架构的 Linux 系统上运行。 ### 回答2: arm-none-linux-gnueabi-gcc 4.8.3 是一个特定版本的 GCC 编译器,用于在 ARM 架构上编译运行 Linux 的应用程序。GCCGNU Compiler Collection 的缩写,是一个开源的编译器套件,用于编写和运行 C、C++ 和其他支持的编程语言。 arm-none-linux-gnueabiGCC 的一个目标后端选项,用于指定编译生成针对 ARM 架构的可执行程序。gnueabi 表示该编译器使用了 GNU C 库和一些 EABI(嵌入式应用二进制接口)的规范。 4.8.3 表示编译器的具体版本号。版本号通常包含主版本号、次版本号和修订号,用于标识编译器的重要更新和改进。具体版本的编译器可以选择更好的优化选项、修复已知的错误,并提供更好的兼容性和性能。 arm-none-linux-gnueabi-gcc 4.8.3 可能是为了满足某些特定的项目要求而开发的版本,也可能是该产品版本的标准推荐编译器。开发者可以根据项目需求选择合适的 GCC 版本,并使用相关命令进行编译、链接、优化和调试。 通过使用 arm-none-linux-gnueabi-gcc 4.8.3,开发者可以在 ARM 架构上编写高效、可靠和兼容的 Linux 应用程序。这些应用程序可以在嵌入式设备、移动设备和其他 ARM 架构的系统上运行,为用户提供强大的功能和灵活性。编译器版本号的选择取决于开发者对编译器功能和性能的需求,以及与其他软件组件和库的兼容性要求。 ### 回答3: arm-none-linux-gnueabi-gcc 4.8.3 是一个GCC编译工具链的版本,专门用于编译适用于ARM架构(arm-none-linux-gnueabi)的Linux操作系统。GCCGNU编译器套件(GNU Compiler Collection)的缩写,它是一个广泛使用的开源编译器集合,支持多种编程语言。 arm-none-linux-gnueabi-gcc 4.8.3 的"arm-none-linux-gnueabi"部分表示目标平台为ARM架构的嵌入式设备,而"gnueabi"则表示使用了GNUGNU is Not Unix)工具链,并且目标操作系统为Linux。因此,该编译器适用于开发基于ARM架构的嵌入式Linux应用程序。 版本号4.8.3表示该工具链的具体版本为4.8.3,版本号的更新通常意味着对新语言标准、性能改进和错误修复的支持。因此,arm-none-linux-gnueabi-gcc 4.8.3可能具有一些特定的新功能和改进之前版本的问题。此外,版本号对于确保编译生成的代码与其他开发工具和库保持兼容性也非常重要。 总而言之,arm-none-linux-gnueabi-gcc 4.8.3 是一个适用于ARM架构的嵌入式系统的GNU编译器工具链。它用于编译适用于ARM架构的Linux操作系统上的应用程序。版本号4.8.3表示该编译器的具体版本,版本号的更新通常带来新功能和改进。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值