OS开发(1) - 构建交叉编译器
什么是交叉编译器,为什么需要
普通的编译器(如gcc)只能把代码翻译成当前机器架构和系统能运行的的机器码,如x86的windows只能编译出的windows的二进制可运行程序。交叉编译器可以将当前机器上的代码编译成其他机器可运行的二进制文件。普通编译器一般情况下是没问题的,但是OS不一样,他虽然在A平台上构建,但需要在B平台上运行。所以我们需要交叉编译器来编译我们的操作系统。
构建交叉编译器
整个OS开发式基于 osdev 。我们选择gcc编译器和binutils编译工具套,目标是i686-elf平台,在ubuntu上开发。
安装依赖
需要的依赖:
- Make
- Bison
- Flex
- GMP
- MPFR
- MPC
sudo apt install build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo
下载源代码
- gcc:https://ftp.gnu.org/gnu/gcc/
- Binutils:https://ftp.gnu.org/gnu/binutils/
可以下载到$HOME/src
中方便管理。
准备环境
直接将交叉编译器构建在系统目录中是危险的,因为可能会覆盖系统自带的编译器。所以我们将我们构建好的交叉编译器放入$HOME
中。将以下写入~/.bashrc
中:
export PREFIX="$HOME/opt/cross"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"
构建Binutils
cd $HOME/src
mkdir build-binutils
cd build-binutils
../binutils-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
make
make install
编译对应$TARGET
的Binutils到$PREFIX
中,注意将x,y,z替换为下载的版本。
–disable-nls:不包括原语言支持。这基本上是可选的,但可以减少依赖性和编译时间。
–with-sysroot:在交叉编译器中启用sysroot支持,把它指向一个默认的空目录。默认情况下,链接器拒绝使用sysroot。gcc能够在运行时处理两种情况,这在后面会很有用。
构建GCC
cd $HOME/src
# 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-x.y.z/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
编译对应$TARGET
的libgcc(编译中会用到的低级库)到$PREFIX
中,提供了整数、浮点、十进制、堆栈展开(处理异常)和其他支持功能。这个编译过程会很慢(一两个小时),注意将x,y,z替换为下载的版本。
–disable-nls:与Binutils相同。
–without-headers:GCC编译时不要依赖任何C语言标准库。
–enable-languages:GCC编译时不要编译它所支持的所有语言,而只编译C语言(以及可选的C++)。
使用交叉编译器
完成以上步骤后,新的交叉编译器会在$HOME/opt/cross
完成,使用方法:
# 语法同于普通gcc编译器
$HOME/opt/cross/bin/$TARGET-gcc --version
为了方便可以将其添加到$PATH
中然后给$TARGET-gcc
写一个alias,这里就不在赘述。