驚いたこと
Tripletの一覧に efi とかあるのですっかりそちらに気を取られていたのですが、まさか Windows Executable (or DLL) をネイティブビルドするのとほぼ同じ要領で EFI Application もビルドできるとは。
やったこと
といってもコンパイルオプションとリンクオプションだけですが。
コンパイルオプション
-Oz とか -flto とかの最適化や、-Wall -Werror -Wextra -pedantic あたりのオプションは好みに合わせてどうぞ。
必須なのはたぶん --target に指定するTripletの OS-ABI1 の部分と -ffreestanding と -nostdlib あたりかと思います。
$ clang \
--target=<triplet> \
-Oz \
-Wall \
-Werror \
-Wextra \
-c <path-to-source-file> \
-ffreestanding \
-flto \
-fno-builtin \
-fno-stack-check \
-fno-stack-protector \
-fshort-wchar \
-isystem <path-to-efi-headers> \
-mno-red-zone \
-nostdlib \
-o <path-to-object-file> \
-pedantic
リンクオプション
意外だった2のが、-fuse-ld=lld で lld ではなく lld-link を自動的に使ってくれること。
最重要ポイントは -Wl,/subsystem:efi_application 3 ですね。
clang \
--target=<triplet> \
-Wl,/dll \
-Wl,/entry:<name-of-entrypoint-function> \
-Wl,/nodefaultlib \
-Wl,/subsystem:efi_application \
-ffreestanding \
-flto \
-fuse-ld=lld \
-nostdlib
実演
試したTriplet
| Architecture | Triplet |
|---|---|
| x64 | x86_64-pc-windows-msvc |
| arm64 | aarch64-pc-windows-msvc |
最後に
今回使用したclangの --version を載せておきます。
$ clang --version
Ubuntu clang version 14.0.0-++20220209123220+8344ab9c4f191~exp1~20220209123314.30
Target: x86_64-pc-linux-gnu
Thread model: posix