使用源码制作交叉编译工具链
一、简述
之前我们讲述了《使用buildroot制作交叉编译工具链》,通过buildroot可以很方便的编译想要的工具链,但是因为在实际情况下,buildroot里面自带的一些配置可能不太适应某些实际环境,如内核版本很低,buildroot没有对应的选项,再如需要安装特定版本的gcc,同样没有对应的选项。为了解决这些问题,我们可以从源码编译的方式,制作交叉工具链。
交叉工具链通常包含以下几个源码包:
- binutils:这一工具集中存在的一些工具,可以说是我们开发和调试不可缺少的利器。 Binutils中的工具不少和GCC相类似,也是针对特定的处理器的。
- gcc:C语言编译器
- g++:C++语言编译器
- glibc/uclibc:libc库
- linux kernel、patch:Linux内核、补丁包(为了支持不同的CPU架构)
以下以编译gcc 2.95.3、linux内核版本2.4.21、glibc版本2.2.4、arm720t的CPU架构的交叉工具链为例。
二、环境准备
1、系统
CentOS 4.5 x86 |
2、下载地址
尽量选择与工具链版本相近的旧版的系统环境进行编译,因为新版的系统的gcc版本较高,适合的标准不一致,可能会编译报错,虽然说新版系统也可以安装旧版的gcc,但是比较复杂,这里为了方便大家,选择了一种简易的方式,选择的是以下系统,使用迅雷下载:
如果是用VMWare虚拟机安装系统,需要安装旧版本的vmtools,这里下载。
三、编译步骤
1、创建目录
这里的系统用户名为user,可以按照自己的进行修改
cd /home/user/
mkdir toolchain
cd toolchain
mkdir download src kernel build output
2、设置环境变量
设置环境变量是为了方便编译
export PRJROOT=/home/user/toolchain
export TARGET=arm-linux
export PREFIX=$PRJROOT/output
export TARGET_PREFIX=$PREFIX/$TARGET
export PATH=$PREFIX/bin:$PATH
3、下载源码
下载以下源码文件到download目录
cd $PRJROOT/download
wget ftp://ftp.gnu.org/gnu/binutils/binutils-2.11.2.tar.gz
wget ftp://ftp.gnu.org/gnu/gcc/gcc-2.95.3/gcc-core-2.95.3.tar.gz
wget ftp://ftp.gnu.org/gnu/gcc/gcc-2.95.3/gcc-g++-2.95.3.tar.gz
wget ftp://ftp.gnu.org/gnu/glibc/glibc-2.2.4.tar.gz
wget ftp://ftp.gnu.org/gnu/glibc/glibc-linuxthreads-2.2.4.tar.gz
wget http://cdn.kernel.org/pub/linux/kernel/v2.4/linux-2.4.21.tar.gz
wget http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/v2.4/patch-2.4.21-rmk1.gz
4、编译内核
解压源码,打上arm架构的补丁,编译依赖,将头文件拷贝到output目录
cd $PRJROOT/kernel
tar xzf ../download/linux-2.4.21.tar.gz
gunzip ../download/patch-2.4.21-rmk1.gz
cd linux-2.4.21
patch -p1 < ../../download/patch-2.4.21-rmk1
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
make dep
选择System Type
选中支持ARM720T处理器
退出并保存
输入make dep,进行编译
5、编译完毕
6、拷贝头文件
mkdir -p $TARGET_PREFIX/include
cp -r $PRJROOT/kernel/linux-2.4.21/include/linux $TARGET_PREFIX/include
cp -r $PRJROOT/kernel/linux-2.4.21/include/asm-arm $TARGET_PREFIX/include/asm
cd $TARGET_PREFIX/include/asm
ln -s arch-epxa arch
ln -s proc-armv proc
5、编译binutils
cd $PRJROOT/src
tar xzf ../download/binutils-2.11.2.tar.gz
mkdir $PRJROOT/build/build-binutils
cd $PRJROOT/build/build-binutils
../../src/binutils-2.11.2/configure --target=$TARGET --prefix=$PREFIX
make
make install
6、编译gcc
cd $PRJROOT/download
mv gcc-core-2.95.3.tar.gz gcc-2.95.3.tar.gz
cd $PRJROOT/src
tar xzf ../download/gcc-2.95.3.tar.gz
tar xzf ../download/gcc-g++-2.95.3.tar.gz
# 修改编译参数
sed -i 's/fPIC/fPIC -Dinhibit_libc -D__gthr_posix_h/g' $PRJROOT/src/gcc-2.95.3/gcc/config/arm/t-linux
mkdir $PRJROOT/build/build-gcc
cd $PRJROOT/build/build-gcc
../../src/gcc-2.95.3/configure --target=$TARGET --prefix=$PREFIX --without-headers --enable-languages=c
make
make install
7、编译glibc
在这里设定了install_root变量,指向链接库组件目前所要安装的目录。这样可以让链接库及其头文件安装到通过TARGET_PREFIX指定的与目标板有关的目录,而不是建立系统本身的/usr目录。因为之前使用--prefix选项来设定prefix变量的值,而且prefix的值会被附加到install_root的值之后,成为链接库组件的安装目录,所以需要重新设定prefix的值。这样所有的glibc组件将会安装到$TARGET_PREFIX指定的目录下。
cd $PRJROOT/src
tar xzf ../download/glibc-2.2.4.tar.gz
tar xzf ../download/glibc-linuxthreads-2.2.4.tar.gz --directory=glibc-2.2.4
mkdir $PRJROOT/build/build-glibc
cd $PRJROOT/build/build-glibc
CC=arm-linux-gcc ../../src/glibc-2.2.4/configure --host=$TARGET --prefix="/usr" --enable-add-ons --with-headers=$TARGET_PREFIX/include
make
make install_root=$TARGET_PREFIX prefix="" install
进入$TARGET_PREFIX/lib目录,编辑文件libc.so,更改如下(将/lib/去掉):
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
GROUP ( libc.so.6 libc_nonshared.a )
8、编译g++
cd $PRJROOT/build/build-gcc
make clean
../../src/gcc-2.95.3/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++
make all
make install
四、测试效果
测试程序helloworld.cpp:
#include <iostream>
int main()
{
using namespace std;
cout << "Hello World" << endl;
return 0;
}
c++编译成功,显示是arm架构程序。