Help us understand the problem. What is going on with this article?

ごく簡単なcmakeの使い方

More than 3 years have passed since last update.

なんかcmakeの使い方わからんかった、という記事を最近見たのでごく簡単な部分をまとめる。

単一のソースファイルの場合

${PROJECT_HOME}/
  main.cpp

の時は以下の2行を書くだけでOK:

cmake_minimum_required(VERSION 2.8)
add_executable(Main main.cpp)

これをCMakeLists.txtとしてmain.cppと同じディレクトリに置く:
(CMakeList*s*.txt な事に注意)

${PROJECT_HOME}/
  main.cpp
  CMakeLists.txt

同じディレクトリで

cmake . # .を忘れずに
make

を実行すれば実行ファイルMainが作成される。
コンパイルフラグが必要な場合は2通り方法がある:

add_definitions

環境に依らず必要な場合はadd_definitionsを使う

cmake_minimum_required(VERSION 2.8)
add_definitions("-Wall -std=c++11") # <= new
add_executable(Main main.cpp)

ccmake (cmake-cli), cmake-gui

コンパイル毎に変えたい場合はccmakeコマンドあるいはcmake-guiコマンドを使う

ccmake .
cmake-gui .

cmake本体とは別パッケージになっている事が多いのでapt,yum,pacman等で検索する。
ccmakeを実行すると
CMAKE_BUILD_TYPE
CMAKE_INSTALL_PREFIX
の2つだけ表示される。変更したいのは
CMAKE_CXX_FLAGSであって、これはtを入力すると出現する。
ここで必要なフラグを調整する。

少数のソースとヘッダの場合

${PROJECT_HOME}/
  main.cpp
  mod.hpp
  mod_func1.cpp
  mod_func2.cpp

この場合も同じディレクトリに以下のCMakeLists.txtを追加する。

cmake_minimum_required(VERSION 2.8)
add_executable(Main
  main.cpp
  mod_func1.cpp
  mod_func2.cpp
)

add_executableに引数を追加した。
ヘッダの依存関係はcmakeが勝手に解決してくれる

ディレクトリが分かれている場合

${PROJECT_HOME}/
  main.cpp
  mod1.hpp
  mod1/
    func1.cpp
    func2.cpp
  mod2.hpp
  mod2/
    func1.cpp
    func2.cpp

このくらいになってくるとcmakeによる管理の効果がでてくる。
この場合、

  • 単一のCMakeLists.txtを使う方法
  • 各ディレクトリにCMakeLists.txtを作る方法

がある。個人的には後者がおすすめである。

単一のCMakeLists.txtを用いる

${PROJECT_HOME}/
  CMakeLists.txt <- new
  main.cpp
  mod1.hpp
  mod1/
    func1.cpp
    func2.cpp
  mod2.hpp
  mod2/
    func1.cpp
    func2.cpp

上述のケースと同様にプロジェクトのトップにCMakeLists.txtを作り、

cmake_minimum_required(VERSION 2.8)
add_executable(Main
  main.cpp
  mod1/func1.cpp
  mod1/func2.cpp
  mod2/func1.cpp
  mod2/func2.cpp
)

のようにする。上述のケースと本質的に同じである。

各ディレクトリにCMakeLists.txtを作る

${PROJECT_HOME}/
  CMakeLists.txt <- new
  main.cpp
  mod1.hpp
  mod1/
    CMakeLists.txt <- new
    func1.cpp
    func2.cpp
  mod2.hpp
  mod2/
    CMakeLists.txt <- new
    func1.cpp
    func2.cpp
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_subdirectory(mod1)                # <- new
add_subdirectory(mod2)                # <- new
add_executable(Main main.cpp)
target_link_libraries(Main Mod1 Mod2) # <- new
mod1/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_library(Mod1 STATIC
  func1.cpp
  func2.cpp
)
mod2/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_library(Mod2 STATIC
  func1.cpp
  func2.cpp
)

のようにする。少し手間かもしれないが、この方がモジュール化が分りやすいし増えてくると管理が楽。
cmakeでは静的ライブラリが簡単に作れ、さらにリンクも簡単。

add_library

STATICを付けると静的ライブラリを作る。
上の例だとUnix上ではmod1/libMod1.a,mod2/libMod2.aを作る。

target_link_libraries

ライブラリを実行ファイルにリンクする。
具体的にはフラグに-lMod1 -lMod2が追加される形。
名前の解決はcmakeが行い、cmakeは自分で作ったライブラリの名前は
(ディレクトリ関係なく)グローバルに保持するので、
ここでmod1/Mod1のようにする必要はない。

add_subdirectory

ディレクトリをcmakeの管理に追加する。
そのディレクトリにCMakeLists.txtが存在しないとエラーになる。
add_definitionssetによる変数の定義は子ディレクトリには伝わりますが、
親ディレクトリには伝わらない。
cmakeにおける変数の扱い

Further Reading

以上、cmakeのごく簡単な使い方を説明しました。
自分が使うだけの簡単なツールをbuildするのには十分な情報だったと思います。
cmakeにはctestと呼ばれるテスト実行支援ツールもあります。

cmakeは比較的普及しているツールですが、日本語の情報が非常に乏しいです。
最近cmake3.0がリリースされ、それに伴いドキュメントが整備されました

cmakeはmakeの出力をかっこよく隠すので、表示したい時はCMakeLists.txtの先頭に

set(CMAKE_VERBOSE_MAKEFILE 1)

とするとmakeの完全な実行コマンドが見えます。デバッグのお供に。

ricos
FEMによる構造解析、機械学習の専門家集団。計算資源のクラウド提供もしています。
https://www.ricos.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした