blog

作成日 : 2023/09/26
更新日 : 2023/09/26

WSLのカーネルをdockerを利用して手軽にビルドする

概要

WSLのカーネルに追加したい機能 (例えば#9132 ) がある場合などにカーネルをビルドする必要がある。

カーネルのバージョンアップに追従し、 機能を追加していくためにも手軽にビルドするスクリプトの実装例を示す。

前提条件

  • WSL上にdockerをインストール済み
  • WSL上にgit clientをインストール済み
  • WSL上にpython3をインストール済み

ファイル構成及び、呼び出す流れ

WSL上の作業ディレクトリ

. 
|- Dockerfile 
|- update.sh 
|- config.sh 
|- output.sh 
|- wsl_kernel_default_latest_tag.py 
|- main.sh 
|- WSL2-Linux-Kernel/ 
  |- .config 
  |- .config.bak

Windows上のディレクトリ

C: 
|- wslkernel/ 
  |- vmlinux 
  |- vmlinux.bak 
|- Users/ 
  |- {ユーザ名}/ 
    |- .wslconfig

スクリプトを呼び出す流れ

作業準備

WSL上の作業ディレクトリで、以下コマンドを実施する。

cat <<'EOS' > Dockerfile
FROM debian:stable-slim

WORKDIR /buildir

RUN : \
  && apt-get update \
  && apt-get install -y \
       build-essential \
       flex \
       bison \
       libssl-dev \
       libelf-dev \
       pkg-config \
       libncurses-dev \
       dwarves \
       bc \
       python3 \
  && apt-get -y clean \
  && rm -rf /var/lib/apt/lists/* \
  && :
EOS


cat <<'EOS' > update.sh
#!/bin/bash

set -euxo pipefail

docker pull debian:stable-slim
docker build --tag wsl-kernel-builder:latest .

cd WSL2-Linux-Kernel
lastest_tag=$(python3 ../wsl_kernel_default_latest_tag.py)
git checkout $lastest_tag
EOS


cat <<'EOS' > config.sh
#!/bin/bash

set -euxo pipefail

docker run --rm -it -v ".:/buildir" wsl-kernel-builder:latest \
  bash -c 'cd WSL2-Linux-Kernel && cp -p --backup --suffix ".bak" Microsoft/config-wsl .config && make menuconfig'
EOS


cat <<'EOS' > output.sh
#!/bin/bash

set -euxo pipefail

docker run --rm -it -v ".:/buildir" wsl-kernel-builder:latest \
  bash -c "cd WSL2-Linux-Kernel && make -j $(nproc)"

cd WSL2-Linux-Kernel

if [ ! -d "/mnt/c/wslkernel" ]; then
  mkdir "/mnt/c/wslkernel"
fi

cp -p --backup --suffix ".bak" ./vmlinux /mnt/c/wslkernel/
EOS


cat <<'EOS' > wsl_kernel_default_latest_tag.py
import requests
import sys

repo_owner = "microsoft"
repo_name = "WSL2-Linux-Kernel"

repo_info_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}"
releases_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases"

headers = {
    "Accept": "application/json"  # JSON 形式のレスポンスを指定
}

try:
    response = requests.get(repo_info_url, headers=headers)
    response.raise_for_status()

    default_branch = response.json()["default_branch"]

    response = requests.get(releases_url, headers=headers)
    response.raise_for_status()

    releases = response.json()

    for release in releases:
        if release["target_commitish"] == default_branch:
            print(release["tag_name"])
            sys.exit(0)
except Exception as e:
    print(e, file=sys.stderr)
    sys.exit(1)

sys.exit(1)

EOS


cat <<'EOS' > main.sh
#!/bin/bash

set -euxo pipefail

# 最新のビルド環境にアップデート
bash update.sh
# `make menuconfig`でカーネルのビルドパラメータを設定
bash config.sh
# WSLの最新のカーネルをWindowsのディレクトリに出力
bash output.sh
EOS
# WSLカーネルのGitHubリポジトリをクローン
git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
# カーネルを格納するディレクトリの作成
mkdir /mnt/c/wslkernel

カーネルのビルド

2回目以降は、本章のみ実行し、カーネルを更新する。 すぐにビルドしたカーネルを適用するときは、カーネルの適用のWSLの再起動も実施する。

bash main.sh

make menuconfig によるカーネルのビルド時の設定が表示されるので、 やりたいことに合わせて設定する。

カーネルの適用

vim "$(wslpath "$(powershell.exe 'echo $env:USERPROFILE')" | tr -d "\r")/.wslconfig"

以下の内容を追加する。

wslconfig

[wsl2] 
kernel=C:\\wslkernel\\vmlinux
# WSLの再起動
powershell.exe 'wsl --shutdown'

WSLを開くとビルドしたカーネルを適用した状態になる。

参考

WSLカーネルのGitHubリポジトリ

https://github.com/microsoft/WSL2-Linux-Kernel