
2026/05/31 2:29
Zig ELF リンカーの改善に関する開発ログ
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Zig コンパイラは、効率性と安定性における最近の画期的な進展により、独立への歩みとより速い開発サイクルに向けて重要な転換点に達しました。主なマイルストーンの一つとして、特定のビルドフラグを通じて新しい ELF リンカーの改善(LLVM および LLD)を用いて完全に自己ホスト化可能な機能を挙げる必要があります。これらの更新により、Linux 上でパフォーマンスオーバーヘッドなしに高度に最適化された増分コンパイルが可能となり、ウォールクロック時間におけるビルド時間は 150ms からわずか 14.3ms に短縮されました。これは 90% 以上もの減少です。このリワークはまた、設定プロセスと実行プロセスを分離し、設定情報をキャッシュして速度を向上させ、メモリおよび CPU の使用量を大幅に削減する機能も導入しています。
開発者は現在、リンカーされたライブラリと C ソースコードを約 30ms で再構築できるようになり、エラー解決が数秒ではなくミリ単位で行われる効果的なリアルタイムウォッチモードを実現しています。これらの更新はまた、
zig libc が静的アーカイブとして分離されるのではなく、他の Zig コードとコンパイルユニットを共有できるようにするため、バイナリサイズとインストールのオーバーヘッドを削減するとともに LTO の利点を向上させることを可能にします。
今後の展望として、バージョン 0.17.0 は数週間でリリースされることが予想されており、そのリリース直前に欠落している DWARF デバッグ情報の修正を行う予定があります。将来的なバージョン(例:0.17.1)では必要に応じてさらなる修正が行われる予定です。過去の改良には、オーバーアナライシス削減のための型解決の再設計や、Win32 ラッパーを優先するのではなくネイティブ API を重視する Windows ポリシーの変化などが含まれます。
本文
Zig 2026 年変更履歴
📅 2026 年 5 月 30 日:ELF リンカーの改良
著者: Matthew Lugg
Zig 0.16.0 で登場した新しい ELF リンカーの開発が進みました。当初は外部ライブラリとのリンクに制限がありましたが、現在は大幅な進歩を遂げました!
🚀 セルフホストビルドの進化
LLVM および LLD ライブラリを搭載した Zig コンパイラーをビルドできるようになりました。以下のコマンドを使用します:
# 新しいリンカーを使用して Zig コンパイラーをビルド zig build -Dno-lib -Dnew-linker -Denable-llvm # そのコンパイラーを使用して LLVM および LLD で何かをビルド ./zig-out/bin/zig build-exe ~/hello.zig -fllvm -flld
⚡ 高速なインクリメンタルコンパイル
新リンカーの最大のメリットは、増分解再ビルド(インクリメンタルコンパイル)への対応です。x86_64 Linux 環境では:
- 外部ライブラリや C ソースファイルとのリンクが可能になりました。
- パフォーマンスオーバーヘッドは一切発生しません。
ビルド速度の比較
Andrew のテトロス(Tetris)クローンにおける増分解再ビルドの例:
いくつかの些細な変更が、それぞれ約 30ms で構築されています。
Zig コンパイラー自体での再ビルドも同様に高速化されています:
# 監視モードで実行(インクリメンタルコンパイル有効) zig build -Dno-lib -Denable-llvm -fincremental --watch
- 1 回目: 36s
- 2 回目: 244ms
- 以降: 約 230ms で完了
注意: 現在の最大未実現機能は DWARF デバッグ情報の生成です。これを次期優先事項としています。しかし、その欠損でもミリ秒単位の再ビルドが可能という大きな利点があります。
Zig の
master ブランチを使用し x86_64 Linux を環境とする方は、インクリメンタルコンパイルを試すことを強く推奨します!バグは Issue でご報告ください。0.17.0 リリースで正式にサポートされます。
📅 2026 年 5 月 26 日:ビルドシステムの再構築
著者: Andrew Kelley
「ビルダー(Maker)」プロセスと「コンフィギュレーター(Configurer)」プロセスの分離という大規模なブランチがマージされました。
🔧 仕組みの変化
旧システムでは
build.zig とビルドグラフの実行が 1 つのプロセスで行われていましたが、現在は以下のようになります:
- コンフィギュレーター:
を小さなプロセスでコンパイルし、ビルドグラフを構築。メモリ上に構築されたデータをシリアライズしてファイルに保存します。build.zig - メーカー: シリアライズされたファイルを読み込み、最適化有効の状態で実際のビルド実行を行います。
これにより、ビルドシステム自体と
build.zig ロジックが分離され、zig build の実行時間が大幅に短縮されました。
ベンチマーク結果
| バージョン | コマンド | 平均時間 | 変化 |
|---|---|---|---|
| Master (旧) | | 150ms ± 5.52ms | - |
| Branch (新) | | 14.3ms ± 744us | ⚡ -90.4% |
📉 API の変更点
以下のコードパターンが廃止されました:
// ❌ 以前はこれで引数を渡していました if (b.args) |args| { run_cmd.addArgs(args); }
→
に変更が必要です。run_cmd.addPassthruArgs()
ビルドスクリプトが引数を検知できなくなるため、この機能が廃止されました。代わりに、引数を変更してもソースからの再構築が不要になります。0.17.0 リリース直前にリリースされる予定です。
📅 2026 年 4 月 8 日:LLVM とのインクリメンタルコンパイル
著者: Matthew Lugg
LLVM コード生成バックエンドにおけるインクリメンタルコンパイルが実現しました。
✨ メリット
- エラー検知の高速化: コンパイルエラーがある場合、"LLVM Emit Object"をスキップすることでエラーを非常に早く検知できます。
- 成功ビルドも高速: わずかながら速度向上が見られます。
※完全な「LLVM Emit Object」の時間短縮は LLVM の特性上困難ですが、Zig コンパイラー側の処理时间是最小化されています。
利用方法:
master ブランチで以下のコマンドを渡してください。
zig build -fincremental --watch
Zig コアチームはこの機能を利用しており、CI 環境でのテストカバレッジも確保されています。数秒単位だったコンパイルエラーがミリ秒単位に短縮される驚くべき変化があります。
📅 2026 年 3 月 10 日:タイプ解決のリデザインと言語変更
著者: Matthew Lugg
約 3 万行規模の PR をマージしました。Zig コンパイラー内部のタイプ解決ロジックを再構築し、より論理的で単純な設計に改めました。
🎯 主な変更点
1. タイプの「怠け者」化(Opt-out of Initialization)
初期化されない場合、そのタイプのフィールドについてコンパイラーが「見た目」を気にする必要がありません。
std.Io.Writer のような名前空間として機能するタイプに役立ちます。
// 以前はエラーでしたが、今は正常にコンパイルされます const Foo = struct { bad_field: @compileError("i am an evil field, muahaha"), // チェックされません const something = 123; }; comptime { _ = Foo.something; // 名前空間としてのみ使用 }
2. 依存関係ループのエラー改善
以前の Zig ではエラーメッセージが役に立たなかった依存関係ループに対し、現在はどこでループが発生したかを詳細に示すエラーメッセージを表示します。
const Foo = struct { inner: Bar }; const Bar = struct { x: u32 align(@alignOf(Foo)) }; // ループ発生箇所
エラーメッセージ例:
error: dependency loop with length 2 repro.zig:1:29: note: type 'repro.Foo' depends on type 'repro.Bar' for field declared here repro.zig:2:44: note: type 'repro.Bar' depends on type 'repro.Foo' for alignment query here note: eliminate any one of these dependencies to break the loop
3. インクリメンタルコンパイルの改善
「過剰分析」の問題がほぼ解消され、インクリメンタルコンパイルは大幅に高速化されました。
📅 2026 年 2 月 13 日:io_uring および Grand Central Dispatch 実装への統合
著者: Andrew Kelley
std.Io.Evented を基盤とした以下の機能を実装しました:
- io_uring 実装 (Linux)
- Grand Central Dispatch 実装 (macOS/iOS)
これらは「fibers」「stackful coroutines」「green threads」と呼ばれるユーザースペーススタックスイッチング機構に基づいています。
🛠️ 利用に向けた準備
信頼性・堅牢性の向上のため、以下を追跡作業中です:
- より良いエラーハンドリング
- ログの削減
の予期せぬパフォーマンス低下の診断IoMode.evented- 実装されていない関数の追加
- テストカバージージョンの増加
- オーバーコミットオフ時の最大スタックサイズ通知関数の提供
未来の姿: Zig コードで I/O 実装を簡単に切り替えられる「約束の地」を目指しています。
const std = @import("std"); pub fn main(init: std.process.Init.Minimal) !void { var debug_allocator: std.heap.DebugAllocator(.{}) = .init; const gpa = debug_allocator.allocator(); var threaded: std.Io.Threaded = .init(gpa, .{ .argv0 = .init(init.args), .environ = init.environ, }); defer threaded.deinit(); const io = threaded.io(); return app(io); } fn app(io: std.Io) !void { try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); }
📅 2026 年 2 月 6 日:パッケージ管理ワークフローの強化二つの追加
著者: Andrew Kelley
依存関係を持つ Zig プロジェクト向けの 2 つの重大な変更です。
1. ローカルパッケージ格納場所の変更
フェッチされたパッケージは、プロジェクトルートにある
zig-pkg ディレクトリ(build.zig の隣)に保存されるようになりました。
ファイルシステム構成例:
$ du -sh zig-pkg/* 13M freetype-2.14.1-... 20K opus-0.0.2-... 4.3M pulseaudio-16.1.1-... 5.2M uucode-0.1.0-...
推奨事項:
をzig-pkg
に追加してください。.gitignore- 自己完結型の tarball を配布する場合、このディレクトリはキャッシュ外のため問題ありません。
- グローバルキャッシュ: 未使用ファイルの削除や再圧縮が行われ、バンド幅を削減します。
$ du -sh ~/.cache/zig/p/* 2.4M freetype-2.14.1-...tar.gz 4.0K opus-0.0.2-...tar.gz
メリット:
- エディタによるパッケージコードの直接編集が可能。
- IDE の自動補完やツリー可視化が容易に。
- ピア対ピアのネットワークで圧縮パッケージを共有(帯域幅節約)。
2. --fork
フラグの追加
--forkローカルフォークされた依存関係をプロジェクトでオーバーライドするための新機能です。
# ローカルフォークの使用 zig build --fork=[path]
- マッチなしの場合: エラーが発生し、混乱を防ぎます。
$ zig build --fork=/home/andy/dev/mime error: fork /home/andy/dev/mime matched no mime packages - マッチした場合: フォークが利用されることを示します。
$ zig build --fork=/home/andy/dev/dvui info: fork /home/andy/dev/dvui matched 1 (dvui) packages
ワークフロー例:
- エコシステムからビルド失敗(破断)。
でローカルフォークを使用し、動作を確認。--fork- オプション:パッチの上流に提出するか、独自運用かを選択。
📅 2026 年 2 月 3 日:kerenl32.dll の回避による面白さのための恩恵
著者: Andrew Kelley
Windows の
kernel32.dll は低レベル API(ntdll.dll)のラッパーですが、不必要なヒープ割り当てや失敗モード、CPU 使用量を増大させます。Zig は「Win32 よりもネイティブ API を優先する」方針を徹底しています。
💡 具体的な改善事例
例 1: エントロピー生成
Windows 8 以降、
SystemFunction036 を呼び出すと bcryptprimitives.dll が自動読み込まれ、不要なオーバーヘッドが生じます。代わりに直接 NtDeviceIoControlFile を使用することで、ランダム数値の取得を決定論的かつ低遅延で行えます。
例 2: ファイル I/O
kernel32 ラッパー:
- 状態コードが隠され、
で返却。エラーはBOOL
で取得が必要。GetLastError
はフェイク型で、非同期処理でも内部管理を行ってしまいます。OVERLAPPED
Native API (NtReadFile):
- 実際のプリミティブ(イベント、APC、IO_STATUS_BLOCK)を使用。
- 同期・非同期を問わず、適切な状態コードが返却され、リソース管理が適切に行われます。
pub extern "ntdll" fn NtReadFile( FileHandle: HANDLE, Event: ?HANDLE, ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, Buffer: *anyopaque, Length: ULONG, ByteOffset: ?*const LARGE_INTEGER, Key: ?*const ULONG, ) callconv(.winapi) NTSTATUS;
詳細は Issue #XXX を参照してください。
📅 2026 年 1 月 31 日:zig libc
著者: Andrew Kelley
zig libc サブプロジェクトへの貢献が活発化しています。C ソースファイルをそのまま使用するのではなく、Zig ラッパーとして機能させることで、不要なコードを漸次削除し、コンパイル速度を向上させています。
🚀 主な特徴
- シンプルマッピング:
,memcpy
などは 1:1 マッピング。atan2
などはジェネリック関数にラップ。strnlen - サイズ削減: リポジトリから約 250 の C ファイルを削除(残り 2,032 ファイル)。静的リンクユーザーのバイナリサイズが小さくなりました。
- ZCU (Zig Compile Unit) 共有:
も ZCU を共有できるようになり、関数が共通最適化可能になりました(LTO のような効果)。zig libc
🔮 将来の可能性
の変化と組み合わせることで、I/O を io_uring イベントループに強制するなど、より柔軟な制御が可能になります。std.Io- サードパーティ C コードにおけるリソースリーク検出などの実験的機能も視野にあります。
Zig が静的 libc プロバイダーに移行する過渡期です。musl や wasi-libc などが提供しない機能で問題が発生した場合、まず Zig のバグ報告をよろしくお願いいたします。