全部博文(2759)
分类: LINUX
2013-09-11 12:11:08
原文地址:搭建交叉编译环境 作者:sh_ch_ping1987
构建ARM Linux交叉编译工具链
构建交叉编译器的第一个步骤就是确定目标平台。在GNU系统中,每个目标平台都有一个明确的格式,这些信息用于在构建过程中识别要使用的不同工具的正确版本。因此,当在一个特定目标机下运行GCC时,GCC便在目录路径中查找包含该目标规范的应用程序路径。GNU的目标规范格式为CPU-PLATFORM-OS。例如x86/i386 目标机名为i686-pc-linux-gnu。本章的目的是讲述建立基于ARM平台的交叉工具链,所以目标平台名为arm-linux-gnu。
通常构建交叉工具链有3种方法:
方法一:分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。该方法相对比较困难,适合想深入学习构建交叉工具链的读者。如果只是想使用交叉工具链,建议使用方法二或方法三构建交叉工具链。
方法二:通过Crosstool脚本工具来实现一次编译生成交叉编译工具链,该方法相对于方法一要简单许多,并且出错的机会也非常少,建议大多数情况下使用该方法构建交叉编译工具链。
方法三:直接通过网上(ftp.arm.kernel.org.uk)下载已经制作好的交叉编译工具链。该方法的优点不用多说,当然是简单省事,但与此同时该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的没有灵活性,所以构建所用的库以及编译器的版本也许并不适合你要编译的程序,同时也许会在使用时出现许多莫名的错误,建议读者慎用此方法。
对于不同的嵌入式目标开发过程来说,搭建交叉编译环境的过程基本类似,包括操作系统以及连接器,编译器、调试器在内的软件开发工具。
一个完整的linux下C研发环境包括以下三个组成:
1:函数库glibc
它linux下C的主要函数库
2:编译器GCC
3:系统头文档glibc_header
缺少系统头文档的话,很多用到系统功能的C程序将无法编译
交叉编译工具需要由binutils,GCC,glibc几个部分组成
(1) binutils:一套用来构造和使用二进制的工具集,由下面几个部分组成as GNU汇编器 ,将汇编语言编译成二进制目标代码GAS linux的标准汇编器,它只能编译x86的汇编语言
ld GNU连接器(8)制作交叉编译器
使用方法一即一般的方法,具体如下:(下载地址:)
gcc源码包:gcc-3.x.x.tar.bz2 (下载地址:)
c库源码包:glibc-2.x.x-tar.bz (下载地址:)
glibc-linuxthreads-2.x.x.tar.bz
gdb源码包:gdb-6.x.tar.bz (下载地址:)
下载gcc的补丁包,补丁包的后缀为“.patch”
下载内核的补丁包
(2):建立工作目录
首先建立工作目录,工作目录就是在什么目录下构建交叉工具链,目录的构建一般没有特别的要求,可以根据个人喜好建立。以下所建立的目录是作者自定义的
#cd opt/embedsky/
#mkdir arm_linux
再在这个工作目录arm_linux下建立3个目录 build-tools、kernel 和 tools。具体操作如下:
# cd arm_linux
# mkdir build-tools kernel tools
其中各目录的作用如下。
● build-tools 用来存放下载的binutils、gcc、glibc等源代码和用来编译这些源代码的目录;
● kernel 用来存放内核源代码及补丁
● tools 用来存放编译好的交叉编译工具和库文件。
(3)建立环境变量(# vi etc/profile ,在profile文件中添加PATH路径)
该步骤的目的是为了方便重复输入路径,因为重复操作每件相同的事情总会让人觉得很麻烦,如果读者不习惯使用环境变量就可以略过该步,直接输入绝对路径就可以。声明以下环境变量的目的是在之后编译工具库的时候会用到,很方便输入,尤其是可以降低输错路径的风险。
# export PRJROOT=/ opt/embedsky/ arm_linux/
# export TARGET=arm-linux
# export PREFIX=$PRJROOT/tools
# export TARGET_PREFIX=$PREFIX/$TARGET
# export PATH=$PREFIX/bin:$PATH
注意,用export声明的变量是临时的变量,也就是当注销或更换了控制台,这些环境变量就消失了,如果还需要使用这些环境变量就必须重复export操作,所以有时会很麻烦。值得庆幸的是,环境变量也可以定义在bashrc文件中,这样当注销或更换控制台时,这些变量就一直有效,就不用老是export这些变量了。
你可以在通过glibc下的config.sub脚本来知道,你的TARGET变量是否被支持,例如:
$./config.sub arm-unknown-linux-gnu |
在我的环境中,config.sub 在 glibc-2.2.3/scripts 目录下。
网上还有一些 HOWTO 可以参考,ARM 体系结构的《The GNU Toolchain for ARM Target
HOWTO》,PowerPC 体系结构的《Linux for
PowerPC Embedded Systems HOWTO》等。对TARGET的选取可能有帮助。
(4)复制建立交叉编译环境所需的源代码包到相应的目录下
#cp binutils-2.XX.tar.bz /opt/embedsky/arm_linux/
#cp gcc-x.x.x.tar.bz2 /opt/embedsky/arm_linux/
#cp glibc-2.x.x-tar.bz /opt/embedsky/arm_linux/
#cp glibc-linuxthreads-2.x.x.tar.bz /opt/embedsky/ arm_linux/
#cp gdb-x.x.tar.bz /opt/embedsky/arm_linux/
#cp linux-2.6.XX.tar.bz2 /opt/embedsky/kernel/
相应的补丁包也要一起拷贝过来
(5) 4. 建立编译目录
为了把源码和编译时生成的文件分开,一般的编译工作不在的源码目录中,要另建一个目录来专门用于编译。用以下的命令来建立编译你下载的binutils、gcc和glibc的源代码的目录。
$cd /opt/embedsky/ arm_linux
$mkdir build-binutils
build-boot-gcc build-gcc build-glibc gcc-patch
其中:
build-binutils-编译binutils的目录
build-boot-gcc-编译gcc 启动部分的目录
build-glibc-编译glibc的目录
build-gcc-编译gcc 全部的目录
gcc-patch-放gcc的补丁的目录
2:建立内核头文件
编译器需要通过系统内核的头文件来获得目标平台所支持的系统函数调用所需要的信息。对于Linux内核,最好的方法是下载一个合适的内核,然后复制获得头文件。需要对内核做一个基本的配置来生成正确的头文件;不过,不需要编译内核
#cd /opt/embedsky/kernel
解压内核源代码:
#tar xvfj linux-2.6.XX.tar.bz2 –C
给内核打补丁(根据情况选择):
#tar xvfj patch-2.x.x-rmkx.gz ;解压源码包
#cd linux-2.6.x
#patch –p1< ../patch-2.x.x-rmkx
编译内核生成头文件:
修改linux-2.6.x的makefile文件以对平台进行配置
#vi makefile
修改makefile的内容如下:
ARCH=arm CROSS_COMPIL=arm-linux-
修改完成后保存,运行配置命令根据系统进行相关配置
#make menuconfig
其中ARCH=arm表示是以 arm为体系结构,CROSS_COMPILE=arm-linux-表示是以arm-linux-为前缀的交叉编译器。也可以用config和 xconfig来代替menuconfig,推荐用make menuconfig,这也是内核开发人员用的最多的配置方法。注意在配置时一定要选择处理器的类型,这里选择三星的S3C2410(System Type->ARM SystemType->/Samsung S3C2440)配置完成退出并保存,检查一下内核目录中的include/linux下是否生成了autoconf.h和version.h。这是编译glibc时要用到的,autoconf.h和version.h的文件存在,也说明了生成了正确的头文件复制头文件到交叉编译工具链的目录,首先需要在/opt/embedsky/arm_linux/tools/arm-linux目录下建立工具的头文件目录inlcude,然后复制内核头文件到此目录下,具体操作如下:
# mkdir –p $TARGET_PREFIX/include
# cp –r $PRJROOT/kernel/linux-2.6.x/include/linux $TARGET_PREFIX/include
# cp –r $PRJROOT/kernel/linux-2.6.x/include/asm-arm $TARGET_PREFIX/include/asm
3:建立二进制工具(binutils)
#cd /opt/embedsky/arm_linux
#tar xvfj binutils-2.x.x.tar.bz2
然后进入build-binutils目录配置和编译binutils
#cd build-binutils
#../binutils-2.x.x/configure –target=$TARGET –prefix=$PREFIX
--target选项是指我们生成的arm-linux工具(指定交叉工具的体系结构,所有运行在主机上的交叉工具都要配置这个选项),--prefix是指我们可执行文件的位置(指定路径前缀),会出现很多check,最后产生makefile文件执行上说操作后,将在build-binutils下看到一个makefile
有了makefile后,来编译并安装binutils
#make
#make install
安装完成后,我们会在/ opt/embedsky/ arm_linux/tools/bin内看到以下文件:
$ls / opt/embedsky/ arm_linux/tools/bin
arm-linux-addr2line arm-linux-gasp arm-linux-objdump arm-linux-strings arm-linux-ar arm-linux-ld arm-linux-ranlib arm-linux-strip arm-linux-as arm-linux-nm arm-linux-readelf arm-linux-size arm-linux-c++filt arm-linux-objcopy
4:建立初始编译器(bootstrap gcc)
这一步的目的主要是建立arm- linux-gcc工具,注意这个gcc没有glibc库的支持,所以只能用于编译内核、BootLoader等不需要C库支持的程序,后面创建C库也要用到这个编译器,所以创建它主要是为创建C库做准备,如果只想编译内核和BootLoader,那么安装完这个就可以到此结束
(1)进入/opt/embedsky/arm_linux(等价于$PRJROOT/arm_linux)目录下,将gcc源代码解压
#cd /opt/embedsky/arm_linux
#tar xvzf gcc-x.x.x.tar.gz
(2)然后进入gcc.x.x.x目录给gcc打上补丁
#cd gcc-x.x.x
#patch –p1< ../gcc-x.x.x-2.patch
#patch –p1< ../gcc-x.x.x-no-fixinc.patch
#patch –p1< ../gcc-x.x.x-returntype-fix.patch
(3)配置并编辑t-linux文件
因为现在还没有glibc库的支持,所以需要简单配置一些简单选项
在我们编译并安装 gcc 前,我们先要改一个文件$PRJROOT/gcc/config/arm/t-linux
使用命令:#vi /$PRJROOT/gcc/config/arm/t-linux 打开文件,把TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC
这一行改为TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h
(或者TARGET_LIBGCC2-CFLAGS += -Dinhibit_libc -D__gthr_posix_h T_CFLAGS = -Dinhibit_libc -D__gthr_posix_h)
-Dinhibit_libc的意思是禁止使用libc,因为现在还没有编译出glibc库
你如果没定义 -Dinhibit,编译时将会报如下的错误
../../gcc-2.95.3/gcc/libgcc2.c:41: stdlib.h: No such
../../gcc-2.95.3/gcc/libgcc2.c:42: unistd.h: No such make[3]: *** [libgcc2.a] Error 1 make[2]: *** [stmp-multilib-sub] Error 2 make[1]: *** [stmp-multilib] Error 1 make: *** [all-gcc] Error 2 |
In file included from gthr-default.h:1,from ../../gcc-2.95.3/gcc/gthr.h:98,from ../../gcc-2.95.3/gcc/libgcc2.c:3034: ../../gcc-2.95.3/gcc/gthr-posix.h:37: pthread.h: No such file or directory make[3]: *** [libgcc2.a] Error 1 make[2]: *** [stmp-multilib-sub] Error 2make[1]: *** [stmp-multilib] Error 1 make: *** [all-gcc] Error 2 |
这条命令中的 -target、--prefix 和配置 binutils 的含义是相同的,其中选项--enable-languages=c表示只支持C语言,--disable-threads表示去掉thread功能,这个功能需要glibc的支持。--disable-shared表示只进行静态库编译,不支持共享库编译,这样就不依赖glibc了。
(5)编译、安装
#make all-gcc
#make install-gcc
我们来看看 $PREFIX/bin 里面多了哪些东西
$ls $PREFIX/bin |
你会发现多了 arm-linux-gcc 、arm-linux-unprotoize、cpp 和 gcov 几个文件。
Gcc-gnu 的 C 语言编译器
Unprotoize-将
ANSI C 的源码转化为 K&R C 的形式,去掉函数原型中的参数类型。
Cpp-gnu的 C 的预编译器
Gcov-gcc 的辅助测试工具,可以用它来分析和优程序。glibc是GUN C库,它是编译Linux系统程序很重要的组成部分。安装glibc-2.3.2版本之前推荐先安装以下的工具:
● GNU make 3.79或更新;
● GCC 3.2或更新;
● GNU binutils 2.13或更新。
(1)首先解压
glibc-2.x.x.tar.gz 和 glibc-linuxthreads-2.x.x.tar.gz 源代码
$cd /opt/embedsky/ arm_linux/ build-tools ($PRJROOT/build-tools )
$tar -xvzf glibc-2.x.x.tar.gz
$tar -xzvf glibc-linuxthreads-2.x.x.tar.gz --directory=glibc-2.x.x(2)然后进入 build-glibc 目录配置 glibc,配置生成makefile
告诉 glibc 我们的linux 内核头文件的目录位置。
(3)配置完后就可以编译和安装 glibc语言。
然后编译和安装你的 full gccc++ 编译器。
Protoize-与Unprotoize相反,将K&R C的源码转化为ANSI C的形式,函数原型中加入参数类型。
C++-gnu 的c++ 编译器。
到这里你的交叉编译工具就算做完了,简单验证一下你的交叉编译工具。7:制作交叉调试器
(1)解压gdb源文件包
#cd /opt/embedsky/arm_linux
sh all.sh --notest
echo Done.
天嵌交叉编译器的安装: