1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WasabiOSのビルドを自動化してみた

1
Posted at

はじめに

こんにちは.だいみょーじんです.
この記事は,自作OSアドベントカレンダー2025の20日目の記事として公開したものです.

WasabiOSとは

WasabiOSは,hikaliumさんの自作OSのひとつです.
WasabiOSはその上でd0iasmさんによるSaBAというブラウザが動かせるという特徴を持っています.
WasabiOSとSaBAは,それぞれ作って学ぶOSのしくみおよび作って学ぶブラウザのしくみとして書籍化されており,低レイヤから高レイヤまで一気通貫で学べる優れた教材です.

SaBA on WasabiOS

今回はDockerを使ったWasabiOSおよびSaBAのビルドの自動化,およびQEMUにおける実行の自動化を行いました.
自動化スクリプトはこちらからご覧ください.

WasabiOSのビルド

以下の手順でSaBAを含むWasabiOSのディレクトリツリーmntおよびそれを圧縮したwasabi.zipを得ます.

WasabiOSのビルド
/somewhere $ git clone https://github.com/TaiseiIto/wasabi.git
/somewhere $ cd wasabi
/somewhere/wasabi $ make build
/somewhere/wasabi $ ls wasabi.zip
wasabi.zip
/somewhere/wasabi $ find mnt
mnt
mnt/uname
mnt/httpget
mnt/sheet
mnt/dig
mnt/saba
mnt/init.txt
mnt/window2
mnt/paint
mnt/hello0
mnt/README.md
mnt/window0
mnt/EFI
mnt/EFI/BOOT
mnt/EFI/BOOT/BOOTX64.EFI
mnt/window1
mnt/hello1
mnt/loop
mnt/rev

mntをUSBにコピーし,そのUSBから起動すれば実機でWasabiOSを動かせます.
大まかなビルドの流れは以下のとおりです.

  1. WasabiOSをビルドできる環境をDockerで構築
  2. Dockerコンテナ内でWasabiOSをビルド
  3. ビルドされたディレクトリツリーmntwasabi.zipに圧縮
  4. mntおよびwasabi.zipをDockerコンテナからホストにコピー

WasabiOSをビルドするコマンドはmake buildです.
では,Makefileの中身を見てみましょう.

Makefile
REPOSITORY=$(shell git config --get remote.origin.url) # リモートリポジトリのURL
PRODUCT=$(shell echo $(REPOSITORY) | awk -F '[./]' '{print $$(NF-1)}') # リポジトリ名'wasabi'
IMAGE=$(shell echo $(PRODUCT) | awk '{print tolower($$0)}') # Dockerイメージ名'wasabi'
CONTAINER=$(IMAGE) # Dockerコンテナ名'wasabi'
VNC_PORT=5905

.PHONY: build
build:
	./build.sh $(IMAGE) $(CONTAINER) $(VNC_PORT) # WasabiOSをビルド

IMAGECONTAINERはそれぞれDockerのイメージ名とコンテナ名で,リポジトリ名wasabiと同じになるはずです.
VNC_PORTWasabiOSの実行で使用しますが,ビルド時は使わないので無視してください.
そして,build.shにDockerイメージ名とDockerコンテナ名を渡しています.
では,build.shを見てみましょう.

build.sh
#!/bin/bash

image=$1 # Dockerイメージ名
container=$2 # Dockerコンテナ名
vnc_port=$3

# Build a docker image.
if [ -z "$(docker images --format {{.Repository}} | grep -x $image)" ]; then
	docker build --build-arg vnc_port=$vnc_port -t $image . # Dockerイメージを作成
fi

# Create a docker container.
if [ -z "$(docker ps -a --format {{.Names}} | grep -x $container)" ]; then
	docker create -i -t -p $vnc_port:$vnc_port --privileged --name $container $image /bin/bash # Dockerコンテナを作成
fi

# Start the docker container.
if [ -z "$(docker ps --format {{.Names}} | grep -x $container)" ]; then
	docker start $container
	docker exec --workdir /root/saba $container ./build_saba.sh # Dockerコンテナ内でSaBAをビルド
	docker exec --workdir /root/wasabi $container ./build_wasabi.sh # Dockerコンテナ内でWasabiOSをビルド
	docker stop $container
fi

# Extract WasabiOS
if [ ! -e wasabi.zip ]; then
	docker cp $container:/root/wasabi/wasabi.zip wasabi.zip # wasabi.zipをホストにコピー
fi
if [ ! -d mnt ]; then
	docker cp $container:/root/wasabi/mnt mnt # mntをホストにコピー
fi

