建立ARM交叉编译环境 (arm-none-linux-gnueabi-gcc with EABI)【转】
转自: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)【转】的更多相关文章
- Ubuntu18.04 LTS x64 构建ARM交叉编译环境(尝试,但失败了!!!估计是编译器没选对)
[测试而已,由于需要了解编译器和处理器体系,因此先放弃该方法] 动机 入门嵌入式开发,又需要 Windows 又需要 Linux,但资料给的竟然是 Ubuntu9,导致我不能使用 VSCode Rem ...
- Ubuntu12.04下arm交叉编译环境的建立
http://blog.csdn.net/heyangya2009/article/details/5424376 备注:ubuntu12.04+Android+Real6410 在主机上用来编译其他 ...
- 从头编译ARM交叉编译环境
首先Cygwin需安装基本的命令 例如make binutils gcc 还有diffutils 没有他会报找不到cmp命令 这些都可以在setup.exe中找到 编译gcc时,需要注意一个原则:不要 ...
- NeuSoft(1)构建嵌入式交叉编译环境
操作系统版本:ubuntu 12.04 内核名称:Linux 内核发行版:3.2.0-generic 内核版本:#50-Ubuntu SMP Mon Sep 12 21:18:14 UTC 2011 ...
- 用Eclipse和GDB构建ARM交叉编译和在线调试环境
我们在 Linux 主机中搭建我们的开发环境,使用 Ubuntu 10.04 LTS 为例. 搭建应用开发环境 安装 JRE Eclipse 依赖于Java 环境,所以必须先安装 JRE 或 JD ...
- Linux ARM交叉编译工具链制作过程【转】
本文转载自:http://www.cnblogs.com/Charles-Zhang-Blog/archive/2013/02/21/2920999.html 一.下载源文件 源代码文件及其版本与下载 ...
- arm汇编--ubuntu12.04 安装arm-linux交叉编译环境
1. 安装标准的C开发环境,由于Ubuntu安装默认是不安装的,所以需要先安装一下:sudo apt-get install gcc g++ libgcc1 libg++ make gdb 2.从ft ...
- 【转】ARM交叉编译工具链
原文网址:http://www.veryarm.com/cross-tools 为什么要用交叉编译器? 交叉编译通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,比如在PC平台( ...
- Zedboard学习(二):zedboard的Linux下交叉编译环境搭建 标签: 交叉编译linuxzedboard 2017-07-04 23:49 19人阅读
环境准备 首先肯定是要下载xilinx-2011.09-50-arm-xilinx-linux-gnueabi.bin文件,这是官方提供的linux下交叉编译链安装文件,下载地址为:https://p ...
随机推荐
- Qt——用于表格QTableView的模型
如果想使用表格来呈现数据,Qt提供了一个方便的部件QTableWidget,但是直接用它实现一些功能可能比较困难.这里将介绍一种强大.灵活的方式来操作表格. 一.模型/视图架构 在这个架构中,模型用于 ...
- DAY6-Flask项目
1.ViewModel:处理原始数据:裁剪修饰合并 2.访问静态资源 默认情况下,访问的路径为app根目录的下的static文件,为什么说app是根目录而不是fisher.py下,因为在实例化对象的时 ...
- 【BZOJ4006】管道连接(动态规划,斯坦纳树)
题面 BZOJ 洛谷 题解 和这题区别不是很大吧. 基本上拿过来改一下就做完了. #include<iostream> #include<cstdio> #include< ...
- 【Learning】常系数线性齐次递推
给定数列前k项\(h_0...h_{k-1}\),其后的项满足:\(h_i=\sum_{i=1}^kh_{i-j}a_i\),其中\(a_1...a_k\)是给定的系数,求\(h_n\) 数据范围小的 ...
- 【hdu4010】 Query on The Trees
http://acm.hdu.edu.cn/showproblem.php?pid=4010 (题目链接) 题意 link cut tree板子 Solution link cut tree 细节 注 ...
- 开源入侵检测系统SELKS系统搭建
一.系统环境配置 系统环境:centos7x64 ip地址:172.16.91.130 1.设置静态IP地址 [root@localhost backlion]#vi /etc/sys ...
- 【Asp.net入门11】第一个ASP.NET 应用程序-创建摘要视图
目前已经完成了应用程序的基本结构单元,受邀者也能够做出回复.这一节将添加一个支持组件,以显示收到的回复摘要,以便用户的朋友了解谁会参加晚会,并做出适当安排.在Solution Explorer中右键单 ...
- Python之socket(套接字)补充
IO多路复用 I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. Linux Linux中的 select,poll,e ...
- 通过TodoList案例对比Vue.js的MVVM设计模式与JQuery的MVP设计模式
Vue MVVM设计模式: 在使用vue进行编程时,不会再涉及到DOM的操作,取而代之的是修改数据层,当把数据进行变更的时候,vue之中它的底层会自动的根据数据的不同帮助我们去重新渲染页面. 编码时不 ...
- Mongodb 笔记06 副本集的组成、从应用程序连接副本集、管理
副本集的组成 1. 同步:MongoDB的复制功能是使用操作日志oplog实现的,操作日志包含了主节点的每一次写操作.oplog是主节点的local数据库中的一个固定集合.备份节点通过查询整个集合就可 ...