|
1. 内核头文件:遵循老方法,将内核源码包解压缩并进行配置后,将需要的头文件直接拷贝到目标目录下:
# tar jxvf linux-2.6.10.x.tar.bz2
# cd linux-2.6.10.x
make ARCH=i386 CROSS_COMPILE=i386-linux- menuconfig
变量ARCH=i386告诉编译器目标版的CPU架构是i386类型的;将变量CROSS_COMPILE设置为i386-linux- ,Makefile会在其后添加gcc,使得编译工具变为i386-linux-gcc,这个工具一般在/usr/bin/目录下,但未必是这个名字。有的系统,例如FC6会将其命名为i386-redhat-linux-gcc,这种情况下,shell会提示i386-linux-gcc:command not found,即找不到这个程序。可以在/usr/bin目录下建立一个符号链接:
ln –s /usr/bin/i386-redhat-linux-gcc /usr/bin/i386-linux-gcc
或者不用管它,因为这一步与交叉编译还没有关系。
2.6的内核与2.4的内核不同,在执行make menuconfig之后不会自动生成version.h这个头文件,而这个头文件在后续的glibc的安装过程中是必需的,所以要手动生成这个文件:
Make include/linux/version.h
最后将生成的内核头文件复制到目标目录下:
mkdir –p ${TARGET_PREFIX}/include
cp –r include/linux ${TARGET_PREFIX}/include
cp –r include/asm-i386 ${TARGET_PREFIX}/include/asm
cp –r include/asm-generic ${TARGET_PREFIX}/include
头文件的设置已经完成,但是不要删除内核源码包,glibc的编译过程需要指定内核源码包的位置,从而搜寻所需要的头文件,包括刚刚生成的version.h
2. 二进制程序binutiles:
首先设置一些变量,这些变量在后续的交叉工具链的建立过程中始终需要。
export PREFIX=~/target
export TARGET=i386-linux
export TARGET_PREFIX=$PREFIX/$TARGET
Binutile的安装过程应该是最顺利的,它需要的条件很少,最终会在目标下安装二进制目标文件。其中最重要的2个工具是汇编器as和连接器ld。
mkdir build-binutiles
cd build-binutiles
对软件包进行配置:
../binutils-2.17/configure --prefix=${PREFIX} \
--target=$TARGET
prefix和target选项告诉编译器二进制文件的安装位置和这些二进制文件都是面向交叉编译的。
接下来编译并安装:
Make && make install
3. glibc头文件glibc-linuxthreads的安装
glibc-linuxthreads是linux的附加包,里面包括了一些重要的头文件,这些文件在GCC已经Glibc的安装中都需要。但是,glibc-2.3.6之后的版本放弃了对linuxthreads的支持。
将glibc-linuxthreads解包到glibc的源码目录下面进行安装:
# tar jxvf ../tars/glibc-2.3.6.tar.bz2
# tar jxvf ../tars/glibc-linuxthreads.tar.bz2 --directory=glibc-2.3.5
glibc的readme建议用户在源码包之外的目录下编译安装,所以建立一个目录
# mkdir build-glibc-headers && cd build-glibc-headers
# ../glibc-2.3.5/configure --prefix=/usr –host=$TARGET –enable-add-ons –with-headers=$TARGET_PREFIX/include
--enable-add-ons选项告诉编译器在编译glibc-linuxthreads的时候添加对附加包的支持
--with-headers=$TARGET_PREFIX/include选项告诉编译器,使用刚刚产生的、将来要用在目标机器上新的头文件,而不是用本来宿主系统下的头文件。
# make cross-compiling=yes install_root=$TARGET_PREFIX prefix=”” install-headers
由于目前使用的编译器还不是交叉编译器,将cross-compiling设置为yes,就不会建立原生的链接库;
install_root=$TARGET_PREFIX告诉编译器头文件的安装目录;
install-headers告诉编译器只安装头文件。
4. 建立引导编译器gcc-3.4.2
解压缩gcc源码包后进入并打1个补丁:
# tar jxvf ../tars/gcc-3.4.2.tar.bz2 && cd gcc-3.4.2
patch -Np1 -i ../ gcc-3.4.2-20040916-1-src.diff
GCC的安装说明中明确提出,建议在gcc源码包之外的目录下编译gcc,因此最好不要在源码目录下操作。进入预先设置好的build-boot-gcc进行编译:
# mkdir build-boot-gcc && # cd build-boot-gcc
../gcc-3.4.2/configure --prefix=${PREFIX} \
--target=$TARGET --disable-shared \
--with-newlib --enable-languages=c
--with-headers=$TARGET_PREFIX/include
--disable-shared这个选项告诉gcc在编译时不要生成共享库。这一项设置与否都不会报错;
--with-newlib选项告诉编译器不要使用glibc,因为针对目标版的glibc尚未编译安装;
--with-headers=$TARGET_PREFIX/include告诉编译器使用刚刚产生的内核头文件,而不是宿主系统上的。
编译以及安装启动编译器;
# make all-gcc && # make install
5. 编译安装glibc
glibc在建立工具链的软件中是最“脆弱”的一个,由于glibc与Gcc的兼容性问题,它极易受到GCC版本的影响,因此在安装glibc之前很有必要调查一下匹配比较好的GCC-Glibc的版本组合,包括与即将建立的GCC编译器的版本兼容性和宿主系统GCC的版本兼容性。我这里选择了GCC-3.4.2-Glibc-2.3.5-GCC-4.1.0这个组合,并通过一些补丁程序以及对源码包里文件的修改,工具链最终搭建起来。
首先在Glibc的源码目录为其打6个补丁:
# cd glibc-2.3.5
# patch –Np1 –i ../ glibc-2.3.5-gcc4_fix_elf-1.patch
# patch –Np1 –i ../ glibc-2.3.5-gcc4_fix_iconvdata-1.patch
# patch –Np1 –i ../ glibc-2.3.5-gcc4_fix_string-1.patch
# patch –Np1 –i ../ glibc-2.3.5-gcc4_fix_symbols-1.patch
# patch –Np1 –i ../ glibc-libgcc_eh.patch
# patch –Np1 –i ../ libpthread.diff
其中,第一个补丁是解决elf问题的;第四个补丁修复符号链接问题;第5个补丁解决i386-linux/bin/ld: cannot find –lgcc_eh的错误;第6个补丁用来解决多线程问题:libpthread.a的问题,如图所示:
接下来在glibc源码目录之外的目录下进行编译和安装:
# cd .. && # mkdir build-glibc && # cd build-glibc
# CC=i386-linux-gcc ../glibc-2.3.5/configure --prefix=/usr --host=i386-linux --build=i686-linux \ --enable-add-ons=linuxthreads –with-headers=$TARGET_PREFIX/include --enable-kernel=2.6.10 \
--with-binutils=$PREFIX/bin
CC=i386-linux-gcc:binutils产生的交叉编译工具来编译;
--prefix=/usr:这里的prefix表示glibc安装到目标版根文件系统后,其链接库组件的位置,即,安装到目标版的根文件系统的/usr目录下;
--host=i386-linux:告诉编译器,最终的文件要在x86架构的目标版上运行;
--build=i686-linux:宿主系统的cpu架构,这一项最好不要省略,INSTALL文件中提到,--host和--build最好要一起出现;
--enable-add-ons=linuxthreads:使用linux附加包,在linuxthreads目录下;
--with-headers=$TARGET_PREFIX/include:使用刚生成在目标版上的头文件进行编译;
--enable-kernel=2.6.10:只支持2.6.10版本以上的内核,这样做使得工具链以及以后的目标版程序不再支持2.6.10版本以下的内核,启动时会提示内核太旧。优点是不编译安装与2.6.10版本以前的内核的文件。
--with-binutils=$PREFIX/bin:设定搜索编译器的路径。这一项是很必要的,因为我们已经设置了交叉编译工具为i386-linux-gcc,如果没有这一项,就会在配置的过程中出错:
#>checking size of long double... configure: error: cannot compute sizeof (long double), 77
在编译过程中会出现有关于UNAME的一些问题,编译器会通知一些形如UNAME_SYSNAME的变量没有声明,从而致使编译中止,为了解决此问题,需要自己亲手做一个文件:
# vim $PREFIX/build/glibc-2.3.5/linuxthreads/sysdeps/generic/config-name.h
在vim编辑器里输入:
#ifdef config_name_h
#define config_name_h
#define UNAME_SYSNAME “Linux”
#define UNAME_RELEASE “2.6.10”
#define UNAME_VERSION “1 SMP FRI JUN 4 16:20:25 CST 2007”
#define UNAME_MACHINE “i386”
#endif /* config_name_h */
这些变量的内容都是根据命令uname –a 输出进行填写。
准备工作做好了,进行编译和安装:
# LC_ALL=c make
# make install_root=$TARGET_PREFIX prefix=”” install
install_root告诉编译器文件的安装位置;Makefile会将$prefix加在$install_root的后面形成完整的安装路径。由于在install_root中已经给出了安装路径,这里我设置prefix为空。
6. 完整编译器gcc-4.1.0的编译与安装
解压gcc-4.1.0并在源码包之外的目录下进行编译安装:
# tar jxvf ../tars/gcc-4.1.0.tar.bz2 && cd gcc-4.1.0
为gcc源码包打1个补丁:
# patch –Np1 –i ../ 88_all_gcc-make-POSIX-syntax-updates.patch
这个补丁是用来修复gcc-4.1.0在glibc-2.3.5下的语法错误,形如:
error: expected ‘)’ before the ‘;’ token
在glibc的安装过程中,由于make install 的命令安装会假定将链接库安装到根文件系统,因此libc.so链接命令脚本中以绝对路径给出了需要的链接库,这会导致编译过程的失败,因此要修改这个文件。
# vim $TARGET_PREFIX/lib/libc.so
去掉所有的/lib/字样
# cd .. && mkdir build-gcc && cd build-gcc
# ../gcc-4.1.0/configure --prefix=$PREFIX --target=i386-linux --enable-languages=c,c++
# make all && make install
交叉工具链到这里就做好了,自己可以编写一个小程序进行测试,如果没什么问题,说明交叉工具链构建成功,已经可以用来构建嵌入式linux系统了。
本人菜鸟初级,水平有限,如有错误请多多指教,呵呵 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|