2/14/2017

Googleでのソフトウェア・エンジニアリング (2.2)

Googleでのソフトウェア・エンジニアリング」と題する論文。

2.2. ビルド・システム

Googleは、コンパイル、ソフトウェアのリンク、テストを行うBlaze*と知られる分散型ビルドシステムを使用している。これはリポジトリ全体を横断して働くソフトウェアのビルドとテストの標準コマンドを提供する。これらの標準コマンドや高度に最適化された実装が、Googleエンジニアにとって、リポジトリのソフトウェアをビルドやテストするのがとても単純で素早くなることを意味する。この一貫性が、エンジニアがプロジェクトの境界を横断して変更を行うことを実践すのに役立つ成功への鍵である。

* オープンソース化したものがBazel思われる

プログラマはBlazeがソフトウェアのビルド方法を決定するために使用する"BUILD"ファイルを書く。ライブラリ、プログラム、そしてテストのようなビルド・エンティティ(実体)は、各エンティティ、名前、ソースファイル、ライブラリあるいは依存する他のビルド・エンティティを指定する極めて高水準な宣言的ビルド仕様を使って宣言される。これらのビルド仕様は「ビルド・ルール(規約)」と呼ばれる宣言で構成される。各々が「ここに他のライブラリに依存するソースファイルを持つC++ライブラリがある」のような高水準なコンセプトを規定する。そして、一連のビルドステップに各ビルドルールをマッピングするのをビルドシステムに委ねられる。例えば、各ソースファイルをコンパイルするステップや、リンクのためのステップ、使用するコンパイラやコンパイルフラグを決定するためのステップである。

一部の例、特にGoプログラムは、(しばしば)BUILDファイルの依存情報がソースファイルの依存情報を抽象化しているので、ビルドファイルが自動的に生成(更新)できる。しかし、それでもリポジトリにチェックインされる。これにより、ビルドシステムはソースファイルよりむしろビルドファイルのみを分析することで依存関係を迅速に判断でき、サポートされる多くの様々なプログラミング言語のためのビルドシステム、コンパイラ、解析ツール間で過度な結合を回避することを保証する。

ビルドシステムの実装は、Googleの分散コンピューティング・インフラを使用している。各ビルドの作業は通常、数百あるいは数千のコンピュータに分散されている。これにより、非常に大きなプログラムを迅速にビルドし、並行して数千のテストを実行することを可能にしている。

個々のビルドステップは外部から影響されないよう(hermetic)にしなければならない: それらは宣言された入力にのみ依存する。全ての依存関係が正しく宣言されるようにすることは、ビルドの配布の結果である: 宣言された入力のみがビルドステップが実行されているコンピュータに送られる。その結果、ビルドシステムは真の依存関係を知る頼みにできる。ビルドシステムが呼び出すコンパイラは入力として扱われる。

個々のビルドステップは決定論的(deterministic)である。結果として、ビルドシステムはビルド結果をキャッシュできる。ソフトウェア・エンジニアはワークスペースを古い変更番号に同期させ再構築し、正確に同じバイナリを取得できるだろう。さらに、このキャッシュは様々なユーザ間で安全に共有できる。(この作業を適切に行うには、例えば生成された出力ファイルのタイムスタンプを取りやめるなど、ビルドによって呼び出されたツールの非決定性を取り除く必要がある。)

ビルドシステムは信頼性がある。ビルドシステムは、ビルド・ルール自体への変更の依存関係を追跡し、生産アクションが変更された場合、例えばコンパイラオプションのみが変更された場合など、たとえアクションへの入力が無かった場合でも、ターゲットを再ビルドすることができる。ビルド途中での中断、あるいはビルド中のソースファイルの修正でも、適切に処理を行う: そのような場合は、ビルドコマンドを再実行するだけで良い。"make clean"に相当するコマンドを実行する必要はない。

ビルド結果はクラウドにキャッシュされる。これには中間結果も含まれる。もし、別のビルド要求が同じ結果が必要な場合、ビルドシステムは要求が別のユーザからであっても、再ビルドではなく自動的に再利用を行う。

インクリメンタル再ビルドは高速である。ビルドシステムはメモリに常駐しているので、再ビルドには、最後のビルドから変更されたファイルだけをインクリメンタルに解析できる。

事前サブミット(Presubmit)・チェック。Googleはコードレビューを開始するあるいはリポジトリに変更をコミットする準備をする際、一連のテストを自動的に実行するツールを持っている。リポジトリの各サブツリーは、どのテストを実行するか、コードレビュー時あるいはサブミット前直ちに実行するか、あるいはその両方かを決定する設定ファイルを含むことができる。テストは同期的に、例えばレビューの変更を送る前、あるいはリポジトリに変更をコミットする前に実行する(高速な実行テストに適している)、あるいは非同期に行うことができる。そして、結果がレビュー・ディスカッション・スレッドにメールで送信される。[レビュー・スレッドは、コードレビューが行われるメールスレッドである; そのスレッド内の全情報がウェブベースのコードレビュー・ツールにも表示される。]