😺

【C/C++】CMakeの活用

2024/07/14に公開

はじめに

C/C++のプロジェクトを作成する場合、小さいプロジェクトであれば、gccやclangコマンドで実行ファイル生成すればよいが、
複数のライブラリを使用する場合などはCMakeを使うと、リンクの設定などがやりやすい
この記事では、基本的なCMakeの使用手順を記載する
なお、環境はUbuntu22.04LTS

CMakeのインストール

CMakeはUbuntuであればaptからすぐにインストールが可能

sudo apt update
sudo apt install cmake
cmake --version #インストールバージョンの確認

ファイル構成

複数のファイルを使用するプロジェクトでは、必ずではないが下記のようなファイル構成になることが多い
CMakeではCMakeLists.txtというファイルを設定ファイルとして準備する必用がある
CMakeLists.txtはproject_rootの直下に含め、その他のファイルは種類ごとにディレクトリを分けて格納すると管理がしやすい

project_root/
├── include/
│   └── function.hpp   # function.cppのヘッダーファイル
├── lib/
│   └── mylib.a        # ビルド済みのライブラリファイル
├── src/
│   └── main.cpp       # main関数のソースコード
│   └── function.cpp   # 自作メソッドなどのソースコード
└── CMakeLists.txt

ビルドを実行する場合、
project_root内にbuildディレクトリを作成
→ cmakeでMakefileなどの設定ファイルを生成
→ makeで実行ファイルのビルド
という順で実行ファイルを生成することになる

cd project_root
mkdir build
cd buold
cmake.. #..はCMakeLists.txtがひとつ上の階層にあることを意味
make -j8 #j8オプションで並列ビルド実行

基本設定

ここからは、CMakeLists.txtの具体的な設定を解説する
project名は基本的にCMakeLists.txtの冒頭に記載しておく
cmake_minimum_requiredは使用可能なCMakeの最小バージョンを記載する
現在使用中のCMakeのバージョンは"cmake --version"で確認できる
projectは単にビルドするプロジェクトの名前を適当に設定する

CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject)

使用するコンパイラもCMakeLists.txtで設定できる

CMakeLists.txt
set(CMAKE_C_COMPILER /usr/bin/gcc)
set(CMAKE_CXX_COMPILER /usr/bin/g++)

コンパイラの設定は省略でき、省略した場合は標準のコンパイラを使用する
標準コンパイラの設定は環境変数を変更する
なお、通常、コンパイラは/usr/binなどに配置されていることが多い

.bashrc
#GCCを使用する場合
export CC=/path/to/gcc
export CXX=/path/to/g++

#clangを使用する場合
export CC=/path/to/clang
export CXX=/path/to/clang++

または、cmake実行時に引数指定することも可能

#clangの場合はgccの部分をclangに切り替え
cmake -DCMAKE_C_COMPILER=/path/to/gcc -DCMAKE_CXX_COMPILER=/path/to/g++

メッセージの表示

messageコマンドを使うことでデバッグ情報などの表示が可能

CMakeLists.txt
# message(<MODE>, "This is message")
message(STATUS, "This is STATUS message")
message(STATUS "Project source dir : ${PROJECT_SOURCE_DIR}")
モード 内容
FATAL_ERROR メッセージをエラーとして表示. cmake処理を即時停止する
SEND_ERROR メッセージをエラーとして表示. cmake処理は続行
WARNING メッセージを警告として表示. cmake処理は続行
STATUS 情報メッセージを表示

[補足]変数の使用

setコマンドを使うことでCMakeLists.txt内でも変数を設定できる

CMakeLists.txt
#set(VAR_NAME value)
set(SOURCES src/main.cpp)

変数を使用する場合は${変数名}で使用できる

CMakeLists.txt
#${VAR_NAME}
target_link_libraries(main ${SOURCES})

パッケージの探査

find_packageでパッケージを探して、パッケージ内のライブラリなどを利用できるようにする
REQUIREDの部分はオプションで、他のオプションに変更することも可能
REQUIREDはパッケージが見つからない場合にエラー表示してビルドを停止するオプション

# OpenCVパッケージを探す
find_package(OpenCV REQUIRED)

パッケージをみつけたら、includeやライブラリを含むディレクトリにCMakeLists.txt内でパスを通していく
includeするファイルがある場合は、includeファイルを含むディレクトリに"include_directories(<path/to/include>)"でパスを通す
ライブラリの場合は"link_directories(<path/to/include>)"を使用する

CMakeLists.txt
#includeファイルへのパス追加
include_directories(${OpenCV_INCLUDE_DIRS} # OpenCVなどインストールしていればここでincludeへのパスを追加しておく
include_directories(${PROJECT_SOURCE_DIR}/include)

#ライブラリへのパス追加
link_directories(${PROJECT_SOURCE_DIR}/lib)

実行ファイルの作成

最後にadd_executableコマンドで実行ファイルを作成していく
"add_executable(<実行ファイル名> <path/to/source>)"でソースファイルと実行ファイルを設定する
ライブラリをリンクさせる場合はtarget_link_librariesコマンドで実行ファイルにリンクする
"target_link_libraries(<実行ファイル名> <path/to/libs>)"でリンクさせる実行ファイルとリンクするライブラリを設定する

CMakeLists.txt
# 実行ファイルを作成
add_executable(main src/main.cpp)

# OpenCVライブラリをリンク
target_link_libraries(main MyLib ${OpenCV_LIBS})

Discussion