- Zig言語は、libc機能をZig標準ライブラリとして直接実装する方向へ移行しており、既存のCソースコードを段階的に削除中
- 現在までに約250個のCソースファイルが削除され、2032個が残っている
- この移行により、コンパイル速度の向上、インストールサイズの削減、静的リンク時のバイナリサイズ縮小などの効果が生じている
- 最近の改善により、**zig libcは別個の静的アーカイブではなくZigコンパイルユニット(ZCU)**内で他のコードとともに最適化され、重複コードの除去とLTOレベルの最適化が可能になった
- Zigが独自の静的libc提供者へ移行するのに伴い、関連する問題が発生した場合はZigプロジェクトへ直接バグレポートを提出する必要がある
Zig libcプロジェクト概要
- 複数の貢献者がzig libcサブプロジェクトに参加し、既存のCベースのlibc実装をZig標準ライブラリのラッパーへ置き換えている
- 目標は重複したCコードを削除し、
memcpy、atan2などの単純なマッピング関数や、strnlenのような一般的な関数をラップする形で提供すること
- 例として
strnlen関数は、Zigのstd.mem.findScalarを使って実装されている
- 現在までに約250個のCソースファイルが削除され、2032個が残っている
性能と構造の改善
- 各関数がZigへ移行されるほど、外部プロジェクトおよびC言語への依存が減少
- コンパイル速度の向上、インストールサイズの簡素化と削減、静的リンクされたユーザーアプリケーションのバイナリサイズ削減という効果がある
- 最近の変更により、**zig libcはZig Compilation Unit(ZCU)**内で他のZigコードとともにコンパイルされる
- 別個の静的アーカイブとしてリンクするのではなく、コンパイラとリンカの統合構造を活用する
- これにより、重複コードの除去と関数間最適化が可能
- これは**リンク時最適化(LTO)**に似ているが、リンカ段階ではなくフロントエンド段階で実行される
今後の拡張可能性
- 最近のstd.Ioの変更と組み合わせることで、libcのI/O動作をユーザーが制御できる可能性がある
- 例:
read、write呼び出しをio_uringイベントループに統合
- リソースリーク検出機能をサードパーティーのCコードにも適用可能
- ただし現時点では未検証のアイデア段階である
テストと品質保証
- Szabolcs Nagyのlibc-testプロジェクトが数学関数のリグレッション防止に大きく役立っている
- このテストセットでZig libcの正確性を検証している
ユーザー向け案内
- Zigはmusl、mingw-w64、wasi-libcの機能を独自に提供する段階へ移行中
- 関連する問題が発生した場合はZigプロジェクトへ直接バグレポートを提出する必要がある
- これは既存の独立したlibcプロジェクトのメンテナーに誤って問題が送られるのを防ぐため
まとめ
- 記事の最後の文は「Abolish ICE」で締めくくられている(追加説明なし)
1件のコメント
Hacker Newsのコメント
Cファイルが250個削除され、現在は2032個が残っている
Zigがlibcを内側から置き換えていく過程を見守るのは、長期的に見てかなりワクワクするプロジェクトだ
多くの言語がCの代替を名乗るが、実際にC ABIとビルドシステムを自然に統合したのはZigがほぼ唯一だった
translate-c機能も驚くほどよく動く
C++のように99%互換を維持しようとせず、Cの単純さを生かしつつ言語の落とし穴を避けた選択のほうが賢明だったと思う
これが長期的にZigがOpenBSDで動かなくなるという意味なのか気になる
OpenBSDは直接syscallするのを禁じ、libc経由でのみ呼び出すよう強制しているので
詳細はこのスレッドを参照
-dynamic -lcオプションを付ければ対象システムのlibc関数が提供されるmacOSのように動的libcのみをサポートするシステムもあり、OpenBSDは静的libcもサポートしているはず
Zigプロジェクトにとって、Cライブラリをリンクする際の非常に興味深い変化だ
ただ、MinGWを使うWindows向けCプログラムをZigでクロスコンパイルする場合でも、引き続きMinGWのlibcを静的リンクできるのか気になる
-target x86_64-windows-gnu -lcを指定すると、一部のlibc関数はZigが、一部はvendored mingw-w64が提供する別途mingw-w64をインストールしなくてもZigがすべて提供する
必要なら
--libc libc.txtで外部libcを明示的に指定することもできるすばらしいアイデアではあるが、移植されたコードについてglbicやmuslのCVE脆弱性を継続して追跡する必要があるのか気になる
数学のような共有コードパスでは、むしろ潜在的なバグは減る
「libcの境界を越えてLTOを有効にするのに似ているが、リンカではなくフロントエンドで正しく行われる」という説明があったが
なぜリンカ段階では遅すぎるのか、ZigはLLVM IRレベルのリンカより多くの最適化ができるのか気になる
最適化済み静的ライブラリでは、リンク時にこうした最適化を行うのが難しいためだ
最近のstd.Io変更と組み合わさると、libcのI/O動作をユーザーが直接制御できる点が興味深い
たとえば、すべてのread/write呼び出しをio_uringイベントループに参加させるようなことができる
個人的にはkqueueのほうにより関心があるが、この引用はそちらにも当てはまりそうだ
libcには怖い部分も多いが、これは本当に興味深いプロジェクトだ
たとえば「memfrob」や「strfry」のようなものだが、冗談半分とはいえこういうのはglibcにしかない :)
Rustにもこういうものがあるのか気になる
Zig vs Rustの議論をしたいわけではなく、Rustプロジェクトでももう少し独立した環境を作りたい
Zigが1.0バージョンに到達するのがいつなのか知っている人はいるだろうか
言語には強い関心があるが、まだ変化が多く、重要なプロジェクトで使うにはためらいがある
それでもBun、Ghostty、Tigerbeetleのような大規模な本番プロジェクトはうまく追従している
Zigの意味論は単純なので、バージョンアップ時もコンパイラを更新していくつか機械的な修正をするだけで済む
自分を止めているのは同僚の採用意欲だけなので、とりあえず一人で作れるプロジェクトから進めている
参考までにこの動画は興味深いかもしれない