WasabiOSをビルドできる環境をDockerイメージとして構築し,それをコンテナ化します.
build_saba.shがコンテナ内でSaBAをビルドし,build_wasabi.shがコンテナ内でWasabiOSをビルドします.
要するにコンテナ外のbuild.shがコンテナ内のbuild_saba.shおよびbuild_wasabi.shを呼び出してビルドを依頼する形になっています.
その後SaBAを含むWasabiOSのビルド済みディレクトリツリーmntと,それを圧縮したwasabi.zipを,コンテナ内からコンテナ外にコピーします.
次に,環境を構築する手順を記載しているDockerfileを見てみましょう.

Dockerfile
FROM ubuntu:22.04

# Don't ask stdin anything to install software automatically.
ENV DEBIAN_FRONTEND=noninteractive

# Install softwares.
RUN apt-get update && apt-get upgrade -y && apt-get install -y bison
RUN apt-get update && apt-get upgrade -y && apt-get install -y build-essential
RUN apt-get update && apt-get upgrade -y && apt-get install -y clang
RUN apt-get update && apt-get upgrade -y && apt-get install -y curl
RUN apt-get update && apt-get upgrade -y && apt-get install -y dejagnu
RUN apt-get update && apt-get upgrade -y && apt-get install -y dosfstools
RUN apt-get update && apt-get upgrade -y && apt-get install -y flex
RUN apt-get update && apt-get upgrade -y && apt-get install -y git
RUN apt-get update && apt-get upgrade -y && apt-get install -y gnupg
RUN apt-get update && apt-get upgrade -y && apt-get install -y iasl
RUN apt-get update && apt-get upgrade -y && apt-get install -y libexpat-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y libgcrypt20-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y libglib2.0-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y libgmp-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y libmpfr-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y libpixman-1-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y libslirp-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y lld
RUN apt-get update && apt-get upgrade -y && apt-get install -y nasm
RUN apt-get update && apt-get upgrade -y && apt-get install -y netcat-openbsd
RUN apt-get update && apt-get upgrade -y && apt-get install -y ninja-build
RUN apt-get update && apt-get upgrade -y && apt-get install -y pkg-config
RUN apt-get update && apt-get upgrade -y && apt-get install -y python3
RUN apt-get update && apt-get upgrade -y && apt-get install -y python3-venv
RUN apt-get update && apt-get upgrade -y && apt-get install -y texinfo
RUN apt-get update && apt-get upgrade -y && apt-get install -y tmux
RUN apt-get update && apt-get upgrade -y && apt-get install -y tzdata
RUN apt-get update && apt-get upgrade -y && apt-get install -y uuid-dev
RUN apt-get update && apt-get upgrade -y && apt-get install -y vim
RUN apt-get update && apt-get upgrade -y && apt-get install -y wget
RUN apt-get update && apt-get upgrade -y && apt-get install -y zip

# Install Rust.
RUN curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh -s -- -y

# Install QEMU.
WORKDIR /root
RUN git clone --branch v8.0.0 --depth 1 --recursive --shallow-submodules --single-branch https://gitlab.com/qemu-project/qemu.git
WORKDIR qemu
RUN ./configure --enable-gcrypt --enable-slirp --target-list=x86_64-softmmu CFLAGS="-O0 -g -fno-inline" CXXFLAGS="-O0 -g -fno-inline"
RUN make
RUN make install
WORKDIR roms/edk2
RUN ./OvmfPkg/build.sh -a X64

# Install WasabiOS.
WORKDIR /root
RUN git clone https://github.com/hikalium/wasabi.git
WORKDIR wasabi
RUN git checkout 8e23542da41be26f37d52f2be1b728c06c53fffa
COPY build_wasabi.sh build_wasabi.sh
COPY run_wasabi.sh run_wasabi.sh

# Install saba.
WORKDIR /root
RUN git clone https://github.com/d0iasm/saba.git
WORKDIR saba
RUN git checkout 29b43505168a2be021509bd25061342a4fd30004
COPY build_saba.sh build_saba.sh

# Expose VNC port.
ARG vnc_port
EXPOSE $vnc_port

SaBAおよびWasabiOSはRustで書かれているので,Rustをはじめ,必要なソフトウェアをインストールしています.
その後,WasabiOSとSaBAそれぞれについて,クローン,特定のコミットへのチェックアウト,ビルドスクリプトのイメージ内への配置を行います.
次にDockerコンテナ内でSaBAをビルドするbuild_saba.shを見てみましょう.

build_saba.sh
#!/bin/bash

source /root/.cargo/env # Cargoの環境を読み込む
make # SaBAをビルドする

Cargoの環境を読み込んでmakeしているだけです.
次にDockerコンテナ内でWasabiOSをビルドするbuild_wasabi.shを見てみましょう.

build_wasabi.sh
#!/bin/bash

source /root/.cargo/env # Cargoの環境を読み込む
make # WasabiOSをビルドする
make run_deps # WasabiOSのディレクトリツリーをmntに作成する
cp target/x86_64-unknown-uefi/debug/os.efi mnt/EFI/BOOT/BOOTX64.EFI # WasabiOSをmnt以下にコピーする
cp /root/saba/target/x86_64-unknown-none/release/saba mnt/saba # SaBAをmnt以下にコピーする
zip -r wasabi.zip mnt # ディレクトリツリーを圧縮

