最小バージョン
ここで、すべてのCMakeLists.txt
の最初の行は、CMakeが探すファイルの必須の名前です:
cmake_minimum_required(VERSION 3.1)
少しCMake構文を言及しましょう。 コマンド名cmake_minimum_required
は大文字と小文字を区別しないので、小文字を使うのが一般的です。 1 VERSION
は、この機能のための特別なキーワードです。 そして、バージョンの値は、キーワードに続いています。 この本のどこでもそうですが、公式のドキュメントを見るにはコマンド名をクリックし、CMakeのバージョン間でドキュメントを切り替えるにはドロップダウンを使用します。
この行は特別です 2 CMakeのバージョンはまた、動作の変更を定義するポリシーを指示します。 つまり、minimum_required
を VERSION2.8
に設定すると、最新の CMake バージョンであっても、例えば macOS では間違ったリンク動作が行われます。 3.3以下に設定すると、間違ったhidden symbolsの動作になる、などです。 ポリシーとバージョンのリストは、policies.
CMake 3.12 からは、VERSION 3.1...3.15
のような範囲をサポートします。これは 3.1 までサポートしますが、新しいポリシーの設定で 3.15 までテストしていることを意味します。 これは、より良い設定を必要とするユーザーにとってより良いもので、構文のトリックにより、古いバージョンの CMake との下位互換性があります(ただし、実際に CMake 3.1-3.11 を実行すると、この例のポリシーの 3.1 バージョンしか設定されません、これらのバージョンではこの特別な扱いがないからです)。 ポリシーの新しいバージョンは、通常 CMake の非常に新しいバージョンを持っている macOS および Windows ユーザーにとって最も重要である傾向があります。
これは、新しいプロジェクトが行うべきことです。 CMake が 3.12 以上の場合、if ブロックは false になりますが、cmake_minimum_required
の新しい構文が尊重され、これは引き続き正しく機能します!
WARNING: MSVC の CMake サーバー モードには、もともとこの形式の読み込みに問題がありました。したがって、古い MSVC バージョンの非コマンド ライン Windows ビルドをサポートする必要がある場合、代わりにこれを実行する必要があります。 少なくとも macOS ユーザーにはこのようにしてください!
Setting a project
さて、すべてのトップレベルの CMake ファイルは次の行を持ちます:
project(MyProject VERSION 1.0 DESCRIPTION "Very nice project" LANGUAGES CXX)
ここでさらに多くの構文を見てください。 文字列は引用され、空白は関係なく、プロジェクト名は最初の引数(位置指定)です。 ここでのすべてのキーワード引数はオプションです。 バージョンは、MyProject_VERSION
や PROJECT_VERSION
のような変数の束を設定します。 言語は、C
, CXX
, Fortran
, ASM
, CUDA
(CMake 3.8+), CSharp
(3.8+), SWIFT
(CMake3.15+ experimental)のようになります。 C CXX
がデフォルトです。 CMake 3.9 では、プロジェクトの説明を設定するために DESCRIPTION
も追加されました。
#
文字でコメントを追加することができます。 CMake にもコメント用のインライン構文がありますが、ほとんど使われません。
プロジェクト名については、特に何もありません。
実行ファイルを作る
ライブラリはもっと面白く、私たちはほとんどの時間をそれに費やしますが、まずは簡単な実行ファイルから始めてみましょう。 one
は生成された実行ファイルの名前と、作成された CMake ターゲットの名前です (ターゲットについては、もうすぐたくさん聞けるようになります。)。 次にソースファイルのリストが来ますが、好きなだけリストアップすることができます。 CMakeは賢いので、ソースファイルの拡張子だけをコンパイルします。 ヘッダはほとんどの場合、無視されます。ヘッダをリストアップする唯一の理由は、IDEで表示させるためです。 ターゲットは多くの IDE でフォルダーとして表示されます。 一般的なビルドシステムとターゲットについての詳細は buildsystem.
Making a library
Making a library is done with add_library
and is just about simple:
add_library(one STATIC two.cpp three.h)
You get to pick the type of library, STATIC, SHARED, or MODULE.
次のセクションで説明するように、しばしば架空のターゲット、つまり何もコンパイルする必要のない、ヘッダーのみのライブラリーを作る必要があります。
また、既存のライブラリを使って ALIAS
ライブラリを作ることもでき、これは単にターゲットに新しい名前を与えるだけです。 この場合の利点は、名前に::
を含むライブラリを作ることができることです(これは後ほど説明します)。 3
ターゲットは友達
さて、ターゲットを指定しましたが、ターゲットに関する情報をどのように追加すればよいのでしょうか。 たとえば、include ディレクトリが必要かもしれません:
target_include_directories(one PUBLIC include)
target_include_directories
はターゲットに include ディレクトリを追加します。 PUBLIC
は実行ファイルではあまり意味がありませんが、ライブラリでは CMake にこのターゲットにリンクするターゲットがインクルードディレクトリも必要であることを知らせます。 他のオプションは、PRIVATE
(依存関係ではなく現在のターゲットにのみ影響) と INTERFACE
(依存関係にのみ必要) です。
次にターゲットを連結します。 これはターゲット (another
) を受け取り、ターゲットが与えられていれば依存関係を追加します。 もしその名前のターゲット (one
) が存在しなければ、パス上の one
というライブラリへのリンクを追加します (これがコマンドの名前の由来です)。 また、ライブラリへのフルパスを指定することもできる。 あるいはリンカフラグを指定することもできます。 最後に少し混乱を付け加えると、古典的な CMake では PUBLIC
などのキーワード選択を省略することができました。 これがターゲット上で行われた場合、さらに下位のスタイルを混合しようとするとエラーが発生します。
どこでもターゲットを使用し、どこでもキーワードを使用することに集中すれば、うまくいきます。
ターゲットには、インクルード ディレクトリ、リンクしたライブラリ(またはリンクしたターゲット)、コンパイル オプション、コンパイル定義、およびコンパイル機能(C++11 章を参照)など、があります。 プロジェクトを含む 2 つの章で説明するように、多くの場合、使用するすべてのライブラリを表すターゲットを得ることができます (そして、常にターゲットを作ることができます)。 OpenMPのような真のライブラリでないものでさえ、ターゲットで表現することができます。 これが Modern CMake が素晴らしい理由です!
Dive in
次のファイルを追えるかどうか見てみてください。 簡単なC++11のライブラリとそれを使ったプログラムを作っています。 依存関係はありません。 後でもっと多くの C++ 標準オプションについて説明しますが、今は CMake 3.8 システムを使っています。
cmake_minimum_required(VERSION 3.8)project(Calculator LANGUAGES CXX)add_library(calclib STATIC src/calclib.cpp include/calc/lib.hpp)target_include_directories(calclib PUBLIC include)target_compile_features(calclib PUBLIC cxx_std_11)add_executable(calc apps/calc.cpp)target_link_libraries(calc PUBLIC calclib)
1. この本では、間違った方法を紹介することはほとんど避けたいと思います。 時々、代替品について言及しますが、これらは絶対に必要でない限り推奨しません。多くの場合、それらは古い CMake コードを読むのに役立つだけです。
2. これは CMake <2.6 でこれを実行したときの素晴らしい失敗をサポートするために必要でしたが、もう問題はないはずです。
3.
::
構文は元々INTERFACE IMPORTED
ライブラリ用で、現在のプロジェクトの外で定義されたライブラリであることが 明示的に想定されていました。 しかし、このため、target_*
コマンドのほとんどはIMPORTED
ライブラリでは動作せず、自分で設定することが困難になっています。 ですから、今のところIMPORTED
キーワードは使用せず、代わりにALIAS
ターゲットを使用してください。 この制限は CMake 3.11 で修正されました。