toolchain Binutils360如何打补丁丁

Cross Toolchain-交叉编译工具链
我的图书馆
Cross Toolchain-交叉编译工具链
Cross&Toolchain-交叉编译工具链
读者可能会有疑问,为什么要用交叉编译器?交叉编译通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,比如在PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平台上的程序,编译得到的程序在X86 CPU平台上是不能运行的,必须放到ARM CPU平台上才能运行,虽然两个平台用的都是Linux系统。这种方法在异平台移植和嵌入式开发时非常有用。相对与交叉编译,平常做的编译叫本地编译,也就是在当前平台编译,编译得到的程序也是在本地执行。用来编译这种跨平台程序的编译器就叫交叉编译器,相对来说,用来做本地编译的工具就叫本地编译器。所以要生成在目标机上运行的程序,必须要用交叉编译工具链来完成。在裁减和定制Linux内核用于嵌入式系统之前,由于一般嵌入式开发系统存储大小有限,通常都要在性能优越的PC上建立一个用于目标机的交叉编译工具链,用该交叉编译工具链在PC上编译目标机上要运行的程序。交叉编译工具链是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils、gcc和glibc 3个部分组成。有时出于减小 libc 库大小的考虑,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。建立交叉编译工具链是一个相当复杂的过程,如果不想自己经历复杂繁琐的编译过程,网上有一些编译好的可用的交叉编译工具链可以下载,但就以学习为目的来说读者有必要学习自己制作一个交叉编译工具链。本章通过具体的实例讲述基于ARM的嵌入式Linux交叉编译工具链的制作过程。
2.2 构建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)下载已经制作好的交叉编译工具链。该方法的优点不用多说,当然是简单省事,但与此同时该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的没有灵活性,所以构建所用的库以及编译器的版本也许并不适合你要编译的程序,同时也许会在使用时出现许多莫名的错误,建议读者慎用此方法。
为了让读者真正的学习交叉编译工具链的构建,下面将重点详细地介绍前两种构建ARM Linux交叉编译工具链的方法。
2.2.1 分步构建交叉编译链
分步构建,顾名思义就是一步一步地建立交叉编译链,不同于2.2.2节中讲述的Crosstool脚本工具一次编译生成的方法,该方法适合那些希望深入学习了解构建交叉编译工具链的读者。该方法相对来说难度较大,通常情况下困难重重,犹如唐僧西天取经,不过本文会尽可能详细地介绍构建的每一个步骤,读者完全可以根据本节的内容自己独立实践,构建自己的交叉工具链。该过程所需的时间较长,希望读者有较强的耐心和毅力去学习和实践它,通过实践可以使读者更加清楚交叉编译器的构建过程以及各个工具包的作用。该方法所需资源如表2.1所示。
表2.1 所需资源
linux-2.6.10.tar.gz
ftp.kernel.org
glibc-2.3.2.tar.gz
ftp.gnu.org
binutils-2.15.tar.bz2
ftp.gnu.org
glibc-linuxthreads-2.3.2.tar.gz
ftp.gnu.org
gcc-3.3.6.tar.gz
ftp.gnu.org
通过相关站点下载以上资源后,就可以开始建立交叉编译工具链了。
1.建立工作目录
首先建立工作目录,工作目录就是在什么目录下构建交叉工具链,目录的构建一般没有特别的要求,可以根据个人喜好建立。以下所建立的目录是作者自定义的,当前的用户定义为mike,因此用户目录为/home/mike,在用户目录下首先建立一个工作目录(armlinux),建立工作目录的命令行操作如下:
# cd /home/mike
# mkdir armlinux
再在这个工作目录armlinux下建立3个目录 build-tools、kernel 和 tools。具体操作如下:
# cd armlinux
# mkdir build-tools kernel tools
其中各目录的作用如下。
&& ● build-tools 用来存放下载的binutils、gcc、glibc等源代码和用来编译这些源代码的目录;
&& ● kernel 用来存放内核源代码;
&& ● tools 用来存放编译好的交叉编译工具和库文件。
2.建立环境变量
该步骤的目的是为了方便重复输入路径,因为重复操作每件相同的事情总会让人觉得很麻烦,如果读者不习惯使用环境变量就可以略过该步,直接输入绝对路径就可以。声明以下环境变量的目的是在之后编译工具库的时候会用到,很方便输入,尤其是可以降低输错路径的风险。
# export PRJROOT=/home/mike/armlinux
# export TARGET=arm-linux
# export PREFIX=$PRJROOT/tools
# export TARGET_PREFIX=$PREFIX/$TARGET
# export PATH=$PREFIX/bin:$PATH
注意,用export声明的变量是临时的变量,也就是当注销或更换了控制台,这些环境变量就消失了,如果还需要使用这些环境变量就必须重复export操作,所以有时会很麻烦。值得庆幸的是,环境变量也可以定义在bashrc文件中,这样当注销或更换控制台时,这些变量就一直有效,就不用老是export这些变量了。
3.编译、安装Binutils
Binutils是GNU工具之一,它包括连接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具。安装Binutils工具包含的程序有addr2line、 ar、as、c++filt、gprof、ld、nm、objcopy、objdump、ranlib、readelf、size、strings、 strip、libiberty、libbfd和libopcodes。对这些程序的简单解释如下。
&& ● addr2line 把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号。
&& ● ar 建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。
&& ● as 主要用来编译GNU C编译器gcc输出的汇编文件,产生的目标文件由连接器ld连接。
&& ● c++filt 连接器使用它来过滤 C++ 和 Java 符号,防止重载函数冲突。
&& ● gprof 显示程序调用段的各种数据。
&& ● ld 是连接器,它把一些目标和归档文件结合在一起,重定位数据,并连接符号引用。通常,建立一个新编译程序的最后一步就是调用ld。
&& ● nm 列出目标文件中的符号。
&& ● objcopy 把一种目标文件中的内容复制到另一种类型的目标文件中。
&& ● objdump 显示一个或者更多目标文件的信息。使用选项来控制其显示的信息,它所显示的信息通常只有编写编译工具的人才感兴趣。
&& ● ranlib 产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。
&& ● readelf 显示elf格式可执行文件的信息。
&& ● size 列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个归档文件中的每个模块只产生一行输出。
&& ● strings 打印某个文件的可打印字符串,这些字符串最少4个字符长,也可以使用选项-n设置字符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对于其他类型的文件它打印整个文件的可打印字符。这个程序对于了解非文本文件的内容很有帮助。
&& ● strip 丢弃目标文件中的全部或者特定符号。
&& ● libiberty 包含许多GNU程序都会用到的函数,这些程序有getopt、obstack、strerror、strtol和strtoul。
&& ● libbfd 二进制文件描述库。
&& ● libopcode 用来处理opcodes的库,在生成一些应用程序的时候也会用到它。
Binutils工具安装依赖于Bash、Coreutils、Diffutils、GCC、Gettext、Glibc、Grep、Make、Perl、Sed、Texinfo等工具。
介绍完Binutils工具后,下面将分步介绍安装binutils-2.15的过程。
首先解压binutils-2.15.tar.bz2包,命令如下:
# cd $PRJROOT/build-tools
# tar –xjvf binutils-2.15.tar.bz2
接着配置Binutils工具,建议建立一个新的目录用来存放配置和编译文件,这样可以使源文件和编译文件独立开,具体操作如下:
# cd $PRJROOT/build-tools
# mkdir build-binutils
# cd build-binutils
# ../ binutils-2.15/configure --target=$TARGET --prefix=$PREFIX
其中选项–target的意思是制定生成的是 arm-linux 的工具,--prefix 是指出可执行文件安装的位置。执行上述操作会出现很多check信息,最后产生 Makefile 文件。接下来执行make和安装操作,命令如下:
# make install
该编译过程较慢,需要数十分钟,安装完成后查看/home/mike/armlinux/tools/bin目录下的文件,如果查看结果如下,表明此时Binutils工具已经安装结束。
# ls $PREFIX/bin
arm-linux-addr2line&& arm-linux-ld&&&&&&& arm-linux-ranlib&&& arm-linux-strip
arm-linux-ar&&&&&& &&&&& arm-linux-nm&&&&&& arm-linux-readelf
arm-linux-as&&&&&& &&&&& arm-linux-objcopy arm-linux-size
arm-linux-c++filt&&& &&& arm-linux-objdump arm-linux-strings
4.获得内核头文件
编译器需要通过系统内核的头文件来获得目标平台所支持的系统函数调用所需要的信息。对于Linux内核,最好的方法是下载一个合适的内核,然后复制获得头文件。需要对内核做一个基本的配置来生成正确的头文件;不过,不需要编译内核。对于本例中的目标arm-linux,需要以下步骤。
(1)在kernel目录下解压linux-2.6.10.tar.gz内核包,执行命令如下:
# cd $PRJROOT/kernel
# tar –xvzf linux-2.6.10.tar.gz
(2)接下来配置编译内核使其生成正确的头文件,执行命令如下:
# cd linux-2.6.10
# make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
其中ARCH=arm表示是以 arm为体系结构,CROSS_COMPILE=arm-linux-表示是以arm-linux-为前缀的交叉编译器。也可以用config和 xconfig来代替menuconfig,推荐用make menuconfig,这也是内核开发人员用的最多的配置方法。注意在配置时一定要选择处理器的类型,这里选择三星的S3C2410(System Type-&ARM System Type-&/Samsung S3C2410),如图2.1所示。配置完退出并保存,检查一下内核目录中的include/linux/version.h和 include/linux/autoconf.h文件是不是生成了,这是编译glibc时要用到的,如果version.h 和 autoconf.h 文件存在,说明生成了正确的头文件。
图2.1 Linux 2.6.10内核配置界面
复制头文件到交叉编译工具链的目录,首先需要在/home/mike/armlinux/tools/arm-linux目录下建立工具的头文件目录inlcude,然后复制内核头文件到此目录下,具体操作如下:
# mkdir –p $TARGET_PREFIX/include
# cp –r $PRJROOT/kernel/linux-2.6.10/include/linux $TARGET_PREFIX/include
# cp –r $PRJROOT/kernel/linux-2.6.10/include/asm-arm $TARGET_PREFIX/include/asm
5.编译安装boot-trap gcc
这一步的目的主要是建立arm- linux-gcc工具,注意这个gcc没有glibc库的支持,所以只能用于编译内核、BootLoader等不需要C库支持的程序,后面创建C库也要用到这个编译器,所以创建它主要是为创建C库做准备,如果只想编译内核和BootLoader,那么安装完这个就可以到此结束。安装命令如下:
# cd $PRJROOT/build-tools
# tar –xvzf gcc-3.3.6.tar.gz
# mkdir build-gcc&&&&
# cd gcc-3.3.6
# vi gcc/config/arm/t-linux
由于是第一次安装ARM交叉编译工具,没有支持libc库的头文件,所以在gcc/config/arm/t- linux文件中给变量TARGET_LIBGCC2_CFLAGS增加操作参数选项-Dinhibit_libc -D__gthr_ posix_h来屏蔽使用头文件,否则一般默认会使用/usr/inlcude头文件。
将TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer –fPIC改为TARGET_LIBGCC2- CFLAGS=-fomit-frame-pointer–fPIC -Dinhibit_libc -D__gthr_posix_h
修改完t-linux文件后保存,紧接着执行配置操作,如下命令:
# cd build-gcc
# ../ build-gcc /configure --target=$TARGET --prefix=$PREFIX --enable-languages=c
--disable-threads --disable-shared
其中选项--enable-languages=c表示只支持C语言,--disable-threads表示去掉thread功能,这个功能需要glibc的支持。--disable-shared表示只进行静态库编译,不支持共享库编译。
接下来执行编译和安装操作,命令如下:
# make install
安装完成后,在/home/mike/armlinux/tools/bin下查看,如果arm-linux-gcc等工具已经生成,表示boot-trap gcc工具已经安装成功
6.建立glibc库
glibc是GUN C库,它是编译Linux系统程序很重要的组成部分。安装glibc-2.3.2版本之前推荐先安装以下的工具:
&& ● GNU make 3.79或更新;
&& ● GCC 3.2或更新;
&& ● GNU binutils 2.13或更新。
首先解压glibc-2.2.3.tar.gz和glibc-linuxthreads-2.2.3.tar.gz源代码,操作如下:
# cd $PRJROOT/build-tools
# tar -xvzf glibc-2.2.3.tar.gz
# tar -xzvf glibc-linuxthreads-2.2.3.tar.gz --directory=glibc-2.2.3
然后进行编译配置,glibc-2.2.3配置前必须新建一个编译目录,否则在glibc-2.2.3目录下不允许进行配置操作,此处在$PRJROOT/build-tools目录下建立名为build-glibc的目录,配置操作&&& 如下:
# cd $PRJROOT/build-tools
# mkdir build-glibc
# cd build-glibc
# CC=arm-linux-gcc ../glibc-2.2.3 /configure --host=$TARGET --prefix="/usr"
--enable-add-ons --with-headers=$TARGET_PREFIX/include
选项CC=arm-linux- gcc是把CC(Cross Compiler)变量设成刚编译完的gcc,用它来编译glibc。--prefix="/usr"定义了一个目录用于安装一些与目标机器无关的数据文件,默认情况下是/usr/local目录。--enable-add-ons是告诉glibc用linuxthreads包,在上面已经将它放入 glibc源代码目录中,这个选项等价于-enable-add-ons=linuxthreads。--with-headers告诉glibc linux内核头文件的目录&&& 位置。
配置完后就可以编译和安装 glibc了,具体操作如下:
# make install
7.编译安装完整的gcc
由于第一次安装的gcc没有交叉glibc的支持,现在已经安装了glibc,所以需要重新编译来支持交叉glibc。并且上面的gcc也只支持C语言,现在可以让它同时支持C语言还要和C++语言。具体操作如下:
# cd $PRJROOT/build-tools/gcc-2.3.6
# ./configure --target=arm-linux --enable-languages=c,c++ --prefix=$PREFIX
# make install
安装完成后会发现在$PREFIX/bin目录下又多了arm-linux-g++ 、arm-linux-c++等文件。
# ls $PREFIX/bin
arm-linux-addr2line arm-linux-g77 &&&&& arm-linux-gnatbind arm-linux-ranlib
arm-linux-ar&&&&&& arm-linux-gcc&&&&&& arm-linux-jcf-dump arm-linux-readelf
arm-linux-as&&&&&& arm-linux-gcc-3.3.6 arm-linux-jv-scan arm-linux-size
arm-linux-c++&&&& && arm-linux-gccbug&& arm-linux-ld&&&&& && arm-linux-strings
arm-linux-c++filt arm-linux-gcj&&&&&& arm-linux-nm&&&&& && arm-linux-strip
arm-linux-cpp&&&&& arm-linux-gcjh&&&&& arm-linux-objcopy grepjar
arm-linux-g++&&& &&& arm-linux-gcov&&&& arm-linux-objdump jar
8.测试交叉编译工具链
到此为止,已经介绍完了用分步构建的方法建立交叉编译工具链。下面通过一个简单的程序测试刚刚建立的交叉编译工具链看是否能够正常工作。写一个最简单的hello.c源文件,内容如下:
#i nclude &stdio.h&
int main( )
&&&& printf(“Hello,world!\n”);
&&&& return 0;
通过以下命令进行编译,编译后生成名为hello的可执行文件,通过file命令可以查看文件的类型。当显示以下信息时表明交叉工具链正常安装了,通过编译生成了ARM体系可执行的文件。注意,通过该交叉编译链编译的可执行文件只能在ARM体系下执行,不能在基于X86的普通PC上执行。
# arm-linux-gcc –o hello hello.c
# file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.4.3,
dynamically linked (uses shared libs), not stripped
2.2.2 用Crosstool工具构建交叉工具链
Crosstool是一组脚本工具集,可构建和测试不同版本的gcc和glibc,用于那些支持glibc的体系结构。它也是一个开源项目,下载地址是http: ///crosstool。用Crosstool构建交叉工具链要比上述的分步编译容易得多,并且也方便许多,对于仅仅为了工作需要构建交叉编译工具链的读者建议使用此方法。用Crosstool工具构建所需资源如表2.2所示。
表2.2 所需资源
crosstool-0.42.tar.gz
/crosstool
linux-2.6.10.tar.gz
ftp.kernel.org
binutils-2.15.tar.bz2
ftp.gnu.org
gcc-3.3.6.tar.gz
glibc-2.3.2.tar.gz
glibc-linuxthreads-2.3.2.tar.gz
linux-libc-headers-2.6.12.0.tar.bz2
1.准备资源文件
首先从网上下载所需资源文件 linux-2.6.10.tar.gz、binutils-2.15.tar.bz2、gcc-3.3.6.tar.gz、glibc- 2.3.2.tar.gz、glibc-linuxthreads-2.3.2.tar.gz和linux-libc-headers- 2.6.12.0.tar.bz2。然后将这些工具包文件放在新建的/home/mike/downloads目录下,最后在/home/mike目录下解压crosstool-0.42.tar.gz,命令如下:
# cd /home/mike
# tar –xvzf crosstool-0.42.tar.gz
2.建立脚本文件
接着需要建立自己的编译脚本,起名为arm.sh,为了简化编写arm.sh,寻找一个最接近的脚本文件demo-arm.sh作为模板,然后将该脚本的内容复制到arm.sh,修改arm.sh脚本,具体操作如下:
# cd crosstool-0.42
# cp demo-arm.sh arm.sh
# vi arm.sh
修改后的arm.sh脚本内容如下:
TARBALLS_DIR=/home/mike/downloads # 定义工具链源码所存放位置。
RESULT_TOP=/opt/crosstool&&&&&&& &&& # 定义工具链的安装目录
export TARBALLS_DIR RESULT_TOP
GCC_LANGUAGES="c,c++"&&&& &&&&&&&&&& # 定义支持C, C++语言
export GCC_LANGUAGES
# 创建/opt/crosstool目录
mkdir -p $RESULT_TOP
# 编译工具链,该过程需要数小时完成。
eval 'cat arm.dat gcc-3.3.6-glibc-2.3.2.dat' sh all.sh --notest
echo Done.
3.建立配置文件
在arm.sh脚本文件中需要注意arm.dat和gcc-3.3.6-glibc-2.3.2.dat两个文件,这两个文件是作为Crosstool的编译的配置文件。其中 arm.dat文件内容如下,主要用于定义配置文件、定义生成编译工具链的名称以及定义编译选项等。
KERNELCONFIG='pwd'/arm.config # 内核的配置
TARGET=arm-linux-&&& &&&&&&&&&&& # 编译生成的工具链名称
TARGET_CFLAGS="-O"&&&&&&&&&&& &&& # 编译选项
gcc-3.3.6-glibc-2.3.2.dat文件内容如下,该文件主要定义编译过程中所需要的库以及它定义的版本,如果在编译过程中发现有些库不存在时,Crosstool会自动在相关网站上下载,该工具在这点上相对比较智能,也非常有用。
BINUTILS_DIR=binutils-2.15
GCC_DIR=gcc-3.3.6
GLIBC_DIR=glibc-2.3.2
GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.2
LINUX_DIR=linux-2.6.10
LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0
4.执行脚本
将Crosstool的脚本文件和配置文件准备好之后,开始执行arm.sh脚本来编译交叉编译工具。具体执行命令如下:
# cd crosstool-0.42
# ./arm.sh
经过数小时的漫长编译之后,会在/opt/crosstool目录下生成新的交叉编译工具,其中包括以下内容:
arm-linux-addr2line arm-linux-g++&&&& && arm-linux-ld&&&&& && arm-linux-size
arm-linux-ar&&&&&& arm-linux-gcc&&&&& arm-linux-nm&&&&& && arm-linux-strings
arm-linux-as&&&&&& arm-linux-gcc-3.3.6 arm-linux-objcopy arm-linux-strip
arm-linux-c++&&&&& arm-linux-gccbug arm-linux-objdump fix-embedded-paths
arm-linux-c++filt arm-linux-gcov&&&& arm-linux-ranlib
arm-linux-cpp&&&&& arm-linux-gprof&&& arm-linux-readelf
5.添加环境变量
然后将生成的编译工具链路径添加到环境变量PATH上去,添加的方法是在系统/etc/ bashrc文件的最后添加下面一行,如图2.2所示。
图2.2 用Vi编辑器在bashrc文件中添加环境变量
export PATH=/opt/crosstool/gcc-3.3.6-glibc-2.3.2/arm-linux/bin:$PATH
设置完环境变量,也就意味着交叉编译工具链已经构建完成,然后就可以用2.2.1.8节中的方法进行测试刚刚建立的工具链,此处就不用再赘述
TA的最新馆藏[转]&[转]&
喜欢该文的人也喜欢Linux ARM交叉编译工具链制作过程 - qtzsq84c - ITeye博客
博客分类:
Linux ARM交叉编译工具链制作过程

  一、下载源文件 源代码文件及其版本与下载地址:
  Binutils-2.19.tar.bz2 gcc-4.4.4.tar.bz2 Glibc-2.11.2.tar.bz2 Glibc-ports-2.11.tar.bz2 Gmp-4.2.tar.bz2 Mpfr-2.4.0.tar.bz2 Linux-2.6.29.tar.bz2 Patch-2.6.29.bz2&& 一般一个完整的交叉编译器涉及到多个软件,主要包括binutils、gcc、glibc等。其中,binutils主要生成一些辅助工具;gcc是用来生成交叉编译器,主要生成arm-linux-gcc交叉编译工具,而glibc主要提供用户程序所需要的一些基本函数库。 二、建立工作目录
  编译所用主机型号 FC12.i686
  第一次编译时用的是root用户(第二次用一般用户karen,该用户可以使用sudo指令)
  所有的工作目录都在/home/Karen/cross下面建立完成,首先在/home/karen目录下建立cross目录& [root@localhost& karen] mkdir cross 进入工作目录:
  [root@localhost& root]#cd /home/karen/cross&&&&&&&&&&&
  查看当前目录:
  [root@localhost& cross ]# pwd&
  /home/karen/cross&
  创建工具链文件夹: [root@localhost& cross]# mkdir embedded-toolchains 在建立了顶层文件夹embedded- toolchains,下面在此文件夹下建立如下几个目录:
  ??& setup-dir,存放下载的压缩包;
  ??& src-dir,存放binutils、gcc、glibc解压之后的源文件;
  ??& kernel,存放内核文件,对内核的配置和编译工作也在此完成;
  ??& build-dir ,编译src-dir下面的源文件,这是GNU推荐的源文件目录与编译目录分离的做法;
  ??& tool-chain,交叉编译工具链的安装位;
  ??& program,存放编写程序;
  ??& doc,说明文档和脚本文件;
  下面建立目录,并拷贝源文件。
  [root@localhost& cross] #cd embedded- toolchains
  [root@localhost& embedded- toolchains] #mkdir setup-dir src-dir kernel build-dir tool-chain program doc
  [root@localhost& embedded- toolchains] #ls
  build-dir doc kernel program setup-dir src-dir tool-chain
  [root@localhost& embedded- toolchains] #cd setup-dir
  拷贝源文件:
  这里我们采用直接拷贝源文件的方法,首先应该修改setup-dir的权限
  [root@localhost& embedded- toolchains] #chmod 777 setup-dir 然后直接拷贝/home/karen目录下的源文件到setup-dir目录中,如下图:
  
  建立编译目录:
  [root@localhost& setup-dir] #cd ../build-dir
  [root@localhost& build -dir] #mkdir build-binutils build-gcc build-glibc
  三、输出环境变量 输出如下的环境变量方便我们编译。
  为简化操作过程。下面就建立shell命令脚本environment-variables:
  [root@localhost& build -dir] #cd ../doc
  [root@localhost& doc] #mkdir scripts
  [root@localhost& doc] #cd scripts
  用编辑器vi编辑环境变量脚本envionment-variables:
  [root@localhost& scripts] #vi envionment-variables&&
  export& PRJROOT=/home/mxl/diliuzhang/embedded- toolchains
  export& TARGET=arm-linux
  export& PREFIX=$PRJROOT/tool-chain
  export& TARGET_PREFIX=$PREFIX/$TARGET
  export& PATH=$PREFIX/bin:$PATH
  截图如下:
  
  %% Q:为什么用了source ./environment-variables才正常执行,去掉source就没有执行? %%
  %%& 如果用source 执行,不需要脚本有执行权限,权限为664也可以,执行命令如下:%%
  %%& Source environment-variables %%
  说明: TARGET变量用来定义目标板的类型,以后会根据此目标板的类型来建立工具链。参
  看表6-1所示。目标板的定义与主机的类型是没有关系的,但是如果更改TARGET的值,
  GNU工具链必须重新建立一次。
  PREFIX变量提供了指针,指向目标板工具程序将被安装的目录。
  TARGET_PREFIX变量指向与目标板相关的头文件和链接库将被安装的目录。
  PATH变量指向二进制文件(可执行文件)将被安装的目录。
  如果不惯用环境变量的,可以直接用绝对或相对路径。如果不用环境变量,一般都用绝对路径,相对路径有时会失败。环境变量也可以定义在.bashrc文件中,这样就不用老是export这些变量了。
  体系结构和TAEGET变量的对应如下表6-1所示:
  表6-1 体系结构和TAEGET变量的对应 四、建立二进制工具(binutils) Binutils是GNU工具之一,它包括连接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具。安装Binutils工具包含的程序有addr2line、ar、as、c++filt、gprof、ld、nm、objcopy、objdump、ranlib、readelf、size、strings、strip、libiberty、libbfd和libopcodes。对这些程序的简单解释如下。
  ??& addr2line& 把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号。
  ??& ar& 建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。
  ??& as& 主要用来编译GNU C编译器gcc输出的汇编文件,产生的目标文件由连接器ld连接。
  ??& c++filt& 连接器使用它来过滤 C++ 和 Java 符号,防止重载函数冲突。
  ??& gprof& 显示程序调用段的各种数据。
  ??& ld& 是连接器,它把一些目标和归档文件结合在一起,重定位数据,并连接符号引用。通常,建立一个新编译程序的最后一步就是调用ld。
  ??& nm& 列出目标文件中的符号。
  ??& objcopy& 把一种目标文件中的内容复制到另一种类型的目标文件中。
  ??& objdump& 显示一个或者更多目标文件的信息。使用选项来控制其显示的信息,它所显示的信息通常只有编写编译工具的人才感兴趣。
  ??& ranlib& 产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。
  ??& readelf& 显示elf格式可执行文件的信息。
  ??& size& 列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个归档文件中的每个模块只产生一行输出。
  ??& strings& 打印某个文件的可打印字符串,这些字符串最少4个字符长,也可以使用选项-n设置字符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对于其它类型的文件它打印整个文件的可打印字符。这个程序对于了解非文本文件的内容很有帮助。
  ??& strip& 丢弃目标文件中的全部或者特定符号。
  ??& libiberty& 包含许多GNU程序都会用到的函数,这些程序有getopt、obstack、strerror、strtol和strtoul。
  ??& libbfd& 二进制文件描述库。
  ??& libopcode& 用来处理opcodes的库,在生成一些应用程序的时候也会用到它。
  Binutils工具安装依赖于Bash、Coreutils、Diffutils、GCC、Gettext、Glibc、Grep、Make、Perl、Sed、Texinfo等工具
  下面将分步介绍安装binutils-2.19.2的过程。
  [root@localhost& script] # cd $PRJROOT/src-dir
  [root@localhost& src-dir] # tar jxvf ../setup-dir/binutils-2.19.tar.bz2
  [root@localhost& src-dir] # cd $PRJROOT/build-dir/build-binutils
  创建Makefile:
  [root@localhost& build-binutils] #../../src-dir/binutils-2.19/configure --target=$TARGET --prefix=$PREFIX&&& 在build-binutils目录下面生成Makefile文件,然后执行make,make install。完成后可以在$PREFIX/bin下面看到我们的新的binutil。
  注意:每个工具的文件名的前缀都是前面为TARGET变量设定的值。如果目标板arm-linux,那么这些工具的文件名前缀就会是arm-linux-。这样就可以根据目标板类型找到正确的工具程序。
  
  五、建立内核头文件 在这里我们使用时2.6.29的内核版本,因为交叉工具链工具链是针对特定的处理器和操作系统的,因此在编译之前就需要对linux内核进行配制,可以通过"make config"或"make menuconfig"命令对内核进行配制,配制完成后,在linux源文件的目录下就会生成一个.config文件,这就是我们所需要的文件。
  Note:目标板的内核版本是2.6.29
  [root@localhost& embedded- toolchains] #cd kernel [root@localhost& kernel] #tar jxvf ../setup-dir/ linux-2.6.29.tar.bz2&&&&&&&&&&&&&&&&
  [root@localhost& kernel] #bunzip2 ../setup-dir/ patch-2.6.29.bz2&
  [root@localhost& kernel] #cd linux-2.6.29
  给Linux内核打补丁: [root@localhost& linux-2.6.29] #patch& p1& C库支持的程序,后面创建C库也要用到这个编译器,所以创建它主要是为创建C库做准备,如果只想编译内核和BootLoader,那么安装完这个就可以到此结束。安装过程如下:
  [root@localhost& build-binutils] #cd $PRJROOT/setup-dir
  重命名:
  [root@localhost& setup-dir] #mv gcc-core-4.4.4.tar.bz2& gcc-4.4.4.tar.bz2&
  [root@localhost& setup-dir] #cd $PRJROOT/src-dir
  [root@localhost& src-dir] #tar jxvf ../setup-dir/gcc-4.4.4.tar.bz2
  从 GCC-4.3起,安装GCC将依赖于GMP-4.1以上版本和MPFR-2.3.2以上版本。如果将这两个软件包分别解压到GCC源码树的根目录下,并分别命名为"gmp"和"mpfr",那么GCC的编译程序将自动将两者与GCC一起编译。建议尽可能使用最新的GMP和MPFR版本。
  [root@localhost src-dir]# tar jxvf ../setup-dir/mpfr-2.4.0.tar.bz2
  [root@localhost src-dir]# tar jxvf ../setup-dir/gmp-4.2.tar.bz2
  [root@localhost src-dir]# mv mpfr-2.4.0 gcc-4.4.4/mpfr
  [root@localhost src-dir]# mv gmp-4.2.0 gcc-4.4.4/gmp
  ??因为是交叉编译器,还不需要目标板的系统头文件,所以需要使用 --without-headers这个选项。否则会有很多*.h头文件找不到的报错
  ??--enable-language=c用来告诉配置脚本,需要产生的编译器支持何种语言,现在只需支持C语言。虽然配置为c,c++也可以的
  ??--disable-threads 是因为threads需要libc的支持。
  ??--disable-decimal-float,需要libc的支持,而我们在初步编译的时候尚未生成libc,否则出现以下的报错:
  ../../../gcc-4.3.1/libgcc/config/libbid/bid_decima l_globals.c:52:18: error: fenv.h: No such file or directory
  ../../../gcc-4.3.1/libgcc/config/libbid/bid_decima l_globals.c: In function '__dfp_test_except':
  ../../../gcc-4.3.1/libgcc/config/libbid/bid_decima l_globals.c:64: error: 'FE_INEXACT' undeclared (first use in this function)
  ../../../gcc-4.3.1/libgcc/config/libbid/bid_decima l_globals.c:64: error: (Each undeclared identifier is reported only once
  ../../../gcc-4.3.1/libgcc/config/libbid/bid_decima l_globals.c:64: error: for each function it appears in.)
  ??--disable-shared,既然是第一次安装ARM交叉编译工具,那么本机的glibc支持的应该是本机的编译工具库,而不是ARM交叉编译工具库。forces GCC to link its internal libraries statically,没有这个选项,会有 crti.o: No such file: No such file or directory collect2: ld returned 1 exit status
  注:由于没有arm的glibc,需要使用--disable-libmudflap --disable-libssp,禁止两个边界检查使用的库。
  同样,由于第一次安装ARM交叉编译工具,那么支持的libc库的头文件也没有,src-dir/gcc-4.4.4/gcc/config/arm/t-linux文件,在TARGET_LIBGCC2_CFLAGS中添加两个定义:-Dinhibit_libc&& D__gthr_posix_h
  原文:
  TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer& fPIC
  改后:
  TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D_gthr_posix.h
  编译:
  [root@localhost& src-dir] #cd $PRJROOT/build-dir/build-gcc
  [root@localhost build-gcc]# ../../src-dir/gcc-4.4.4/configure --target=$TARGET --prefix=$PREFIX --without-headers --enable-languages=c --disable-shared --disable-threads --disable-decimal-float& disable-libmudflap& disable-lipssp
  [root@localhost build-gcc]# make all-gcc
  [root@localhost build-gcc]# make install-gcc
  [root@localhost build-gcc]# make all-target-libgcc
  [root@localhost build-gcc]# make install-target-libgcc 注:很多资料中之有前面两项,这只建立了gcc,没有建立libgcc.a,这样会在glibc的编译中出现-lgcc没有找到的错误。报告:
  ……/build-tools/build-glibc/libc_pic.a
  i586-linux-gcc&& -nostdlib -nostartfiles -r -o /home/wei/workspace/mywork/moblin/build-tools/buil d-glibc/elf/librtld.map.o '-Wl,-(' /home/wei/workspace/mywork/moblin/build-tools/buil d-glibc/elf/dl-allobjs.os /home/wei/workspace/mywork/moblin/build-tools/buil d-glibc/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/home/wei/workspace/mywork/moblin/build-t ools/build-glibc/elf/librtld.mapT
  /workspace/wei/mywork/moblin/tools/bin/../lib/gcc/ arm-linux/4.4.4/../../../../ram-linux/bin/ld: cannot find -lgcc
  在glibc的编译中,还需要libgcc_eh.a(否则出现错误:-lgcc_eh没有找到……bin/ld: cannot find -lgcc_eh),使用了--disable-shared的选项,将不会生成libgcc_eh.a,可以通过对libgcc.a的链接来实现。
  [root@localhost build-gcc]# ln -vs libgcc.a `arm-linux-gcc -print-libgcc-file-name | sed 's/libgcc/&_eh/'`
  Note:arm-linux-gcc与-print-libgcc-file-name之间有一个空格&
  运行报告:
  "/workspace/wei/mywork/moblin/tools/bin/../lib/gcc/ i586-linux/4.3.3/libgcc_eh.a" -& "libgcc.a" 装完成后,查看结果: [root@localhost& build-gcc] #ls $PREFIX/bin&&
  
  如果arm-linux-gcc等工具已经生成,表示boot trap gcc工具已经安装成功 七、编译glibc
  这一步是最为繁琐的过程,目标板必须靠它来执行或者是开发大部分的应用程序。glibc套件常被称为C链接库,但是glibc实际产生很多链接库,其中之一是C链接库libc。因为嵌入式系统的限制,标准GNU C链接库显得太大,不适合应用在目标板上。所以需要寻找C链接库的替代品,在这里现以标准GNU C为例建立工具链。 [root@localhost& build-gcc] #cd $PRJROOT/src-dir
  [root@localhost& src-dir] # tar jxvf ../setup-dir/glibc-2.11.2.tar.bz2
  [root@localhost& src-dir] # tar jxvf ../setup-dir/glibc-ports-2.11.tar.bz2 [root@localhost& src-dir] # mv& v glibc-ports-2.11 glibc-2.11.2/ports [root@localhost& src-dir] # cd glibc-2.11.2 [root@localhost& glibc-2.11.2] # patch& Np1& i ../../setup-dir/glibc-2.11.2-gcc_fix-1.patch [root@localhost& glibc-2.11.2] # patch& Np1& i ../../setup-dir/glibc-2.11.2-makefile_fix-1.patch& [root@localhost& glibc-2.11.2] # cd $PRJROOT/build-dir/build-glibc [root@localhost build-glibc] # CC=arm-linux-gcc AR=arm-linux-ar RANLIB=arm-linux-ranlib \
  ../../src-dir/glibc-2.11.2/configure \
  --host=arm-linux \
  --prefix=$PREFIX/$TARGET \ --with-tls --disable-profile \
  --enable-add-ons \ --with-headers=$PREFIX/$TARGET/include \
  libc_cv_forced_unwind=yes \
  libc_cv_c_cleanup=yes \ libc_cv_arm_tls=yes& [root@localhost build-glibc] # make& [root@localhost build-glibc] # make install&&& 注:以上完成后,请查看一下$TARGET_PREFIX/lib目录下的文件libc.so,看看GROUP的内容是否指定到可以用于交叉编译的库,如果不是请修改,如下。&&& libc.so 文件(所在目录是$TARGET_PREFIX/lib),将GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a)改为GROUP ( libc.so.6 libc_nonshared.a)
  这样连接程序 ld 就会在 libc.so 所在的目录查找它需要的库,因为你的机子的/lib目录可能已经装了一个相同名字的库,一个为编译可以在你的宿主机上运行的程序的库,而不是用于交叉编译的。 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%& 经过查看,发现libc.so中的GROUP已经是交叉编译链的目录,所以不用更改
  对 libc.so 的修正.
  vi $PREFIX /${TARGET}/lib/libc.so&
  去掉绝对路径,修改后的内容如下:
  /* GNU ld script&
  Use the shared library, but some functions are only in&
  the static library, so try that secondarily. */&
  OUTPUT_FORMAT(elf32-littlearm)&
  GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.3 ) )
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&
  八、建立全套编译器(full gcc)
  [root@localhost& build-gcc] #../../src-dir/gcc-4.4.4/configure --target=$TARGET --prefix=$PREFIX& --enable-languages=c,c++ --enable-shared
  [root@localhost& build-gcc] #make all
  [root@localhost& build-gcc] #make install
  
  下面编写一个简单的C程序,使用建立的工具链。、
  [root@localhost& bin] #cd $PRJROOT/program
  [root@localhost& program] #vi hello.c
  #include&
  int main(void)
  printf("hello linux\n");
  return 0;
  [root@localhost& program] #arm-linux-gcc hello.c -o hello& static (制作静态可执行文件)& 制作的可执行文件hello可以直接在目标机上运行。
浏览: 10366 次}

我要回帖

更多关于 win10如何打补丁 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信