Cargoの環境を読み込んでWasabiOSをビルドし,mntとしてディレクトリツリーを作成してSaBAも取り込み,wasabi.zipに圧縮しています.

GitHub Actionsによるビルド

1コマンドでWasabiOSをビルドできるようになったので,次はGitHub Actionsを使って,ゼロコマンドでビルド済みのWasabiOSを取得できるようにします.
build.ymlを見てみましょう.

build.yml
name: build
on:
  push:
    branches:
      - main
jobs:
  build:
    name: build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the repository
        uses: actions/checkout@main
      - name: Build Wasabi
        run: make build
      - name: Upload Wasabi
        uses: actions/upload-artifact@main
        with:
          name: WasabiOS
          path: mnt

mainブランチにpushされた時にGitHub Actionsでmake buildを実行し,生成されたディレクトリツリーmntをアップロードしています.
これでGitHubからSaBAを含むビルド済みのWasabiOSをダウンロードできるようになりました.

WasabiOSの実行

ビルドを実行できたので,次はDockerコンテナ内のQEMU上でWasabiOSの実行を自動化してみましょう.
ありがたいことに,WasabiOSのリポジトリでは既にmake runでQEMU上での実行をサポートしているので,それを呼び出せばよいです.
またMakefileを見ると,VNCで5905番ポートにパスワードwasabiでアクセスできるっぽいです.

Makefile
PORT_OFFSET_VNC?=5
VNC_PASSWORD?=wasabi

なので,MakefileにVNCポート番号を書いておいて,それをbuild.shに渡します.

Makefile
VNC_PORT=5905

.PHONY: build
build:
	./build.sh $(IMAGE) $(CONTAINER) $(VNC_PORT)

build.shはさらにDockerfileにVNCポート番号を渡します.

build.sh
vnc_port=$3

# Build a docker image.
if [ -z "$(docker images --format {{.Repository}} | grep -x $image)" ]; then
	docker build --build-arg vnc_port=$vnc_port -t $image .
fi

DockerfileはVNCポートを外部に公開します.

Dockerfile
# Expose VNC port.
ARG vnc_port
EXPOSE $vnc_port

Dockerイメージができると,今度はbuild.shでDockerコンテナ作成時にホストのVNCポートとコンテナのVNCポートを直結します.

build.sh
# Create a docker container.
if [ -z "$(docker ps -a --format {{.Names}} | grep -x $container)" ]; then
	docker create -i -t -p $vnc_port:$vnc_port --privileged --name $container $image /bin/bash
fi

これでホスト側のVNCポートとDockerコンテナ側のVNCポートを直結できました.
次に,make runコマンドでDockerコンテナ内のQEMU上でWasabiOSを起動できるように,Makefilerunコマンドを記述します.

Makefile
.PHONY: run
run: build
	./run.sh $(CONTAINER)

run.shは,Dockerコンテナ内のrun_wasabi.shを呼び出します.

run.sh
#!/bin/bash

container=$1

docker stop $container
docker start $container
docker exec --workdir /root/wasabi $container ./run_wasabi.sh

run_wasabi.shは,DockerfileでDockerイメージ内にあらかじめコピーされています.

Dockerfile
COPY run_wasabi.sh run_wasabi.sh

run_wasabi.shは,WasabiOSのMakefileを呼び出し,QEMU上でliumOSを起動します.

run_wasabi.sh
#!/bin/bash

source /root/.cargo/env # Cargoの環境を読み込む
make vnc > vnc.log 2>&1 & # VNCのプロキシを起動
make run WITH_APP_BIN=/root/saba/target/x86_64-unknown-none/release/saba # SaBAを含めてWasabiOSを起動

これでWasabiOSの実行を自動化できます.
以下のコマンドにより,WasabiOSが起動します.

WasabiOS起動手順
/somewhere $ git clone https://github.com/TaiseiIto/wasabi.git
/somewhere $ cd wasabi
/somewhere/wasabi $ make run

そして,VNC viewerでlocalhost:5905にアクセスし,パスワードaでWasabiOSを操作できるようになります.
WasabiOSの画面でsabaというコマンドを実行するとブラウザが立ち上がり,アドレスバーにURLを入力するとページが表示されます.

SaBA on WasabiOS

まとめ

  • hikalium氏のWasabiOSおよびd0iasm氏のSaBAのビルドを自動化
  • Dockerを使うことで,1コマンドで環境構築からビルドまでできるように
  • GitHub Actionsを使うことで,GitHubからSaBAを含むビルド済みのWasabiOSをダウンロードできるように
  • VNC通信によりDockerコンテナ内のQEMU上で動くWasabiOSを操作

参考文献

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?