- .NET Unified Build プロジェクトは、従来の分散リポジトリベースのビルド構造における複雑さと非効率を減らすため、製品全体を**「仮想単一リポジトリ(Virtual Monolithic Repository, VMR)」**として統合した新しいビルド体系
- 従来の分散型製品構成方式は独立性と柔軟性が高い一方で、依存関係管理・ビルド一貫性・速度の面で大きな負担を生んでいた
- Unified Build はLinux ディストリビューション向け Source Buildの原理を拡張し、単一のソースレイアウトと**「垂直ビルド(Vertical Build)」**構造を導入して、ビルド時間を短縮し予測可能性を確保
- 双方向コードフロー(two-way code flow)、シナリオテスト、自動検証および署名インフラの改善などを通じて、開発者の効率と製品品質を同時に向上
- .NET 10 で正式導入されたこの仕組みは、ビルド時間短縮(24時間→7時間未満)、保守コスト削減、配布信頼性向上などの実質的な成果を達成
.NET ビルド構造の変化の背景
- .NET は 2015〜2016 年のオープンソース化の過程で、CoreCLR、CoreFX、ASP.NET Core、SDK など多数のリポジトリに分かれて開発された
- 各リポジトリが独立してビルド・配布され、製品全体は依存関係グラフを通じて組み合わされる構造
- この方式は OSS エコシステムに近いが、セキュリティパッチや緊急修正の際に複数チームの同時調整が必要となり、時間の予測ができない問題が発生
- 分散開発の利点(レイヤリング、コミュニティ分化、非同期開発など)がある一方で、**製品の一貫性(coherency)**の確保には非効率だった
製品構成の複雑さとオーバーヘッド
- 複雑性(Complexity): 変更が顧客に届くまでに必要な段階数として定義
- リポジトリ・依存ノードが多いほど、一貫性確保により多くの時間と人的調整が必要
- オーバーヘッド(Overhead): 顧客に届けられる成果物を直接生み出さない時間
- 例: PR 作成・承認待ち、キューイング、環境設定など
- .NET 8 ランタイムのビルド分析の結果、全体ビルド時間の約 38.5% がオーバーヘッドであることが確認された
- 複雑性とオーバーヘッドが結び付くと、ビルド効率は急激に低下し、リリース全体のサイクルが長くなる
Source Build と Unified Build の起源
- Source Buildは、Linux ディストリビューションが .NET を単一ソースからオフラインビルドできるよう設計されたシステム
- 単一実装、単一プラットフォーム、単一ビルド環境の原則
- ビルドオーケストレーターが各構成要素の依存関係とビルド順序を管理
- Source Build は低い複雑性・低いオーバーヘッドで 50 分以内にビルド可能
- Microsoft 内部ビルドにもこの概念を適用しようとしたが、**クローズドソース・レガシー依存関係・プラットフォーム間のジョイン(join)**などにより困難があった
- これを解決するために、参照専用パッケージ(source-build-reference-packages)、単一実装の原則、ジョインの除去などのアプローチを導入
Unified Build の目標と設計
- 単一コミットで .NET 製品全体をビルド可能
- すべてのプラットフォーム向け配布物を単一環境で生成
- Microsoft 外部でも独立してビルド・検証可能
- 双方向コードフローを通じて VMR と個別リポジトリ間の変更を自動同期
- シナリオテストを通じて製品全体レベルの機能検証を実施
- **垂直ビルド(Vertical Build)**構造でプラットフォーム別ビルドを並列化
- 約 35〜40 本のビルド垂直ライン(short/tall stack)で構成
Unified Build の実装段階
- .NET 7: 概念設計と承認
- .NET 8: Source Build インフラ改善と基盤構築
- .NET 9: 垂直ビルドとコードフローの実験
- .NET 10: 正式製品化と RTM 反映
- Preview 4 で新しいビルドプロセスを導入し、Preview 5 から完全移行
主な構成要素
Virtual Monolithic Repository (VMR)
- dotnet/dotnet リポジトリがすべての構成要素の単一ソースレイアウトの役割を担う
- 開発者は個別リポジトリまたは VMR で作業でき、分散型の柔軟性と単一型の一貫性を同時に確保
Vertical Build
- 各プラットフォーム・ランタイムごとに独立ビルドを実行
- 並列ビルド後に結果を統合し、一部のジョイン(join)は追加ビルドパスで処理
Code Flow
- 双方向コード同期: 構成要素リポジトリ → VMR、VMR → 構成要素リポジトリ
eng/Version.Details.xml に最後のコードフロー状態を記録
- 変更事項をパッチファイルとして生成し、自動で PR を作成
- 競合処理およびエラー復旧ロジックを内蔵
Scenario Test Validation
- 従来の単体テストに加えて、製品全体の機能を検証するシナリオテストを追加
- ビルド成果物基準で実行され、リグレッション防止と品質保証を強化
成果と効果
- ビルド時間短縮: 24 時間超 → 7 時間未満(署名含む)
- 柔軟性向上: ビルド・配布サイクル短縮、緊急修正の反映が容易
- 予測可能性の確保: 変更後にビルド完了する時点が明確
- インフラ改善: 署名ツール、ログ、並列ビルド、依存関係フロー自動化など
- Linux ディストリビューション向け Source Buildも常に事前ビルドのクリーン状態を維持
今後の方向性
- .NET 11 ではコードフロー自動化および AI ベースの監視エージェントを導入予定
- 長期的にはジョインポイントの除去を通じてビルド簡素化と高速化を推進
結論
- 分散型ビルドモデルの限界を克服したUnified Buildは、.NET のビルド・配布効率を根本的に改善
- 複雑性・オーバーヘッド削減、一貫性・速度・品質向上という 3 つの軸で実質的な前進を達成
- .NET 10 RTM からこの仕組みが全面適用され、今後のバージョンでも継続的な改善が予定されている
1件のコメント
Hacker Newsの意見
自分は .NET チームを本当に尊敬している
彼らはたびたび掘り下げた技術記事を出していて、パフォーマンス最適化への執着がすごい(例: Kestrel、Entity Framework の進化)
ASP.NET は Python 2→3 級の大きな変化を経ても生き残った数少ない大規模プロジェクトの 1 つだ
昔はセッション同期のために魔法のような機能に頼っていたが、今ではまったく別の方式で動いている
3 兆ドル規模の企業が自分の使うスタックを本気で改善しようとしているのは気分がいい
そこで Dapper と自作のマイグレーションシステムに置き換えたところ、起動時の DB 検証およびシーディング時間が 10 秒 → 2 秒未満まで縮んだ(低スペックハードウェア + SQLite 環境)
Entity が生成するクエリには不要な多重 join が多かった
最近はシンプルな Go バックエンドへ移行中で、.NET は別のソリューションでだけ使っている
WPF のようなフレームワークは Win32 ハックが必要になるほど問題が多かった
たとえば .NET 9 になってようやく、すべてのネットワークインターフェースを正しく返すようになった。それ以前のランタイムは有効な NIC しか公開していなかった
いまだに Windows 7 サポートを維持しなければならないプロジェクトもある
新しいプロジェクトでも依然として .NET 4.8 を使わざるを得ないことがある。たとえば Excel 数式のビルド時に async/await のデッドロック問題が起きる
さらに Windows 統合機能が壊れていて、同じネットワーク呼び出しでも 4.8 では認証されるのに Core では失敗する
無数のライブラリで 下位互換性が崩れたため、マイグレーションは簡単ではない
パフォーマンスは良くなったが、機能面では .NET Framework が化石化したように感じる
JSON serializer が標準ライブラリに追加されるまで 15 年かかり、webp や heic のような最新画像フォーマットのサポートもない
Visual Studio は毎日のようにクラッシュメッセージを出す
昔は熱烈な .NET ファンだったが、Anders のリーダーシップが恋しい
最近のサイドプロジェクトでは、macOS の VSCode で C# REST API バックエンドを開発し、3 年間 Linux にデプロイしている
SQLite、EFCore、Minimal API を使っているが、フロントエンド(NextJS/React/MaterialUI、npm パッケージ 50 個以上)よりずっと快適だ
個人的には一番好きな API フレームワークだ
次善策は TS + Hono + Zod-OpenApi + SwaggerUI の組み合わせだが、型コンテキストの設定がやや面倒だ
.NET の オープンソース化とクロスプラットフォーム化の基盤が Linux ディストリビューションのビルドシステムだった点は印象的だった
そのため彼らの要件を満たすビルドシステムが必要で、結局 Linux ディストリビューションモデルへ統合するのが唯一の道だった
このモデルはシンプルだが性能は劣る。キャッシュ付きの分散ビルドシステムのほうが速いが、メンテナーのワークフローには合わない
シンプルさを最適化するほうがコミュニティ参加を促すには良いと判断した
BSD、S390x など多様なプラットフォームのビルドと配布をコミュニティ自身で行えるようにするのが目標だ
この 10 年間の プルリクエストと前向きな成果物の量は驚くほどだ
今年読んだ中で最も印象深い ソフトウェアエンジニアリング記事が Microsoft から出るとは思わなかった
自分は最近の .NET バージョンが好きだが、その堅牢さは偶然の産物だと思っていた
しかし今回の記事は 品質向上のための体系的な取り組みを示している(図表や LLM 活用事例まで含む)
今後こうした投資が減るとしても、これは「どうあるべきか」を示す良い事例だ
このプロジェクトに参加した人たちは本当にすごい経験をしたのだろうと思う
記事は良かったが、.NET チームは Azure DevOpsを捨てるべきだと思う
キュー待ち時間が最大のボトルネックだ。ベアメタルのビルドサーバーを回すべきだ
Mac ハードウェアは素早く接続されて起動する
我々は各ジョブごとに クリーン VMを新しく立ち上げて、コンプライアンスと安定性を確保している
事前に用意したホットマシンを維持すれば待ち時間はなくせるが、コストが高すぎる
さまざまな SKU を常時待機状態にしておくのは現実的に難しいので、折衷している
なぜ Microsoft の Developer Divisionは業界最高水準なのに、他の部門は無能と官僚主義の象徴になってしまったのか気になる
Bill が去ってから、自分たちを振り返る文化が消えた
複雑なシステムを単純化しようとする 抽象化中心の考え方が問題の根源だと思う
上位レベルですべてを解決しようとするより、下位レベルから積み上げるアプローチのほうが、より多くの問題を根本からなくせる
「1 か月に 3〜4 個の主要バージョンと数十個の SDK バンドをビルドしている」という文を見て、なぜこんなに バリエーションが多いのか気になった
また各バージョンごとに SDK/aspnet/runtime が x64/arm32/arm64、Linux/macOS/Windows などさまざまなプラットフォーム向けにビルドされている
Node が流行する前、.NET はバックエンド構築の 堅実な選択肢だった(性能も Node より優れていた)
最近の Node エコシステムでの サプライチェーン攻撃のあと、多くの開発者が安定したプラットフォームへ戻ってくることを願っている
大きな変化は .NET Core への移行だったが、それももうほぼ 10 年前の話だ
フレームワークや依存関係の更新は多少面倒だが、React プロジェクトの更新に比べればずっと楽だ
短い LTS サイクルのおかげで最新状態の維持はそれほど難しくない。速い開発サイクルでは、こうした保守は当然のことだ
現実には Node.js、Java、ローコード(iPaaS)中心だ
それでも性能問題のおかげで、ときどき C++ アドオンを提案する機会はある