ARM交叉编译链的制作参考模板.docx
- 文档编号:28302321
- 上传时间:2023-07-10
- 格式:DOCX
- 页数:13
- 大小:20.63KB
ARM交叉编译链的制作参考模板.docx
《ARM交叉编译链的制作参考模板.docx》由会员分享,可在线阅读,更多相关《ARM交叉编译链的制作参考模板.docx(13页珍藏版)》请在冰豆网上搜索。
ARM交叉编译链的制作参考模板
ARM交叉编译链的制作
1.直接下载已经编译好的文件。
例如:
http:
//arm.linux.org.uk,这里提供已经编译好的cross,如cross-3.3.2.tar.bz2,cross-3.0.tar.bz2。
直接下载某个包后解压,然后创建合适的链接或者输出环境变量即可调用。
这种做法操作很简单,但是不能根据自己的需求去定义,只能选择已经编译好的东西。
2.自己动手利用crosstool来制作。
A.在CROSSTOOL官方网站下载源码包,解压,进入解压后的目录。
$sudowget
$sudotar-xzvfcrosstool-0.42.tar.gz
$cdcrosstool-0.42
B.以ROOT建立目录,存放生成的交叉编译链
改变该目录的所有者为普通用户
例如,存放生成的交叉编译链目录为/opt/crosstool,如下所示:
sudomkdir/opt/crosstool
sudochown$USER/opt/crosstool
C.修改针对目标板的脚本文件。
$sudovidemo-arm.sh
(1)这几个环境变量可以根据实际情况修改
TARBALLS_DIR=$HOME/downloads
RESULT_TOP=/opt/crosstool
exportTARBALLS_DIRRESULT_TOP
GCC_LANGUAGES="c,c++"
exportGCC_LANGUAGES
(2)在若干行eval语句中选择要建立的交叉编译链的组合,去掉该行eval的#号。
例如要做gcc为3.3.3,glibc为2.3.2的工具链
eval`catarm.datgcc-3.4.5-glibc-2.3.6.dat`shall.sh--notest
D.修改目标板脚本文件demo-arm.sh中eval那一行出现的体系结构的配置文件
$sudoviarm.dat
KERNELCONFIG=`pwd`/arm.config
TARGET=arm-unknown-linux-gnu
TARGET_CFLAGS="-O"
可以修改TARGET变量为
TARGET=arm-S3C2410-linux-gnu(你的arm型号)
E.修改目标板脚本文件demo-arm.sh中eval那一行出现的工具链的匹配文件
$sudovigcc-3.4.5-glibc-2.3.6.dat
BINUTILS_DIR=binutils-2.15
GCC_DIR=gcc-3.3.3
GLIBC_DIR=glibc-2.3.2
LINUX_DIR=linux-2.4.26
GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.2
以上变量要根据实际情况修改。
不过
例如想下载linux2.6的版本,并且下载gdb最新的版本。
内核具体的版本要参照http:
//kernel.org/和ftp:
//ftp.gnu.org/pub/gnu/gdb。
例如。
LINUX_DIR=linux-2.6.12.1
GDB_DIR=gdb-6.0
F.以普通用户运行脚本
$sudoshdemo-arm.sh
进入漫长的等待过程中……
3.安装完成后路径设置和测试。
编辑~/.bash_profile,在其中exportPATH前加入这样一行,PATH=/opt/crosstool/gcc-3.4.5-glibc-2.3.6/arm-S3C2410-linux-gnu/bin:
$PATH
,改完后我的是这样的
#Userspecificenvironmentandstartupprograms
PATH=$PATH:
$HOME/bin
PATH=/opt/crosstool/gcc-3.4.5-glibc-2.3.6/arm-S3C2410-linux-gnu/bin:
$PATH
exportPATH
unsetUSERNAME
然后就好了。
可以开始测试使用了。
测试的方法很简单,随便找个程序源码编译一下就好了。
这里用的这些编译器生成的是二进制文件,和平时的gcc生成的可执行文件并不相同。
例如我测试时的文件是test.c,
#include
intmain()
{
printf("Hello!
");
return0;
}
调用新的arm-linux-gcc来编译:
arm-S3C2410-linux-gnu-gcc-otesttest.c,这时生成的test文件是一个二进制的可执行文件,并不是我们平时常用的,所以在PC上执行这个文件的话是不行的,系统会提示:
bash:
./test:
cannotexecutebinaryfile。
所以不能用这种方法来测试交叉编译是否成功。
而应改采用file命令,例如我的是这样的:
filetest
结果如下:
test:
ELF32-bitLSBexecutable,ARM,version1(ARM),forGNU/Linux2.4.3,dynamicallylinked(usessharedlibs),forGNU/Linux2.4.3,notstripped
如果出现这样的结果说明交叉编译环境已经安装成功。
否则…………重新想办法吧……
第二种方法中,gcc,gdb等文件的下载方法有两种,一是设置好网络后让shell程序自己去下载,这种方法简单,但是下载速度不敢恭维。
另外一种是自己使用下载工具去下载,然后将存放路径告诉demo-arm.sh,即2.C里面的内容。
这种方法速度让人满意。
推荐使用。
建立ARM交叉编译环境(arm-none-linux-gnueabi-gccwithEABI)2011-03-2411:
00昨天终于把交叉编译环境、移植内核和制作root文件系统在arm开发板上顺利跑通了。
期间有的步骤很顺利,但更多的是被诸多问题困扰,比如最后一个不起眼的小问题导致文件系统无法加载,郁闷了我一个星期,最终通过分析慢慢发现了这个bug。
还有各源码包版本的问题,而且网上很多介绍都是基于旧版本的。
我这里全部用最新或较新的版本,当然,至于新旧版本到底哪个更好更合适,这是个智者见智的论题,不在本文讨论之列。
我坚信很多人也遇到过或者即将遇到我曾经历过的错误和问题,因此我觉得把我过去两周做过的相关工作,详细地写下来,希望对大家有所帮助!
首先是平台和环境,我过去两周都是基于vmware中ubuntu10.04的,但是我发现ubuntu这个很火的桌面linux发行版本并不适合进行嵌入式开发,典型的麻烦就是系统缺少很多库、服务等等,需要自己手动安装,增加了不少额外的工作,和我以前用的SuSe9比麻烦不少。
不过所以现在我干脆全新装了一个SUSE11.2EnterpriseServer32bit,把过去的工作重复一遍,边编译边纪录,力求不遗漏细节!
过程预览:
1,准备工作,包括下载源码包、补丁、建立文件夹和设置环境变量等
2,建立内核头文件
3,建立binutils
4,建立bootstrapgcc
5,建立glibc
6,建立完整版本gcc
7,测试helloworld
现在就让我们开始吧!
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三个子文件夹、我们以后的操作就都在这里进行了。
$mkdirEmbedded
$cdEmbedded
$mkdirbuild-toolskerneltool
$ls
build-toolskerneltool
各文件夹作用如下:
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,在文档最后输入下面几行,然后注销当前用户,重新登录
exportPRJROOT=/home/jinglelong/MySoftware/Embedded
exportTARGET=arm-none-linux-gnueabi
exportPREFIX=$PRJROOT/tools
exportTARGET_PREFIX=$PREFIX/$TARGET
exportPATH=$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时必须的,使用命令:
makeinclude/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:
Infunction‘make_mapping_symbol’:
../../binutils-2.20/gas/config/tc-arm.c:
2489:
error:
suggestbracesaroundemptybodyinan‘if’statement
打开文件binutils-2.20/gas/config/tc-arm.c,把2490行的语句,用一对大括号括起来就可以了
安装:
makeinstall
完成后检查一下$PREFIX文件夹,是不是多了三个子文件夹,bin,lib,share?
打开bin,发现里面生成了14个可执行文件:
[root@localhostbin]#ls
arm-none-linux-gnueabi-addr2linearm-none-linux-gnueabi-asarm-none-linux-gnueabi-gprofarm-none-linux-gnueabi-nmarm-none-linux-gnueabi-objdumparm-none-linux-gnueabi-readelfarm-none-linux-gnueabi-stringsarm-none-linux-gnueabi-ararm-none-linux-gnueabi-c++filtarm-none-linux-gnueabi-ldarm-none-linux-gnueabi-objcopyarm-none-linux-gnueabi-ranlibarm-none-linux-gnueabi-sizearm-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:
剥掉目标文件的所有的符号信息
4建立bootstrapgcc
首先,我们为什么要建立bootstrapgcc,而不能一次性成功?
原因有两点:
一是由于平台本身的gcc编译器和我们要建立的gcc版本不同,第一次用平台本身的编译器去build目标版本的gcc编译器的时候,新生成的目标编译器(相当于初始编译器编译链接生成的可执行文件)必然带有初始编译器的特征。
而当我们用新生成的编译器再次编译自身时,便可去掉这种差异性。
二是因为gcc编译器依赖于glibc,而当前我们的glibc是基于本机的,所以我们首先要build基于arm体系结构的glibc,再在glibc的基础上生成基于arm体系结构的gcc。
这一步是最容易出错的,对每一步都必须谨慎,不要犯粗心之类的低级错误。
解压源码
解压gcc源码到build-tool文件夹下
修改源码:
gcc-4.3.5
CRTSTUFF_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
编译:
makeall-gcc
安装gcc:
makeinstall
再编译安装libgcc,这个是后面编译glibc必须的。
编译:
makeall-target-libgcc
安装libgcc:
makeinstall-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=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:
cannotfind-lgcc_eh
打开glibc根目录下Makeconfig文件,去掉第541,546行中的-lgcc_eh,重新make
安装:
makeinstall_root=$TARGET_PREFIXprefix=""install
修改libc.so:
用vi或gedit打开libc.so文件,将文件中的:
GROUP(/lib/libc.so.6/lib/libc_nonshared.aAS_NEEDED(/lib/ld-linux.so.2))
更改为
GROUP(libc.so.6libc_nonshared.a)
保存后退出
6建立完整版gcc
有了前面的经验,现在就简单多了,进入目录build-gcc,
配置:
../gcc-4.3.5/configure--target=$TARGET--prefix=$PREFIX--enable-languages=c,c++--disable-libgomp
编译:
makeall
安装:
makeinstall
安装完成后,在$PREFIX/bin下多了gnu的c++编译器:
arm-none-linux-gnueabi-gcc
arm-none-linux-gnueabi-c++
7验证工具链
创建,编译生成一个helloworld程序helloworld,查看elf文件信息:
$arm-none-linux-gnueabi-readelf-dhelloworld
是不是看到了ARM的信息?
更直接的,就是把这个helloworld和相关依赖的动态库拷到开发板上,看它是不是真的能helloworld!
8总结
这次在SUSE11.2上编译安装工具链,整个过程非常顺利,其实我相信只要环境,配置等正确,常见linux发行版上都会比较顺利。
不过我还是建议直接下在编译好的工具链,省下了不少麻烦,而且可靠性也能保证。
最后,希望本教程对大家有所帮助,如果有什么遗漏或错误之处,希望大家能批评指正!
(本资料素材和资料部分来自网络,仅供参考。
请预览后才下载,期待您的好评与关注!
)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ARM 交叉 编译 制作 参考 模板