「C++のプロジェクトが大きくなって、コンパイルが面倒…」
「WindowsでもLinuxでもMacでも動くプログラムを作りたいけど、どうすれば?」
C/C++でプログラミングをしていると、必ず出てくるのがビルド(コンパイル)の管理という課題です。
その解決策として広く使われているのがCMake(シーメイク)というツールと、その設定ファイルであるCMakeLists.txtです。
この記事では、CMakeLists.txtとは何か、どう書けばいいのか、そして実際のプロジェクトでどう使うのかを、初心者の方にも分かりやすく解説します。
難しいビルドシステムの話を、実例を交えながら説明していきますね。
C/C++開発を効率化したい方は、ぜひ最後までお読みください!
CMakeとは?基本を理解しよう

CMakeLists.txtを理解する前に、まずCMakeについて知る必要があります。
CMakeの定義
CMake(シーメイク)とは、C/C++プロジェクトのビルドプロセスを管理するためのツールです。
正式名称:
- Cross-platform Make(クロスプラットフォーム メイク)
- 「クロスプラットフォーム」= どんなOSでも動く
開発:
- Kitware社が開発
- オープンソース
- 2000年から開発開始
なぜCMakeが必要なのか?
C/C++のプログラムは、ソースコードをコンパイルして実行ファイルにする必要があります。
小さなプログラムなら:
g++ main.cpp -o program
これだけで済みます。
でも、大きなプロジェクトになると:
- ファイルが数十個、数百個
- ライブラリの依存関係
- コンパイルオプションが複雑
- 複数のOS(Windows、Linux、Mac)に対応
手動では無理!
ここでCMakeの出番です。
CMakeが解決する問題
問題1:プラットフォームの違い
- Windows:Visual Studio、MSVC
- Linux:Makefile、GCC
- Mac:Xcode、Clang
CMakeの解決策:
一つのCMakeLists.txtから、各プラットフォーム用のビルドファイルを自動生成!
問題2:複雑な依存関係
- main.cppがutil.hを使う
- util.cppがmath_lib.aを使う
- どの順番でコンパイル?
CMakeの解決策:
依存関係を自動で解決!
問題3:ライブラリの管理
- OpenCVを使いたい
- Boostを使いたい
- どこにインストールされている?
CMakeの解決策:
自動でライブラリを探して設定!
CMakeLists.txtとは?
いよいよ本題です。
CMakeLists.txtの定義
CMakeLists.txtとは、CMakeに対して「どうビルドするか」を指示する設定ファイルです。
ファイル名:
- 必ず「CMakeLists.txt」(大文字小文字を区別)
- プロジェクトのルートディレクトリに置く
役割:
- プロジェクトの構造を定義
- コンパイルオプションを指定
- ライブラリの依存関係を記述
- ビルドターゲットを定義
Makefileとの違い
よく比較されるのがMakefileです。
Makefile:
- 直接ビルドコマンドを実行
- プラットフォーム依存
- Linuxでは便利、Windowsでは使いづらい
CMakeLists.txt:
- ビルドファイル(Makefileなど)を生成する
- プラットフォーム非依存
- どのOSでも使える
つまり:
CMakeは「Makefileを作るツール」なんです。
基本的なワークフロー
CMakeLists.txt を書く
↓
cmake コマンドを実行
↓
Makefile(またはVisual Studioプロジェクト)が生成される
↓
make コマンド(またはビルドボタン)でコンパイル
↓
実行ファイルが完成
最もシンプルなCMakeLists.txt
実際のコード例を見ていきましょう。
Hello World プログラム
ソースコード(main.cpp):
#include <iostream>
int main() {
std::cout << "Hello, CMake!" << std::endl;
return 0;
}
CMakeLists.txt:
# 最小限のCMakeバージョンを指定
cmake_minimum_required(VERSION 3.10)
# プロジェクト名を定義
project(HelloWorld)
# 実行ファイルを作成
add_executable(hello main.cpp)
これだけです!
ビルド方法
ステップ1:ビルドディレクトリを作成
mkdir build
cd build
ステップ2:CMakeを実行
cmake ..
ステップ3:ビルド
make
ステップ4:実行
./hello
出力:
Hello, CMake!
各行の意味
cmake_minimum_required(VERSION 3.10)
- 必要なCMakeのバージョンを指定
- 古いCMakeでは動かないことを防ぐ
project(HelloWorld)
- プロジェクトの名前を設定
- この名前は後で使える
add_executable(hello main.cpp)
- 実行ファイル「hello」を作成
- ソースファイルは「main.cpp」
よく使うCMakeコマンド
CMakeLists.txtで頻繁に使うコマンドを紹介します。
プロジェクト設定
cmake_minimum_required()
cmake_minimum_required(VERSION 3.15)
必須コマンド。最小バージョンを指定します。
project()
project(MyProject VERSION 1.0 LANGUAGES CXX)
プロジェクト名、バージョン、使用言語を指定します。
ターゲット追加
add_executable()
add_executable(my_program main.cpp utils.cpp)
実行ファイルを作成します。
add_library()
# 静的ライブラリ
add_library(mylib STATIC lib.cpp)
# 共有ライブラリ
add_library(mylib SHARED lib.cpp)
ライブラリを作成します。
ファイル収集
file(GLOB …)
file(GLOB SOURCES "src/*.cpp")
add_executable(my_program ${SOURCES})
複数のファイルを自動で収集します。
ただし注意:
GLOBは推奨されません(ファイルを追加してもCMakeが気づかない)。明示的にファイルを列挙する方が良いです。
ディレクトリ指定
include_directories()
include_directories(include)
ヘッダーファイルの検索パスを追加します。
target_include_directories()(推奨)
target_include_directories(my_program PUBLIC include)
特定のターゲットに対してのみ、インクルードパスを設定します。
ライブラリのリンク
target_link_libraries()
target_link_libraries(my_program pthread)
ライブラリをリンクします。
C++標準の指定
set(CMAKE_CXX_STANDARD …)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
C++17を使用することを指定します。
コンパイルオプション
target_compile_options()
target_compile_options(my_program PRIVATE -Wall -Wextra)
コンパイラの警告オプションなどを追加します。
実践的なCMakeLists.txt

