OSXで自作OSのための環境を構築する

はじめに

30日自作本を終えて,フルスクラッチでOSを書くにあたり,OSXで環境構築をしなければならなくなったので,その軌跡をログとしてまとめた.別にLinux上に構築すればいいじゃんというのはもっともである.

ながれ

今回の最終目的はi686向けのgcc(クロスコンパイル用)とGRUB2の構築だ.
まずはクロスコンパイル用gccをビルドするための環境を構築する.
そしてi686向けgccをビルドした後に,GRUB2をインストールする.

GMP&MPFR&libmpc&gccのインストール

僕はHomebrewを使っているので,brewを叩いて必要な3つをインストールする.

brew install gmp
brew install mpfr
brew install libmpc
brew install gcc

順番は以上のようにやるとよいらしいが,詳しくはわからない. Macにはデフォルトでgccが入っているのに,どうしてわざわざgccをインストールするのかと疑問に思うかも知れないが,Macに入っているgccはバックエンドをLLVMに開発されたClangというGNU gccとは別物である.とにかくクロスコンパイルgccをビルドするにはGNU gccが必要だから入れたというわけである.
嘘だと思うならgcc -vしてみるとよい.きっとClangが入っているはずだ.

binutilsのインストール

まずは環境変数を定義しておく.

export CC=/usr/local/bin/gcc-7
export LD=/usr/local/bin/gcc-7
export PREFIX="/usr/local/i686elfgcc"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"

CCとLDには先程インストールしたgccを指定する. PREFIXやTARGETなどはみたままである.

mkdir binutilssrc
cd binutilssrc
wget http://ftp.gnu.org/gnu/binutils/binutils-2.29.tar.gz
tar xf binutils-2.29.tar.gz
mkdir binutils-build
cd binutils-build
../binutils-2.29/configure --target=$TARGET --enable-interwork --enable-multilib --disable-nls --disable-werror --prefix=$PREFIX
make
sudo make install

もちろんだがビルドするときはソースファイル上では行わず,別途ディレクトリを作るのがよい.

libiconvのインストール

エンコード関係のライブラリらしい.gccをビルドするために最新のバージョンを入れておく必要があるらしい.

wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz
tar xf libiconv-1.15.tar.gz
cd libiconv-1.15
./configure -prefix=/usr/local
make
make install

i686向けgccをビルドする

wget https://ftp.gnu.org/gnu/gcc/gcc-7.2.0/gcc-7.2.0.tar.gz
tar xf gcc-7.2.0.tar.gz
mkdir gcc-build
cd gcc-build
../gcc-7.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-libssp --enable-languages=c --without-headers --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpfr=/usr/local --with-libiconv-prefix=/usr/local
make all-gcc 
make all-target-libgcc 
sudo make install-gcc 
sudo make install-target-libgcc

やっとクロスコンパイラが出来上がった!

objconvのインストール

よくわからないが必要らしい.

$ wget http://www.agner.org/optimize/objconv.zip
$ mkdir objconv
$ cd objconv
$ mv ../objconv.zip .
$ unzip objconv.zip
$ unzip source.zip
$ sh build.sh
$ cp objconv /usr/local/bin/

GRUB2のインストール

./autogen.sh
mkdir dobuild
cd dobuild
../configure --disable-werror TARGET_CC=/usr/local/i686elfgcc/bin/i686-elf-gcc TARGET_OBJCOPY=/usr/local/i686elfgcc/bin/i686-elf-objcopy TARGET_STRIP=/usr/local/i686elfgcc/bin/i686-elf-strip TARGET_NM=/usr/local/i686elfgcc/bin/i686-elf-nm TARGET_RANLIB=/usr/local/i686elfgcc/lib/i386-elf-ranlib --target=i686-elf
make
sudo make install

configureに渡すpathはみたままなので各自今まで入れた環境を指定してconfigする.

bareboneを動かす

これを動かしてみる.

/usr/local/i686elfgcc/bin/i686-elf-as boot.s -o boot.o
/usr/local/i686elfgcc/bin/i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
/usr/local/i686elfgcc/bin/i686-elf-gcc -T linker.ld -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc -o myos.elf

elfを出力した後に,GRUB2のcfgを書いて,grub-mkrescueを叩いて起動イメージをつくる.

set timeout=0
set default=0

menuentry "MyOS" {
    multiboot2 /boot/myos.elf
    boot
}
mkdir -p isofiles/boot/grub
cp grub.cfg isofiles/boot/grub/
cp myos.elf isofiles/boot/
grub2-mkrescue -o os.iso isofiles/

出力したisoをVirtualBoxに入れて動かす. f:id:morimolymoly:20171231143817p:plain

さいごに

OSXで開発環境が作れたので大学の授業中にもOSがかけるようになった!
これからはLinuxの実装を真似て小さなカーネルを書いて行こうかなと思う.

参考にしたサイト様

Mountain Lionユーザのためのクロスコンパイラビルド
MacでクロスコンパイラのGCCをビルドする
OS X Mountain Lion で i686-elf 向け GCC をビルドする
Mac OS XでGRUB2のコマンドを使いたい
Installing GRUB 2 on OS X
GRUB2から自作OSを起動する