cmake チートシート
[履歴] [最終更新] (2019/10/02 00:26:50)
最近の投稿
注目の記事

概要

cmake の簡単な使い方をまとめます。

静的ライブラリ 動的ライブラリ 実行ファイル
Linux .a .so 無し
Windows .lib .dll .exe
ビルド方法 add_library(mylib STATIC mylib.cpp) add_library(mylib SHARED mylib.cpp) add_executable(main main.cpp)

実行ファイルのビルド add_executable

main.cpp

#include <iostream>

int main() {
    std::cout << "hi" << std::endl;
    return 0;
}

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)
add_executable(main main.cpp)

ビルド例

mkdir build
cd build/
cmake ..
make
./main
hi

静的/動的ライブラリのビルド add_library

mylib.cpp

#include <iostream>

void MyFunc() {
    std::cout << "hi" << std::endl;
}

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED mylib.cpp)
add_library(mylib2 STATIC mylib.cpp)

ビルド例

mkdir build
cd build/
cmake ..
make

成果物

libmylib.so
libmylib2.a

静的ライブラリと実行ファイルのビルド

mylib.cpp

#include <iostream>

void MyFunc() {
    std::cout << "hi" << std::endl;
}

include/mylib.hpp

#pragma onceインクルードガードの方法の一つです。

#pragma once
void MyFunc();

main.cpp

#include <mylib.hpp>

int main() {
    MyFunc();
    return 0;
}

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)

add_library(mylib STATIC mylib.cpp)

add_executable(main main.cpp)
target_link_libraries(main mylib)
target_include_directories(main PRIVATE include)

ビルド例

mkdir build
cd build/
cmake ..
make
./main
hi

成果物

libmylib.a
main

動的ライブラリと実行ファイルのビルド

静的ライブラリと実行ファイルのビルドにおける CMakeLists.txt を以下のように変更します。

cmake_minimum_required (VERSION 3.10)

add_library(mylib SHARED mylib.cpp)

add_executable(main main.cpp)
target_link_libraries(main mylib)
target_include_directories(main PRIVATE include)

成果物

libmylib.so
main

/usr/lib/libfoo.so-lfoo

動的ライブラリのリンク方法には、絶対パスを指定する方法とリンカに検索させる方法の二つがあります。

後者について、-L で指定したディレクトリ等に存在する libxxx.so/a という静的または動的ライブラリを g++ などで指定するときは "lib" を除外して -lxxx とします。

既定では実行ファイルは動的ライブラリを絶対パスで参照します。実行時に検索するように変更するためには以下のようにします。

cmake_minimum_required (VERSION 3.10)

set(CMAKE_SKIP_BUILD_RPATH true)
add_library(mylib SHARED mylib.cpp)

add_executable(main main.cpp)
target_link_libraries(main mylib)
target_include_directories(main PRIVATE include)

ldd main の結果が

libmylib.so => /path/to/build/libmylib.so (0x00007f4676f50000)

から以下のように変更されます。

libmylib.so => not found

カレントディレクトリがライブラリの検索対象ではないため LD_LIBRARY_PATH 等で対応します。

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./main
hi

よく使う cmake 設定

project

プロジェクト名を指定します。

project( gtest_main )

PROJECT_NAME で参照できます。

add_executable(${PROJECT_NAME} main.cpp)

cmake_minimum_required

CMakeLists.txt の一番最初に記載します。project() コマンドよりも前である必要があります。最低限必要な cmake のバージョンを指定します。

cmake_minimum_required(VERSION 2.8)

message

変数をコンソールに出力できます。CMakeLists.txt のデバッグ時に便利です。

message("hi")
find_library(gtest NAMES libgtest.a PATHS googletest-master/googletest)
message(${gtest})

CMAKE_VERBOSE_MAKEFILE

出力情報を増やして cmake デバッグしやすくします。

set(CMAKE_VERBOSE_MAKEFILE TRUE)

