はじめに
みなさん、こんにちは。今回は CMake スクリプトを記述する上で便利なコマンドや変数について紹介していきます。
list()
コマンド
リストの長さ取得や追加など、リスト操作の便利な機能を提供するコマンドです。CMake: リストで詳しく述べられています。
file()
コマンド
file()
コマンドは、各種ファイル操作やファイルの検索に加えて、ダウンロードやアップロード機能など様々な機能を提供します。よく使いそうな機能を下記に示します。
ファイル生成・削除と入出力
WRITE・APPEND
file(WRITE <filename> [<content1> ...])
file(APPEND <filename> [<content1> ...])
WRITE
はファイル<filename>
に指定した文字列<content1> ...
を出力します。このとき、指定したファイルが存在しない場合は作成します。APPEND
はファイル末尾への追加となります。
file(WRITE hoge.txt a b c) #[[
$ cat hoge.txt
abc
]]
file(APPEND hoge.txt a b c) #[[
$ cat hoge.txt
abcabc
]]
READ
file(READ <filename> <variable> [LIMIT <length>] [OFFSET <offset>] [HEX])
ファイル<filename>
を変数<variable>
に読み込みます。HEX
オプションが付与されると16進表記のバイト列として読み込みます。また、読み込む範囲を<offset>..(<offset> + <length> - 1)
で指定できます。
$ echo abc > hoge.txt
file(READ hoge.txt content) # abc
file(READ hoge.txt content HEX) # 616263
file(READ hoge.txt content LIMIT 2 OFFSET 1) # bc
MAKE_DIRECTORY
file(MAKE_DIRECTORY [<directory1> ...])
ディレクトリ<directory1> ...
を作成します。
REMOVE・REMOVE_RECURSE
file(REMOVE [<file1> ...])
file(REMOVE_RECURSE [<file1> ...])
ファイル<file1> ...
を削除します。ディレクトリを削除するためにはREMOVE_RECURSE
を使用します。
ファイルの探索と取得
GLOB・GLOB_RECURSE
file(GLOB <variable> [RELATIVE <path>] [<globbing_expressions>]...)
file(GLOB_RECURSE <variable> [RELATIVE <path>]
[FOLLOW_SYMLINKS] [<globbing_expressions>]...)
指定されたGLOBパターン<globbing_expressions>
にマッチするファイルを探索し、その一覧をリストとして変数<variable>
に格納します。このとき絶対パスで格納されますが、RELATIVE <path>
が指定されていると、このパスからの相対パスとなります。add_executable()
などに指定する依存ソースファイルの一覧を取得するのに使い、おそらくfile()
コマンドの中でもっともよく使うことになるでしょう。以下の正規表現のメタ文字に似たものが使えます。
- 任意の文字の0回以上の繰り返し
*
- 任意の文字
?
- ブラケット内で指定された文字
[ ]
とその範囲-
/path/to/
├── CMakeLists.txt
├── test1.txt
└── .txt
file(GLOB files *.txt) # /path/to/CMakeListx.txt;/path/to/test1.txt;/path/to/.txt
file(GLOB files test1*.txt) # /path/to/test1.txt
file(GLOB files [t-z]*.txt) # /path/to/test1.txt
file(GLOB files test?.txt) # /path/to/test1.txt
ファイル情報の取得
MD5・SHA1・SHA224・SHA256・SHA384・SHA512
file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> <filename> <variable>)
指定のハッシュ関数により、ファイル<filename>
のダイジェストを生成し、変数<variable>
に出力します。
パスの変換
RELATIVE_PATH
file(RELATIVE_PATH <variable> <directory> <file>)
基準となるパス<directory>
からの対象のパス<file>
への相対パスを変数<variable>
に格納します。
ファイルのダウンロード
DOWNLOAD
file(DOWNLOAD <url> file [INACTIVITY_TIMEOUT <timeout>]
[TIMEOUT <timeout>] [STATUS <status>] [LOG <log>] [SHOW_PROGRESS]
[EXPECTED_HASH ALGO=<value>] [EXPECTED_MD5 <sum>]
[TLS_VERIFY on|off] [TLS_CAINFO <file>])
指定したURL<url>
のリソースをファイル<file>
にダウンロードします。外部プロジェクトやデータなどをダウンロードするのに使用するでしょう。
これ以外のコマンドについては、file — CMake 3.0.2 Documentation に記述されています。
get_filename_component()
コマンド
get_filename_component(<variable> <path> <comp> [CACHE])
get_filename_component()
コマンドはファイル名や拡張子、ディレクトリなど指定したパス<path>
の構成要素<comp>
を取得し、変数<variable>
に格納します。指定できる構成要素は以下のとおりです。
- ディレクトリのパス
DIRECTORY
- ファイル名
NAME
- 拡張子
EXT
- 拡張子を除いたファイル名
NAME_WE
- 絶対パス
ABSOLUTE
- シンボリックリンクのリンク先の絶対パス
REALPATH
/path/to/
├── script.cmake
└── script-alias.cmake -> script.cmake
get_filename_component(result "/path/to/script.cmake" DIRECTORY) # /path/to
get_filename_component(result "/path/to/script.cmake" NAME) # script.cmake
get_filename_component(result "/path/to/script.cmake" EXT) # .cmake
get_filename_component(result "/path/to/script.cmake" NAME_WE) # script
get_filename_component(result "script.cmake" ABSOLUTE) # /path/to/script.cmake
get_filename_component(result "script-alias.cmake" REALPATH) # /path/to/script.cmake
configure_file()
コマンド
configure_file(<input> <output>
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
configure_file()
コマンドは、元となるファイルからファイルに埋め込まれた変数を展開し、新しいファイルを生成する、いわゆるテンプレートエンジンの機能を提供するコマンドです。
@osamu0329 さんの CMake:configure_fileコマンド で詳しく解説されています。
string()
コマンド
string()
コマンドは、各種文字列処理を行うためのコマンドです。よく使いそうな機能を下記に示します。
文字列の探索と置換
REGEX MATCH・REGEX MATCHALL
string(REGEX MATCH <regexp> <variable> <input1> [...])
string(REGEX MATCHALL <regexp> <variable> <input1> [...])
文字列<input1> ...
が正規表現<regexp>
にマッチするかを判定し、マッチした場合は、マッチした部分の文字列が変数<variable>
に格納されます。REGEX MATCH
では最初にマッチした部分しか格納されませんが、REGEX MATCHALL
ではマッチした部分すべてがリストとして格納されます。
REGEX REPLACE・REPLACE
string(REGEX REPLACE <pattern> <replace> <variable> <input> [...])
string(REPLACE <pattern> <replace> <variable> <input> [...])
文字列input
でパターン<pattern>
と一致した部分を文字列<replace>
で置換します。REGEX REPLACE
とREPLACE
の違いは正規表現が使えるかどうかです。また、REGEX REPLACE
の場合、置換する文字列<replace>
の中で\1
の形で後方参照することができます。
SUBSTRING
string(SUBSTRING <string> <begin> <length> <variable>)
文字列<string>
の中から<begin>..(<begin> + <length>)
の範囲の文字列を変数<variable>
に格納します。
文字列の情報取得
MD5・SHA1・SHA224・SHA256・SHA384・SHA512
string(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> <variable> <input>)
file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512>)
と同じですが、こちらはファイルの内容ではなく、任意の文字列を指定します。
LENGTH
string(LENGTH <string> <variable>)
文字列<string>
の長さを変数<variable>
に格納します。
文字列の変換
STRIP
string(STRIP <string> <variable>)
文字列<string>
の両端から空白文字を削除し、変数<variable>
に格納します。
TOUPPER・TOLOWER
string(TOUPPER <string> <variable>)
string(TOLOWER <string> <variable>)
文字列<string>
をすべて大文字/小文字にして、変数<variable>
に格納します。
文字列の生成
CONFIGURE
string(CONFIGURE <string> <variable>
[@ONLY] [ESCAPE_QUOTES])
configure_file()
コマンドと同様の動作をしますが、こちらはファイルではなく任意の文字列<string>
に対して処理を行い、その結果を変数<variable>
に出力します。
RANDOM
string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]
[RANDOM_SEED <seed>] <variable>)
乱数を生成し、変数<variable>
に格納します。
TIMESTAMP
string(TIMESTAMP <variable> [<string>] [UTC])
ファイル<filename>
のタイムスタンプを変数<variable>
に出力します。通常はローカル時間(たとえばJST)ですが、UTC
オプションを指定すると標準時間となります。また、<format>
により、任意のフォーマットに変換できます。指定できるフォーマットは下記のとおりとなります。
- 年(4桁)
%Y
- 年(2桁)
%y
- 月(01-12)
%m
- 日(01-31)
%d
- 日(001-336)
%j
- 週(00-53)
%U
- 曜日(0-6)
%w
- 時(00-24)
%H
- 時(00-12)
%I
- 分(00-59)
%M
- 秒(00-60)
%S
これ以外のコマンドについては、string — CMake 3.0.2 Documentation に記述されています。
math()
コマンド
math(EXPR <variable> <expr>)
math()
コマンドは、四則演算やビット演算を行うコマンドです。<expr>
に式を指定し、<variable>
に出力される変数を指定します。math()
コマンドでは、以下の演算が可能です。また、括弧()
も使用できます。
- 可算
+
- 減算
-
- 乗算
*
- 除算
/
- 剰余
%
- ビット和
|
- ビット積
&
- ビット排他的論理和
^
- 右シフト
>>
- 左シフト
<<
注意点として、負の数を指定するとエラーになってしまうようです。また、ビット否定~
が使えるはずですが、同じくエラーになってしまいます。
math(EXPR result "1 + 1") # 2
math(EXPR result "1 - 5") # -4
math(EXPR result "2 * 3") # 6
math(EXPR result "2 * 3 + (2 + 4)") # 12
math(EXPR result "1 << 3") # 8
math(EXPR result "8 >> 2") # 2
math(EXPR result "12 % 10") # 2
math(EXPR result "8 | 15") # 15
math(EXPR result "8 & 15") # 8
math(EXPR result "-1 + 2") # エラー
math(EXPR result "~1") # エラー
execute_process()
コマンド
execute_process(COMMAND <cmd1> [<arg1> ...]]
[COMMAND <cmd2> [<arg2> ...] [...]]
[WORKING_DIRECTORY <directory>]
[TIMEOUT <seconds>]
[RESULT_VARIABLE <variable>]
[OUTPUT_VARIABLE <variable>]
[ERROR_VARIABLE <variable>]
[INPUT_FILE <file>]
[OUTPUT_FILE <file>]
[ERROR_FILE <file>]
[OUTPUT_QUIET]
[ERROR_QUIET]
[OUTPUT_STRIP_TRAILING_WHITESPACE]
[ERROR_STRIP_TRAILING_WHITESPACE])
execute_process()
コマンドは、外部コマンドを実行するコマンドです。
set(build_dir ${CMAKE_CURRENT_LIST_DIR}/build)
file(MAKE_DIRECTORY ${build_dir})
execute_process(
COMMAND ${CMAKE_COMMAND} ..
WORKING_DIRECTORY ${build_dir}
)
cmake_host_system_information()
コマンド
cmake_host_system_information(RESULT <variable> QUERY <key> ...)
cmake_host_system_information()
とは、メモリ量やCPUのコア数、ホスト名などシステム情報を取得するコマンドです。QUERY <key> ...
に取得したい情報を指定し、<variable>
に出力する変数を指定します。指定できる情報には以下があります。なお、<key>
を複数指定した場合は、対応する値がリストとして格納されます。
- CPUの論理コア数
NUMBER_OF_LOGICAL_CORES
- CPUの物理コア数
NUMBER_OF_PHYSICAL_CORES
- ホスト名
HOSTNAME
- ドメイン名
FQDN
- 全仮想メモリ量
TOTAL_VIRTUAL_MEMORY
- 空き仮想メモリ量
AVAILABLE_VIRTUAL_MEMORY
- 全メモリ量
TOTAL_PHYSICAL_MEMORY
- 空きメモリ量
AVAILABLE_PHYSICAL_MEMORY
中でもコア数を示すNUMBER_OF_LOGICAL_CORES
・NUMBER_OF_PHYSICAL_CORES
は、make
コマンドやctest
コマンドの並列数の指定によく使うでしょう。
cmake_host_system_information(RESULT cores QUERY NUMBER_OF_LOGICAL_CORES)
execute_process(COMMAND make -j ${cores})
execute_process(COMMAND ctest -j ${cores})
CMAKE_COMMAND・CMAKE_CTEST_COMMAND 変数
これらの変数は、cmake
コマンドやctest
コマンドのフルパスを返します。
message("CMAKE_COMMAND: ${CMAKE_COMMAND}") # /usr/bin/cmake
message("CMAKE_CTEST_COMMAND: ${CMAKE_CTEST_COMMAND}") # /usr/bin/ctest
CMAKE_CURRENT_LIST_FILE・CMAKE_CURRENT_LIST_DIR 変数
これらの変数は、現在のCMakeスクリプトファイルのディレクトリ・パスを返します。スクリプトモードでよく使うでしょう。
message("CMAKE_CURRENT_LIST_FILE: ${CMAKE_CURRENT_LIST_FILE}") # /path/to/current.cmake
message("CMAKE_CURRENT_LIST_DIR: ${CMAKE_CURRENT_LIST_DIR}") # /path/to
おわりに
以上、CMake スクリプトで使う便利なコマンド・変数でした。これらのコマンドは必須ではありませんが、CMake スクリプトを書く上で便利に使用することができるでしょう。
明日は、mrk_21 さんの『CMake でのメタプログラミングとその応用』です。