チュートリアルの内容が、次に利用するのが変数だったので。
参考:
Adding a Version Number and Configured Header File
The first feature we will add is to provide our executable and project with a version number. While you can do this exclusively in the source code, doing it in the CMakeLists.txt file provides more flexibility. To add a version number we modify the CMakeLists.txt file as follows:
cmake_minimum_required (VERSION 2.6) project (Tutorial) # The version number. set (Tutorial_VERSION_MAJOR 1) set (Tutorial_VERSION_MINOR 0) # configure a header file to pass some of the CMake settings # to the source code configure_file ( "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h include_directories("${PROJECT_BINARY_DIR}") # add the executable add_executable(Tutorial tutorial.cxx)
Since the configured file will be written into the binary tree we must add that directory to the list of paths to search for include files. We then create a TutorialConfig.h.in file in the source tree with the following contents:
// the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
いきなり変数がいくつか出てきている。そして、その変数をビルドするソース内のヘッダなどに埋め込めるということらしいが、 変数の中身がわからないのがあるのでこれを確認したい。
message
https://cmake.org/cmake/help/v3.8/command/message.html
ログメッセージを出力する関数。
message([<mode>] "message to display" ...)
省略可能な
<mode>
には以下のようなものがある(一部):
mode description 処理の継続 出力先 (none) 重要な情報 Yes STDERR STATUS INFO的なやつ Yes STDOUT WARNING 警告 Yes STDERR FATAL_ERROR 致命的エラー No STDERR 出力先は、STATUS以外は
STDOUT
である。
最後 STDOUT
は STDERR
の間違いのようだが、これで出力することができるようだ。
で、どのように変数をこの関数に渡してあげればよいのか。
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
変数の値の参照
変数の値の参照は、
${variable-name}
という構文で行います。set(value 1) message(${value}) # 1
普通に ${Variable}
で表示してくれるようだ。なのでこんな CMakeLists.txt を作って実行してみる。
cmake_minimum_required(VERSION 3.14)
message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}")
message(STATUS "PROJECT_BINARY_DIR = ${PROJECT_BINARY_DIR}")
$ mkdir build && cd build && cmake ..
-- The C compiler identification is AppleClang 10.0.0.10001145
-- The CXX compiler identification is AppleClang 10.0.0.10001145
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- PROJECT_SOURCE_DIR = /Users/leico_studio/pro/C++/cmake
-- PROJECT_BINARY_DIR = /Users/leico_studio/pro/C++/cmake/build
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/leico_studio/pro/C++/cmake/build
内容が判明したので、このチュートリアルで利用されている変数についてまとめた。
変数に格納されているパスが確定したので、その場所、 PROJECT_SOURCE_DIR
に config 用ヘッダファイル TutorialConfig.h.in を置く。
内容は上記の通り、
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
config 用ヘッダファイル内で cmake
の変数を利用するには、上記の通り @Variable@
という記述となるようだ。
ここまでを踏まえて、以下の内容で cmake
の設定などを書き換えて実際に動かしてみた。
$ ls -l
total 24
-rw-r--r-- 1 leico_studio staff 307 6 23 20:08 CMakeLists.txt
-rw-r--r-- 1 leico_studio staff 165 6 23 20:01 TutorialConfig.h.in
-rw-r--r-- 1 leico_studio staff 499 6 23 20:10 main.cpp
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include "TutorialConfig.h"
int main ( int argc, char* argv[] ) {
fprintf( stdout, "%s ver. %d.%d\n", argv[ 0 ], Tutorial_VERSION_MAJOR, Tutorial_VERSION_MINOR );
if( argc < 2 ) {
fprintf( stdout, "Usage: %s number\n ", argv[ 0 ] );
return 1;
}
double inputValue = atof( argv[ 1 ] );
double outputValue = sqrt( inputValue );
fprintf( stdout, "The square root of %g is %g\n", inputValue, outputValue );
return 0;
}
cmake_minimum_required(VERSION 3.14)
project(Tutorial)
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
include_directories("${PROJECT_BINARY_DIR}")
add_executable(Tutorial main.cpp)
$ mkdir build && cd build && cmake .. && make && ./Tutorial 144
-- The C compiler identification is AppleClang 10.0.0.10001145
-- The CXX compiler identification is AppleClang 10.0.0.10001145
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/leico_studio/pro/C++/cmake/build
Scanning dependencies of target Tutorial
[ 50%] Building CXX object CMakeFiles/Tutorial.dir/main.cpp.o
[100%] Linking CXX executable Tutorial
[100%] Built target Tutorial
./Tutorial ver. 1.0
The square root of 144 is 12
cmake
実行、 make
実行Tutorial
の実行を1行でやってしまっているのでちょっとわかりにくいか。
$ ls -l
total 88
-rw-r--r-- 1 leico_studio staff 13731 6 23 20:10 CMakeCache.txt
drwxr-xr-x 15 leico_studio staff 480 6 23 20:10 CMakeFiles
-rw-r--r-- 1 leico_studio staff 4942 6 23 20:10 Makefile
-rwxr-xr-x 1 leico_studio staff 8532 6 23 20:10 Tutorial
-rw-r--r-- 1 leico_studio staff 119 6 23 20:10 TutorialConfig.h
-rw-r--r-- 1 leico_studio staff 1391 6 23 20:10 cmake_install.cmake
Makefile などがある以外に、 TutorialConfig.h が TutorialConfig.h.in から生成されているようだ。 TutorialConfig.h の中身を確認してみる
$ cat TutorialConfig.h
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 0
各々の値に書き換わっているのが確認できる。
以下、ここまでで触れることができなかったものに遭遇したのでまとめておく。
インクルードパスを指定する
インクルードパスを指定するときは
include_directories
コマンドを使う。cmake_minimum_required(VERSION 2.8) include_directories(/path/to/include) add_executable(myapp main.cpp)
なお、
include_directories
は複数回指定可能で、デフォルトでは後で指定したものは後ろにつく。 ただし、オプションでBEFORE
を指定したときは前につく。例えば、include_directories(/path1/include) include_directories(/path2/include)
としたときは
"-I/path1/include -I/path2/include"
となり、include_directories(/path1/include) include_directories(BEFORE /path2/include)
としたときは
"-I/path2/include -I/path1/include"
となる。
変数の生成・代入
変数は、
set()
コマンドを用いて生成することができます。set(value 1) # 値が1の変数valueを生成
また、既存の変数への代入もset()コマンドを用います。
set(value 1) # 値が1の変数valueを生成 set(value 2) # 既存の変数valueに値1を代入
また、
変数の値の参照は、入れ子にすることもできます。
set(value 1) set(value_name value) message(${${value_name}}) # 1
これは
set(value 1) # value に 1 をセット
set(value_name value) # value_name に value をセット
set(${${value_name}})
# ${value_name} が展開され ${${value_name}} が ${value} になり、これが展開されて 1 になる
ということのようだ。
さらに波括弧の中では
組み合わせることもできます
set(value_10 1) set(value_basename value) set(value_no 10) message(${${value_basename}_${value_no}}) # 1
他、定義していない変数を利用した場合は
空文字列が返されます。
message("not_existing_value: '${not_existing_value}'") # not_existing_value: ''
同じページに削除する方法も載っていた
変数の削除
変数の削除には、
unset()
コマンドを用います。set(value 1) # 変数valueを生成 unset(value) # 変数valueを削除
CMakeのなかで使われている変数はたくさんあって (よく使うのは
CMAKE_CXX_FLAGS
とかですかね)、 それらをすべて出力する方法はないかと思って調べてみたら、stackoverflowにあった。CMAKE: Print out all accessible variables in a script - Stack Overflow
CMakeLists.txt に次のコードを書いて実行すると、
*** dump start cmake variables ***
と*** dump end ***
の間にすべての変数が出力される。message(STATUS "*** dump start cmake variables ***") get_cmake_property(_variableNames VARIABLES) foreach(_variableName ${_variableNames}) message(STATUS "${_variableName}=${${_variableName}}") endforeach() message(STATUS "*** dump end ***")