「ビルド (ソフトウェア)」の版間の差分

削除された内容 追加された内容
Goのインクリメンタルビルドについて追記。
 
(2人の利用者による、間の3版が非表示)
1行目:
[[ソフトウェア]]の'''ビルド'''({{lang-en-short|build}})は、[[プログラミング言語]]で書かれた[[ソースコード]]ファイルや各種[[リソースファイル]]{{要曖昧さ回避|date=2023年3月}}を独立したソフトウェア生成物に変換する[[コンピュータ]]上で実行されるプロセス、またはその結果を指す。ビルドの最終生成物は[[バイナリ形式]]の[[実行ファイル]]であったり、再利用可能な[[ライブラリ]]であったり、[[バイトコード]]あるいはそれらをまとめた[[アーカイブ (コンピュータ)|アーカイブ]]であったりすることもある<ref>例えば[[Java]]では[[JAR (ファイルフォーマット)|JAR]]を、[[Android (オペレーティングシステム)|Android]]では[[APK (ファイル形式)|APK]]をアーカイブ形式としている。</ref>。
 
== 概要 ==
ビルドにはいくつかのステップがあり、その内容は[[プログラミング言語]]やビルドツール、開発環境や実行環境(ターゲットアーキテクチャ、[[オペレーティングシステム]]あるいは[[仮想マシン]])によっても異なる。例えば[[C言語]]あるいは[[C++]]の場合、[[ソースファイル]](ソースコード)を[[コンパイラ]]によって[[オブジェクトファイル]](オブジェクトコード)に翻訳(コンパイル)した後、[[リンケージエディタ|リンカ]]によってオブジェクトコードを結合し、[[実行ファイル]]を生成する。プログラムから実行時に参照される各種アイコン画像やローカライズされた文字列などを実行ファイル内に「リソース」として含めることもあり、ビルドプロセスでリソースのコンパイルとリンクを実行する。
 
単純なプログラムでは、単一のソースファイルをコンパイルするだけで済むが、複雑なソフトウェアでは通例メンテナンス性向上の観点からソースコードはモジュールごとに分類・分割された多数のファイルによって構成されており、各ファイルを個別にコンパイル(分割コンパイル)した後で、リンク時に実体の依存関係を解決する。C/C++のような原始的なプログラミング言語では、[[ヘッダファイル]]を利用して、ユーザー定義型や定数、および関数などの定義または宣言を共有することが多い。ヘッダーファイルのインクルードにより、ファイル間の依存関係が発生する。
39行目:
 
== インクリメンタルビルド ==
複数のソースファイルから成るソフトウェアの開発プロセスにおいて、ソースファイルにちょっとした変更を加えただけで、毎回すべてのソースファイルを無条件にコンパイルし直すのは効率が悪い。自動化されたビルドシステムでは、[[タイムスタンプ]]などを利用して変更のあったファイルのみを検出し、そのファイル自身とそれに依存する関連ファイルのみをコンパイルし直してリンクする「インクリメンタルビルド」(増分ビルド)をサポートしている<ref>[https://docs.microsoft.com/ja-jp/visualstudio/msbuild/incremental-builds インクリメンタル ビルド - Visual Studio | Microsoft Docs]</ref><ref>[https://blog.gradle.org/introducing-incremental-build-support Introducing Incremental Build Support | Gradle Blog]</ref>。これにより、コード編集・ビルド・実行・テストの開発サイクルを高速化することができる。
 
さらに、変更のあったモジュールのみをリンクし直す「インクリメンタルリンク」(増分リンク)をサポートする処理系も存在する<ref>[https://docs.microsoft.com/en-us/cpp/build/reference/incremental-link-incrementally /INCREMENTAL (Link Incrementally) | Microsoft Docs]</ref>。実行時に個別のライブラリモジュールをロードして結合する[[動的リンク]]ライブラリ方式の場合、リンク処理はシンボル情報のみが書かれたインポートライブラリを実行ファイルにリンクするだけなので高速だが、ビルド時にすべてのモジュールを結合して1つのファイルを生成する[[静的リンク]]ライブラリ方式の場合、リンク処理には時間がかかるため、インクリメンタルリンクが特に効果を発揮する。
 
ビルドシステムではなく、コンパイラモジュール自身が「インクリメンタルコンパイル」(増分コンパイル)をサポートしている言語もある。例えば[[Rust (プログラミング言語)|Rust]]のコンパイラはバージョン1.24以降でインクリメンタルコンパイルをサポートする<ref>[https://doc.rust-lang.org/edition-guide/rust-2018/the-compiler/incremental-compilation-for-faster-compiles.html Incremental Compilation for faster compiles - The Edition Guide]</ref><ref>[https://blog.rust-lang.org/2016/09/08/incremental.html Incremental Compilation | Rust Blog]</ref>。Rustコンパイラは、最初のステップとして[[抽象構文木]] (abstract syntax tree, AST) を構築し、次にASTを解析することで型情報 (type information) および個々の関数に関する中位の中間表現 (mid-level intermediate representation, MIR) を生成する。その後、エラーが見つからなければ、ソースレベルのモジュールごとにオブジェクトファイルを生成しながら、MIRから機械語コードに変換される。これらの型情報やMIR、およびオブジェクトファイルの要素を中間結果 (intermediate result) とみなし、ディスクにキャッシュとして保存しておき、2回目以降のコンパイルではキャッシュからロードする。また依存関係グラフをもとに、変更のあった要素だけを更新する。ただしRustのインクリメンタルコンパイルは2回目以降のビルドサイクルを高速化させるものの、最終的に生成されるバイナリの実行速度を若干低下させるデメリットがあるため、リリースビルドでは有効化されない。
ビルドシステムではなく、コンパイラモジュール自身が「インクリメンタルコンパイル」(増分コンパイル)をサポートしている言語もある<ref>[https://blog.rust-lang.org/2016/09/08/incremental.html Incremental Compilation | Rust Blog]</ref>。
 
=== Go ===