Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
25
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

Organization

CMake: モジュール

はじめに

みなさん、こんにちは。今回はモジュールについて書いていきます。

モジュールとは何か?

モジュールとは、定義したコマンドなどを複数のスクリプトで再利用するためのもので、include()コマンドやfind_package()コマンドなどで読み込まれます。

/path/to/module.cmake
function(func)
  message(func)
endfunction()
include(/path/to/module.cmake)
func() # func

また、モジュール内の各コマンドは読み込み元の文脈で評価されるので、モジュール内での変数の設定は読み込み元に影響します。

/path/to/module.cmake
set(value 2)
set(value 1)
message("value: ${value}") # value: 1
include(/path/to/module.cmake)
message("value: ${value}") # value: 2

include() コマンド

モジュールを読み込む方法はいくつかありますが、本エントリーではinclude()コマンドについて述べます。

include()コマンドとはモジュールを読み込む基本的な方法で、定義は以下となります。

include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>]
                      [NO_POLICY_SCOPE])

include — CMake 3.0.2 Documentation

モジュールの指定

使用するモジュールの指定は<file|module>引数で行いますが、これには以下の2つの方法があります。

絶対パスで指定

モジュールのファイルへの絶対パスで指定する方法です。

include(/path/to/module.cmake)

モジュール名で指定

モジュール名で指定する方法です。モジュール名とは、変数(もしくはキャッシュ変数)CMAKE_MODULE_PATHに登録されているパスからモジュールへの相対パスで、拡張子.cmakeを除去したものです。

set(CMAKE_MODULE_PATH /path/to)
include(module)

set(CMAKE_MODULE_PATH /path)
include(to/module)

また、変数CMAKE_MODULE_PATHには複数のパスをリストとして設定することが可能です。この場合、リストの先頭から線形探索していき、最初に見つかったモジュールをロードします。

# /path/to
# ├── module.cmake
# └── dir
#        └── module.cmake

set(CMAKE_MODULE_PATH /path/to /path/to/dir)
include(module)     # /path/to/module.cmake
include(dir/module) # /path/to/dir/module.cmake

set(CMAKE_MODULE_PATH /path/to/dir /path/to)
include(module)     # /path/to/dir/module.cmake
include(dir/module) # /path/to/dir/module.cmake

ここで注意したいのは、CMake が提供している標準モジュールは最後に探索されるということです。つまり、標準モジュールと同名のモジュールがCMAKE_MODULE_PATHの中に存在する場合、その標準モジュールは隠蔽されてしまいます。

# /path/to
# └── Documentation.cmake

include(Documentation) # 標準ライブラリ Documentation

set(CMAKE_MODULE_PATH /path/to)
include(Documentation) # /path/to/Documentation.cmake

OPTIONAL オプション

OPTIONALオプションを付与すると、モジュールが見つからない場合でもエラーになりません。

include(/not/existing/module.cmake) # エラー
include(/not/existing/module.cmake OPTIONAL) # OK

RESULT_VARIABLE オプション

RESULT_VARIABLEオプションを付与すると、ロードしたモジュールの絶対パスが指定の変数に設定されます。

set(CMAKE_MODULE_PATH /path/to)
include(module RESULT_VARIABLE module_path)
message("module_path: ${module_path}") # module_path: /path/to/module.cmake

また、OPTIONALオプションも付与し、かつ指定したモジュールが見つからない場合には、指定の変数にNOTFOUNDが設定されます。

include(/not/existing/module.cmake OPTIONAL RESULT_VARIABLE module_path)
message("module_path: ${module_path}") # module_path: NOTFOUND

NO_POLICY_SCOPE オプション

include()コマンドは、ポリシースコープを生成するので、モジュール内でのポリシーの設定が呼び出し元に影響することはありません。

/path/to/module.cmake
cmake_policy(GET CMP0007 cmp0007_behavior)
message("cmp0007_behavior: ${cmp0007_behavior}")

cmake_policy(SET CMP0007 OLD)

cmake_policy(GET CMP0007 cmp0007_behavior)
message("cmp0007_behavior: ${cmp0007_behavior}")
cmake_policy(GET CMP0007 cmp0007_behavior)
message("cmp0007_behavior: ${cmp0007_behavior}") # cmp0007_behavior: NEW

include(/path/to/module.cmake) #[[
  cmp0007_behavior: NEW
  cmp0007_behavior: OLD
]]

cmake_policy(GET CMP0007 cmp0007_behavior)
message("cmp0007_behavior: ${cmp0007_behavior}") # cmp0007_behavior: NEW

しかし、NO_POLICY_SCOPEオプションを付与すると、ポリシースコープを生成しなくなるので、モジュール内でのポリシーの設定が呼び出し元に影響します。

cmake_policy(GET CMP0007 cmp0007_behavior)
message("cmp0007_behavior: ${cmp0007_behavior}") # cmp0007_behavior: NEW

include(/path/to/module.cmake NO_POLICY_SCOPE) #[[
  cmp0007_behavior: NEW
  cmp0007_behavior: OLD
]]

cmake_policy(GET CMP0007 cmp0007_behavior)
message("cmp0007_behavior: ${cmp0007_behavior}") # cmp0007_behavior: OLD

このオプションは、ポリシーの設定を目的とするモジュールをロードするときに必要となるでしょう。


なお、include()コマンドは同じモジュールを何回でも読み込むことに注意してください。

/path/to/module.cmake
set(value 1)
message(module)
include(/path/to/module.cmake) # module
message("value: ${value}") # value: 1
set(value 2)
message("value: ${value}") # value: 2

include(/path/to/module.cmake) # module
message("value: ${value}") # value: 1

モジュールの種類

モジュールには、自分や第三者が作成したものの他に、CMake が標準で提供しているものが多数あります。この標準モジュールの詳細は、cmake-modules(7) にあります。

おわりに

以上、モジュールでした。よく使う共通の処理をモジュールとしておくことで、コードを再利用することができます。

明日は、mrk_21 さんの『CMake: Generator Expressions』です。

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
25
Help us understand the problem. What are the problem?