<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Build System on kenji.blog</title><link>http://kenji.blog/tags/build-system/</link><description>Recent content in Build System on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ja</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/tags/build-system/index.xml" rel="self" type="application/rss+xml"/><item><title>CMakeを使ったクロスプラットフォームなC++ビルド環境の構築手順</title><link>http://kenji.blog/p/cmake-cross-platform-build-environment-guide/</link><pubDate>Sat, 12 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/p/cmake-cross-platform-build-environment-guide/</guid><description>&lt;img src="http://kenji.blog/p/cmake-cross-platform-build-environment-guide/img/eyecatch.jpg" alt="Featured image of post CMakeを使ったクロスプラットフォームなC++ビルド環境の構築手順" />&lt;p>C++でのソフトウェア開発において、長年多くの開発者を悩ませてきたのが「ビルドシステム」の選択と構築です。C++には公式の標準パッケージマネージャやビルドシステムが存在しないため、プラットフォーム（Windows、Linux、macOS）ごとに異なるコンパイラやビルドツール（MSVC、GCC、Clang、Make、Ninjaなど）を使い分ける必要がありました。&lt;/p>
&lt;p>しかし、現在では &lt;strong>CMake&lt;/strong> が事実上の業界標準（デファクトスタンダード）として定着しており、CMakeを正しく活用することで、単一の &lt;code>CMakeLists.txt&lt;/code> からクロスプラットフォームなビルド環境をエレガントに構築できるようになっています。&lt;/p>
&lt;p>本記事では、CMakeを用いた最新（モダンCMake）のクロスプラットフォームなC++ビルド環境の構築手順について、基礎から高度なテクニックまで、徹底的かつ詳細に解説します。&lt;/p>
&lt;h2 id="1-cmakeとは何かメタビルドシステムの概念">1. CMakeとは何か？（メタビルドシステムの概念）
&lt;/h2>&lt;p>CMakeは、それ自体が直接ソースコードをコンパイルするツールではありません。CMakeは「ビルドシステムを生成するシステム」、すなわち &lt;strong>メタビルドシステム (Meta-Build System)&lt;/strong> です。&lt;/p>
&lt;p>CMakeの主な役割は、プラットフォームやコンパイラに依存しない抽象的な設定ファイル（&lt;code>CMakeLists.txt&lt;/code>）を読み込み、それぞれの環境に最適なネイティブのビルドスクリプト（例：Linuxなら &lt;code>Makefile&lt;/code>、Windowsなら Visual Studioの &lt;code>.sln&lt;/code> プロジェクトファイル、あるいは高速な &lt;code>build.ninja&lt;/code>）を自動生成することです。&lt;/p>
&lt;p>以下の図は、CMakeの生成プロセスを表しています。&lt;/p>
&lt;div class="mermaid">graph TD
A["CMakeLists.txt (抽象的なビルド定義)"] --> B["CMake (Configure &amp; Generate)"]
B --> C["Unix Makefiles"]
B --> D["Ninja Build Files"]
B --> E["Visual Studio Solutions"]
B --> F["Xcode Projects"]
C --> G["Native Build Tool (make, ninja, MSBuild, xcodebuild)"]
D --> G
E --> G
F --> G
G --> H["Executable / Shared Library / Static Library"]&lt;/div>
&lt;p>このように、CMakeを間に挟むことで、開発者はOSごとの細かなコマンドの違いを意識することなく、C++プロジェクトを管理できます。&lt;/p>
&lt;h2 id="2-モダンcmakeの基本変数からターゲットへ">2. モダンCMakeの基本：変数からターゲットへ
&lt;/h2>&lt;p>CMake 3.0以降の記法は「モダンCMake」と呼ばれ、それ以前（レガシーCMake）とは設計思想が根本的に異なります。レガシーCMakeでは、ディレクトリ単位でグローバル変数を書き換えていく（例：&lt;code>include_directories()&lt;/code> や &lt;code>link_libraries()&lt;/code> を使う）アプローチが主流でしたが、これは設定が意図せず他のモジュールに波及してしまうという深刻な副作用を引き起こしがちでした。&lt;/p>
&lt;p>モダンCMakeでは、すべてを &lt;strong>ターゲット (Target)&lt;/strong> と &lt;strong>プロパティ (Property)&lt;/strong> として扱います。オブジェクト指向プログラミングにおけるクラスとメンバ変数の関係に似ています。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>ターゲット&lt;/strong>: 実行可能ファイル（Executable）やライブラリ（Library）。&lt;/li>
&lt;li>&lt;strong>プロパティ&lt;/strong>: そのターゲットをビルドするために必要なソースファイル、インクルードディレクトリ、コンパイルオプション、リンクする他のライブラリなど。&lt;/li>
&lt;/ul>
&lt;p>設定を特定のターゲットにのみカプセル化（閉じ込める）することで、大規模なプロジェクトでも破綻しない安全なビルド定義が可能になります。&lt;/p>
&lt;h3 id="最小限の-cmakeliststxt">最小限の &lt;code>CMakeLists.txt&lt;/code>
&lt;/h3>&lt;p>まずは、もっとも基本的な &lt;code>CMakeLists.txt&lt;/code> を見てみましょう。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># CMakeの最小要求バージョンを指定
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># プロジェクト名と使用する言語を指定
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">VERSION&lt;/span> &lt;span class="s">1.0.0&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># C++の標準規格（C++20）を要求
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_EXTENSIONS&lt;/span> &lt;span class="s">OFF&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c"># コンパイラ固有の拡張機能を無効化
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># 実行可能ターゲットの定義
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>このわずか数行で、C++20を要求し、コンパイラ拡張を無効化したポータブルな実行可能ファイルのビルド設定が完了します。&lt;/p>
&lt;h2 id="3-依存関係とスコープ-public--private--interface">3. 依存関係とスコープ: PUBLIC / PRIVATE / INTERFACE
&lt;/h2>&lt;p>モダンCMakeをマスターする上で最も重要かつ難解なのが、&lt;code>target_include_directories&lt;/code> や &lt;code>target_link_libraries&lt;/code> などで使用される &lt;strong>&lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code>, &lt;code>INTERFACE&lt;/code>&lt;/strong> という3つのアクセス修飾子（スコープ）の概念です。&lt;/p>
&lt;p>これらは、ターゲットのプロパティ（インクルードパスや依存ライブラリ）を、「自分自身のビルドに必要か？」「自分に依存している他のターゲットにも伝播させるか？」を制御するためのものです。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>PRIVATE&lt;/code>&lt;/strong>: そのターゲット自身のビルドにのみ必要。依存先のターゲットには伝播&lt;strong>しない&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>&lt;code>INTERFACE&lt;/code>&lt;/strong>: そのターゲット自身のビルドには不要だが、依存先のターゲットのビルドには伝播&lt;strong>する&lt;/strong>（ヘッダーオンリーライブラリなどで使用）。&lt;/li>
&lt;li>&lt;strong>&lt;code>PUBLIC&lt;/code>&lt;/strong>: そのターゲット自身のビルドに必要であり、かつ、依存先のターゲットにも伝播&lt;strong>する&lt;/strong>（&lt;code>PRIVATE&lt;/code> + &lt;code>INTERFACE&lt;/code>）。&lt;/li>
&lt;/ol>
&lt;p>以下の図で、依存関係の伝播（Usage Requirements の伝播）を視覚化してみましょう。&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Libraries"
MathLib["MathLib (Static Library)"]
NetworkLib["NetworkLib (Shared Library)"]
HeaderLib["HeaderLib (Header Only)"]
end
subgraph "Application"
App["Main Application"]
end
App -- "target_link_libraries(App PRIVATE MathLib)" --> MathLib
App -- "target_link_libraries(App PUBLIC NetworkLib)" --> NetworkLib
NetworkLib -- "target_link_libraries(NetworkLib INTERFACE HeaderLib)" --> HeaderLib
note1["AppはMathLibの実装に依存するが、外部には見せない"]
note2["NetworkLibはHeaderLibのインターフェースを公開する"]&lt;/div>
&lt;h3 id="スコープの具体的な使用例">スコープの具体的な使用例
&lt;/h3>&lt;p>あるライブラリ &lt;code>MyLib&lt;/code> が、内部の実装として &lt;code>nlohmann/json&lt;/code> を使用しており、公開しているヘッダファイル &lt;code>MyLib.hpp&lt;/code> の中では &lt;code>nlohmann/json&lt;/code> をインクルードしていないと仮定します。この場合、&lt;code>MyLib&lt;/code> を使う側（アプリケーション）は JSONライブラリの存在を知る必要はありません。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># ライブラリの定義
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">src/MyLib.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># 自プロジェクトのインクルードディレクトリの指定
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># includeディレクトリは、MyLibを使う人にも必要なので PUBLIC にする
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># srcディレクトリは、MyLibの実装でのみ使うので PRIVATE にする
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_include_directories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PUBLIC&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">INSTALL_INTERFACE:include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">${&lt;/span>&lt;span class="nv">CMAKE_CURRENT_SOURCE_DIR&lt;/span>&lt;span class="o">}&lt;/span>&lt;span class="s">/src&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># jsonライブラリは内部実装でのみ使うため PRIVATE でリンクする
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">nlohmann_json::nlohmann_json&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>逆に、&lt;code>MyLib.hpp&lt;/code> の中で &lt;code>#include &amp;lt;nlohmann/json.hpp&amp;gt;&lt;/code> と書いている場合は、&lt;code>MyLib&lt;/code> を使う側も JSON のヘッダパスを知らなければコンパイルエラーになるため、&lt;code>PUBLIC&lt;/code> でリンクする必要があります。このスコープを適切に設定することで、ビルド時間の短縮や不要な依存関係の漏洩（リポイズニング）を防ぐことができます。&lt;/p>
&lt;h2 id="4-アウトオブソースビルド-out-of-source-build">4. アウトオブソースビルド (Out-of-source Build)
&lt;/h2>&lt;p>CMakeを使う上で必ず守るべきベストプラクティスが &lt;strong>アウトオブソースビルド&lt;/strong> です。
これは、ソースコードが置かれているディレクトリ（ソースツリー）にビルド成果物（オブジェクトファイルや実行ファイル）を一切出力せず、別の専用ディレクトリ（通常は &lt;code>build/&lt;/code>）に分離してビルドを行う手法です。&lt;/p>
&lt;div class="mermaid">graph TD
Root["Project Root (Git Repository)"]
Root --> Src["src/"]
Root --> Inc["include/"]
Root --> CMake["CMakeLists.txt"]
Root -. "Create build dir" .-> Build["build/ (Out-of-source)"]
Build --> Obj["CMakeFiles/ (Object files, caches)"]
Build --> Bin["Binaries (MyApp.exe)"]
Build --> Gen["Generated Makefile / build.ninja"]&lt;/div>
&lt;p>この構成により、ビルド環境をリセットしたい場合は &lt;code>build&lt;/code> ディレクトリを丸ごと削除するだけで済み、ソースツリーが汚れないため Git の管理も容易になります（&lt;code>.gitignore&lt;/code> に &lt;code>build/&lt;/code> を追加するだけで済みます）。&lt;/p>
&lt;h3 id="ビルドの実行手順">ビルドの実行手順
&lt;/h3>&lt;p>モダンCMakeでは、OSやビルドツールに依存しない共通のコマンドでビルドを実行できます。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. コンフィグレーションと生成（ビルドディレクトリを作成しつつ設定）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake -S . -B build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. 実際のビルド（コンパイルとリンク）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># (オプション) マルチスレッドでビルドする場合は -j オプションを使用&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ここで &lt;code>cmake -S . -B build&lt;/code> は、「現在のディレクトリ（&lt;code>.&lt;/code>）をソースディレクトリとし、&lt;code>build&lt;/code> をビルドディレクトリとして設定する」という意味になります。&lt;/p>
&lt;h2 id="5-サードパーティライブラリの導入方法">5. サードパーティライブラリの導入方法
&lt;/h2>&lt;p>C++開発において、外部ライブラリ（サードパーティ製ライブラリ）の導入は常にハードルが高いものでした。しかし現在では、主に以下の3つのアプローチが標準的です。&lt;/p>
&lt;h3 id="51-find_package-システムインストール済みのライブラリ検索">5.1. find_package (システムインストール済みのライブラリ検索)
&lt;/h3>&lt;p>システムに既にインストールされているライブラリ（例: OpenSSLやZlibなど）を見つけてリンクする、最も伝統的な方法です。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">find_package&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB&lt;/span> &lt;span class="s">REQUIRED&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB_FOUND&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">ZLIB::ZLIB&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-fetchcontent-ソースからのダウンロードと組み込み">5.2. FetchContent (ソースからのダウンロードと組み込み)
&lt;/h3>&lt;p>CMake 3.11で導入され、3.14以降で強力になったモジュールです。ビルド時に外部のGitリポジトリやURLから直接ソースコードをダウンロードし、プロジェクトの一部として一緒にビルドします。依存関係を一元管理できるため、クロスプラットフォームでの再現性が極めて高くなります。&lt;/p>
&lt;p>以下は GoogleTest を FetchContent で導入する例です。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">FetchContent&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">FetchContent_Declare&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">googletest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_REPOSITORY&lt;/span> &lt;span class="s">https://github.com/google/googletest.git&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_TAG&lt;/span> &lt;span class="s">v1.14.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ライブラリをプロジェクトに取り込む
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">FetchContent_MakeAvailable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">googletest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># テスト用実行ファイルの作成とリンク
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">test/main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-vcpkg-との連携">5.3. vcpkg との連携
&lt;/h3>&lt;p>Microsoftが主導するC++向けパッケージマネージャ &lt;strong>vcpkg&lt;/strong> を使うと、何千ものライブラリを簡単に導入できます。vcpkg はCMakeとシームレスに連携できるように設計されています。&lt;/p>
&lt;p>CMake実行時に、vcpkg のツールチェーンファイルを指定するだけで、&lt;code>find_package&lt;/code> が自動的に vcpkg 内のライブラリを探索するようになります。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE&lt;span class="o">=&lt;/span>/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>また、&lt;code>vcpkg.json&lt;/code>（マニフェストモード）をプロジェクトルートに配置することで、必要なライブラリのバージョン管理を完全に自動化できます。&lt;/p>
&lt;h2 id="6-クロスプラットフォーム対応のコンパイラフラグ">6. クロスプラットフォーム対応のコンパイラフラグ
&lt;/h2>&lt;p>Windows (MSVC)、Linux (GCC/Clang)、macOS (Apple Clang) のいずれの環境でもビルドを通すためには、コンパイラ固有のフラグを適切に設定する必要があります。&lt;/p>
&lt;p>CMakeの &lt;strong>ジェネレータ式 (Generator Expressions)&lt;/strong> を使うことで、「もしコンパイラがMSVCならこのフラグ、そうでないならあのフラグ」といった条件分岐を宣言的に記述できます。ジェネレータ式は &lt;code>$&amp;lt;...&amp;gt;&lt;/code> という構文を使用し、ビルドシステムの生成時（Generateフェーズ）に評価されます。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 全プラットフォームで最高レベルの警告を有効にする例
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># MSVCの場合
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;CXX_COMPILER_ID:MSVC&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">:/W4&lt;/span> &lt;span class="s">/WX&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># GCC または Clang の場合
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;OR:$&amp;lt;CXX_COMPILER_ID:GNU&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:Clang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:AppleClang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;gt;:-Wall&lt;/span> &lt;span class="s">-Wextra&lt;/span> &lt;span class="s">-Wpedantic&lt;/span> &lt;span class="s">-Werror&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>この方法を用いることで、&lt;code>if(MSVC)&lt;/code> のような条件分岐を多用して &lt;code>CMakeLists.txt&lt;/code> が読みにくくなるのを防ぎ、ターゲットごとに柔軟な設定が可能になります。&lt;/p>
&lt;h2 id="7-テスト環境の構築-ctest">7. テスト環境の構築 (CTest)
&lt;/h2>&lt;p>クロスプラットフォーム環境における品質保証において、自動テストの導入は必須です。CMakeには &lt;strong>CTest&lt;/strong> というテストランナーが標準で付属しています。&lt;/p>
&lt;p>前述の &lt;code>FetchContent&lt;/code> で導入した GoogleTest を CTest と統合する手順は以下の通りです。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># テスト機能を有効化（ルートのCMakeLists.txtに一度だけ記述）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">test/math_test.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span> &lt;span class="s">MyLib&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># CTestにテストとして登録する
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">GoogleTest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">gtest_discover_tests&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ビルド後、ビルドディレクトリ内で &lt;code>ctest&lt;/code> コマンドを実行するだけで、すべてのテストが実行され結果がレポートされます。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ctest --output-on-failure -C Release
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="8-ビルドシステムの理論と数理モデル">8. ビルドシステムの理論と数理モデル
&lt;/h2>&lt;p>ここで少し視点を変えて、大規模プロジェクトにおけるビルドシステムと並列コンパイルの効率性について、数学的なモデルを用いて考察してみましょう。&lt;/p>
&lt;p>ビルド時間（コンパイル時間）の短縮は、C++開発における永遠の課題です。ソースコードの分割と並列コンパイルを行うことで、ビルド時間を短縮できます。この並列化による速度向上（Speedup）は、&lt;strong>アムダールの法則 (Amdahl&amp;rsquo;s Law)&lt;/strong> によってモデル化されます。&lt;/p>
&lt;p>プログラムのうち、並列化可能な部分の割合を $P$ 、直列で実行しなければならない（並列化不可能な）部分の割合を $1-P$ とし、使用するプロセッサの数を $N$ とした場合、全体的な理論上の最大速度向上率 $S(N)$ は次の数式で表されます。&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;p>C++のビルドプロセスにおいて、「各 &lt;code>.cpp&lt;/code> ファイルから &lt;code>.o&lt;/code> または &lt;code>.obj&lt;/code> へのコンパイル」は独立しており並列化可能ですが（$P$ の部分）、「最終的なリンカ (Linker) による結合処理」は基本的に直列で行われます（$1-P$ の部分）。&lt;/p>
&lt;p>したがって、どれだけコア数の多いCPU（$N \to \infty$）を用意したとしても、リンク時間というボトルネックが存在する限り、最大速度向上率は以下の式に漸近してしまいます。&lt;/p>
$$ \lim_{N \to \infty} S(N) = \frac{1}{1 - P} $$
&lt;p>この数式が示唆しているのは、「単にCPUコアを増やすだけではビルド時間の短縮には限界がある」ということです。モダンCMakeにおける &lt;code>PRIVATE&lt;/code> や &lt;code>INTERFACE&lt;/code> を適切に使い分け、ヘッダーファイルの依存関係を最小限に抑える（前方宣言を活用する等）ことで、$P$ の割合を大きくし、インクリメンタルビルド時の再コンパイル対象を減らすことが、実用上最も効果的なビルド高速化の戦略となります。&lt;/p>
&lt;p>また、リンク時間の短縮においては、静的ライブラリ（Static Library）から共有ライブラリ / DLL （Shared Library）への切り替えや、LLD / Mold などの高速なリンカを採用することが重要です。&lt;/p>
&lt;p>CMakeでは、次のようにリンカの指定を簡単に行うことができます。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Clang/GCC環境で lld リンカを使用するよう設定
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">UNIX&lt;/span> &lt;span class="s">AND&lt;/span> &lt;span class="s">NOT&lt;/span> &lt;span class="s">APPLE&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s2">&amp;#34;-fuse-ld=lld&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="9-複雑なディレクトリ構成の実践例">9. 複雑なディレクトリ構成の実践例
&lt;/h2>&lt;p>実際のアプリケーション開発では、多数のモジュールが組み合わさったディレクトリ構成になります。最後に、理想的な中規模プロジェクトのディレクトリ構造と、親子の &lt;code>CMakeLists.txt&lt;/code> の関係を示します。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ProjectRoot/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── CMakeLists.txt (Root: プロジェクト全体の定義)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── vcpkg.json (依存ライブラリの定義)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── external/ (外部モジュール)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── include/ (公開ヘッダー)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── myapp/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── src/ (ソースコードと内部ビルド定義)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── main.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── math/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── Vector3.hpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └── Vector3.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── network/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── NetworkManager.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── tests/ (テストコード)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── math_test.cpp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ルートの &lt;code>CMakeLists.txt&lt;/code> は、環境設定や全体のオプション定義のみを行い、サブディレクトリを &lt;code>add_subdirectory()&lt;/code> で追加していきます。&lt;/p>
&lt;p>&lt;strong>Root &lt;code>CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># グローバルな設定
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># テストの有効化
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># サブディレクトリの追加
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">src&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">tests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>&lt;code>src/CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 各モジュールを追加
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">math&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">network&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># 最終的な実行ファイル
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># モジュールのリンク
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">MathLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">NetworkLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>このようにディレクトリごとに &lt;code>CMakeLists.txt&lt;/code> を分割し、ターゲット同士の依存関係として定義していくことで、モジュールの再利用性が高まり、ビルドの並列性も向上します。これがモダンCMakeが提唱する「モジュール化されたビルド環境」の真骨頂です。&lt;/p>
&lt;h2 id="10-まとめ">10. まとめ
&lt;/h2>&lt;p>CMakeを用いたクロスプラットフォームなC++ビルド環境の構築手順について解説しました。
ポイントを振り返ります。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>メタビルドシステムの理解&lt;/strong>: CMakeはビルドスクリプトを生成するツールである。&lt;/li>
&lt;li>&lt;strong>モダンCMakeの徹底&lt;/strong>: 変数を使わず、&lt;code>add_executable&lt;/code>, &lt;code>target_link_libraries&lt;/code>, &lt;code>target_include_directories&lt;/code> などの&lt;strong>ターゲット指向&lt;/strong>で設定をカプセル化する。&lt;/li>
&lt;li>&lt;strong>スコープの適切な設定&lt;/strong>: &lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code>, &lt;code>INTERFACE&lt;/code> を正しく使い分け、依存関係の波及を制御する。&lt;/li>
&lt;li>&lt;strong>アウトオブソースビルドの徹底&lt;/strong>: &lt;code>build/&lt;/code> ディレクトリ内でビルドを行い、ソースツリーを汚さない。&lt;/li>
&lt;li>&lt;strong>サードパーティ連携&lt;/strong>: &lt;code>FetchContent&lt;/code> や &lt;code>vcpkg&lt;/code> を駆使し、依存ライブラリの解決を自動化する。&lt;/li>
&lt;li>&lt;strong>ジェネレータ式の活用&lt;/strong>: コンパイラごとのフラグの違いをスマートに吸収する。&lt;/li>
&lt;li>&lt;strong>数理的アプローチ&lt;/strong>: アムダールの法則を意識し、依存関係を減らして並列コンパイルの効率を高める。&lt;/li>
&lt;/ol>
&lt;p>最初は難解に感じるCMakeですが、ターゲットとプロパティの概念さえ掴んでしまえば、どんなに複雑で巨大なC++プロジェクトであっても、整然としたビルド環境を維持することができます。ぜひ本記事を参考に、最新のモダンCMakeの記法でC++開発環境を構築してみてください。&lt;/p></description></item></channel></rss>