转自:http://lib.csdn.net/article/embeddeddevelopment/60172?knId=886

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

作者:wyjkk

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

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

过程预览:
,准备工作,包括下载源码包、补丁、建立文件夹和设置环境变量等
,建立内核头文件
,建立binutils
,建立bootstrap gcc
,建立glibc
,建立完整版本gcc
,测试hello world 现在就让我们开始吧! 准备工作 我使用的源码包和补丁 如下:
linux-2.6..tar.bz2
binutils-2.20.tar.gz
gcc-4.3..tar.bz2
glibc-2.11.tar.gz
glibc-linuxthreads-2.5.tar.bz2
glibc-ports-2.11.tar.bz2
glibc-2.11.-gcc_fix-.patch
至于怎么得到这些源码包,找google吧! 建立工作目录
自己选一个合适的地方,建立一个总文件夹Embedded,并且在其下建立 build-tools、kernel和tools三个子文件夹、我们以后的操作就都在这里进行了。 $ mkdir Embedded
$ cd Embedded
$ mkdir build-tools kernel tool
$ ls
build-tools kernel tool 各文件夹作用如下: build-tools : 保存binutils、gcc 和 glibc的源代码和用来编译这些源代码的目录。
kernel : 保存内核源代码和补丁。
tools : 保存编译好的交叉编译工具和库文件。
然后在build-tools文件夹中建立如下子文件夹: $ cd build-tools
$ mkdir build-binutils build-boot-gcc build-glibc build-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 : 添加可执行文件的路径,这里主要是只中间编译工具等 建立内核include文件 $ ln -s /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6./include/linux $TARGET_PREFIX/include/linux
$ ln -s /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6./include/asm-generic/ $TARGET_PREFIX/include/asm-generic
$ ln -s /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6./arch/arm/include/asm/ $TARGET_PREFIX/include/asm 编译生成version头文件 这个是编译glibc时必须的,使用命令:make include/linux/version.h 建立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:: 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 :打印出目标文件中可以打印的字符串,有个默认的长度,为4
strip :剥掉目标文件的所有的符号信息 建立bootstrap gcc 首先,我们为什么要建立bootstrap gcc,而不能一次性成功?原因有两点: 一是由于平台本身的gcc编译器和我们要建立的gcc版本不同,第一次用平台本身的编译器去build目标版本的gcc编译器的时候,新生成的目标编译器(相当于初始编译器编译链接生成的可执行文件)必然带有初始编译器的特征。而当我们用新生成的编译器再次编译自身时,便可去掉这种差异性。 二是因为gcc编译器依赖于glibc,而当前我们的glibc是基于本机的,所以我们首先要build基于arm体系结构的glibc,再在glibc的基础上生成基于arm体系结构的gcc。 这一步是最容易出错的,对每一步都必须谨慎,不要犯粗心之类的低级错误。 解压源码
解压gcc源码到build-tool文件夹下 修改源码:
gcc-4.3.
CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC -Dinhibit_libc -D__gthr_posix_h 确保本机已经安装了mpc, mpfr, gmp, 如果没有,则在yast里面安装好再往后走。 配置:
../gcc-4.3./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. : gnu的 C 语言编译器,其实和arm-linux-gcc是一样的
arm-none-linux-gnueabi-gccbug : 一个可执行脚本,具体作用未知。
arm-none-linux-gnueabi-gcov : gcc 的辅助测试工具,用来分析和优化程序 建立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=yes
libc_cv_c_cleanup=yes
libc_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. /lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so. ) )
更改为
GROUP ( libc.so. libc_nonshared.a )
保存后退出 建立完整版gcc 有了前面的经验,现在就简单多了,进入目录build-gcc, 配置: ../gcc-4.3./configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --disable-libgomp 编译:
make all 安装:
make install 安装完成后,在$PREFIX/bin下多了gnu的c++编译器:
arm-none-linux-gnueabi-gcc
arm-none-linux-gnueabi-c++ 验证工具链
创建,编译生成一个hello world程序helloworld, 查看elf文件信息:
$ arm-none-linux-gnueabi-readelf -d helloworld
是不是看到了ARM的信息?更直接的,就是把这个helloworld和相关依赖的动态库拷到开发板上,看它是不是真的能helloworld! 总结
这次在SUSE .2上编译安装工具链,整个过程非常顺利,其实我相信只要环境,配置等正确,常见linux发行版上都会比较顺利。不过我还是建议直接下在编译好的工具链,省下了不少麻烦,而且可靠性也能保证。最后,希望本教程对大家有所帮助,如果有什么遗漏或错误之处,希望大家能批评指正! 参考文献: , 如何为嵌入式开发建立交叉编译环境: http://www.ibm.com/developerworks/cn/linux/l-embcmpl/

