使用源码制作交叉编译工具链

一、简述

之前我们讲述了《使用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、下载地址

https://vault.centos.org/4.5/isos/i386/

尽量选择与工具链版本相近的旧版的系统环境进行编译,因为新版的系统的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架构程序。

五、参考链接

https://blog.csdn.net/zqixiao_09/article/details/50783007

https://icode.best/i/81197240924005

留下评论

您的电子邮箱地址不会被公开。 必填项已用*标注