cmake tutorialその1:プロジェクトバージョン設定、C++規格指定、out-of-sourceビルド
- 環境
- ubuntu 18.04
- cmake 3.16.0-rc3
- g++ 7.4.0
公式チュートリアルを進めたときの作業記録というかコメンタリー的なものをを適当にブログに起こした。
- とりあえず「A Basic Starting Point (Step 1)」を全部読んだ。
- cmake概略
- 2019年11月時点最新バージョン3.16
- メタビルドシステム
CMakeLists.txt
ファイルに書いた独自DSLを解釈しそれぞれのプラットフォーム用のビルドファイルmake,visual studio,xcodeを作成する- プロジェクトの依存関係やテストの構成なども記述できるのでCLionというIEDはcmake対応前提な作りになっている
- C++の(メタ)ビルドシステムとして2019年時点で支配的な位置を占めている
- 仕事で
C++
書くなら知らないとお話にならないレベル(個人の感想、っていうか俺が今そんなかんじw) - アカデミアとかだとまだまだ慣れていない人も多いらしく、今勉強しておいて身につけておくと重宝されるかも。
- 仕事で
- バージョンごとに作法が違うので最低でも3.1以降のやり方を身につけると良さそう。
- tutorial
- 公式(再掲)
- CGold:英語で公式tutorialの足りない部分が補完できる資料
- 日本語のわかりやすいもの
ステップ1基本
A Basic Starting Pointの内容です
以下の内容のCMakeLists.txtを用意します
# 利用するcmakeのバージョン設定 cmake_minimum_required(VERSION 3.10) #プロジェクト名の設定 project(Tutorial) #ビルド対象のソースの指定 add_executable(Tutorial tutorial.cxx)
command()
的なシンタックスのものを"コマンド"という。- cmakeを解説する資料での"コマンド"という単語はCMakeLists.txtファイル中に記載するものなのか、shellで叩くものなのか、文脈で区別する必要があるので注意
- こういうの割と混乱の元
- cmakeを解説する資料での"コマンド"という単語はCMakeLists.txtファイル中に記載するものなのか、shellで叩くものなのか、文脈で区別する必要があるので注意
- cmakeコマンドは大文字、小文字を無視する
project(Tutorial)
ともPROJECT(Tutorial)
ともかける。
// A simple program that computes the square root of a number #include <cmath> #include <cstdlib> #include <iostream> #include <string> int main(int argc, char* argv[]) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } // convert input to double const double inputValue = atof(argv[1]); // calculate square root const double outputValue = sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0; }
プロジェクトへのバージョン番号設定とヘッダファイルへのバージョン情報の書き込み
- Adding a Version Number and Configured Header Fileの内容です
- プロジェクトにバージョン番号の追加
CMakeLists
に以下を記載
# set the project name and version project(Tutorial VERSION 1.0)
configure_file(TutorialConfig.h.in TutorialConfig.h)
- TutorialConfig.h.inの場所を指定します
- この設定はCMakeListsの末尾に指定する必要があります。*1
- 末尾じゃないとビルドできなかった。理由は謎。
- この設定はCMakeListsの末尾に指定する必要があります。*1
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" )
- 設定ファイル
TutorialConfig.h.in
を作ります
// the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
.h.in
ファイルの@Tutorial_VERSION_MAJOR@
,@Tutorial_VERSION_MINOR@
をビルド時にcmakeが書き換えた.h
ファイルを作成する
$ cat TutorialConfig.h // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR 1 #define Tutorial_VERSION_MINOR 0
どのC++規格を利用するのか指定
# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True)
初ビルド
- ビルドの前に最終的なファイル構成、ファイル内容を確認します
- ファイル
step1/ ├── CMakeLists.txt ├── TutorialConfig.h.in └── tutorial.cxx
- ファイル内容
- CMakeLists.txt
cmake_minimum_required(VERSION 3.10) # set the projetct name project(Tutorial VERSION 1.0) configure_file(TutorialConfig.h.in TutorialConfig.h) # specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) #add the executable add_executable(Tutorial tutorial.cxx) target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" )
- TutorialConfig.h.in
// the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
- tutorial.cxx
// A simple program that computes the square root of a number #include <cmath> #include <cstdlib> #include <iostream> #include <string> #include "TutorialConfig.h" int main(int argc, char* argv[]) { if (argc < 2) { // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } // convert input to double const double inputValue = atof(argv[1]); // calculate square root const double outputValue = sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0; }
ビルド(out of source build)
- ビルドはsourceコードを格納しているディレクトリと同じ高さのディレクトリで行います。
- これはout of source buildと言われるものでソースファイルを汚さないためバージョン管理等と相性がよいらしいです。
- https://qiita.com/osamu0329/items/7de2b190df3cfb4ad0ca
- 仕事でのcmakeもこの作法が普通です。
├── Step1_build ←ここでビルド └── step1 ←こっちはビルド時に汚さない! ├── CMakeLists.txt ├── TutorialConfig.h.in └── tutorial.cxx
- 以下のコマンドを実行すると実行ファイルが作られます
mkdir Step1_build cd Step1_build cmake ../Step1 cmake --build .
cmake
コマンドを2回実行していることに注目してください。- 1回目のコマンド
cmake ../Step1
でビルドに必要なMakefileやバージョン情報を記載した.h
ファイルを作っています。 - 2回目のコマンド
cmake --build .
で下位のビルドシステム(今回はmake)を使って実行ファイルを作っています。
- 1回目のコマンド
cmake --build .
実行前後のディレクトリを見比べてみます- ★が付いているのが
cmake --build
によって作られたファイルです
- ★が付いているのが
前
$ tree . ├── CMakeCache.txt ├── CMakeFiles │ ├── 3.16.0-rc3 │ │ ├── CMakeCCompiler.cmake │ │ ├── CMakeCXXCompiler.cmake │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ ├── CMakeSystem.cmake │ │ ├── CompilerIdC │ │ │ ├── CMakeCCompilerId.c │ │ │ ├── a.out │ │ │ └── tmp │ │ └── CompilerIdCXX │ │ ├── CMakeCXXCompilerId.cpp │ │ ├── a.out │ │ └── tmp │ ├── CMakeDirectoryInformation.cmake │ ├── CMakeOutput.log │ ├── CMakeTmp │ ├── Makefile.cmake │ ├── Makefile2 │ ├── TargetDirectories.txt │ ├── Tutorial.dir │ │ ├── DependInfo.cmake │ │ ├── build.make │ │ ├── cmake_clean.cmake │ │ ├── depend.make │ │ ├── flags.make │ │ ├── link.txt │ │ └── progress.make │ ├── cmake.check_cache │ └── progress.marks ├── Makefile ├── TutorialConfig.h └── cmake_install.cmake 8 directories, 27 files
- 後
. ├── CMakeCache.txt ├── CMakeFiles │ ├── 3.16.0-rc3 │ │ ├── CMakeCCompiler.cmake │ │ ├── CMakeCXXCompiler.cmake │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ ├── CMakeSystem.cmake │ │ ├── CompilerIdC │ │ │ ├── CMakeCCompilerId.c │ │ │ ├── a.out │ │ │ └── tmp │ │ └── CompilerIdCXX │ │ ├── CMakeCXXCompilerId.cpp │ │ ├── a.out │ │ └── tmp │ ├── CMakeDirectoryInformation.cmake │ ├── CMakeOutput.log │ ├── CMakeTmp │ ├── Makefile.cmake │ ├── Makefile2 │ ├── TargetDirectories.txt │ ├── Tutorial.dir │ │ ├── ★CXX.includecache │ │ ├── DependInfo.cmake │ │ ├── build.make │ │ ├── cmake_clean.cmake │ │ ├── ★depend.internal │ │ ├── depend.make │ │ ├── flags.make │ │ ├── link.txt │ │ ├── progress.make │ │ └── ★tutorial.cxx.o │ ├── cmake.check_cache │ └── progress.marks ├── Makefile ├── ★Tutorial ├── TutorialConfig.h └── cmake_install.cmake 8 directories, 31 files
- もちろん新規に作られたTutorialファイルが実行ファイルです。
- build中のstdioのログ
Scanning dependencies of target Tutorial [ 50%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o [100%] Linking CXX executable Tutorial [100%] Built target Tutorial
- 実行結果
$ ./Tutorial 1024 The square root of 1024 is 32
- Versionの表示
$ ./Tutorial ./Tutorial Version 1.0 Usage: ./Tutorial number
*1:Add the following lines to the end of the CMakeLists.txt file: