「Qtの設定 - CMake」の版間の差分
41行目: | 41行目: | ||
cmake_minimum_required(VERSION <メジャー番号>.<マイナー番号>[.<バグフィックス番号>.<ビルド番号>]) | cmake_minimum_required(VERSION <メジャー番号>.<マイナー番号>[.<バグフィックス番号>.<ビルド番号>]) | ||
<br> | <br> | ||
<code>VERSION</ | <code>VERSION</code>オプションは常に必要であり、<code><メジャー番号></code>および<code><マイナー番号></code>も記述する必要がある。<br> | ||
ほとんどのCMakeプロジェクトでは、<code><バグフィックス番号></code>および<code><ビルド番号></code>を指定する必要はない。(CMakeの新しい機能はマイナー番号のアップデートでのみ現れるため)<br> | ほとんどのCMakeプロジェクトでは、<code><バグフィックス番号></code>および<code><ビルド番号></code>を指定する必要はない。(CMakeの新しい機能はマイナー番号のアップデートでのみ現れるため)<br> | ||
特定のバグフィックスが必要な場合のみ、<code><バグフィックス番号></code>を指定すべきである。 | 特定のバグフィックスが必要な場合のみ、<code><バグフィックス番号></code>を指定すべきである。 | ||
49行目: | 49行目: | ||
詳細を知りたい場合は、[[Qtの設定 - CMake#CMakeのポリシー設定]]において、<code>cmake_minimum_required</code>コマンドの挙動を調整する方法を参照すること。<br> | 詳細を知りたい場合は、[[Qtの設定 - CMake#CMakeのポリシー設定]]において、<code>cmake_minimum_required</code>コマンドの挙動を調整する方法を参照すること。<br> | ||
これにより、CMakeは内部でバグを修正し、新しい機能を導入しながらも、過去の特定のリリースの期待される振る舞いを維持することができる。<br> | これにより、CMakeは内部でバグを修正し、新しい機能を導入しながらも、過去の特定のリリースの期待される振る舞いを維持することができる。<br> | ||
<br><br> | |||
== projectコマンド == | |||
全てのCMakeプロジェクトは、<code>project</code>コマンドを含む必要があり、<code>cmake_minimum_required</code>コマンドの後に記述する。<br> | |||
<syntaxhighlight lang="cmake"> | |||
# CMake 3.0以降 | |||
project( | |||
<プロジェクト名> | |||
[VERSION <メジャー番号>[.<マイナー番号>.<バグフィックス番号>.<ビルド番号>]] | |||
[LANGUAGES <プログラム言語名 例. CやCXX等>] | |||
) | |||
# CMake 2.x以前 | |||
project( | |||
<プロジェクト名> | |||
[<プログラム言語名 例. CやCXX等>] | |||
) | |||
</syntaxhighlight> | |||
<br> | |||
<code><プロジェクト名></code>オプションは必須であり、英数字、アンダースコア(<code>_</code>)、ハイフン(<code>-</code>)が使用できる。<br> | |||
ただし、空白は使用できない。<br> | |||
<code><プロジェクト名></code>は、引用符で囲む必要はない。<br> | |||
<br> | |||
<code>VERSION</code>オプションは、CMake 3.0以降でのみサポートされている。<br> | |||
<br> | |||
<code>LANGUAGES</code>オプションは、CMakeプロジェクトで有効にするプログラム言語を指定する。(<code>C</code>、<code>CXX</code>、<code>Fortran</code>、<code>ASM</code>、<code>Java</code>等)<br> | |||
複数の言語を指定する場合は、それぞれをスペースで区切る。<br> | |||
<br> | |||
特殊な状況下では、CMakeプロジェクトはプログラム言語を使用しないことを示す必要がある場合が存在する。<br> | |||
このような場合、<code>LANGUAGES NONE</code>を指定する。 | |||
<br> | |||
CMake 2.x以前では、<code>LANGUAGES</code>オプションがサポートされていないため、<code><プロジェクト名></code>の後にプログラム言語を指定する。<br> | |||
<br> | |||
<code>project</code>コマンドの重要な役割の1つは、有効化された各言語のコンパイラをチェックして、正常にコンパイルとリンクを行えるかどうかを確認することである。<br> | |||
コンパイラやリンカのチェックが正常に終了した後、その結果はキャッシュされて、ビルドディレクトリのCMakeCache.txtファイルに保存される。<br> | |||
その後、CMakeは有効化された機能を制御する多くの変数とプロパティをセットアップする。<br> | |||
<br><br> | <br><br> | ||
2022年12月14日 (水) 14:02時点における版
概要
CMakeは、アメリカ国立医学図書館の出資により医療系画像解析に利用されるITK(Insight Toolkit)のために開発されたクロスプラットフォーム向けのメタビルドシステムであり、
qmakeと同様、クロスプラットフォーム向けに各種ビルドシステムのためのレシピファイルを生成する。
qmakeがQtのために開発されているのに対して、CMakeはITKのためにと開発されたが、メタビルドシステムとして独立のオープンソースプロジェクトとして単独で提供されている。
このため、KDE、LLVM、OpenCVをはじめ多数のプロジェクトで採用されている。
CMakeは、主に、C/C++等のプログラム言語のビルドに使用される。
CMakeが存在する以前では、C系言語のビルドには多数のビルドシステム(MakefileやNinjaやIDE等)が乱立していた。
これを隠蔽して、包括的に扱える様にしたものがCMakeである。
また、CMakeには、CUI版とGUI版が存在する。
CMakeは、変数、コマンド、マクロ、条件論理、ループ、コメント等の開発者にとって馴染みのある多くのものを備えている。
CMakeで使用されるコマンド名も大文字小文字を区別しないため、以下は全て等価である。
ただし、最近では、コマンド名を全て小文字で記述することが一般的である。(これは、CMakeのドキュメントでビルトインコマンドのために従われている慣習でもある)
add_executable(myExe main.cpp)
ADD_EXECUTABLE(myExe main.cpp)
Add_Executable(myExe main.cpp)
CMakeのバージョン管理 (cmake_minimum_requiredコマンド)
CMakeは、新しいツールやプラットフォーム、機能のサポートを追加するために継続的に更新および拡張されている。
開発者は、新しいリリースごとに後方互換性を維持することに非常に注意を払うことになる。
そのため、ユーザがCMakeの新しいバージョンに更新した時、プロジェクトは以前と同じようにビルドし続けることができる。
時には、CMakeの特定の動作を変更する必要があったり、より厳しいチェックや警告が新しいバージョンで導入されたりすることがある。
全てのプロジェクトに直ちにこのような対応を要求するのではなく、CMakeは、プロジェクトが"CMakeのバージョン X.Y.Zのように振る舞う"というようなポリシー機構を提供する。
CMakeのバージョン動作の詳細を指定する主な方法は、cmake_minimum_required
コマンドを使用することである。
これは、CMakeLists.txtファイルの最初の行で記述するべきであり、プロジェクトの要件が他の何よりも先にチェックされ、確立されるようにするものである。
cmake_minimum_required
コマンドは、以下に示す2つのことを実行する。
- プロジェクトが必要とするCMakeの最小バージョンを指定する。
CMakeLists.txtファイルが指定されたバージョンより古いCMakeのバージョンで処理された場合、エラーが発生して直ちに停止する。
これにより、処理を進める前に、CMakeの機能の特定の最小セットが利用可能であることが保証される。 - CMakeの動作を指定されたバージョンに一致させるためのポリシー設定を強制するものである。
もし、cmake_minimum_required
コマンドを記述しなかった場合は警告を出力する。
ほとんどのプロジェクトでは、cmake_minimum_required
コマンドは、単に必要最小限のCMakeのバージョンを指定するものとして扱えば十分である。
cmake_minimum_required(VERSION <メジャー番号>.<マイナー番号>[.<バグフィックス番号>.<ビルド番号>])
VERSION
オプションは常に必要であり、<メジャー番号>
および<マイナー番号>
も記述する必要がある。
ほとんどのCMakeプロジェクトでは、<バグフィックス番号>
および<ビルド番号>
を指定する必要はない。(CMakeの新しい機能はマイナー番号のアップデートでのみ現れるため)
特定のバグフィックスが必要な場合のみ、<バグフィックス番号>
を指定すべきである。
さらに、CMake 3.0以降では、<ビルド番号>
を使用していないため、指定する必要はない。
詳細を知りたい場合は、Qtの設定 - CMake#CMakeのポリシー設定において、cmake_minimum_required
コマンドの挙動を調整する方法を参照すること。
これにより、CMakeは内部でバグを修正し、新しい機能を導入しながらも、過去の特定のリリースの期待される振る舞いを維持することができる。
projectコマンド
全てのCMakeプロジェクトは、project
コマンドを含む必要があり、cmake_minimum_required
コマンドの後に記述する。
# CMake 3.0以降
project(
<プロジェクト名>
[VERSION <メジャー番号>[.<マイナー番号>.<バグフィックス番号>.<ビルド番号>]]
[LANGUAGES <プログラム言語名 例. CやCXX等>]
)
# CMake 2.x以前
project(
<プロジェクト名>
[<プログラム言語名 例. CやCXX等>]
)
<プロジェクト名>
オプションは必須であり、英数字、アンダースコア(_
)、ハイフン(-
)が使用できる。
ただし、空白は使用できない。
<プロジェクト名>
は、引用符で囲む必要はない。
VERSION
オプションは、CMake 3.0以降でのみサポートされている。
LANGUAGES
オプションは、CMakeプロジェクトで有効にするプログラム言語を指定する。(C
、CXX
、Fortran
、ASM
、Java
等)
複数の言語を指定する場合は、それぞれをスペースで区切る。
特殊な状況下では、CMakeプロジェクトはプログラム言語を使用しないことを示す必要がある場合が存在する。
このような場合、LANGUAGES NONE
を指定する。
CMake 2.x以前では、LANGUAGES
オプションがサポートされていないため、<プロジェクト名>
の後にプログラム言語を指定する。
project
コマンドの重要な役割の1つは、有効化された各言語のコンパイラをチェックして、正常にコンパイルとリンクを行えるかどうかを確認することである。
コンパイラやリンカのチェックが正常に終了した後、その結果はキャッシュされて、ビルドディレクトリのCMakeCache.txtファイルに保存される。
その後、CMakeは有効化された機能を制御する多くの変数とプロパティをセットアップする。
CMakeとqmakeの特徴
qmake | CMake | |
---|---|---|
レシピファイル | <Qtプロジェクト名>.pro | CMakeLists.txt |
レシピの呼び方 | プロジェクトファイル | CMakeソースコード |
特徴 | 変数ベース | コマンドベース |
ターゲット | 1ファイル 1ターゲット | 1ファイル 複数ターゲット |
プロジェクト間の連携 | 不可 | ターゲット名でリンク可能 |
Qtのサポート | ◎ | ○ |
Qt Creatorの対応 | ◎ | ファイルの追加等の対応がイマイチ |
カスタムコンパイラの対応 | △ | ◎ |
Packageの作成 | △ | ○ |
レシピファイルの違い
qmakeとCMakeは、レシピの考え方が異なる。
qmakeは、変数SOURCES
等のような変数に適切な値を設定していくことにより、対応するアーキテクチャの設定ファイル等から取得した値を使用して、
MakefileやVisual Studio / XCode向けのプロジェクトファイルを生成する。
CMakeは、コマンドと呼ばれる関数の引数に、ターゲットの情報、Define情報、インクルードパス等をプログラムして、Makefileや各種プロジェクトファイルを生成する。
# qmakeの場合
TEMPLATE = app
CONFIG -= qt # Qtライブラリを使用しない場合は、変数CONFIGからqtを削除する
SOURCES = main.cpp
# CMakeの場合
cmake_minimum_required(VERSION 3.15)
project(HelloWorld LANGUAGES CXX)
add_executable(helloworld main.cpp)
以下の例は、Qt Coreライブラリのみを使用するQtソフトウェアにおける最低限のレシピファイルである。
CMakeは汎用的なツールのため、Qtライブラリを使用する場合、CMakeのコマンド量が増加する。
find_package
関数を使用してQtライブラリ全体からQt Coreライブラリを要求することにより、
Qt Coreライブラリを変数Qt5::Core(Qt6では、Qt6::Coreとなる)経由で、target_link_libraries
に指定してリンクを指示する。
# qmakeの場合
TEMPLATE = app
QT -= gui # qmakeの初期状態はGUIが有効なため、変数QTからguiを削除することにより、Qt Coreライブラリのみとなる
SOURCES = main.cpp hello.cpp
HEADERS = hello.h
# CMakeの場合
cmake_minimum_required(VERSION 3.15)
project(HelloWorld LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5 COMPONENTS Core REQUIRED)
add_executable(helloworld
main.cpp
hello.cpp
hello.h
)
target_link_libraries(helloworld
Qt5::Core
)
共通の機能
- サブディレクトリ(サブプロジェクト)に対応
- ファイルの読み書き
- 独自関数の定義
- 別ファイルに分割したレシピをインクルードできる
- 自動的にmocを呼び出す
- Qtのリソースファイル対応
- インストールの定義
- 繰り返し文や条件分岐文
- プラットフォームの判定
- インストール
- テストの設定および実行
- 追加機能およびモジュール等の提供
CMakeの強みは、カスタムコンパイラ、機能の拡張性、パッケージ作成まで行う機能が提供されていることである。
qmakeでは、QTestによりテストの設定および実行もできるが、ビルドを補助するツールとしての特色が強い。
CMakeでは、CTest、CPack等の機能により、テストやパッケージ作成も可能である。
qmakeもCMakeも制御構文を持ち複雑なプロジェクトの作成も可能であるが、プロジェクトでの採用検討という視点から将来性も含めて考慮した場合、CMakeの方が有力である。
変数
変数の宣言と代入
変数は、set
コマンドを使用して、変数を宣言および代入することができる。
set(value 1) # 値が1の変数valueを宣言
既存の変数への代入もset
コマンドを使用する。
変数の値の参照は、入れ子にすることもできる。
set(value 1) # 値が1の変数valueを生成
set(value 2) # 既存の変数valueに値1を代入
set(value_name value) # 変数value_nameに変数valueの値を代入
message(${${value_name}}) # ${value_name}が展開されて、${${value_name}}が${value}になり、これが展開されて2になる
set(USE_CCACHE OFF CACHE BOOL "")
変数の削除
変数の削除する場合は、unset
コマンドを使用する。
set(value 1) # 変数valueを宣言
unset(value) # 変数valueを削除
定義された全ての変数を出力
get_cmake_property(variableNames VARIABLES)
foreach(variableName ${variableNames})
message(STATUS "${variableName}=${${variableName}}")
endforeach()
ログメッセージの出力
messageコマンドとは
message([<mode>] "message to display" ...)
下表に、<mode>
に指定できる項目を示す。(一部)
modeの種類 | 説明 | 処理の継続 | 出力先 |
---|---|---|---|
省略する場合 | 重要な情報 | CMakeの処理を継続する | STDERR |
STATUS | 情報 | CMakeの処理を継続する | STDOUT |
WARNING | 警告 | CMakeの処理を継続する | STDERR |
SEND_ERROR | エラー | CMakeの処理を継続する | STDERR |
FATAL_ERROR | 致命的なエラー | CMakeの処理を終了する | STDERR |
以下の例では、message
コマンドにおいて、第1引数にFATAL_ERROR
を指定することにより、エラーメッセージを出力して、CMakeコマンドを終了している。
message(FATAL_ERROR "cmake to terminate.")
また、message
コマンドにおいて、第1引数にSEND_ERROR
を指定することにより、エラーメッセージを出力して動作を継続する。
message(SEND_ERROR "Continue cmake.")
以下の例では、Linux以外のOSの場合は、エラーメッセージを出力して、cmake
コマンドを終了している。
if(NOT (UNIX AND NOT APPLE))
message(FATAL_ERROR "ERROR! Only Linux can build this software.")
else()
set(LINUX TRUE)
endif()
以下の例では、CMakeの特殊変数であるCMAKE_COMMAND
とCMAKE_CTEST_COMMAND
を出力している。
message("${CMAKE_COMMAND}") # /usr/bin/cmake
message("${CMAKE_CTEST_COMMAND}") # /usr/bin/ctest
インクルードパスの指定
インクルードパスを指定する場合、include_directories
コマンドを使用する。
include_directories(/path/to/include)
include_directories
コマンドを複数使用する場合、デフォルトでは、指定したパスは最後尾となる。
ただし、include_directories
コマンドにBEFORE
オプションを付加した場合は最前となる。
以下の例では、"-I/path1/to/include -I/path2/to/include"となる。
include_directories(/path1/to/include)
include_directories(/path2/to/include)
以下の例では、"-I/path2/to/include -I/path1/to/include" となる。
include_directories(/path1/to/include)
include_directories(BEFORE /path2/to/include)
ライブラリパスの指定
ライブラリパスを指定する場合、link_directories
コマンドを使用する。
link_directories(/path/to/lib)
link_directories
コマンドを複数使用する場合、デフォルトでは、指定したパスは最後尾となる。
ただし、link_directories
コマンドにBEFORE
オプションを付加した場合は最前となる。
以下の例では、"-I/path1/to/lib -I/path2/to/lib"となる。
link_directories(/path1/to/lib)
link_directories(/path2/to/lib)
以下の例では、"-I/path2/to/lib -I/path1/to/lib" となる。
link_directories(/path1/to/lib)
link_directories(BEFORE /path2/to/lib)
qt5_create_translation
TSファイルやTSファイルがあるディレクトリを指定して、Qt LinguistからTSファイルを生成する。
TSファイルは、ビルドディレクトリに保存される同じベースネームのQMファイルにコンパイルされる。
生成されたQMファイルへのパスは、<変数名>に追加される。
作成または更新する翻訳ファイルの拡張子は.ts
である必要がある。
与えられたTSファイルのパスが相対パスの場合、現在のプロジェクトのトップディレクトリからの相対パスで解決される。
TSファイルが存在しない場合、qt5_create_translation
は何もしない。
lupdate
コマンドは、ソースファイルまたはディレクトリを入力として受け付ける。
<オプション>は、lupdate
コマンドの実行時に使用するオプションを指定することができる。
指定可能なオプションは、Qtの設定 - Qt Linguist#lupdateコマンドを参照すること。
qt5_create_translation(<変数名> <TSファイル 1> <TSファイル 2> <TSファイル 3> ... <オプション>)
# 例.
# まず、プロジェクトのトップディレクトリにあるTSファイルを検索する。(helloworld_en.tsファイルとhelloworld_ja.tsファイル)
# 次に、lupdateコマンドを実行してTSファイルをコンパイルすることにより、helloworld_en.qmファイルとhelloworld.ja.qmファイルを生成または更新する。
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} helloworld_en.ts helloworld_de.ts)