ビルド成果物の出力先を指定 (EXECUTABLE_OUTPUT_PATHLIBRARY_OUTPUT_PATH)

set(EXECUTABLE_OUTPUT_PATH /tmp)
set(LIBRARY_OUTPUT_PATH /tmp)

コンパイラのオプション指定 target_compile_options

add_executable(main main.cpp)
target_compile_options(main PRIVATE "-Wall")

ヘッダーファイルのインクルード -I target_include_directories

add_executable(main main.cpp)
target_include_directories(main PRIVATE path/to/include)

ファイルシステムに存在するライブラリの絶対パスを検索 find_library

ライブラリの指定方法は複数あります。

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)

find_library(mylib NAMES libcurl.so.4)
find_library(mylib2 NAMES EGL)

message("hi")
message(${mylib})
message(${mylib2})

実行例

mkdir build
cd build/
cmake ..
hi
/usr/lib/x86_64-linux-gnu/libcurl.so.4
/usr/lib/x86_64-linux-gnu/libEGL.so

実行ファイルの絶対パスを検索 find_program

cmake_minimum_required (VERSION 3.10)
find_program(path NAMES python)
message(${path})

cmake パッケージを利用したパス検索 find_package

cmake に登録されているモジュールの一覧は以下のコマンドで確認できます。

cmake --help-module-list

例えば FindPython を利用すると以下のようにパス検索できます。

cmake_minimum_required (VERSION 3.10)
find_package(Python REQUIRED)
message(${Python_FOUND})
message(${Python_EXECUTABLE})

実行例

$ cmake .
TRUE
/usr/bin/python3.7
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/somewhere

ファイル分割

include ファイル分割

cmake_minimum_required (VERSION 3.10)
include("a/1.cmake")
include("a/2.cmake")

ソースコードと CMakeLists.txt が存在するディレクトリを読み込む場合 add_subdirectory

add_subdirectory("b")

正規表現の利用 string

cmake_minimum_required (VERSION 3.10)
string(REGEX REPLACE [[([0-9]+)]] [[!\1!]] replaced "abc123")
message(${replaced})

実行例

abc!123!

make install

install によって make install 時のインストール先を設定できます。

mylib.hpp

#pragma once
void MyFunc();

mylib.cpp

#include <iostream>
void MyFunc() {
    std::cout << "hi" << std::endl;
}

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED mylib.cpp)
install(TARGETS mylib DESTINATION /tmp/lib)
install(FILES mylib.hpp DESTINATION /tmp/include)

実行例

mkdir build
cd build/
cmake ..
make
make install
[100%] Built target mylib
Install the project...
-- Install configuration: ""
-- Installing: /tmp/lib/libmylib.so
-- Installing: /tmp/include/mylib.hpp

外部コマンドの実行 execute_process

cmake_minimum_required (VERSION 3.10)
execute_process(
  COMMAND mkdir -p hello
  WORKING_DIRECTORY /tmp
)

別プロジェクトのライブラリを参照するサンプル

cmake で管理されたソースコードがある場合

main の CMakeLists.txttarget_include_directories していないのがポイントです。ライブラリの利用側で都度設定する必要がなくなるため、特に依存関係が多段になった場合に有用です。

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)
add_subdirectory("a")
add_executable(main main.cpp)
target_link_libraries(main mylib)

main.cpp

#include <mylib.hpp>
int main() {
    MyFunc();
    return 0;
}

a/CMakeLists.txt

cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED mylib.cpp)
target_include_directories(mylib INTERFACE include)
install(TARGETS mylib DESTINATION /tmp/a/lib)
install(DIRECTORY include DESTINATION /tmp/a)

a/mylib.cpp

#include <iostream>
void MyFunc() {
    std::cout << "hi" << std::endl;
}

a/include/mylib.hpp

#pragma once
void MyFunc();

ビルド例

mkdir build
cd build/
cmake ..
make
./main
hi
make install

cmake で target_include_directories する際には PUBLIC、PRIVATE、INTERFACE を選択します。

  • PUBLIC → 上記例で a および main の両方のビルドで必要という設定になります。
  • PRIVATE → 上記例で a のビルドについてのみ必要という設定になります。
  • INTERFACE → 上記例で main のビルドについてのみ必要という設定になります。

自身 a のビルドについては不要で、a を利用する main において必要となるため target_include_directories(mylib INTERFACE include) としています。参考: INTERFACE 設定は、ヘッダーのみからなるライブラリを作る際にも利用できます。

cmake で管理されたソースコードがない場合

IMPORTED ライブラリとして外部ライブラリを add_library しています。依存関係が多段になった場合に有用です。find_library で main に対して直接 target_link_libraries しても動作します。

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)

add_library(mylib SHARED IMPORTED)
set_target_properties(mylib PROPERTIES IMPORTED_LOCATION /tmp/a/lib/libmylib.so)
set_target_properties(mylib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES /tmp/a/include)

add_executable(main main.cpp)
target_link_libraries(main mylib)

main.cpp

#include <mylib.hpp>
int main() {
    MyFunc();
    return 0;
}

ビルド例

mkdir build
cd build/
cmake ..
make
./main 
hi
関連ページ
    概要 Maven, sbt, cmake, make 等と同様に、ビルドツールとして有名な Gradle の基本的な使い方を、特に Java をビルド対象としてまとめます。2017/05/08 現在、Android における標準のビルドツールです。 参考ドキュメント 環境構築 Installation Creating New Gradle Builds
    概要 ロボットシステム開発のためのフレームワーク Robot Operating System (ROS) の環境構築および簡単な使い方について記載します。ここでは Debian9 を利用することにします。ROS は現行バージョン1 の Melodic Morenia ディストリビューションを扱います。 ROS 対応のロボット
    概要 ロボットアプリケーションの開発環境の一つ OpenRAVE (Open Robotics Automation Virtual Environment) の環境を構築するための手順を記載します。ここでは特に Debian9 を利用します。 インストール 依存パッケージ ビルドツール関連 sudo apt install git build-essential cmake
    概要 JHBuild は複数のソースパッケージの依存関係等を定義して、何らかの成果物をビルドするためのツールです。各ソースパッケージはモジュールとよばれます。モジュールのソースコードは Git や Subversion、FTP/Web サーバ上の zip、tar 等様々なものが利用できます。モジュールのビルドシステムとしては
    概要 C++ を Python から利用する方法の一つに pybind11 があります。C++11 をサポートするコンパイラが必要です。サンプルコードを記載します。 pybind11 — Seamless operability between C++11 and Python Reference 簡単なサンプル
    概要 Python から扱う方法ではなく C++ で OpenCV を扱うためのサンプルコードを記載します。ビルドには cmake を用います。 Debian の場合は以下のコマンドで必要なライブラリがインストールされます。 sudo apt install libopencv-dev 画像を開いてウィンドウに表示
    概要 C++ で JSON を扱う際に利用されるライブラリの一つに RapidJSON があります。基本的な使い方を記載します。 インストール cmake を利用してビルドすると簡単です。 ヘッダーファイルのみが必要となります。 git clone https://github.com/Tencent/rapidjson.git ls rapidjson/include/ rapidjso
    概要 Open Dynamics Engine (ODE) を用いた動力学シミュレーションを行います。ここでは ode-python を利用して Python から実行します。 インストール 以下は Linux 環境の例です。 ODE ビルド ODE に付属する DrawStuff をビルドするためには OpenGL と GLUT
    概要 YOCTO Linux で開発している場合など、ビルド速度が開発効率にそのまま影響する際は ccache (compiler cache) で C/C++ ビルドを高速化することを考えます。cmake と併用する場合の設定およびコマンド例を記載します。 インストール sudo apt install ccache