実際のプロジェクトで使える例を見てみましょう。
例1:複数ファイルのプロジェクト
ディレクトリ構造:
MyProject/
├── CMakeLists.txt
├── main.cpp
├── utils.cpp
└── utils.h
CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0)
# C++17を使用
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# 実行ファイルを作成
add_executable(my_program
main.cpp
utils.cpp
)
# 警告オプションを追加
target_compile_options(my_program PRIVATE
-Wall
-Wextra
-pedantic
)
例2:ライブラリを含むプロジェクト
ディレクトリ構造:
MyProject/
├── CMakeLists.txt
├── app/
│ ├── main.cpp
│ └── CMakeLists.txt
└── lib/
├── mylib.cpp
├── mylib.h
└── CMakeLists.txt
ルートのCMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0)
set(CMAKE_CXX_STANDARD 17)
# サブディレクトリを追加
add_subdirectory(lib)
add_subdirectory(app)
lib/CMakeLists.txt:
# ライブラリを作成
add_library(mylib STATIC
mylib.cpp
)
# インクルードディレクトリを公開
target_include_directories(mylib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
app/CMakeLists.txt:
# 実行ファイルを作成
add_executable(my_program
main.cpp
)
# ライブラリをリンク
target_link_libraries(my_program PRIVATE mylib)
例3:外部ライブラリの使用
CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(ImageProcessor)
set(CMAKE_CXX_STANDARD 17)
# OpenCVを探す
find_package(OpenCV REQUIRED)
# 実行ファイルを作成
add_executable(image_app main.cpp)
# OpenCVのインクルードディレクトリを追加
target_include_directories(image_app PRIVATE ${OpenCV_INCLUDE_DIRS})
# OpenCVライブラリをリンク
target_link_libraries(image_app PRIVATE ${OpenCV_LIBS})
変数とオプション
CMakeLists.txtでは、変数やオプションを使えます。
変数の定義
set()
set(MY_SOURCES main.cpp utils.cpp)
set(MY_HEADERS utils.h)
add_executable(my_program ${MY_SOURCES})
よく使う変数
プロジェクト情報:
${PROJECT_NAME} # プロジェクト名
${PROJECT_VERSION} # バージョン
${CMAKE_PROJECT_NAME} # トップレベルプロジェクト名
ディレクトリ:
${CMAKE_SOURCE_DIR} # トップレベルのソースディレクトリ
${CMAKE_BINARY_DIR} # トップレベルのビルドディレクトリ
${CMAKE_CURRENT_SOURCE_DIR} # 現在のソースディレクトリ
${CMAKE_CURRENT_BINARY_DIR} # 現在のビルドディレクトリ
コンパイラ:
${CMAKE_CXX_COMPILER} # C++コンパイラのパス
${CMAKE_CXX_FLAGS} # C++コンパイルフラグ
オプションの定義
option()
option(BUILD_TESTS "Build test programs" ON)
if(BUILD_TESTS)
add_subdirectory(tests)
endif()
使い方:
cmake .. -DBUILD_TESTS=OFF
メッセージ出力
message()
message(STATUS "Building project: ${PROJECT_NAME}")
message(WARNING "This is a warning")
message(FATAL_ERROR "This stops CMake")
条件分岐とループ
CMakeLists.txtは、プログラミング言語のように条件分岐やループが使えます。
if文
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "Debug build")
add_definitions(-DDEBUG)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
message(STATUS "Release build")
add_definitions(-DNDEBUG)
else()
message(STATUS "Unknown build type")
endif()
プラットフォーム判定
if(WIN32)
message(STATUS "Building for Windows")
add_definitions(-DWINDOWS)
elseif(UNIX)
message(STATUS "Building for Unix-like system")
if(APPLE)
message(STATUS "Building for macOS")
else()
message(STATUS "Building for Linux")
endif()
endif()
foreach ループ
set(MY_FILES file1.cpp file2.cpp file3.cpp)
foreach(FILE ${MY_FILES})
message(STATUS "Processing ${FILE}")
endforeach()
ビルドタイプの設定
DebugビルドとReleaseビルドを使い分けられます。
ビルドタイプの指定
# デフォルトのビルドタイプを設定
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
コマンドラインで指定:
cmake .. -DCMAKE_BUILD_TYPE=Debug
cmake .. -DCMAKE_BUILD_TYPE=Release
ビルドタイプごとの設定
# Debugビルドの設定
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
# Releaseビルドの設定
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
よくあるエラーと解決方法

