このブログ記事では、CMakeの基本を紹介します。

DevOpsシリーズの最後の記事Linux基礎 #9 - Makefilesでは、 Makeを使用してプロジェクトを自動構築する方法を説明しました。しかし、コードベースが増大し、クロスプラットフォーム互換性が必要になるにつれて、 Makefilesも混雑になりすぎて口付けなくなります。CMakeは無料でクロスプラットフォームのビルドツールで、主にC++用ですが、 Makefilesやその他のビルドツールのスクリプトを自動生成することができます。
CMakeの設定
CMakeを始めるには、Linuxではapt install cmake
を使用してダウンロードします。macOSやWindowsの場合は、
公式サイトを確認し、指示に従ってください。CMakeは、位置されたCMakeLists.txt
ファイルを解析し、
自動的にビルドスクリプトを生成します。
cmake_minimum_required(VERSION 3.15)
# Project Name, Version, Language (default is C++), etc.
project(MyProject C)
# Naming BINARY (We could have used PROJECT_NAME to set the output binary name to the project's name)
set(BINARY bin)
# Create the executables using the specified files
add_executable(${BINARY} main.c LinkedList.c)
ここで、#はコメント用で、大文字はset
で設定する変数や、あらかじめ定義された変数を示します。
cmake -S <source_path> -B <build_path>
を実行すると、<source_path>
のCMakeLists.txt
を使用して、
指定した<build_path>
に適切なビルドスクリプトやMakefileを生成します。一般的には、
プロジェクトのルートディレクトリの配下に/build
ディレクトリを作成し、cmake -S . -B /build
でMakefileを生成します。
そして/build
ディレクトリに移動し、Makefileが成功製作されたことを確認します。make
を実行すると実行ファイルが生成され、
./bin
で実行できます。
ライブラリの構築
上記の例から、CMakeがMakefilesと比較して構築過程を簡素化することがわかります。CMakeはまた、ソースコードを簡単にライブラリにコンパイルし、
それをメインソースコードにリンクできるようにすることも可能です。例えば、LinkedList
ディレクトリを構築し、
このディレクトリにLinkedList.h
とLinkedList.c
を含めます。その後、以下のようにライブラリを簡単に構築できます。
cmake_minimum_required(VERSION 3.15)
project(LinkedList C)
# Create a library (STATIC by default. We can specify it to be SHARED.)
add_library(LinkedList LinkedList.c)
add_library
関数は静的ライブラリlibLinkedList.a
を作成します。このライブラリはメインのソースコードに以下のようにリンクできます。
cmake_minimum_required(VERSION 3.15)
project(MyProject C)
# Add library as subdirectory in `build_path` to run build on library and to reference it
add_subdirectory(LinkedList)
add_executable(${PROJECT_NAME} main.c)
# Tell where to look for header files not in standard location
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/LinkedList)
# Link Libraries
target_link_libraries(${PROJECT_NAME} LinkedList)
add_subdirectory
は、指定したサブディレクトリ(この場合はLinkedList
)にあるCMakeLists.txt
を利用してLinkedList
を自動的にビルドします。
これは静的ライブラリを作成します。target_include_directories
を使用することで、ヘッダーファイルへのフルパスを指定することなく、
メインソースコードからヘッダーファイルを利用可能にします。さらに、target_link_libraries
を使用してライブラリをリンクします。
プロジェクトをより整理するために、以下のようなファイル構造を構築するのが一般的です。
CMakeLists.txt
main.c
LibraryA/
├── CMakeLists.txt
├── src/
│ ├── module1.c
│ └── module2.c
├── include/
│ ├── module1.h
│ └── module2.h
この構造に基づき、以下のようにサブディレクトリのLinkedList
を指定してプロジェクトをセットアップできます。
cmake_minimum_required(VERSION 3.15)
project(LibraryA C)
# Collect C files from /src
file(GLOB SRC_FILES ${CMAKE_SOURCE_DIR}/LibraryA/src/*.c)
add_library(LibraryA STATIC ${SRC_FILES})
プロジェクトのルートディレクトリのCMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyProject C)
add_subdirectory(LibraryA)
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} LibraryA)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/LibraryA/include)
他人が作成したライブラリコードやサブモジュールをダウンロードし、上記の手順に従ってライブラリとしてビルドして使用できます。 これにより、サードパーティのコードやカスタムライブラリを大規模なプロジェクトに統合するプロセスが簡素化されます。
実行ファイルとライブラリのインストール
ビルドディレクトリで作成したライブラリを使用する代わりに、マシンにインストールして利用することもできます。
例えば、以下のようにinstall
コマンドを使用できます。
cmake_minimum_required(VERSION 3.15)
project(LibraryA C)
file(GLOB SRC_FILES ${CMAKE_SOURCE_DIR}/src/*.c)
add_library(LibraryA STATIC ${SRC_FILES})
# Collect header files from /include
file(GLOB HEADER_FILES ${CMAKE_SOURCE_DIR}/include/*.h)
# Set public header property
set_target_properties(LibraryA PROPERTIES PUBLIC_HEADER "${HEADER_FILES}")
# Install library to local environment "lib" and header files to "include"
# (usually /usr/local/lib and /usr/local/include)
install(
TARGETS LibraryA ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
)
install
コマンドのARCHIVE
引数は静的ライブラリ用であり、共有または動的ライブラリにはLIBRARY
を使用する必要があります。
上記のファイルを使用してsudo make install
を実行すると、ライブラリがローカル環境にインストールされ、
同じ環境内のすべての実行ファイルがパスを指定せずにそれを使用できるようになります。
さらに、実行ファイルもインストールすることで、どこからでも実行できるようにすることが可能です。
cmake_minimum_required(VERSION 3.15)
project(MyProject C)
add_subdirectory(LibraryA)
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} LibraryA)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/LibraryA/include)
# Install executable to local environment "bin" (usually /usr/local/bin)
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
上記の構成を使用してsudo make nstall
を実行すると、実行ファイルがインストールされ、
MyProject
と入力するだけでどこからでも実行できるようになります。
結論
この記事では、CMakeとは何か、なぜCMakeを使用するのか、CMakeの始め方、 そしてCMakeの基本について説明しました。このCMakeシリーズでは、 (少なくとも私の計画では)少数の記事でCMakeについて必要な知識をほぼすべてカバーする予定です。
リソース
- Code, Tech, and Tutorials. 2021. CMake Tutorial EP 1 | Understanding The Basics. YouTube.
- Code, Tech, and Tutorials. 2023. CMake Tutorial EP 2 | Libraries | Installing | Pairing with Executables | RE-DONE!. YouTube.
- Code, Tech, and Tutorials. 2021. CMake Tutorial EP 3 | Git Submodules (adding glfw windowing library example). YouTube.