CMakeで複数ディレクトリ構成を作る方法|add_subdirectoryの使い方

◎ 本記事は「CMake講座」シリーズの第3回です。
前回 -> 【第2回】CMakeLists.txtの基本を理解しよう 〜主要コマンドと構成の基礎〜
次回 ->【第4回】CMakeでビルドタイプとコンパイルオプションを管理しよう!〜Debug/Releaseの理解〜

○ シリーズ全体の構成はこちら: CMake講座トップページ

【第3回】CMakeで複数ディレクトリ構成を作ろう!〜モジュール分割の基本〜

これまでの記事では、単一の CMakeLists.txt で小規模なC++プロジェクトを構築してきました。
実際の開発では、コードを複数のディレクトリに分けて整理することが一般的です。
今回は、CMakeで複数ディレクトリ構成を扱う方法を学びます。


1. ディレクトリを分割する

プロジェクトが大きくなると、ソースコードやライブラリをディレクトリ単位で整理する必要が出てきます。

例として以下のような構成を考えます。

MyProject/
├── CMakeLists.txt
├── app/
│   ├── CMakeLists.txt
│   └── main.cpp
└── lib/
    ├── CMakeLists.txt
    ├── util.cpp
    └── util.hpp

この構成では、アプリケーション部分 (app/) とライブラリ部分 (lib/) を分けています。
それぞれのフォルダに独立した CMakeLists.txt を配置することで、管理しやすくなります。
また、トップレベル(MyProject/)にも CMakeLists.txt を配置することを忘れないようにしましょう。


2. トップレベルのCMakeLists.txt

プロジェクトのルートにある CMakeLists.txt は、全体の構成をまとめる役割を持ちます。

cmake_minimum_required(VERSION 3.10)
project(MyProject LANGUAGES CXX)

add_subdirectory(lib)
add_subdirectory(app)

add_subdirectory() は、指定したフォルダ内の CMakeLists.txt を読み込みます。
これにより、モジュールごとにビルド設定を分割できます。


3. lib/CMakeLists.txt(ライブラリ側)

次に、ライブラリ側の設定を記述します。

add_library(MyLib STATIC util.cpp)
target_include_directories(MyLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

ここでは MyLib という静的ライブラリを作成し、ヘッダーファイル (util.hpp) があるディレクトリを公開しています。

設定内容
add_library()ライブラリの生成
target_include_directories()ヘッダの探索パスを設定

${CMAKE_CURRENT_SOURCE_DIR} というのは、現在の CMakeLists.txt が配置されている場所を指しています。
この変数は自動的にCMakeによって生成されるため、特に宣言する必要はありません。


4. app/CMakeLists.txt(アプリケーション側)

アプリケーション部分は、ライブラリをリンクして実行ファイルを生成します。

add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE MyLib)

このように書くことで、MyAppMyLib を利用できるようになります。
さらに、MyLib では util.hpp が配置されているヘッダのインクルードディレクトリを公開しているため、
main.cpp に対してさらに target_include_directories() などをする必要がありません。


5. main.cpp と util.cpp の内容例

app/main.cpp:

#include <iostream>
#include "util.hpp"

int main() {
    std::cout << "Sum: " << add(2, 3) << std::endl;
    return 0;
}


lib/util.cpp:

#include "util.hpp"

int add(int a, int b) {
    return a + b;
}


lib/util.hpp:

#pragma once
int add(int a, int b);

6. ビルド手順

ルートディレクトリでビルドを行います。

cmake -S ./ -B ./build
cmake --build ./build

ビルドが完了すると、build/app/MyApp が生成されます。
実行すると以下のように出力されます。

Sum: 5

7. 仕組みの整理

add_subdirectory() によって、サブディレクトリ内の CMakeLists.txt が順に処理されます。

処理順内容
1lib/ のライブラリを生成
2app/ の実行ファイルを生成
3app が MyLib にリンクされる

この仕組みにより、大規模なプロジェクトでも構成を分かりやすく整理できます。


8. よくあるエラーと対処法

エラー内容原因対処法
Cannot find source fileファイルパスが間違っている相対パスを確認
Target MyLib not foundadd_subdirectory(lib) が抜けているルートの CMakeLists.txt を確認
Include file not foundヘッダのパスが設定されていないtarget_include_directories() を追加

9. まとめ

目的コマンド役割
複数フォルダの統合add_subdirectory()サブディレクトリの読み込み
ライブラリ定義add_library()再利用可能なモジュール化
アプリケーション構成add_executable()実行ファイル生成
依存関係設定target_link_libraries()ライブラリを接続

◎ CMakeのディレクトリ構成を理解すると、チーム開発や長期保守に強いプロジェクト設計が可能になります。


10. 次回予告

次回は「ビルドタイプとコンパイルオプション」を扱います。
Debug / Release ビルドや最適化オプションの指定方法を整理して、
開発と配布の両方で活用できる設定を構築します。


◇CMake基礎講座

←(第2回:CMakeLists.txtの基本を理解しよう
(第4回:CMakeでビルドタイプとコンパイルオプションを管理しよう!)

CMake講座トップページに戻る