从0创建一个OS (十二) 创建gcc交叉编译器

本节将学习如何为特定目标平台创建专属编译器

关键字: 交叉编译器

目标: 创建一个可以用来建立我们的kernel的开发环境

理论基础

鉴于以后我们将使用C语言编辑我们的操作系统核,因此需要对开发环境进行新的布置,也就是创建一个交叉编译器.

为什么要搞一个交叉编译器?

事实上类Unix系统的编译环境已经足够完善,但其缺点是太完善了,我们在编译时不知道到底使用了什么样的库文件,因此我们需要创建一个交叉编译器,只包含标准C语言库文件.

搞一个交叉编译器需要什么东西?

在生成交叉编译器时,我们需要从网上下载2个源码,对这两个源码进行编译.
binutils
gcc
尽量选择最新版本.本节使用的是binutils2.32和gcc9.2.0. 英文原文教程使用的是binutils2.24和gcc4.9.1.

生成交叉编译器

我使用的是ubuntu16.04环境,在多次尝试之后总结了以下生成交叉编译器的步骤.

接下来的操作务必在同一个Terminal中完成.如果过程中不甚关闭Terminal,需要从头开始.

  1. 首先需要进入超级管理员模式,不然会报很多权限不足的错误.
    sudo su
  2. 确定你的本机gcc位置,使用which gcc指令.我的gcc位置为/usr/bin/gcc.
  3. 使用以下指令,完成对环境变量的暂时修改(退出该Termial之后环境变量会恢复)
    在这里插入图片描述
# 注意这里的gcc-5是我打开/usr/bin,搜索gcc看到的gcc版本,需要根据自身的环境进行调整
export CC=/usr/bin/gcc-5
export LD=/usr/bin/gcc-5
# PREFIX是最终编译完成的交叉编译器总的存储位置,可以修改为你想要存储的地方
# TARGET是交叉编译器的目标平台,这里选择386平台
# PATH即交叉编译器目录下的bin中含有所有可执行文件
export PREFIX="/usr/local/i386elfgcc"
export TARGET=i386-elf
export PATH="$PREFIX/bin:$PATH"

 

  1. 创建临时文件夹src, 将下载到的binutils和gcc放到该文件夹中
mkdir /tmp/src
cd /tmp/src

 

在这里插入图片描述

  1. 先编译binutils
tar xf binutils-2.32.tar.gz
mkdir binutils-build
cd binutils-build
../binutils-2.32/configure --target=$TARGET --enable-interwork --enable-multilib --disable-nls --disable-werror --prefix=$PREFIX 2>&1 | tee configure.log
make all install 2>&1 | tee make.log

 

  1. 再编译gcc
cd ..
tar xf gcc-9.2.0.tar.bz2
mkdir gcc-build
cd gcc-build
# 如果这一步报错说什么gmp\mpfr等库出现问题,使用以下解决办法
# 解决办法:在gcc的根目录下,在terminal中运行  ./contrib/download_prerequisites
# 如果有vpn请开vpn,下载会加速
# 运行之后进入gcc-build文件夹重新configure
../gcc-9.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-libssp --enable-languages=c --without-headers
make all-gcc 
make all-target-libgcc 
make install-gcc 
make install-target-libgcc 

 

编译完成的结果:

------ update 2021.4.9 -------------

重新编译安装后,发现/usr/local/i386elfgcc/bin中的所有程序都变为没有了i386-elf前缀,暂时没有找到原因,可能是gcc-10.2.0和binutils-2.36的搭配导致i386不被支持了。

 

在这里插入图片描述

  1. 修改环境变量,使我们能够直接在terminal中使用交叉编译器进行编译,而无需每次使用时都要切换到/usr/local/i386elfgcc/bin目录下.
sudo vim /etc/profile
# 在最后加上
export PATH="$PATH:/usr/local/i386elfgcc/bin"

# 然后在terminal中输入
source /etc/profile

# 重启termial即可

 

测试

正常情况下如果上面的每一步都不报错,交叉编译器算是生成成功了,这里给出一个示例,跟下一节的内容由部分重合.

首先新建一个c代码文件,test.c,在文件中输入如下源码:

int my_function()
{
    return 0xBABA;
}

 

再在该文件目录下打开terminal,输入

# 如果出现了i386-elf-gcc无法识别的错误,就直接使用gcc -fno-pie -m32替代i386-elf-gcc
i386-elf-gcc -ffreestanding -c test.c -o test.o
# 如果出现了i386-elf-gcc无法识别的错误,就直接使用objdump -m i386 代替
i386-elf-objdump
i386-elf-objdump -d test.o

 

如果显示如下则表示我们本节的创建gcc交叉编译器成功.
在这里插入图片描述

2020.4.4更新
如果发现:

Configuring for a x86_64-pc-linux-gnuoldld host.
Invalid configuration x86_64-pc-linux-gnuoldld': machinex86_64-pc’ not recognized
Invalid configuration x86_64-pc-linux-gnuoldld': machinex86_64-pc’ not recognized
Unrecognized host system name x86_64-pc-linux-gnuoldld.

就参考这里is-there-another-version-of-the-binutils-for-x86-64

 

posted @ 2020-11-19 10:32  EwanHai  阅读(310)  评论(0编辑  收藏  举报