ビルドシステムを使用する理由

問題を報告する ソースを表示

このページでは、ビルドシステムの概要、機能、使用するべき理由、組織のスケーリングを開始するときにコンパイラとビルド スクリプトが最適な選択ではない理由について説明します。このチュートリアルは、ビルドシステムに関してあまり経験のないデベロッパーを対象としています。

ビルドシステムとは

根本的には、すべてのビルドシステムには明確な目的があります。エンジニアが記述したソースコードを、マシンが読み取れる実行可能なバイナリに変換するのです。ビルドシステムは人間が作成したコードだけではなく、テストや本番環境へのリリース用にビルドを自動的に作成できます。何千人ものエンジニアがいる組織では、ほとんどのビルドがエンジニアによって直接トリガーされるのではなく、自動的にトリガーされるのが一般的です。

コンパイラだけを利用することはできますか?

ビルドシステムの必要性はすぐにはわからないかもしれません。ほとんどのエンジニアは、コードの学習中にビルドシステムを使用することはありません。ほとんどの場合、gccjavac などのツールをコマンドラインから直接呼び出すか、統合開発環境(IDE)で同等の関数を呼び出します。ソースコードがすべて同じディレクトリにある限り、次のようなコマンドは問題なく機能します。

javac *.java

これにより、Java コンパイラは現在のディレクトリ内のすべての Java ソースファイルをバイナリクラス ファイルに変換するよう指示されます。最も単純なケースでは、これで十分です。

しかし、コードが拡張するとすぐに、ウォッチフェイスの追加機能が開始します。javac は、現在のディレクトリのサブディレクトリを調べて、インポートするコードを見つけるのに十分です。しかし、ファイル システムの他の部分(複数のプロジェクトで共有されているライブラリなど)に保存されているコードを見つける方法はありません。また、Java コードのビルド方法のみを認識します。大規模なシステムでは多くの場合、さまざまなプログラミング言語で記述された別々のピースと依存関係ウェブがあります。つまり、1 つの言語のコンパイラではシステム全体を構築できない可能性があります。

複数の言語または複数のコンパイル単位からのコードを扱っている場合、コードのビルドはワンステップのプロセスではなくなります。次に、コードが依存する部分を評価し、それぞれの部分で異なるツールセットを使用して、それらの部分を正しい順序でビルドする必要があります。依存関係が変更された場合は、古いバイナリに依存しないように、このプロセスを繰り返す必要があります。中規模のコードベースでも、このプロセスはすぐに煩雑になり、エラーが発生しやすくなります。

また、コンパイラは、Java のサードパーティ JAR ファイルなど、外部依存関係の処理方法についても認識しません。ビルドシステムを使用していない場合は、インターネットから依存関係をダウンロードし、ハードドライブの lib フォルダに固定して、そのディレクトリからライブラリを読み取るようにコンパイラを構成することで、これを管理できます。時間の経過とともに、これらの外部依存関係の更新、バージョン、ソースの維持は困難になります。

シェル スクリプト

趣味のプロジェクトは、コンパイラだけでビルドできるシンプルなものから始まり、前述の問題に直面し始めるとします。ビルドシステムが必要ないと考えている場合でも、正しいシェルでビルドを行う簡単なシェル スクリプトを使用して、面倒な作業を自動化できます。これは当面は役立ちますが、すぐに問題が増えてきます。

  • 面倒なものになります。システムが複雑化するにつれて、実際のコードと同じくらいビルド スクリプトの作業に多くの時間が費やされ始めます。シェル スクリプトのデバッグは手間がかかり、ハッキングがどんどん重なるようになっています。

  • 遅いです。誤って古いライブラリに依存しないようにするため、ビルド スクリプトを実行するたびに、すべての依存関係を順番にビルドするようにします。再ビルドが必要な部分を検出するためのロジックを追加することを検討しますが、これはスクリプトがかなり複雑になり、エラーが発生しやすくなります。毎回再ビルドする必要がある部分を指定すれば、その後は正方形に戻すことができます。

  • このたび、リリースが開始されました。最終的なビルドを作成するために jar コマンドに渡す必要のある引数をすべて調べてください。アップロードして中央リポジトリに push する方法を覚えておいてください。ドキュメントの更新をビルドして push し、ユーザーに通知を送信します。別のスクリプトが必要かもしれません。

  • みなさんにハードドライブがクラッシュしたため、システム全体を再作成する必要があります。すべてのソースファイルをバージョン管理で管理しても問題ありませんが、ダウンロードしたライブラリについてはどうでしょうか。すべて再度表示され、最初のダウンロード時と同じバージョンかどうかをご確認いただけますか?スクリプトは、特定の場所にインストールされる特定のツールに依存している可能性があります。同じ環境を復元して、スクリプトを再度実行できるようにするには、では、コンパイラが正常に動作するように、かなり前に設定していたすべての環境変数のことを覚えておいてください。

  • 問題があるにもかかわらず、プロジェクトは成功し、より多くのエンジニアの雇用を開始できます。新しい開発者がチームに参加するたびに、同じ問題に悩まされ、ブートストラップを順を追って進める必要が生じることに気づきました。しかし、どのような努力を払っても、それぞれの人のシステムには小さな違いがあります。多くの場合、あるユーザーのマシンが機能しても、別のマシン上では機能しません。その差がどこにあるのかを理解するのに、数時間のツールパスまたはライブラリのバージョンをデバッグするたびに時間がかかります。

  • ビルドシステムを自動化する必要があると判断した場合。理論的には、これは新しいコンピュータを取得し、cron を使用して毎晩ビルド スクリプトを実行するように設定するだけです。手間のかかるセットアップ プロセスがまだ必要ですが、人間の脳が軽微な問題を検出して解決できるというメリットはありません。昨朝、昨夜の開発者は、システムには影響があっても自動ビルドシステムでは機能しない変更を行ったため、昨夜のビルドが失敗しました。毎回簡単な修正ですが、多くの場合は、このような簡単な修正を見つけて適用するのに毎日多くの時間を費やしています。

  • プロジェクトの規模が大きくなるほどビルドも遅くなります。ある日、ビルドの完了を待つ間、休暇中の同僚のアイドル状態のデスクトップを悲しそうに見つめ、この計算能力をすべて活用する方法が欲しいと願いました。

スケールというよくある問題に遭遇しました。1 人のデベロッパーが長くても 1 ~ 2 週間は数百行ほどのコードを扱う場合(大学を卒業したばかりのジュニア デベロッパーの場合は、このような状況が続く場合もある)、コンパイラがあれば十分です。スクリプトは少し進歩することがあります。しかし、複数のデベロッパーやそのマシン間で調整が必要な場合、完璧なビルド スクリプトだけでは不十分です。それらのマシンの軽微な違いを考慮するのは、非常に難しいからです。この時点でシンプルなアプローチが完成するので、次は実際のビルドシステムに投資します。