はじめに
第2回ではAutotoolsを使って ./configure → make のフローを理解しました。本記事では同じサンプルプロジェクトをCMakeでビルドし、Autotoolsとの設計の違いを比較しながらCMakeの基本を学びます。
本記事はシリーズの第3回です。
- 第1回:Makefileをちゃんと理解する
- 第2回:
./configureの正体——autoconf/automake入門 - 第3回:CMake入門——Autotoolsとの比較で理解する(本記事)
CMakeとは何か
CMakeは「ビルドシステムを生成するツール」です。CMake自身はビルドを実行しません。
CMakeLists.txt → cmake → Makefile / Ninja / Visual Studio project
↓
make / ninja / msbuild → バイナリ
CMakeが出力するビルドファイルの種類はプラットフォームや好みに応じて選べます。Linux では Makefile、Windows では Visual Studio プロジェクト、高速ビルドを重視する場合は Ninja など、同じ CMakeLists.txt から生成できます。
なぜCMakeが生まれたか
Autotoolsには以下のような課題がありました。
| 課題 | 内容 |
|---|---|
| 複数ファイル必要 |
configure.ac + Makefile.am を階層ごとに用意する必要がある |
| Unix中心 | Windowsへの対応が難しい |
| 学習コストが高い | autoconf のマクロ言語(m4)は独特で習得が難しい |
CMakeはこれらを解決するために設計されました。特にWindows・Mac・Linuxで同一のビルドスクリプトが使えることが最大の利点です。
Autotoolsとのフロー比較
【Autotools】
開発者:configure.ac + Makefile.am → aclocal/autoconf/automake → configure + Makefile.in
ユーザー:./configure → Makefile 生成 → make → バイナリ
【CMake】
開発者:CMakeLists.txt をそのまま配布(事前のツール実行不要)
ユーザー:cmake -S . -B build → Makefile等を生成 → cmake --build build → バイナリ
Autotoolsでは開発者が事前にツールを実行して configure と Makefile.in を生成・配布する必要がありましたが、CMakeでは CMakeLists.txt をそのまま配布するだけです。
また ./configure と make の2ステップだったユーザー操作が、CMakeでは cmake コマンドに統一されています。
サンプルで試す
第1回・第2回と同じプロジェクト構成を使います。
sample/
├── include/
│ └── greet.h
├── src/
│ ├── main.c
│ ├── greet.c
│ └── CMakeLists.txt ← 追加
└── CMakeLists.txt ← 追加
Cのソースコードは第1回と同じです。追加するのは2つの CMakeLists.txt だけです。
CMakeLists.txt(トップレベル)
cmake_minimum_required(VERSION 3.10)
# プロジェクト名・バージョン・使用言語を宣言
project(hello VERSION 1.0.0 LANGUAGES C)
# ヘッダファイルの検索パスをプロジェクト全体に適用
include_directories(include)
# サブディレクトリを追加
add_subdirectory(src)
src/CMakeLists.txt
# 実行バイナリ名とソースファイルを指定
add_executable(hello
main.c
greet.c
)
Autotoolsの configure.ac + Makefile.am × 2ファイルに相当する内容が、CMakeLists.txt 2ファイルに収まっています。また autoconf のマクロ言語(m4)と違い、CMakeの構文は直感的で読みやすいのが特徴です。
ビルド手順
インストール
# macOS
brew install cmake
# Ubuntu / Debian
sudo apt install cmake
ビルド
# ソースディレクトリとビルドディレクトリを分離するのが標準的なやり方
cmake -S . -B build
# ビルド実行
cmake --build build
# 実行
./build/src/hello
実行結果:
-- The C compiler identification is GNU 13.3.0
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features - done
-- Configuring done (0.8s)
-- Generating done (0.1s)
-- Build files have been written to: /path/to/sample/build
Hello, World!
Hello, Qiita!
cmake -S . -B build の意味
-S . はソースディレクトリ(CMakeLists.txt のある場所)、-B build はビルドファイルの出力先です。生成された Makefile や中間ファイルはすべて build/ ディレクトリに収まるため、ソースツリーが汚れません。
Autotoolsで mkdir build && cd build && ../configure としていたのと同じ効果が、1コマンドで実現できます。
CMakeのconfigureステップで何をしているか
cmake -S . -B build を実行したとき、内部では2つのステップが順番に実行されます。
configure ステップ:CMakeLists.txt を読んでコンパイラや環境を調査する
↓
generate ステップ:調査結果をもとにMakefile等のビルドファイルを生成する
Autotoolsの ./configure に相当する処理と、Makefile.in から Makefile を生成する処理の両方を、CMakeが1コマンドでまとめてやっています。
調査結果は build/CMakeCache.txt にキャッシュされます。2回目以降の cmake 実行では変更された部分だけ再処理されるため高速です。
よく使うコマンド対応表
| 目的 | Autotools | CMake |
|---|---|---|
| ビルドファイル生成 | ./configure |
cmake -S . -B build |
| ビルド実行 | make |
cmake --build build |
| インストール | make install |
cmake --install build |
| インストール先の指定 | ./configure --prefix=/opt/foo |
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/opt/foo |
| クリーン | make clean |
cmake --build build --target clean |
| Debug/Releaseの切り替え | ./configure CFLAGS="-O2" |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release |
-D オプションについて
CMakeのカスタマイズは -D変数名=値 のオプションで行います。Autotoolsの ./configure --prefix=... に相当します。よく使う変数を以下に示します。
| 変数 | 意味 |
|---|---|
CMAKE_BUILD_TYPE |
Debug / Release / RelWithDebInfo
|
CMAKE_INSTALL_PREFIX |
インストール先(デフォルトは /usr/local) |
CMAKE_C_COMPILER |
使用するCコンパイラ |
3つのビルドシステム全体比較
シリーズ全体を通じて登場した3つのアプローチを整理します。
| 項目 | 手書きMakefile | Autotools | CMake |
|---|---|---|---|
| 開発者が書くファイル | Makefile |
configure.ac + Makefile.am×階層数 |
CMakeLists.txt×階層数 |
| ユーザーへの配布物 | Makefile |
configure + Makefile.in
|
CMakeLists.txt |
| ビルドコマンド | make |
./configure && make |
cmake -S . -B build && cmake --build build |
| Windows対応 | 困難 | 困難 | ネイティブ対応 |
| 依存関係の自動追跡 |
-MMD -MP を自分で書く |
automakeが自動で組み込む | 自動 |
| 外部ライブラリの検出 | 自分で書く | AC_CHECK_LIB |
find_package() |
| 学習コスト | 低〜中 | 高 | 中 |
| 採用しているOSS例 | git, bash | wget, ffmpeg(旧来のプロジェクト) | LLVM, OpenCV, Qt |
どれを選ぶか
- 手書きMakefile:小規模プロジェクト、Unix環境限定、依存が少ない場合
- Autotools:既存のAutotools採用プロジェクトへの参加・保守
- CMake:新規プロジェクト、クロスプラットフォーム対応が必要な場合
新規にプロジェクトを立ち上げる場合はCMakeを選ぶのが現代的な標準です。
まとめ
| 項目 | ポイント |
|---|---|
| CMakeとは | ビルドシステムを生成するツール。ビルド自体は行わない |
| 最大の利点 |
CMakeLists.txt 1ファイルでWindows/Mac/Linuxに対応 |
| Autotoolsとの違い | 開発者の事前準備が不要、構文がシンプル、1コマンドで設定とビルドファイル生成 |
| out-of-sourceビルド |
-B build オプションでソースを汚さずビルドできる |
シリーズを通じて、Makefile・Autotools・CMakeという3つのビルドシステムの仕組みと使い分けを整理しました。普段何気なく実行していた ./configure や make が何をしているのか、少し見え方が変わったなら幸いです。