建立ARM交叉编译环境 (arm-none-linux-gnueabi-gcc with EABI)【转】的更多相关文章

  1. Ubuntu18.04 LTS x64 构建ARM交叉编译环境(尝试,但失败了!!!估计是编译器没选对)

    [测试而已,由于需要了解编译器和处理器体系,因此先放弃该方法] 动机 入门嵌入式开发,又需要 Windows 又需要 Linux,但资料给的竟然是 Ubuntu9,导致我不能使用 VSCode Rem ...

  2. Ubuntu12.04下arm交叉编译环境的建立

    http://blog.csdn.net/heyangya2009/article/details/5424376 备注:ubuntu12.04+Android+Real6410 在主机上用来编译其他 ...

  3. 从头编译ARM交叉编译环境

    首先Cygwin需安装基本的命令 例如make binutils gcc 还有diffutils 没有他会报找不到cmp命令 这些都可以在setup.exe中找到 编译gcc时,需要注意一个原则:不要 ...

  4. NeuSoft(1)构建嵌入式交叉编译环境

    操作系统版本:ubuntu 12.04 内核名称:Linux 内核发行版:3.2.0-generic 内核版本:#50-Ubuntu SMP Mon Sep 12 21:18:14 UTC 2011 ...

  5. 用Eclipse和GDB构建ARM交叉编译和在线调试环境

    我们在 Linux 主机中搭建我们的开发环境,使用 Ubuntu 10.04 LTS 为例. 搭建应用开发环境   安装 JRE Eclipse 依赖于Java 环境,所以必须先安装 JRE 或 JD ...

  6. Linux ARM交叉编译工具链制作过程【转】

    本文转载自:http://www.cnblogs.com/Charles-Zhang-Blog/archive/2013/02/21/2920999.html 一.下载源文件 源代码文件及其版本与下载 ...

  7. arm汇编--ubuntu12.04 安装arm-linux交叉编译环境

    1. 安装标准的C开发环境,由于Ubuntu安装默认是不安装的,所以需要先安装一下:sudo apt-get install gcc g++ libgcc1 libg++ make gdb 2.从ft ...

  8. 【转】ARM交叉编译工具链

    原文网址:http://www.veryarm.com/cross-tools 为什么要用交叉编译器? 交叉编译通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,比如在PC平台( ...

  9. Zedboard学习(二):zedboard的Linux下交叉编译环境搭建 标签: 交叉编译linuxzedboard 2017-07-04 23:49 19人阅读

    环境准备 首先肯定是要下载xilinx-2011.09-50-arm-xilinx-linux-gnueabi.bin文件,这是官方提供的linux下交叉编译链安装文件,下载地址为:https://p ...

随机推荐

  1. Redis 基础:Redis 事件处理

    Redis 事件处理 Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件(file event):Redis服务器通过套接字与客户端(或其他Redis服务器)进行连接,而文件事 ...

  2. 多进程编程之system()函数

    1.system函数: 使用函数system,在程序中执行一个shell命令字符串很方便.它是一个和操作系统紧密相关的函数,用户可以使用它在自己的程序中调用系统提供的各种命令,执行系统的命令行,其实也 ...

  3. 【BZOJ2724】蒲公英(分块)

    [BZOJ2724]蒲公英(分块) 题面 洛谷 谴责权限题的行为 题解 分块什么的都不会,根本就没写过几次. 复杂度根本不会分析,吓得我赶快来练练. 这题要求的是区间众数,显然没有什么很好的主席树之类 ...

  4. Alpha 冲刺 —— 十分之十

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 测试整体软件 展示GitHub当 ...

  5. 【IOI 2018】Werewolf 狼人

    虽然作为IOI的Day1T3,但其实不是一道很难的题,或者说这道题其实比较套路吧. 接下来讲解一下这个题的做法: 如果你做过NOI 2018的Day1T1,并且看懂了题面,那你很快就会联想到这道题,因 ...

  6. LINUX内核分析第七周——可执行程序的装载

    一.得到一个可执行程序 1. 预处理.编译.链接 gcc hello.c -o hello.exe gcc编译源代码生成最终可执行的二进制程序,GCC后台隐含执行了四个阶段步骤. 预处理 => ...

  7. java关于类加载的面试题

    ---面试题 class SingleTon { private static SingleTon singleTon = new SingleTon(); public static int cou ...

  8. Vulkan vs OpenGL ES

    Vulkan 简介 Vulkan是一个免费开放的.跨平台的.底层的图形API,在一定程度上比AMD Mantle.微软DirectX 12.苹果Metal更值得开发者关注. Vulkan的最大任务不是 ...

  9. 实用 zsh 插件

    zsh 命令补全插件 zsh-users/zsh-autosuggestions laravel5(使用前提:安装了 oh-my-zsh) 使用方法,修改 ~/.zshrc,在 plugins 里面加 ...

  10. Hi35xx 通用GPIO 使用篇(板子3G电源控制脚说明)

    在一个嵌入式系统中使用最多的莫过于 通用输入输出 GPIO口.看到论坛中经常有朋友问海思为什么没有提供GPIO驱动.其实不然. 在海思SDK  xxx/osdrv/tools/board_tools/ ...