実際に使っていると、エラーに遭遇することがあります。
エラー1:「CMake Error: The source directory does not exist」
原因:
CMakeのパスが間違っている
解決策:
# 正しい例
cd build
cmake ..
# 間違った例
cmake . # これはダメ
エラー2:「Could not find a package configuration file」
エラーメッセージ例:
Could not find a package configuration file provided by "OpenCV"
原因:
外部ライブラリがインストールされていない、またはCMakeが見つけられない
解決策:
ライブラリをインストール:
# Ubuntu/Debian
sudo apt-get install libopencv-dev
# macOS
brew install opencv
パスを指定:
cmake .. -DOpenCV_DIR=/path/to/opencv
エラー3:「No CMAKE_CXX_COMPILER could be found」
原因:
C++コンパイラがインストールされていない
解決策:
Linux:
sudo apt-get install build-essential
macOS:
xcode-select --install
Windows:
- Visual Studioをインストール
- または MinGW-w64
エラー4:ヘッダーファイルが見つからない
エラー:
fatal error: myheader.h: No such file or directory
原因:
インクルードパスが設定されていない
解決策:
target_include_directories(my_program PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
エラー5:未定義参照エラー
エラー:
undefined reference to `my_function'
原因:
ライブラリがリンクされていない
解決策:
target_link_libraries(my_program PRIVATE mylib pthread)
CMakeのベストプラクティス
効果的なCMakeLists.txtを書くためのコツです。
1. ソース外ビルドを使う
悪い例:
cmake .
make
良い例:
mkdir build
cd build
cmake ..
make
ソースディレクトリを汚さないようにしましょう。
2. target_xxx を使う
古い書き方(非推奨):
include_directories(include)
link_libraries(pthread)
新しい書き方(推奨):
target_include_directories(my_program PRIVATE include)
target_link_libraries(my_program PRIVATE pthread)
ターゲットごとに設定する方が明確です。
3. PUBLICとPRIVATEを使い分ける
# PRIVATE: このターゲットだけが使う
target_include_directories(mylib PRIVATE src)
# PUBLIC: このターゲットと、これを使うターゲットも使う
target_include_directories(mylib PUBLIC include)
# INTERFACE: このターゲットは使わないが、これを使うターゲットが使う
target_include_directories(mylib INTERFACE interface)
4. モダンCMake(3.0以降)を使う
古いスタイル:
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(my_program ${OpenCV_LIBS})
モダンスタイル:
find_package(OpenCV REQUIRED)
target_link_libraries(my_program PRIVATE OpenCV::OpenCV)
5. ファイルリストは明示的に
避けるべき:
file(GLOB SOURCES "*.cpp")
推奨:
set(SOURCES
main.cpp
utils.cpp
helper.cpp
)
実際のプロジェクト例
総合的な例を見てみましょう。
プロジェクト構造
MyProject/
├── CMakeLists.txt
├── include/
│ └── myproject/
│ └── utils.h
├── src/
│ ├── main.cpp
│ └── utils.cpp
├── tests/
│ ├── CMakeLists.txt
│ └── test_utils.cpp
└── external/
└── CMakeLists.txt
ルートのCMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyProject
VERSION 1.0.0
DESCRIPTION "A sample CMake project"
LANGUAGES CXX
)
# C++17を使用
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# ビルドタイプのデフォルト
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# オプション
option(BUILD_TESTS "Build test programs" ON)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
# ソースファイル
set(SOURCES
src/main.cpp
src/utils.cpp
)
# 実行ファイル
add_executable(${PROJECT_NAME} ${SOURCES})
# インクルードディレクトリ
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# コンパイルオプション
target_compile_options(${PROJECT_NAME}
PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -Wpedantic>
$<$<CXX_COMPILER_ID:MSVC>:/W4>
)
# 外部ライブラリ
add_subdirectory(external)
# テスト
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
# インストール設定
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
よくある質問と回答
Q. CMakeとMakeの違いは?
Makeは直接ビルドツール、CMakeはビルドファイル生成ツールです。
Make:
- Makefileを読んで直接コンパイル
- プラットフォーム依存
CMake:
- CMakeLists.txtから Makefile(など)を生成
- プラットフォーム非依存
Q. CMakeLists.txtはどこに置けばいい?
プロジェクトのルートディレクトリに置きます。
サブディレクトリにも置けます(add_subdirectoryで追加)。
Q. Windowsでも使えますか?
はい、使えます!
CMakeはWindowsでも動作し、Visual Studioのプロジェクトファイルを生成できます。
cmake .. -G "Visual Studio 17 2022"
Q. CMakeのバージョンはどれを使えばいい?
3.15以降を推奨します。
理由:
- モダンCMakeの機能が使える
- 多くのライブラリが対応している
- セキュリティアップデートもある
Q. find_packageが失敗します
ライブラリが見つからない場合の対処法:
1. ライブラリをインストール
2. CMakeにパスを教える
cmake .. -DCMAKE_PREFIX_PATH=/path/to/library
3. 環境変数を設定
export CMAKE_PREFIX_PATH=/path/to/library
Q. ビルドディレクトリを削除してもいい?
はい、いつでも削除できます。
rm -rf build
mkdir build
cd build
cmake ..
ソースコードは影響を受けません。
Q. CMakeとCMakeLists.txtのバージョンは合わせる必要がある?
CMakeLists.txtで指定するのは「最小バージョン」です。
cmake_minimum_required(VERSION 3.15)
CMake 3.15以降なら動作します。より新しいバージョンでも問題ありません。
まとめ:CMakeLists.txtでビルドを自動化
CMakeLists.txtについて、基本から実用まで解説してきました。
この記事のポイント:
✓ CMakeLists.txtはCMakeの設定ファイル
✓ プラットフォーム非依存のビルドシステム
✓ 最小構成はcmake_minimum_required、project、add_executable
✓ target_xxxコマンドで明示的に設定するのが推奨
✓ 外部ライブラリはfind_packageで探す
✓ ソース外ビルド(buildディレクトリ)を使う
✓ 条件分岐やループも使える柔軟な設定が可能
最も大切なこと:
CMakeLists.txtは、クロスプラットフォーム開発には欠かせないツールです。
最初は複雑に見えますが、基本を押さえれば強力な味方になります。
今日から実践すること:
- 簡単なHello WorldプロジェクトでCMakeを試す
- 既存のプロジェクトにCMakeLists.txtを追加してみる
- 外部ライブラリを使うプロジェクトに挑戦
- GitHubの有名プロジェクトのCMakeLists.txtを読んでみる
C/C++開発が、CMakeLists.txtでもっと効率的になりますよ!

コメント