如何构建linux mips交叉编译译工具链

一、下载源文件
源代码文件及其版本与下载地址:
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,下面在此文件夹下建立如下几个目录:
&O&&setup-dir,存放下载的压缩包;
&O&&src-dir,存放binutils、gcc、glibc解压之后的源文件;
&O&&kernel,存放内核文件,对内核的配置和编译工作也在此完成;
&O&&build-dir&,编译src-dir下面的源文件,这是GNU推荐的源文件目录与编译目录分离的做法;
&O&&tool-chain,交叉编译工具链的安装位;
&O&&program,存放编写程序;
&O&&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] #lsbuild-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- toolchainsexport&&TARGET=arm-linuxexport&&PREFIX=$PRJROOT/tool-chainexport&&TARGET_PREFIX=$PREFIX/$TARGETexport&&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变量的对应
TARGET变量的值
Powerpc-linux
MIPS(big endian)
mips-linux
MIPS(little endian)
mipsel-linux
mips64-linux
i386-linux
ia64-linux
m68k-linux
m88k-linux
alpha-linux
sparc-linux
sparc64-linux
四、建立二进制工具(binutils)
Binutils是GNU工具之一,它包括连接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具。安装Binutils工具包含的程序有addr2line、ar、as、c++filt、gprof、ld、nm、objcopy、objdump、ranlib、readelf、size、strings、strip、libiberty、libbfd和libopcodes。对这些程序的简单解释如下。
&O&&addr2line&&把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号。
&O&&ar&&建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。
&O&&as&&主要用来编译GNU C编译器gcc输出的汇编文件,产生的目标文件由连接器ld连接。
&O&&c++filt&&连接器使用它来过滤&C++&和&Java&符号,防止重载函数冲突。
&O&&gprof&&显示程序调用段的各种数据。
&O&&ld&&是连接器,它把一些目标和归档文件结合在一起,重定位数据,并连接符号引用。通常,建立一个新编译程序的最后一步就是调用ld。
&O&&nm&&列出目标文件中的符号。
&O&&objcopy&&把一种目标文件中的内容复制到另一种类型的目标文件中。
&O&&objdump&&显示一个或者更多目标文件的信息。使用选项来控制其显示的信息,它所显示的信息通常只有编写编译工具的人才感兴趣。
&O&&ranlib&&产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。
&O&&readelf&&显示elf格式可执行文件的信息。
&O&&size&&列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个归档文件中的每个模块只产生一行输出。
&O&&strings&&打印某个文件的可打印字符串,这些字符串最少4个字符长,也可以使用选项-n设置字符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对于其它类型的文件它打印整个文件的可打印字符。这个程序对于了解非文本文件的内容很有帮助。
&O&&strip&&丢弃目标文件中的全部或者特定符号。
&O&&libiberty&&包含许多GNU程序都会用到的函数,这些程序有getopt、obstack、strerror、strtol和strtoul。
&O&&libbfd&&二进制文件描述库。
&O&&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&&&&&/setup-dir/patch-2.6.29
然后就是配置内核,第一步是修改Makefile
修改&Makefile:
ARCH = arm&&&&&&&&&&&&&&&&&&&&&&&&&
CROSS_COMPILE = arm-linux- menuconfig&&
接着使用make menuconfig进入内核配置菜单
或者直接写:
# make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig&,注意在配置时一定要选择处理器的类型,比如我的目标机使用的处理器是OMAP类型的,就选TI OMAP:
System Type -&
&&&&&&&&&ARM System Type -&
&&&&&&&&&(x) TI OMAP
配置完退出并保存。
配置完须执行make,参数如下:
[root@localhost linux-2.6.29]# make ARCH=arm CROSS_COMPILE=arm-linux-&(执行过程中有错误出现也没关系,主要目的是产生头文件version.h和autoconf.h)
执行完检查一下内核目录中的/kernel/linux-2.6.29/include/linux/version.h和autoconf.h文件是不是生成了,这是编译glibc要用到的。version.h&和&autoconf.h&文件的存在,说明你生成了正确的头文件。
接下来建立工具链需要的include目录,并将内核头文件复制过去。[root@localhost&&linux-2.6.29] #cd include[root@localhost&&include] #ln -s asm-arm asm
可以查看一下,经过编译可以自动生成。如果已经生成链接,则不必重新链接。(2.6.29已自动生成)[root@localhost&&include] #cd asm[root@localhost&&asm] #ln -s arch-epxa arch&&
[root@localhost&&asm] #ln -s proc-armv proc
可以查看一下,经过编译可以自动生成。如果已经生成链接,则不必重新链接。
复制头文件到交叉编译工具链的安装目录:
[root@localhost&&asm] #mkdir &p $TARGET_PREFIX/include[root@localhost&asm] #cp &r $PRJROOT/kernel/linux-2.6.29/include/linux $TARGET_PREFIX/include[root@localhost&&asm] #cp &r $PRJROOT/ kernel /linux-2.6.29/include/asm-arm $TARGET_PREFIX/include/asm
[root@localhost&&asm] #cp &r $PRJROOT/ kernel /linux-2.6.29/include/asm-generic $TARGET_PREFIX/include
root@localhost&&asm] #cp &r $PRJROOT/ kernel /linux-2.6.29/arch/arm/include/asm&&$TARGET_PREFIX/include
root@localhost&&asm] #cp &r $PRJROOT/ kernel /linux-2.6.29/arch/arm/mach-omap2/include/mach $TARGET_PREFIX/include/asm
Note: mach-xxx是根据目标板所用的cpu类型来选择的
六、建立初始编译器&(boot strap gcc)
这一步的目的主要是建立arm-linux-gcc工具,注意这个gcc没有glibc库的支持,所以只能用于编译内核、BootLoader等不需要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_decimal_globals.c:52:18: error: fenv.h: No such file or directory
/../gcc-4.3.1/libgcc/config/libbid/bid_decimal_globals.c: In function '__dfp_test_except':
/../gcc-4.3.1/libgcc/config/libbid/bid_decimal_globals.c:64: error: 'FE_INEXACT' undeclared (first use in this function)
/../gcc-4.3.1/libgcc/config/libbid/bid_decimal_globals.c:64: error: (Each undeclared identifier is reported only once
/../gcc-4.3.1/libgcc/config/libbid/bid_decimal_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/build-glibc/elf/librtld.map.o '-Wl,-(' /home/wei/workspace/mywork/moblin/build-tools/build-glibc/elf/dl-allobjs.os /home/wei/workspace/mywork/moblin/build-tools/build-glibc/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/home/wei/workspace/mywork/moblin/build-tools/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
我们再来看看&$PREFIX/bin&里面多了哪些东西。你会发现多了&arm-linux-g++&、和&arm-linux-c++&几个文件。
G++-gnu的&c++&编译器。
C++-gnu&的&c++&编译器。
至此,整个交叉编译环境就建立完成了。
&九、完成工具链的设置
&root@localhost&&build-gcc] #&cd $TARGET_PREFIX/bin
查看文件是否为二进制文件:[root@localhost&&bin] #&file as ar gcc ld nm ranlib strip& &
查看缺省的搜寻路径:[root@localhost&&bin] #arm-linux-gcc -print-search-dirs&&
&&十、测试和验证交叉编译工具
&&&&下面编写一个简单的C程序,使用建立的工具链。、[root@localhost&&bin] #cd $PRJROOT/program[root@localhost&&program] #vi hello.c#include &stdio.h&
int main(void)
&&&&&&&&&&&printf("hello linux/n");
&&&&&&&&&&&return 0;
[root@localhost&&program] #arm-linux-gcc hello.c -o hello &static&(制作静态可执行文件)
&制作的可执行文件hello可以直接在目标机上运行。
&&&&&&&&&&&& Karen
阅读(...) 评论()&&&&&&&&配置和编译一个合适的GNU工具链是相对复杂的并且需要很精细的操作,包括你需要对不同软件库之间的依赖关系、它们的各自的任务,不同软件库版本情况都有比较好的了解,编译工具链是一个乏味的工作。
2.制作之前需要了解的一些术语与名称
&&&&&&&& 1)build:你编译你的工具链时所使用的编译系统。
2)host:交叉编译工具链运行在的主机系统。
3)target:你的交叉编译工具链所生成的可执行文件所要运行的目标系统。
&&&&&&&在一些通用非嵌入式的使用,以上三个必须是一样的。但是大部分嵌入式开发中,build跟host是使用相同的机器(开发者的工作空间)。而target则是你所开发应用软件所要运行的嵌入式目标板。
&&&&&&&当我们需要使用GNU配置来为各种交叉工具链组件搭建软件和系统时,我们需要通过用GNU configuration files对build,host,target
系统进行命名,GNU configuration files的标准格式如下:
1)cpu-manufacturer-kernel-os(内核部分):这个是个可选选项,其中指明了3部分:
① cpu:系统的芯片架构。(习惯上在小端变体的架构名称额外加上el)。
② manufacturer:具体的制造商或者使用上述CPU的开发板家族。(这个对交叉编译工具链的影响很小,很多时候都直接指明为unknown 机器类型或者简单的省略机器描述)。
③ kernel:主要用于GNU/Linux 系统,甚至有时候在一些情况下为了简洁而忽略掉。
④ os :在系统上使用的操作系统(或ABI)名称。configuration将被用于描述所有种类的操作系统,包括没有运行任何操作系统的嵌入式系统,这种情况下这个区域用来指明工程文件格式,比如Elf或者COFF。
下面是两个简单的例子:
i386-pc-linux-gnu
APC-style x86 Linux system
powerpc-8540-linux-gnu
AFreescale 8540 PowerQuickIII Linux system
mips-unknown-linux
&&&&&&&&&& A big-endian MIPS Linux system from an unspecified manufacturer
mipsel-linux
&&&&&&& A little-endian MIPS Linux system from an unspecified manufacturer
xscale-unknown-linux
&&&&&&& An XScale (formely StrongARM) Linux system from an &&&&unspecifiedmanufacturer
&&&&&&&在很多典型情况下,交叉编译工具链的工具都是以目标三组合作为前缀的。比如,一个用于arm,linux系统的交叉编译工具将被命名为arm-linux-gnu-gcc(其中gcc是GNU编译系列的可执行文件名)。但是如果连接器是用于little-endian MIPS Linux系统将被命名为mipsel-linux-ld(ld是GNU链接器的可执行文件名)。
3.编译toolchain的成分要求
1)Linux kernelheaders
&&&&&&&C库是toolchain的一部分,封装了目前很多可用的API,编译这个库需要Linux kenel header files的一个子集用来描述内核API。
&&&&&&&理论上来说,toolchain使用的Linuxkernel headers来自的Linux内核版本要与用在目标板上的linux版本相一致。但是实际上,因为Linux kernel的ABI很少改变,使用不同版本但是相似的headers是司空见惯的事。
&&&&&&&&在2.6版本发行之前,C库编译是根据逐字的拷贝在linux内核目录include/asm-architecture和include/linux 的头文件。而到了linux2.6发布了,就不再支持上述方式了,因为内核头文件包含了太多代码所以不适合包含在用户应用空间,而且包含C库会容易中断用户程序的编译。取代这种方式的是:使用一个sanitized的Linux内核头文件版本,适合代替C库用于用户代码空间。自从linux2.6.23内核之后,内核源配备了一耳光自动Make target用于建立类似&sanitized&linux kernelheaders版本。
&&&&&&&从内核源目录,简单执行以下命令,把ppc改成你的体系架构,headers/改成你要把sanitized headers安装所在目录的路径。&&
$make ARCH=ppc&headers_check
$make ARCH=ppc&INSTALL_HDR_PATH=headers/&headers_
2)binutilspackage
这个包包含了很多工具经常用于操作那些二进制对象文件(binary object files)。其中这个包里最重要的两个工具是GNU assembler(as),linker(ld)。以下表包含了在binutils包里所能找到的工具:
3)the C library
&&&&&&&标准C库大部分经常用于当前日常Linux系统的是the GNU C library。而glibc作为精简版的C库。glibc是一个可移植,高效的C库,支持所有相关标准(ISO C99,POSIX.1c,POSIX.1j,POSIX.1d,Unix98,和单一的Unix规范)。
&&&&&&&glibc整个开发工程(包含链接到开发源码树,bug数据库,和许多资源)主网站:
&&&&&&&&这个库所支持的平台列表可以在以下网站查询:
&&&&&&&库本身可以在以下网站下载到:
注意:那些glibc-后面没有加ports的包是不支持Arm和MIPS的,在支持了arm和MIPS的库glibc-后面都会加上ports后缀,可以通过上述相同路径下载到。假如项目要求更小的RAM,可以考虑使用一个有名的嵌入式替代物比如uClibc和dietlibc。
4)the threadinglibrary
&&&&&&&&线程是一种很流行的现代编程技术包含了几个独立,异步的任务但是属于同一个进程地址空间。Linux内核在2.6版本之前对线程提供了很少的支持,为了填补这样的缺陷,一些不同的线程库被开发,其中最通用的是LinuxThreads library。在Linux2.6之后就伴随着一个新的线程实现,称为the New POSIX Threading Library(NPTL)。NPTL依赖与linux内核对线程的支持。NPTL现在已经被Linux threading library所支持了,并且被分配作为最近glibc版本的一部分。
&&&&&&&&&我们可以开始使用LinuxThreads和移植到NPTL上去,因为这两个都符合POSIX标准。
&&&&&&&&可以在运行期间通过调用confstr()函数来测试出哪种线程库被执行:&
#define_XOPEN_SOURCE
#include&unistd.h&
#include&stdio.h&
intmain(void)
& char name[128];
& confstr (_CS_GNU_LIBPTHREAD_VERSION, name,sizeof(name));
& printf ("Pthreads lib is: %s\n",name);
& return 0;
5)componentversions
&&&&&&&&在构建工具链之前需要为你将要用到的每一个部件(GCC,glibc 和binutils)选择合适的版本。并不是每个部件的所有的版本和不同部件的所有版本都能结合构建出合适的工具链。可以使用每一个部件的最新版本但是也不能保证就一定能工作。
&&&&&&&&为了选择合适的版本,我们需要测试出一个组合来适合我们的host和target。可以使用别人以前测试通过了的组合,如果没有,那就需要自己来测试了,先为每一个package选择最新稳定的版本,然后进行测试,如果构建失败了就用上一个版本来代替继续测试,进行相同的操作直到测试出合适的组合。
&&&&&&&&注意:一般情况下,最高版本可能没有经过足够时间的测试就被发布出来,这样的版本其实不能认为是稳定的版本。所以例如:glibc2.3被发布出来,那么,我们最好选择glibc2.2.5直到glibc2.3.1开始有效。
&&&&&&&这里举个测试的例子:假如binutils的最新版本是2.1.8,GCC的最新版本是4.2.2,glibc的最新版本是2.7。通常情况下binutils是可以build成功的并且我们不需要去改变它,然后当我们build GCC4.2.2时,假如失败了尽管所有合适的配置标识已经被提供了。在这种情况下,我们就需要选择GCC4.2.1来测试,重复着这样的方法直到成功为止。但是需要注意的是;有时候最新版本的package期望其他package提供某些功能,所以有时候是需要在你前一个package成功build而下一个package的所有版本build失败后,对上一个成功build的package版本进行回溯。比如上述例子中,我们必须回溯到glibc2.6.0或许就可以适合于GCC4.1和binutils2.17,尽管很多近期的GCC和binutils可以被完美结合。
&&&&&&另外,应用补丁到一些版本来让它们正确为我们的目标编译。
&&&&&&&每当你发现一个新版本结合编译成功,测试你最终的工具链来确定这个工具链确实有效。因为有些版本结合虽然可以编译成功但是在使用的适合却依然失败。而且在某些情况下,一个版本组合被发现可以用于一个处理器家族的某个处理器,但是在同个处理器家族的其他某些处理器又工作不起来。
6)Additionalbuild requirements
为了build cross-platform development toolchain,我们需要一个本机工具链的功能。很多主流发行版提供了这个工具链作为它们packages的一部分。假如这个攻击力没有被安装在你的工作空间或者你选择不安装它来节省空间,你需要安装它。
4.build主要步骤涉及内容
1)Linux headers
2)binary utilities
3)the bootstrap compiler
4)the C library
5)the full compiler
&&&&&&&其中你可能会注意到一点是,compiler好像被built了两次。这是正常的也是必须的,因为一些GCC支持的语言(比如C++)要求glibc支持。因此,a bootstrap compiler 被built只是用于支持C,而full compiler被built一旦C库有效了。
&&&&&&&尽管我们把Linux headers作为第一步,但是headers在C库被设置之前是没有被使用的,所有我们可以修改这个步骤只要是在C库被设置之前就行了。
每一个步骤都涉及到许多它自己本身的迭代。但是,这些步骤在一些行为里是保持相似的。很多的工具链构建步骤包含了一下几个行为:
②为交叉平台开发配置包
&&&&&&&&&一些工具链builds和上面序列有细微的不同。比如:the Linux headers没有要求我们去build或者安装thekernel。因为编译器已经卸载了the bootstrap compiler的设置,所以the full compiler 设置不需要再被要求卸载GCC包.
5.工作空间设置
1)根据早期工作空间目录层次建议,工具链将被built 在${PRJROOT}/tools 目录。之后我们还需要定义一些额外的环境变量。基于这些已经被定义的环境变量使build过程变得方便了很多。以下是关于一个新develdaq脚本用于设置新环境变量:
exportPROJECT=daq-module
exportPRJROOT=/home/gby/bels/control-project/${PROJECT}
export TARGET=powerpc-unknown-linux或者是arm-linux
exportHOST=i686-cross-linux-gnu
exportPREFIX=${PRJROOT}/tools
exportTARGET_PREFIX=${PREFIX}/${TARGET}
exportPATH=${PREFIX}/bin:${PATH}
cd$PRJROOT
PROJECT变量:是工程名,可以随便写
PRJROOT变量:这个工程的绝对路径
TARGET变量:定义了你的工具链将被编译用于的目标平台的体系架构。
HOST变量:定义工具链所运行的主机平台体系架构。
PREFIX变量:提供组件配置脚本指明了你想要把目标工具安装在的目录。
TARGET_PREFIX变量:用于目标依赖头文件和库的安装。
PATH变量:为了可以使用新安装的工具,我们需要修改PATH变量来指明这些二进制文件将要被安装到的目录。
&&&&&&&&在进行时间的制作工具链之前,让我们来看看一些你或许可以发现有用的资源在你制作过程中碰到问题时。
1)最重要的,每个包都有自己的文档。在GCC里面,我们可以找到一个FAQ文件和一个install 目录包含了一些如何配置和安装GCC的说明书。这些包含了大量的编译配置选项的说明。相似的,glibc包也包含了FAQ和INSTALL文件。INSTALL文件涵盖了编译配阿紫选项和安装过程,并且它提供了使用编译工具版本的建议。
2)另外,我们也许想要尝试使用一般的搜索引擎比如Google来寻找其他开发者已经遇到并解决的跟你相似的问题的记录。通常,这是一个很有效的方法来解决用GNU工具链的构建问题。
3)一个非常有用的资源是Cross-Compiled Linux From Scratch(CLFS)(http://trac.cross-lfs.org)已经在一些例子中被使用的组件组合版本的工具链构建已经有很多被提供在这个资源里。
CLFS:CLFS项目提供指导你逐步构建你自己定制的Linux系统全部通过使用原始资料。优点有以下几个:
& 教人们如何构建一个交叉编译器
& 教人们如何利用multilib系统
& 教人们Linux系统内部是如何工作的
& 构建CLFS来产生一个非常紧凑的Linux系统
& 在很多Unix风格操作系统构建CLFS
&CLFS是非常灵活的
&CLFS提供额外的安全性
阅读(...) 评论()

我要回帖

更多关于 linux mips交叉编译 的文章

 

随机推荐