目標
qemu上で起動するlinux kernelをビルドします。
できなかったこと
homebrewのclangでは、コンパイル出来ませんでした。理由はelf.hの不在です。brew install libelfでも解決出来ませんでした
docker+ubuntuの導入
諦めて、dockerと最小構成ubuntuでビルドすることにしました。
dockerインストール
ここからFree planを選んでApple Silicon用をダウンロードします。docker.imgファイルをマウントして、drag&dropでインストールです。

ターミナルから
% docker version
% docker run hello-world
で動作を確認してみてください。
私の場合、PATHがうまく通りませんでした。
なので、以下のコマンドを入力して/usr/local/binにdockerのファイルのパスを手動で通しました
% sudo ln -s /Applications/Docker.app/Contents/Resources/bin/docker /usr/local/bin/docker
% sudo ln -s /Applications/Docker.app/Contents/Resources/bin/docker-compose /usr/local/bin/docker-compose
% sudo ln -s /Applications/Docker.app/Contents/Resources/bin/docker-credential-desktop /usr/local/bin/docker-credential-desktop
% sudo ln -s /Applications/Docker.app/Contents/Resources/bin/docker-credential-osxkeychain /usr/local/bin/docker-credential-osxkeychain
% exec zsh
dockerとmacOS共用のフォルダをmacOSで作成しておきます
% cd ~
% mkdir docker-share
以下のコマンドでx86_64のubuntuが起動します。
% docker run -it \
--platform=linux/amd64 \
-v ~/docker-share:/work \
ubuntu:24.04 bash
Ubuntu 24.04にkernelビルドに必要なツールをインストール
[ubuntu]
# apt update
# apt upgrade
# apt install -y \
git \
build-essential \
bc \
bison \
flex \
libssl-dev \
libelf-dev \
dwarves \
ncurses-dev \
pkg-config \
ca-certificates
Kernel clone
[ubuntu]
# mkdir work
# cd work
# git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
# cd linux
# git tag | grep v6.12
v6.12
v6.12-rc1
v6.12-rc2
v6.12-rc3
v6.12-rc4
v6.12-rc5
v6.12-rc6
v6.12-rc7
% git checkout v6.12
確認です。
[ubuntu]
# git branch
* (HEAD detached at v6.12)
master
ファーストコンパイル
[ubuntu]
# make allnoconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
LEX scripts/kconfig/lexer.lex.c
YACC scripts/kconfig/parser.tab.[ch]
HOSTCC scripts/kconfig/lexer.lex.o
HOSTCC scripts/kconfig/menu.o
HOSTCC scripts/kconfig/parser.tab.o
HOSTCC scripts/kconfig/preprocess.o
HOSTCC scripts/kconfig/symbol.o
HOSTCC scripts/kconfig/util.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
.configの編集
以下のコマンドを入力します。
[ubuntu]
# make x86_64_defconfig
コンパイル&修正
以下のコマンドを入力します。
[ubuntu]
# make -j$(nproc) bzImage
いくつかenterキーをおすと、ビルドが始まります。
エラー修正
私の環境の場合以下のエラーがでました。
root@fb4c69d876e1:/work/linux# make -j$(nproc) bzImage
mkdir -p /work/linux/tools/objtool && make O=/work/linux subdir=tools/objtool --no-print-directory -C objtool
INSTALL libsubcmd_headers
CALL scripts/checksyscalls.sh
CC net/netlabel/netlabel_user.o
CC net/rfkill/core.o
CC net/netlabel/netlabel_kapi.o
CC net/rfkill/input.o
CC net/netlabel/netlabel_domainhash.o
AR net/rfkill/built-in.a
CC net/9p/mod.o
CC net/netlabel/netlabel_addrlist.o
CC net/netlabel/netlabel_mgmt.o
CC net/9p/client.o
CC net/9p/error.o
CC net/netlabel/netlabel_unlabeled.o
CC net/9p/protocol.o
CC net/9p/trans_common.o
CC net/netlabel/netlabel_cipso_v4.o
CC net/9p/trans_fd.o
CC net/9p/trans_virtio.o
make[4]: *** No rule to make target 'net/netfilter/xt_TCPMSS.o', needed by 'net/netfilter/built-in.a'. Stop.
make[3]: *** [scripts/Makefile.build:478: net/netfilter] Error 2
make[3]: *** Waiting for unfinished jobs....
CC net/netlabel/netlabel_calipso.o
AR net/9p/built-in.a
AR net/netlabel/built-in.a
make[2]: *** [scripts/Makefile.build:478: net] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/work/linux/Makefile:1936: .] Error 2
make: *** [Makefile:224: __sub-make] Error 2
以下のコマンドで修正しました
# scripts/config --disable CONFIG_NETFILTER
# scripts/config --disable CONFIG_NETFILTER_ADVANCED
# scripts/config --disable CONFIG_NETFILTER_XT_MATCH_TCPMSS
# make olddefconfig
# make -j$(nproc) bzImage
bzImageが完成しました。
initramfs作成
docker内で以下のツールをインストールします。
[ubuntu]
# apt install -y \
git build-essential \
bc bison flex \
libssl-dev libelf-dev dwarves \
cpio rsync \
busybox-static
次に以下を実行します。
[ubuntu]
# mkdir -p /work/initramfs/rootfs
# cd /work/initramfs/rootfs
# mkdir -p bin sbin etc proc sys dev tmp root mnt
# cp /bin/busybox ./bin/
# chroot . /bin/busybox --install -s
# cat > /work/initramfs/rootfs/init <<'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev 2>/dev/null || true
echo
echo "=== initramfs booted ==="
echo "Kernel cmdline: $(cat /proc/cmdline)"
echo
exec /bin/sh
EOF
# chmod +x /work/initramfs/rootfs/init
# cd /work/initramfs/rootfs
# find . -print0 | cpio --null -ov --format=newc | gzip -9 > /work/initramfs/initramfs.cpio.gz
macOSで以下を実行します。
% qemu-system-x86_64 \
-machine q35 \
-m 2048 \
-cpu qemu64 \
-kernel ~/docker-share/linux/arch/x86_64/boot/bzImage \
-initrd ~/docker-share/initramfs/initramfs.cpio.gz \
-append "console=ttyS0 rdinit=/init" \
-nographic
以下のように表示されれば成功です。
=== initramfs booted ===
Kernel cmdline: initrd=initrd console=ttyS0 earlyprintk=ttyS0
BusyBox v1.36.1 (Ubuntu 1:1.36.1-6ubuntu3.1) built-in shell (ash)
Enter 'help' for a list of built-in commands.
/bin/sh: can't access tty; job control turned off
~ #
busyboxが動いているのでlsコマンドなど使用可能です。
終了方法
Ctrl+Dでshを終わります。(必要に応じてsyncしてください)
[ 229.139209] Code: 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 48 c7 ce
[ 229.139560] RSP: 002b:00007ffc26ce4858 EFLAGS: 00000246 ORIG_RAX: 00000000007
[ 229.139772] RAX: ffffffffffffffda RBX: 0000000013b74940 RCX: 00000000004474cd
[ 229.139902] RDX: 00000000000000e7 RSI: ffffffffffffffe0 RDI: 000000000000007f
[ 229.140035] RBP: 00007ffc26ce4950 R08: 0000000000000000 R09: 0000000000000007
[ 229.140177] R10: 0000000013b76db0 R11: 0000000000000246 R12: 00007ffc26ce4c60
[ 229.140312] R13: 00007ffc26ce4c60 R14: 00000000005fc848 R15: 0000000000000000
[ 229.140499] </TASK>
[ 229.141146] Kernel Offset: 0x14600000 from 0xffffffff81000000 (relocation ra)
[ 229.141639] ---[ end Kernel panic - not syncing: Attempted to kill init! exi-
Ctrl+A, Xでqemu終了です。