操作系统开发系列第1部分:在M1 MacBook上为i386目标构建GCC交叉编译器
#c #cpp #systems

跨编译器是构建操作系统时的重要工具,因为它允许您编写与主机/开发系统不同的目标系统代码。在这种情况下,我正在为基于X86架构的设备构建一个操作系统,尤其是我的主机MacBook的Intel 8086芯片的i386硬件,新的M1芯片是基于ARM的,当时可以引入一些挑战。使用不同的体系结构构建用于芯片的操作系统。这篇博客文章重点介绍了我在开发操作系统时要使用的交叉构造的步骤。

编译器用于将高级代码转换为目标操作系统上可执行的二进制文件。编译器加载正在编译的操作系统的标头文件和依赖项。这是操作系统开发的问题,因为在建立自己的操作系统时,我们不想拥有开发操作系统的依赖性,因为这将导致错误。

构建交叉编译器的步骤:

构建GCC交叉编译器实际上很简单,首先您需要创建一个用于处理操作系统开发的文件夹。

在这种情况下,让我们命名此文件OSDEV

mkdir OSDev

此文件夹是我们保留或操作系统开发相关的代码和工具的地方。这有助于我们的开发,并避免冲突,因为编译器和工具的安装可能与您当前的开发系统冲突。

建议将此OSDEV文件夹保留在其他软件开发工具,代码或软件包的位置。就我而言,我将其保存在 /开发人员文件夹中< /p>

我们安装了两个主要组件:

  • Binutils
  • GCC

二进制文件用于存储您程序从交叉编译器编译时可以使用的实用程序,因为它将无法访问您的OS平台库。

GCC是用于编译您的OS代码的实际交叉编译器。

# Move into the OSDev directory because this is where all your os development tools will be
cd OSDev

接下来,我们将必须下载GCC和Binutils的代码。最简单的方法是通过这些项目的镜子下载代码。

准备就绪

在开始之前,我们必须确保将某些路径参数导出到外壳,以便我们在构建编译器
时可以重复使用它

export PREFIX="$HOME/Developer/OSDev/opt/cross"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"

前缀定义了我们希望在何处找到我们的交叉编译器及其依赖项,而目标定义了我们正在构建的处理器类型。

binutils

您将转到项目的镜子,然后下载.tar.gz压缩文件。建议下载可用的最新版本。镜子的链接是

Index of /gnu/binutils

下载压缩的Binutils代码时,将其提取到OSDEV文件夹

cd OSDev
ls
binutils-2.39/

在我的情况下,binutils的版本为2.39,此文件夹仅在我的OSDEV文件夹中仅是文件夹。您可以从愿意的情况下处置您从中提取的压缩文件。

现在让我们为我们的目标平台构建Bitutils。首先,我们将创建一个build-binutils文件夹,我们将用于构建二进制文件。构建 - 构成应在OSDEV目录中创建。

cd OSDev
mkdir build-binutils
cd build-binutils

../binutils-2.39/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
make
make install 

这将为目标平台构建二元曲线,并将其存储在您定义为“前缀”的文件夹中。

运行此命令将在您的OSDEV文件夹中创建一个OPT文件夹,然后在Opt
中创建一个跨文件夹

cd OSdev
ls
build-binutils/ binutils-2.39/ opt/
cd opt
ls
cross/
cd cross
ls
Lists a bunch of libraries and binaries that are now usable in you cross compiler

GCC

现在,我们将像对Binutils一样下载GCC编译器的源代码。我们将下载压缩.tar.gz文件并将其提取到我们的OSDEV文件夹中。我们将从镜子下载它,可以在此处找到

https://ftp.gnu.org/gnu/gcc/

下载压缩GCC文件时,提取并将结果文件夹移动到OSDEV文件夹

cd OSDev
ls
build-binutils/ binutils-2.39/ opt/ gcc-12.2.0/
cd gcc-12.2.0

# This will install all the required dependencies such as mpc, mpfr and gmp
./contrib/download_prerequisites

在这种情况下,我们正在使用GCC编译器的12.2.0版。

现在让我们构建GCC编译器,就像我们构建Binutils一样。

cd OSDev

# The $PREFIX/bin dir _must_ be in the PATH. We did that above.
which -- $TARGET-as || echo $TARGET-as is not in the PATH

mkdir build-gcc
cd build-gcc
../gcc-12.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers
make all-gcc
make all-target-libgcc
make install-gcc
make install-target-libgcc

恭喜!我们已经成功构建了我们的编译器。编译器位于这里

OSDev/opt/cross/bin/i686-elf-gcc

通过检查版本
测试交叉编译器

OSDev/opt/cross/bin/i686-elf-gcc --version

现在,我们的交叉编译器正常运行,我们要导出路径,以便我们可以从终端中的任何地方调用编译器

export PATH="full-path-to-folder/Developer/OSDev/opt/cross/bin:$PATH"

这将使我们能够在终端中的任何地方致电我们的编译器

i686-elf-gcc --version

这是暂时的,如果我们关闭终端,除非我们重新导出它,否则我们将无法执行此操作。要永久导出路径,我们需要添加导出命令的终端文件。在我的情况下,我使用ZSH,在那里我必须编辑.zshrc文件作为这样的

nano .zshrc

然后将此命令添加到文件末尾

export PATH="full-path-to-folder/Developer/OSDev/opt/cross/bin:$PATH"

现在您有一个交叉编译器,可以使用它来构建我们的内核。