CMakeとは何か? - CMakeのメリットについて大まかに解説
本ページではCMakeというものがどういったものであるかを解説します。
一言でいうと#
CMakeは、一度書いたソースを色々な環境で同じ手順によってビルドができるようになるシステムです。
CMakeの設定ファイルを書けば、Windows / Linux / MacOS で動作するようなプログラムを作成することができます[1] 。
CMakeとは?#
公式サイト から引用すると、CMakeとは次のようなものであると記述されています。
CMake is an extensible, open-source system that manages the build process in an operating system and in a compiler-independent manner. Unlike many cross-platform systems, CMake is designed to be used in conjunction with the native build environment.
勝手に筆者が日本語訳すると以下の通りです。
CMakeはビルドプロセスをOS・コンパイラ非依存に管理することができる拡張可能なオープンソースシステムです。他の多くのクロスプラットフォームシステムと異なり、CMakeはネイティブなビルド環境と組み合わせて利用するように作られています。
具体的に使ったことがあれば何を言いたいかわかるのですが、初めて CMake の存在を知った方には理解が難しいかもしれません。以下に解説します。
「ビルドプロセスをOS・コンパイラ非依存に管理する」とは?#
ビルドプロセスとはその名の通り、 ビルドを実行する手順 のことです。
この手順は、OSやコンパイラによって方式が異なります。つまり CMakeを利用しない場合には大抵 OS・コンパイラに依存した状態になっています 。これが実際にどういう状態であるか見てみます。
例えば、すでに TestProgram というプログラムのソースコードが作成済であるとします。
このソースコードをビルドする場合にはどのような手順が必要となるでしょうか。
Linuxでビルドする場合#
このプログラムを Linux 上でビルドするためにはどうしたらよいでしょうか。
大抵の場合、 Makefile を記述して make するような形になるかと思います[2] 。例えば、以下のようなファイルを書くことになります[4] 。
.PHONY = all clean
CPP = g++
LINKERFLAG = -lm
TARGET := TestProgram
SRCS := $(wildcard *.cpp)
OBJS := $(SRCS:%.cpp=%.o)
BINS := $(SRCS:%.cpp=%)
all: ${TARGET}
${TARGET}: ${OBJS}
@echo "Checking.. ${OBJS}"
${CPP} ${LINKERFLAG} ${OBJS} -o $@
%.o: %.cpp
@echo "Creating object.. $<"
${CPP} -c $<
clean:
@echo "Cleaning up..."
rm -rvf *.o ${BINS}
このファイルを記述するだけでも、中々の労力がかかります。例えば、以下のような前提知識が必要となります。
Makefileの作法を知る必要がある
g++ などのコマンドの利用法を知っている必要がある
このファイルを作成した後、 make コマンドを実行することによってビルドが実施されます。
Windowsでビルドする場合#
Windowsでビルドする場合にはまた様相が異なります。
通常のセオリー通りやろうとするのであれば、WindowsでC++の開発をする場合には Visual Studio をダウンロードし、新規のプロジェクトを作成していく必要があります。
GUIの画面遷移が多いためここでは詳しい手順は割愛させていただきますが、以下のような操作をします。
プロジェクトを新規に作成
すでに存在するソースコードをプロジェクトに配置
上述の Makefile と同じ設定を Visual Studio のGUI経由で実施
そして設定が完了後、プロジェクトを選択してビルドを実施します。
このように、同じプログラムをビルドするだけでも Linux / Windows で大きく異なることがわかります。
CMakeではどうなるか#
CMakeを利用すると、 すべてのプラットフォームに共通の設定ファイルを書くのみでビルドが可能 になります。
cmake_minimum_required(VERSION 3.13)
project(TestProgram)
file(GLOB TARGETS *.cpp *.h)
add_executable(${PROJECT_NAME} ${TARGETS})
これで、先ほど作成した Makefile と同様の効果を得ることができます。設定ファイル自体が非常に単純化しましたね。
このファイルから、Windows / Linux などの各OSのビルドツール向け設定ファイルを生成するのが下記コマンドです。WindowsではPowerShellから実行してください。
mkdir build
cd build
cmake ..
これにより、先ほど作成した Linux / MacOS の Makefile や Windows の Visual Studio ソリューションファイル(プロジェクトファイルをまとめたもの) が生成されます。非常に楽になりました。
そしてビルドを実施するコマンドも共通となっており、上のコマンドに続けて下記コマンドでビルドできます。
# Linuxの場合
cmake --build . --config Release --target install
# windows の場合
cmake --build . --config Release --target INSTALL
これにより、 CMake を利用することOS・コンパイラに依存しないような設定ファイルおよびビルドコマンドをによってビルドが実施できる ことがわかりました。
「ネイティブなビルド環境と組み合わせて利用」とは?#
冒頭の引用部分で、以下のような紹介がありました。
他の多くのクロスプラットフォームシステムと異なり、CMakeはネイティブなビルド環境と組み合わせて利用するように作られています
これはおそらく、そのほかのクロスプラットフォーム対応言語・SDKの仕組みについて言及しているものと思われます[3] 。
例えば、クロスプラットフォームの言語というと以下のようなものが思い浮かびます。
Java
PHP
Python / Ruby などのスクリプト言語
JavaScript などクロスプラットフォームブラウザ上で動作する言語
それぞれの言語で細かく仕組みは違いますが、大まかにいうとこれらはOSなどの違いを吸収するために、一度独自の言語実行用エンジンを介して動作するように作られています。
これはつまり、C++などで作成されたネイティブなコードよりも1つレイヤが増えていることになるため、実行速度の面から見るとネイティブコードに基本的に少し劣ってしまうという欠点があります。
このような欠点を生じさせずに、ネイティブなビルド環境を利用することで速度的な利点を取ることができる、という話なのではないかと思います。