「Qtの設定 - CMake」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
(文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This pag…)
 
(同じ利用者による、間の14版が非表示)
26行目: 26行目:
*: 指定したディレクトリからヘッダファイルを検索するコマンドである。
*: 指定したディレクトリからヘッダファイルを検索するコマンドである。
*: 定義した箇所以降の全てのターゲットが指定したディレクトリをインクルードするため、使用は避けるべきである。
*: 定義した箇所以降の全てのターゲットが指定したディレクトリをインクルードするため、使用は避けるべきである。
*: 代わりに、<code>target_include_directories</code>コマンドを使用する必要がある。
<br>
<br>
* add_definitionsコマンド
* add_definitionsコマンド
** プロジェクト全体に影響を与えてしまう。
** ビルド依存性の管理が難しくなる。
** コンパイラの最適化を阻害する可能性がある。
*: 代わりに、<code>target_compile_definitions</code>コマンドを使用する必要がある。
<br>
<br>
* add_compile_definitionsコマンド
* add_compile_definitionsコマンド
** プロジェクト全体への影響
**: プロジェクト内の全てのターゲットに対して定義を追加される。
**: これにより、意図しないターゲットにまで定義が設定されてしまう可能性がある。
** ビルド依存性の管理が難しくなる
**: 特定のターゲットにのみ必要な定義がプロジェクト全体に設定されると、ビルド依存性の管理が複雑になる。
** コンパイラの最適化への影響
**: 不要な定義が設定されると、コンパイラの最適化が阻害される可能性がある。
*: 代わりに、<code>target_compile_definitions</code>コマンドを使用する必要がある。
<br>
<br>
* add_compile_optionsコマンド
* add_compile_optionsコマンド
*: プロジェクト全体に対してコンパイルオプションを設定してしまうため、以下に示すような問題が発生する可能性がある。
** 意図しないターゲットへの影響
**: プロジェクト内の全てのターゲットに対してコンパイルオプションが設定されるため、意図しないターゲットにも影響を及ぼす。
** ビルド依存性の管理が難しくなる
**: 特定のターゲットにのみ必要なコンパイルオプションがプロジェクト全体に設定されると、ビルド依存性の管理が複雑になる。
** コンパイラの最適化への影響
**: 不要なコンパイルオプションが設定されると、コンパイラの最適化が阻害される可能性がある。
*: 代わりに、<code>target_compile_options</code>コマンドを使用する必要がある。
<br>
<br>
* link_directoriesコマンド
* link_directoriesコマンド
*: プロジェクト内の全てのターゲットに対してリンクディレクトリを追加するため、以下に示すような問題が発生する可能性がある。
** プロジェクト全体への影響
**: 意図しないターゲットにもリンクディレクトリが設定される可能性がある。
** ビルド依存性の管理が難しくなる
**: 特定のターゲットにのみ必要なリンクディレクトリがプロジェクト全体に設定されると、ビルド依存性の管理が複雑になる。
** リンク順序の問題
**: このコマンドで追加したディレクトリは、自動的にコマンドラインのリンカ引数の最後に追加される。
**: これにより、リンク順序に関する問題が発生する可能性がある。
*: 代わりに、<code>target_link_libraries</code>コマンドを使用する必要がある。
<br>
<br>
* link_librariesコマンド
* link_librariesコマンド
*: プロジェクト内の全てのターゲットに対してリンクライブラリを追加するため、以下に示すような問題が発生する可能性がある。
** プロジェクト全体への影響
**: 意図しないターゲットにもリンクライブラリが設定される可能性がある。
** ビルド依存性の管理が難しくなる
**: 例えば、特定のターゲットにのみ必要なライブラリがプロジェクト全体にリンクされると、ビルド依存性の管理が複雑になる。
** リンク順序の問題
**: このコマンドで追加したライブラリは、自動的にコマンドラインのリンカ引数の最後に追加される。
**: これにより、リンク順序に関する問題が発生する可能性がある。
*: 代わりに、<code>target_link_libraries</code>コマンドを使用する必要がある。
<br>
<br>
* キャッシュ変数には、必ず接頭辞を付加する
* キャッシュ変数には、必ず接頭辞を付加する
128行目: 167行目:
  endif()
  endif()
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
== 実行ファイルの構築 (add_executableコマンド) ==
<code>add_executable</code>コマンドは、CMakeにソースファイルのセットから実行ファイルを作成する。<br>
<syntaxhighlight lang="cmake">
add_executable(
    <ターゲット名>
    <ソースコードファイル名 1>
    <ソースコードファイル名 2>
    # ...略
)
# 例. myAppまたはmyApp.exeという名前の実行ファイルが生成される
add_executable(
    myApp
    main.cpp
)
</syntaxhighlight>
<br>
<code><ターゲット名></code>には、英数字、アンダースコア、ハイフンを使用することができる。<br>
CMakeプロジェクトのビルドが正常に終了すると、<code><ターゲット名></code>として実行ファイルが作成される。<br>
<br>
ターゲット名は、CMakeの機能であるターゲットプロパティでカスタマイズすることもできる。<Br>
また、ターゲット名を変更して、<code>add_executable</code>コマンドを複数回呼び出すことにより、1つのCMakeLists.txtファイル内で複数の実行ファイルを定義することができる。<br>
<br>
ただし、同じターゲット名を複数の<code>add_executable</code>コマンドで使用する場合は、CMakeは失敗してエラーがハイライトされる。<br>
<br>
<syntaxhighlight lang="cmake">
# CMakeプロジェクトの例
cmake_minimum_required(VERSION 3.2)
# C++コンパイラは未使用とするため、プラットフォームが持っていない場合に備えて、projectコマンドで使用されないように指定する
project(MyApp VERSION 4.7.2 LANGUAGES C)
# メインの実行ファイルを生成
add_executable(
    mainTool
   main.c
   debug.c # リリースビルドのために最適化される
)
# サブの実行ファイルの生成
add_executable(
    testTool
    testTool.c
)
</syntaxhighlight>
<br><br>
== ライブラリの構築 (add_libraryコマンド) ==
CMakeは様々な種類のライブラリのビルドをサポートしている。<br>
ライブラリを作成して使用する場合、<code>add_library</code>コマンドを使用する。<br>
<syntaxhighlight lang="cmake">
add_library(
    <ターゲット名>
    [<STATIC または SHARED または MODULE>]
    [EXCLUDE_FROM_ALL]
    <ソースコードファイル名 1>
    <ソースコードファイル名 2>
    # ...略
)
</syntaxhighlight>
<br>
<code><ターゲット名></code>は、CMakeLists.txtファイル内でライブラリを参照するために使用される。<br>
ビルドされたライブラリ名は、<code><ターゲット名></code>となる。<br>
<br>
<code>EXCLUDE_FROM_ALL</code>オプションは、<code>add_executable</code>コマンドと同様、ライブラリがデフォルトのALLターゲットに含まれないようにする。<br>
構築するライブラリの種類は、<code>STATIC</code>、<code>SHARED</code>、<code>MODULE</code>のうちの1つを指定する。<br>
<br>
* STATICオプション
*: 静的ライブラリまたはアーカイブを指定する。
*: Windowsでは、デフォルトのライブラリ名は、<u><ライブラリファイル名>.lib</u>となる。
*: Linuxでは、デフォルトのライブラリ名は、<u>lib<ライブラリファイル名>.a</u>となる。
* SHARED
*: 共有ライブラリまたは動的ライブラリを指定する。
*: Windowsでは、デフォルトのライブラリ名は、<u><ライブラリファイル名>.dll</u>となる。
*: Linuxでは、デフォルトのライブラリ名は、<u>lib<ライブラリファイル名>.so</u>となる。
* MODULE
*: 共有ライブラリに似ているが、ライブラリや実行ファイルに直接リンクされるのではなく、実行時に動的にロードされることを意図しているライブラリを指定する。
*: これらは、ユーザがロードするかどうかを選択できるプラグイン、または、オプションのコンポーネントである。
*: Windowsでは、DLL向けのインポートライブラリは作成されない。
<br>
よほどのことがない限り、<code>STATIC</code>または<code>SHARED</code>オプションは、それが必要であることが分かるまで付加しないことを推奨する。<br>
これにより、プロジェクト全体を通して、スタティックライブラリかダイナミックライブラリかをより柔軟に選択することができる。<br>
<br>
ビルドするライブラリの種類を定義するオプションを省略することも可能である。<br>
特定のライブラリが必要でない限り、プロジェクトファイルには指定せずに、プロジェクトの構築時に開発者が選択できるようにすることが望ましい。<br>
そのような場合、ライブラリは<code>STATIC</code>か<code>SHARED</code>のどちらかになり、変数<code>BUILD_SHARED_LIBS</code>の値により選択される。<br>
<br>
変数<code>BUILD_SHARED_LIBS</code>が<code>true</code>を代入する場合はライブラリのターゲットはダイナミックライブラリ、それ以外の場合はスタティックライブラリとなる。<br>
<code>add_library</code>コマンドを呼び出すたびに変更する必要がなく、1ヶ所に記述するだけで設定を変更することができる。<br>
ただし、<code>add_library</code>コマンドを呼び出す前に、変数<code>BUILD_SHARED_LIBS</code>を記述する必要がある。<br>
<syntaxhighlight lang="cmake">
set(BUILD_SHARED_LIBS YES)
</syntaxhighlight>
<br>
変数<code>BUILD_SHARED_LIBS</code>を設定する方法として、<code>cmake</code>コマンドに<code>-DBUILD_SHARED_LIBS</code>オプションを付加する方法がある。<br>
cmake -DBUILD_SHARED_LIBS=YES /path/to/source
<br><br>
== CMAKEキャッシュ変数 ==
==== CMAKE_PREFIX_PATH ====
<syntaxhighlight lang="cmake">
# ライブラリのインストールディレクトリを指定
## ライブラリのインストールディレクトリを1つ指定する場合
set(CMAKE_PREFIX_PATH "<ライブラリのパス>")
## ライブラリのインストールディレクトリを複数指定する場合
set(CMAKE_PREFIX_PATH "<ライブラリのパス 1>;<ライブラリのパス 2>;<ライブラリのパス 3>")
# find_packageコマンドを使用してライブラリを検索
find_package(<ライブラリ名> REQUIRED)
if(<ライブラリ名>_FOUND)
    # ライブラリが見つかった場合
else()
    # ライブラリが見つからなかった場合
endif()
</syntaxhighlight>
<br><br>
== find_packageコマンド ==
==== find_packageコマンドとは ====
<code>find_package</code>コマンドは、特定の名前のCMakeスクリプトを検索して、該当のスクリプトを実行するコマンドである。<br>
<br>
対象となるCMakeスクリプトは、その役割に応じて、ModuleとConfigの2種類に分類される。<br>
<code>find_package</code>コマンドは、Module -> Configの順で検索を行う。<br>
<br>
具体的な動作は以下のとおりです。
* Module<br><パッケージ名>.cmakeファイル、または、Find<パッケージ名>.cmakeファイルを検索する。
** CMakeキャッシュ変数である変数<code>CMAKE_MODULE_PATH</code>で指定されたパス
** CMakeにデフォルトで付いてくるモジュールの配置ディレクトリ (/usr/local/share/cmake/Modulesディレクトリ等)
*: <br>
* Config<br><パッケージ名>Config.cmakeファイル、または、<パッケージ名(小文字)>-config.cmakeファイルを検索する。
** CMake変数<code><PackageName>_DIR</code>で指定されたパス
** CMakeキャッシュ変数である変数<code><パッケージ名>_ROOT</code>で指定されたパス
** 環境変数<code><パッケージ名>_ROOT</code>で指定されたパス
** CMakeキャッシュ変数である変数<code>CMAKE_PREFIX_PATH</code>、変数<code>CMAKE_FRAMEWORK_PATH</code>、変数<code>CMAKE_APPBUNDLE_PATH</code>で指定されたパス
** 環境変数<code><パッケージ名>_DIR</code>、環境変数<code>CMAKE_PREFIX_PATH</code>、環境変数<code>CMAKE_FRAMEWORK_PATH</code>、環境変数<code>CMAKE_APPBUNDLE_PATH</code>で指定されたパス
** 環境変数<code>PATH</code>で指定されたパス (binディレクトリおよびsbinディレクトリで終わるディレクトリの場合は、その親ディレクトリに読み替える)
** その他
<br>
なお、コマンド終了時において、CMake変数<code><パッケージ名>_FOUND</code>に<code>0</code>または<code>1</code>(<code>FALSE</code>または<code>TRUE</code>)が格納されるため、<br>
正常に検索できたかどうかを条件分岐として記述することもできる。<br>
<br>
==== Module (CMakeスクリプト) ====
Moduleは、以下の2種類に分類される。<br>
* Utility Modules
*: よく使用するCMake関数をまとめたもの。
*: 例えば、CheckLanguage.cmake(あるプログラミング言語の開発ツールがインストールされているか確認するための機能をまとめたもの)等がある。
*: Utility ModulesのCMakeスクリプトを読み込む時、<code>check_language</code>コマンド、<code>get_bundle_main_executable</code>コマンド等の関数が定義されるため、
*: それらを呼び出すことで機能を使用することができる。
*: <br>
* Find Modules
*: 外部ライブラリの情報を収集するものであり、ファイル名はFind<パッケージ名>.cmakeファイルである。
*: 例えば、C++で記述された外部ライブラリをリンクする場合、ヘッダファイルのディレクトリ、ライブラリファイルのディレクトリ、ライブラリファイル名の3つの情報が必要になる。
*: これらの情報を自動的に収集するものがFind Modulesである。
*: <br>
*: CMakeでは、Boost、BLAS、GLEW、OpenGL、X11、Qt4等のライブラリのFind Modulesがデフォルトで用意されている。
*: <br>
*: ほとんどのFind Modulesは、以下に示すようなCMake変数に値が自動的に代入される。
*:* 変数<code><パッケージ名>_INCLUDE_DIRS</code>
*:*: インクルードディレクトリのパス
*:* 変数<code><パッケージ名>_LIBRARY_DIRS</code>
*:*: ライブラリファイルがあるディレクトリのパス
*:* 変数<code><パッケージ名>_LIBRARIES</code>
*:*: ライブラリファイル名のリスト
*:* 変数<code><パッケージ名>_DEFINITIONS</code>
*:*: コンパイル時の<code>definition</code>フラグ
*: <br>
*: <code>find_package</code>コマンドを使用することにより、上記の変数は自動的に代入されるため、その変数を<code>target_include_directories</code>コマンド等に設定を記述する。
*: ただし、上記の変数名は必ずしもこの通りになっているわけではないため、ライブラリの情報を変数にまとめるのではなくターゲット(ライブラリ)を作成してそのプロパティにまとめる場合もある。
*: そのため、各ライブラリのFind Modulesを確認することが必要である。
<br>
CMakeでは、初期状態でいくつかのModuleがインストールされている。<br>
<br>
Moduleの一覧は、[https://cmake.org/cmake/help/latest/manual/cmake-modules.7.html CMakeの公式Webサイト]から確認することができる。<br>
<br>
また、Moduleが存在しないライブラリでは、開発者がModuleを作成することもできる。<br>
<br>
==== Config (CMakeスクリプト) ====
Configファイルは、CMakeプロジェクトをビルドしてライブラリをインストールした時に生成される設定ファイルである。<br>
ファイル名は、<code><パッケージ名>Config.cmake</code>ファイル、または、<code><パッケージ名(小文字)>-config.cmake</code>ファイルである。<br>
<br>
ライブラリ情報を提供する点ではFindモジュールと同様であるが、Configファイルはライブラリの開発元が直接提供している設定ファイルである。<br>
ライブラリをインストールした時、cmakeディレクトリやshareディレクトリの中に含まれていることが多い。<br>
<br>
Findモジュールと同様、多くのConfigファイルは以下に示すようなCMake変数が存在する。<br>
また、これらの情報を1つのターゲットにまとめている場合もある。<br>
* 変数<code><パッケージ名>_INCLUDE_DIRS</code>
*: インクルードディレクトリのパス
* 変数<code><パッケージ名>_LIBRARY_DIRS</code>
*: ライブラリファイルがあるディレクトリのパス
* 変数<code><パッケージ名>_LIBRARIES</code>
*: ライブラリファイル名のリスト
* 変数<code><パッケージ名>_DEFINITIONS</code>
*: コンパイル時の<code>definition</code>フラグ
<br>
<u>Configファイルを使用する場合、開発元が公開しているドキュメントやConfigファイルの内容から、各変数名や各ターゲット名を確認する必要がある。</u><br>
<br>
Linuxにおいて、Configファイルの場所は以下に示すようなディレクトリに配置される。<br>
また、初期設定より、/usr/binディレクトリは環境変数<code>PATH</code>に設定されているため、CMakeは自動的にConfigファイルを見つけることができる。<br>
* /usr/lib64/cmake/<パッケージ名>
* /usr/share/cmake/<パッケージ名>
<br>
したがって、Linuxでは、パッケージ管理システムからインストールしたライブラリは、<code>find_package</code>コマンドで見つけることができる。<br>
もし、ライブラリにConfigファイルが付属していない場合、開発者自身でFindモジュールを作成する必要がある。<br>
<br>
<u>また、他の場所にライブラリをインストールしている場合は、CMakeキャッシュ変数<code><パッケージ名>_DIR</code>にライブラリのパスを設定することにより、Configファイルを見つけることができる。</u><br>
<br><br>
<br><br>


440行目: 269行目:
<br><br>
<br><br>


== 変数 ==
== set(CMAKE_AUTORCC ON)コマンド ==
==== 変数の宣言と代入 ====
このコマンドは、CMakeの機能の一部であり、Qtプロジェクトで特によく使用される。<br>
変数は、<code>set</code>コマンドを使用して、変数を宣言および代入することができる。<br>
ただし、この機能はQtプロジェクトの開発のために設計されている。<br>
CMakeでは、全ての変数を文字列として扱っており、変数名には、英数字、<code>_</code>、<code>.</code>、<code>/</code>、<code>-</code>、<code>+</code>を含めることができる。<br>
また、大文字と小文字が区別される。<br>
<br>
変数の値を代入する時、値にスペースが含まれていない限り、引用符で囲む必要はない。<br>
<syntaxhighlight lang="cmake">
set(value 1) # 値が1の変数valueを宣言
</syntaxhighlight>
<br>
既存の変数への代入も<code>set</code>コマンドを使用する。<br>
変数の値の参照は、入れ子にすることもできる。<br>
<syntaxhighlight lang="cmake">
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になる
</syntaxhighlight>
<br>
1つの変数に複数の値を指定する場合、各値はセミコロンで区切って結合される。(<u>文字列リストとして代入される</u>)<br>
また、未定義の変数を参照する場合は、空の文字列となる。<br>
<syntaxhighlight lang="cmake">
set(myVar a b c)    # myVarの値: a;b;c
set(myVar a;b;c)    # myVarの値: a;b;c
set(myVar "a b c")  # myVarの値: a b c
set(myVar a b;c)    # myVarの値: a;b;c
set(myVar a "b c")  # myVarの値: a;b c
</syntaxhighlight>
<br>
<syntaxhighlight lang="cmake">
set(USE_CCACHE OFF CACHE BOOL "")
</syntaxhighlight>
<br>
==== 変数の削除 ====
変数の削除する場合は、<code>unset</code>コマンドを使用する。<br>
<syntaxhighlight lang="cmake">
set(value 1)  # 変数valueを宣言
unset(value)  # 変数valueを削除
</syntaxhighlight>
<br>
==== キャッシュ変数 ====
キャッシュ変数とは、ビルドディレクトリのCMakeCache.txtに記録される変数のことである。<br>
グローバルスコープで参照可能であり、生存期間が<code>cmake</code>コマンドの終了後も継続する。<br>
<br>
次の<code>cmake</code>コマンドの実行でも値を保つため、生成したビルドの構成情報を保存するような用途にも使用される。<br>
<br>
例えば、キャッシュ変数VAR1の値は$CHACHE{VAR1}で参照できる。<br>
同名の通常変数が存在しない場合は、${VAR1}でも参照することができる。<br>
<br>
<code>set(CACHE)</code>コマンドで初回の変数が定義ができる。<br>
<br>
<br>
既に定義されているキャッシュ変数を変更する場合は、<code>FORCE</code>オプションが必要である。<br>
この機能は比較的新しく、CMake 3.9以降で導入された。<br>
指定されていない場合、<code>set(CACHE)</code>コマンドは無視される。<br>
また、<code>cmake</code>コマンドの実行時に<code>-D<オプション名></code>でも定義や変更が可能である。<br>
<br>
<br>
他の変数と異なり、キャッシュ変数は型を持つ。<br>
変数<code>CMAKE_AUTORCC</code>を有効にする場合、CMakeは、Qtのqrcファイルを自動的にコンパイルすることができる。<br>
<code>cmake</code>コマンドの<code>-D<オプション名></code>オプションで型を指定せずに定義することにより、型のない状態で使用することもできる。<br>
qrcファイルは、アプリケーションにバイナリリソース (画像、アイコン、翻訳ファイル等) を埋め込むために使用される。<br>
この場合、<code>set(CACHE)</code>コマンドを実行した時点で型が確定する。<br>
<br>
<br>
 
* CMakeの機能
==== リスト(配列) ====
*: 変数<code>CMAKE_AUTORCC</code>は、CMakeに組み込まれた変数である。
変数は全て文字列として扱われるが、複数の変数をまとめて扱う場合はリストを使用する。<br>
*: CMakeはQtに限らず、多くのプロジェクトタイプをサポートする汎用的なビルドシステムジェネレータである。
これは、複数の文字列をセミコロン<code>;</code>で連結したものである。<br>
* Qtの統合
*: CMakeはQtプロジェクトとの統合を強化するために、この機能を提供している。
*: Qtのリソースコンパイラ (RCC) と連携して動作する。
* 他のフレームワークでの使用
*: RCCと同様のリソース処理システムを持つ他のフレームワークでも使用できる可能性があるが、実際にはQt以外での使用は一般的ではない。
<br>
<br>
リストという型は無く文字列であるが、関数の引数が暗黙的に連結されてリストとして扱うことができ、操作関数により言語レベルでのサポートがあるため、<br>
Qtプロジェクトでqrcファイルを使用する場合、変数<code>CMAKE_AUTORCC</code>を有効にすることが推奨されている。<br>
不定個数の変数をまとめて扱う場合に便利である。<br>
* 自動リソース処理
*: CMakeが自動的にqrcファイルを検出し、必要なリソースコンパイル (rcc) ステップを実行する。
* ビルドプロセスの簡素化
*: 手動でリソースファイルの処理を記述する必要がなくなる。
* 依存関係の管理
*: リソースファイルが変更された場合、CMakeが自動的に再ビルドを行う。
<br>
<br>
<syntaxhighlight lang="cmake">
ただし、以下に示すような場合は、変数<code>CMAKE_AUTORCC</code>を使用しない場合もある。<br>
set(LIST1 "AA" "BB" "CC") # 3つの文字列からなるリストを作成
これらのケースでは、<code>qt_add_resources()</code>コマンドを使用して手動で処理を行うことができる。<br>
message("${LIST1}")      # -> AA;BB;CC
* より細かな制御が必要な場合
* 特定のqrcファイルのみを処理したい場合
list(APPEND LIST1 "DD")   # リスト末尾に要素を追加
* パフォーマンス上の理由で手動処理を行う場合
message("${LIST1}")      # -> AA;BB;CC;DD
list(LENGTH LIST1 LEN)    # リスト要素の個数を取得
message("${LEN}")        # -> 4
list(GET LIST1 2 ITEM)    # 2番目の要素を取得
message("${ITEM}")        # -> CC
</syntaxhighlight>
<br>
<br>
==== 定義された全ての変数を出力 ====
したがって、多くの場合は<code>set(CMAKE_AUTORCC ON)</code>コマンドを実行することにより、qrcファイルの処理が簡単になる。<br>
<syntaxhighlight lang="cmake">
get_cmake_property(variableNames VARIABLES)
foreach(variableName ${variableNames})
    message(STATUS "${variableName}=${${variableName}}")
endforeach()
</syntaxhighlight>
<br><br>
<br><br>


== 条件分岐 ==
== set(CMAKE_AUTOMOC ON)コマンド ==
if()コマンドおよびelseif()コマンドの引数には、そのブロックを実行する条件式を記述する。<br>
変数<code>CMAKE_AUTOUIC</code>は、CMakeにおいてQt User Interface Compiler (UIC) の自動実行を制御するための設定である。<br>
この条件式には、以下に示す種類がある。<br>
<br>
* ブール定数
*: CMakeの値は全て文字列型であるが、条件式では以下に示す値がBooleanとして認識される。
*: <u>これらの値は、大文字・小文字は区別されないことに注意する。</u>
<br>
==== 真と解釈される値 ====
* 0でない数値
* ON
* YES
* TRUE
* Y
# 例
if(1)
if(TRUE)
if(on)
if(Yes)
<br>
==== 偽と解釈される値 ====
* 空文字列
* 0
* OFF
* NO
* FALSE
* N
* IGNORE
* NOTFOUND
* 末尾が<code>-NOTFOUND</code>である文字列
<br>
# 例
if(0)
if(FALSE)
if(off)
if(No)
if(SamplePackage-NotFound)
<br>
==== ブール演算子 ====
論理積を表すAND、論理和を表すOR、否定を表すNOTが使用できる。<br>
<u>これらは、全て大文字でなければならないことに注意する。</u>
# 例
if(true AND true)
if(true OR false)
if(NOT false)
<br>
<br>
==== 変数の確認 ====
変数<code>CMAKE_AUTOUIC</code>は、Qt開発を効率化するための重要な機能の1つである。<br>
変数が定義済みかどうかの確認、および、数値の比較等を行うことができる。<br>
Qt Designerで作成された.uiファイルを自動的にコンパイルして、対応するC++ヘッダファイルを生成する。<br>
# 例
これにより、UIファイルの変更が自動的にビルドプロセスに反映される。<br>
if(DEFINED variable)
if(1 LESS 2)
<br>
<br>
* 対象の存在の確認
多くの場合、この変数を有効にすることで、UIファイルの処理に関する手間を大幅に削減することができる。<br>
*: 対象の存在を判定することができる。
# 例
if(DEFINED value)    # value という変数がセットされているかどうか
if(COMMAND message)  # message というコマンドが存在するかどうか
if(POLICY CMP0011)  # CMP0011 というポリシーが存在するかどうか
if(TARGET test)      # test というターゲットが定義されているかどうか
if(EXISTS src/a.cpp) # src/a.cpp というパスが存在しているかどうか
<br>
<br>
* 対象の性質の確認
Qtコンソールアプリケーションの場合は、GUIを持たないため、.uiファイルを使用しない。<br>
*: 対象の性質を確認することができる。
したがって、この変数の設定は不要である。<br>
# 例
if(IS_DIRECTORY src/)  # src/ がディレクトリかどうか
if(IS_SYMLINK /bin/sh) # /bin/sh がシンボリックリンクかどうか
if(IS_ABSOLUTE /)      # / が絶対パスかどうか
<br>
<br>
==== 数値および文字列等の比較 ====
この機能は、CMake 2.8.11以降で利用可能である。<br>
* 数値の比較
*: 数値の比較することができる。
# 例
if(1 EQUAL 1)
if(1 LESS 2)
if(2 GREATER 1)
<br>
<br>
* 文字列のパターンマッチ
* 目的
*: <code><文字列> MATCHES <正規表現のパターン></code>
*: QtのUIファイル (.ui) を自動的に処理して、対応するヘッダファイルを生成する。
*: 文字列正規表現のパターンにマッチするかどうかを確認することができる。
* 動作
*: もし、文字列が空文字列、または、存在しない場合は、<code>false</code>を返す。
*: 変数<code>CMAKE_AUTOUIC</code>を有効にする時、CMakeはプロジェクト内の.uiファイルを自動的に検出して、UICを実行してヘッダファイルを生成する。
# 例
*: 生成されたファイルは、一般的に、ビルドディレクトリに配置される。
# 文字列がa(1文字以上)から始まり、aの次がbで終わる場合
* 利点
if("aaaab" MATCHES "^a+b$")
*: 手動でUICの実行を設定する必要がなくなり、ビルドプロセスが簡素化される。
*: UIファイルが変更された場合、自動的に再処理される。
* 対象ファイル
*: プロジェクト内の全ての.uiファイルが処理の対象となる。
* 関連する変数
*: CMAKE_AUTOUIC_SEARCH_PATHS : UICが.uiファイルを検索するパスを指定する。
*: CMAKE_AUTOUIC_OPTIONS : UICに渡す追加オプションを指定する。
* パフォーマンス
*: 大規模プロジェクトでは、自動処理が若干のビルド時間の増加をもたらす可能性がある。
<br>
<br>
* 文字列の比較
変数<code>CMAKE_AUTOUIC</code>を無効にする場合、<code>qt_wrap_ui()</code>コマンドを使用して手動で.uiファイルを処理することもできる。<br>
*: 文字列を比較することができる。
*: 辞書順に基づく。
# 例
if("a" STREQUAL "a")   # 文字列が同じ
if("a" STRLESS "aa")  # "a" < "aa"
if("b" STRGREATER "a") # "b" > "a"
<br>
<br>
* バージョンを比較
また、Qtプロジェクトによっては、特定のUIファイルのみを処理したい場合がある。<br>
*: バージョンを比較することができる。
その場合は、この変数<code>CMAKE_AUTOUIC</code>を無効にして手動で制御することも可能である。<br>
*: バージョンのフォーマットは、<メジャー>[.<マイナー>[.<パッチ>[.<ビルド>]]]である。
*: 数値的な順序や辞書順には基づかない。
*: 例えば、0.1という値と0.1.0.0という値は等しいと評価される。
*: また、1.19は、1.2より大きいと評価される。
# 例
if(0.1 VERSION_EQUAL 0.1.0.0)  # 0.1 == 0.1.0.0
if(0.1 VERSION_LESS 0.1.1)    # 0.1 < 0.1.1
if(1.19 VERSION_GREATER 1.2)  # 1.19 > 1.2
<br>
<br>
* ファイルのタイムスタンプの比較
<u>※注意</u><br>
*: ファイル1とファイル2のタイムスタンプを比較することができる。
<u>変数<code>CMAKE_AUTOUIC</code>は、Qt Widgetベースのアプリケーションで使用される.uiファイル (XML形式) を処理するためのものである。</u><br>
*: ファイル1がファイル2より新しい場合、<code>true</code>を返す。
<u>QMLは独自の宣言的UIフォーマットを使用して、.qmlファイルで定義される。</u><br>
*: また、いずれかのファイルが存在しない場合も、<code>true</code>を返す。
<u>したがって、QMLを使用したプロジェクトでは、この変数<code>CMAKE_AUTOUIC</code>の設定は不要である。</u><br>
# 例
if(build/my_exe IS_NEWER_THAN /usr/local/bin/my_exe)
<br><br>
<br><br>


== ログメッセージの出力 ==
== set(CMAKE_AUTOMOC ON)コマンド ==
==== messageコマンドとは ====
変数<code>CMAKE_AUTOMOC</code>は、CMakeにおいてQt Meta-Object Compiler (MOC) の自動実行を制御するための重要な設定である。<br>
<syntaxhighlight lang="cmake">
message([<mode>] "message to display" ...)
</syntaxhighlight>
<br>
<br>
下表に、<code><mode></code>に指定できる項目を示す。(一部)<br>
<u>この変数は、ほとんどのQtプロジェクトで必須の設定である。</u><br>
<center>
Qtのメタオブジェクトシステムに必要なメタデータを生成するために、MOCを自動的に実行する。<br>
{| class="wikitable" | style="background-color:#fefefe;text-align: center;"
これにより、開発者はQtの高度な機能 (シグナル / スロット、プロパティシステム等) を簡単に利用できるようになり、同時にビルドプロセスも自動化される。<br>
|-
! style="background-color:#66CCFF;width: 20%;" | modeの種類
! style="background-color:#66CCFF;width: 30%;" | 説明
! style="background-color:#66CCFF;width: 30%;" | 処理の継続
! style="background-color:#66CCFF;width: 20%;" | 出力先
|-
| 省略する場合 || 重要な情報 || CMakeの処理を継続する || STDERR
|-
| STATUS || 情報 || CMakeの処理を継続する || STDOUT
|-
| WARNING || 警告 || CMakeの処理を継続する || STDERR
|-
| SEND_ERROR || エラー || CMakeの処理を継続する || STDERR
|-
| FATAL_ERROR || 致命的なエラー || CMakeの処理を終了する || STDERR
|}
</center>
<br>
<br>
以下の例では、<code>message</code>コマンドにおいて、第1引数に<code>FATAL_ERROR</code>を指定することにより、エラーメッセージを出力して、CMakeコマンドを終了している。<br>
この機能はCMake 2.8.6以降で利用可能である。<br>
<syntaxhighlight lang="cmake">
message(FATAL_ERROR "cmake to terminate.")
</syntaxhighlight>
<br>
<br>
また、<code>message</code>コマンドにおいて、第1引数に<code>SEND_ERROR</code>を指定することにより、エラーメッセージを出力して動作を継続する。<br>
* 動作
<syntaxhighlight lang="cmake">
*: 変数<code>CMAKE_AUTOMOC</code>を有効にする時、CMakeはプロジェクト内のQtクラス (<code>Q_OBJECT</code>マクロを使用しているクラス等) を自動的に検出して、
  message(SEND_ERROR "Continue cmake.")
*: 必要に応じてMOCを実行する。
</syntaxhighlight>
* 処理対象
** Q_OBJECTマクロを含むヘッダファイル
** シグナルやスロットを使用しているクラス
** プロパティシステムを使用しているクラス
** その他のQt固有の機能をC++で使用する場合
* メリット
** 手動でMOCの実行を設定する必要がなくなり、開発プロセスが簡素化される。
** ソースファイルの変更時に自動的にMOC処理が行われる。
* 生成ファイル
*: moc_*.cppファイルがビルドディレクトリに生成される。
* 関連する変数
** <code>CMAKE_AUTOMOC_MACRO_NAMES</code>
**: 追加のマクロ名を指定して、MOC処理の対象を拡張できる。
** <code>CMAKE_AUTOMOC_PATH_PREFIX</code>
**: 生成されるmocファイルのパスプレフィックスを設定する。
* パフォーマンスへの影響
*: 大規模プロジェクトでは、ビルド時間が若干増加する可能性がある。
* デバッグ
*: 変数<code>CMAKE_AUTOMOC_VERBOSE</code>を有効にする時、MOC処理の詳細なログが出力され、問題のデバッグに役立つ。
* QtとC++の統合
*: この変数を有効にすることにより、QtのメタオブジェクトシステムとC++のコードがシームレスに統合される。
<br>
<br>
以下の例では、Linux以外のOSの場合は、エラーメッセージを出力して、<code>cmake</code>コマンドを終了している。<br>
また、特定のファイルのみMOCを処理をしたい場合は、変数<code>CMAKE_AUTOMOC</code>を無効にして、<code>qt_wrap_cpp()</code>コマンドを使用して手動で制御できる。<br>
<syntaxhighlight lang="cmake">
if(NOT (UNIX AND NOT APPLE))
    message(FATAL_ERROR "ERROR! Only Linux can build this software.")
else()
    set(LINUX TRUE)
endif()
</syntaxhighlight>
<br>
<br>
以下の例では、CMakeの特殊変数である<code>CMAKE_COMMAND</code>と<code>CMAKE_CTEST_COMMAND</code>を出力している。<br>
<u>※注意</u><br>
<syntaxhighlight lang="cmake">
<u>プリコンパイル済みヘッダ (PCH、GCH等) を使用する場合、追加の設定が必要になることがある。</u><br>
message("${CMAKE_COMMAND}")        # /usr/bin/cmake
message("${CMAKE_CTEST_COMMAND}") # /usr/bin/ctest
</syntaxhighlight>
<br><br>
 
== ライブラリパスの指定 ==
ライブラリパスを指定する場合、<code>link_directories</code>コマンドを使用する。<br>
<syntaxhighlight lang="cmake">
link_directories(/path/to/lib)
</syntaxhighlight>
<br>
<code>link_directories</code>コマンドを複数使用する場合、デフォルトでは、指定したパスは最後尾となる。<br>
ただし、<code>link_directories</code>コマンドに<code>BEFORE</code>オプションを付加した場合は最前となる。<br>
<br>
以下の例では、"-I/path1/to/lib -I/path2/to/lib"となる。<br>
<syntaxhighlight lang="cmake">
link_directories(/path1/to/lib)
link_directories(/path2/to/lib)
</syntaxhighlight>
<br>
以下の例では、"-I/path2/to/lib -I/path1/to/lib" となる。<br>
<syntaxhighlight lang="cmake">
link_directories(/path1/to/lib)
link_directories(BEFORE /path2/to/lib)
</syntaxhighlight>
<br><br>
<br><br>


742行目: 408行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:Qt]]
[[カテゴリ:Qt]]

2024年10月14日 (月) 11: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)



非推奨のコマンドおよび設定

  • include_directoriesコマンド
    指定したディレクトリからヘッダファイルを検索するコマンドである。
    定義した箇所以降の全てのターゲットが指定したディレクトリをインクルードするため、使用は避けるべきである。
    代わりに、target_include_directoriesコマンドを使用する必要がある。


  • add_definitionsコマンド
    • プロジェクト全体に影響を与えてしまう。
    • ビルド依存性の管理が難しくなる。
    • コンパイラの最適化を阻害する可能性がある。
    代わりに、target_compile_definitionsコマンドを使用する必要がある。


  • add_compile_definitionsコマンド
    • プロジェクト全体への影響
      プロジェクト内の全てのターゲットに対して定義を追加される。
      これにより、意図しないターゲットにまで定義が設定されてしまう可能性がある。
    • ビルド依存性の管理が難しくなる
      特定のターゲットにのみ必要な定義がプロジェクト全体に設定されると、ビルド依存性の管理が複雑になる。
    • コンパイラの最適化への影響
      不要な定義が設定されると、コンパイラの最適化が阻害される可能性がある。
    代わりに、target_compile_definitionsコマンドを使用する必要がある。


  • add_compile_optionsコマンド
    プロジェクト全体に対してコンパイルオプションを設定してしまうため、以下に示すような問題が発生する可能性がある。
    • 意図しないターゲットへの影響
      プロジェクト内の全てのターゲットに対してコンパイルオプションが設定されるため、意図しないターゲットにも影響を及ぼす。
    • ビルド依存性の管理が難しくなる
      特定のターゲットにのみ必要なコンパイルオプションがプロジェクト全体に設定されると、ビルド依存性の管理が複雑になる。
    • コンパイラの最適化への影響
      不要なコンパイルオプションが設定されると、コンパイラの最適化が阻害される可能性がある。
    代わりに、target_compile_optionsコマンドを使用する必要がある。


  • link_directoriesコマンド
    プロジェクト内の全てのターゲットに対してリンクディレクトリを追加するため、以下に示すような問題が発生する可能性がある。
    • プロジェクト全体への影響
      意図しないターゲットにもリンクディレクトリが設定される可能性がある。
    • ビルド依存性の管理が難しくなる
      特定のターゲットにのみ必要なリンクディレクトリがプロジェクト全体に設定されると、ビルド依存性の管理が複雑になる。
    • リンク順序の問題
      このコマンドで追加したディレクトリは、自動的にコマンドラインのリンカ引数の最後に追加される。
      これにより、リンク順序に関する問題が発生する可能性がある。
    代わりに、target_link_librariesコマンドを使用する必要がある。


  • link_librariesコマンド
    プロジェクト内の全てのターゲットに対してリンクライブラリを追加するため、以下に示すような問題が発生する可能性がある。
    • プロジェクト全体への影響
      意図しないターゲットにもリンクライブラリが設定される可能性がある。
    • ビルド依存性の管理が難しくなる
      例えば、特定のターゲットにのみ必要なライブラリがプロジェクト全体にリンクされると、ビルド依存性の管理が複雑になる。
    • リンク順序の問題
      このコマンドで追加したライブラリは、自動的にコマンドラインのリンカ引数の最後に追加される。
      これにより、リンク順序に関する問題が発生する可能性がある。
    代わりに、target_link_librariesコマンドを使用する必要がある。


  • キャッシュ変数には、必ず接頭辞を付加する
    キャッシュ変数はグローバル変数であるため、名前の衝突を避けるために接頭辞を付加する。


  • 変数CMAKE_<LANG>_FLAGS
    代わりに、target_compile_optionsを使用する。
    target_compile_options(<ターゲット名> PUBLIC -Wall)


  • 変数CMAKE_CXX_FLAGStarget_compile_optionsコマンドに、-std=c++17等を指定しない。
    変数CMAKE_CXX_STANDARDを使用する(CMake 3.1以降)、または、target_compile_featuresコマンドにcxx_std_17を指定する。(CMake 3.8以降)


  • 変数CMAKE_SOURCE_DIRを使用しない
    変数CMAKE_SOURCE_DIRは、トップレベルのディレクトリを指す。
    異なるプロジェクトがネストしている場合、自身のプロジェクトのルートディレクトリ以外のパスを指すため、使用すべきでない。
    代わりに、変数CMAKE_CURRENT_SOURCE_DIR、変数PROJECT_SOURCE_DIR、変数<プロジェクト名>_SOURCE_DIRを使用する。


  • macroコマンドの代わりにfunctionコマンドを使用する
    functionコマンドは、関数を定義するためのコマンドである。
    macroコマンドは、呼び出す側のスコープにある変数を上書きするため、自身のスコープを持つfunctionコマンドを使用する。
    親ディレクトリのスコープにある変数を上書きする場合は、set(<変数名> <値> ... PARENT_SCOPE)コマンドを使用する。


  • file(GLOB)コマンド
    file(GLOB)コマンドは、CMakeを実行するたびに条件に合致するファイルのリストを自動的に作成するコマンドである。
    ただし、特定のIDEでは正常に動作しない可能性があるため、コマンドラインから実行するような場合ではない限り使用すべきではない。
    IDEで使用する場合は、CMakeLists.txtファイルにadd_subdirectoryコマンドとtarget_sourcesコマンドを使用して、再帰的にファイルを明示して追加する。
 # CMakeLists.txtファイル
 
 add_executable(<ターゲット名>)
 add_subdirectory(<ディレクトリ名1>)
 add_subdirectory(<ディレクトリ名2>)
 # 同様に子ディレクトリを追加する


 # <ディレクトリ名1>/CMakeLists.txtファイル
 
 # CMake 3.12以前
 target_sources(<ターゲット名> PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/file1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp
    # 絶対パスで指定しないとエラーになるため注意すること
 )
 
 # CMake 3.13以降
 cmake_policy(SET CMP0076 NEW)  # CMakeが自動的に相対パスを絶対パスへ変換する
 target_sources(<ターゲット名> PRIVATE
    file1.cpp
    file2.cpp
 )


 # 画像ファイルの取得 (PNG, JPG, SVG)
 execute_process(
    COMMAND find ${CMAKE_CURRENT_SOURCE_DIR}/Image -iname "*.png" -o -iname "*.jpg" -o -iname "*.svg"
    OUTPUT_VARIABLE IMAGES
 )
 
 string(REPLACE "\n" ";" IMAGE_FILES "${IMAGES}")


  • PRIVATEオプション、PUBLICオプション、INTERFACEオプションを適切に使用する。
    これらのオプションは、コマンドのターゲットおよびそのターゲットに依存するターゲットに対する必要性を表す。
    ヘッダファイルのみのライブラリの場合は、INTERFACEオプションを使用する。
オプション ターゲットが必要とする ターゲットに依存するターゲットが必要とする
PRIVATE
PUBLIC
INTERFACE


  • ライブラリの種類を指定しない
    ビルドするユーザがスタティックライブラリまたはダイナミックライブラリを指定できるようにする。
    BUILD_SHARED_LIBSオプションを付加して選択することもできるが、各ライブラリごとにオプションを設定すべきである。
 option(<変数名1> "build library as a shared library" ON)
 
 if(<変数名1>)
    add_library(<ターゲット名> SHARED)
 else()
    add_library(<ターゲット名> STATIC)
 endif()



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(CMAKE_AUTORCC ON)コマンド

このコマンドは、CMakeの機能の一部であり、Qtプロジェクトで特によく使用される。
ただし、この機能はQtプロジェクトの開発のために設計されている。

この機能は比較的新しく、CMake 3.9以降で導入された。

変数CMAKE_AUTORCCを有効にする場合、CMakeは、Qtのqrcファイルを自動的にコンパイルすることができる。
qrcファイルは、アプリケーションにバイナリリソース (画像、アイコン、翻訳ファイル等) を埋め込むために使用される。

  • CMakeの機能
    変数CMAKE_AUTORCCは、CMakeに組み込まれた変数である。
    CMakeはQtに限らず、多くのプロジェクトタイプをサポートする汎用的なビルドシステムジェネレータである。
  • Qtの統合
    CMakeはQtプロジェクトとの統合を強化するために、この機能を提供している。
    Qtのリソースコンパイラ (RCC) と連携して動作する。
  • 他のフレームワークでの使用
    RCCと同様のリソース処理システムを持つ他のフレームワークでも使用できる可能性があるが、実際にはQt以外での使用は一般的ではない。


Qtプロジェクトでqrcファイルを使用する場合、変数CMAKE_AUTORCCを有効にすることが推奨されている。

  • 自動リソース処理
    CMakeが自動的にqrcファイルを検出し、必要なリソースコンパイル (rcc) ステップを実行する。
  • ビルドプロセスの簡素化
    手動でリソースファイルの処理を記述する必要がなくなる。
  • 依存関係の管理
    リソースファイルが変更された場合、CMakeが自動的に再ビルドを行う。


ただし、以下に示すような場合は、変数CMAKE_AUTORCCを使用しない場合もある。
これらのケースでは、qt_add_resources()コマンドを使用して手動で処理を行うことができる。

  • より細かな制御が必要な場合
  • 特定のqrcファイルのみを処理したい場合
  • パフォーマンス上の理由で手動処理を行う場合


したがって、多くの場合はset(CMAKE_AUTORCC ON)コマンドを実行することにより、qrcファイルの処理が簡単になる。


set(CMAKE_AUTOMOC ON)コマンド

変数CMAKE_AUTOUICは、CMakeにおいてQt User Interface Compiler (UIC) の自動実行を制御するための設定である。

変数CMAKE_AUTOUICは、Qt開発を効率化するための重要な機能の1つである。
Qt Designerで作成された.uiファイルを自動的にコンパイルして、対応するC++ヘッダファイルを生成する。
これにより、UIファイルの変更が自動的にビルドプロセスに反映される。

多くの場合、この変数を有効にすることで、UIファイルの処理に関する手間を大幅に削減することができる。

Qtコンソールアプリケーションの場合は、GUIを持たないため、.uiファイルを使用しない。
したがって、この変数の設定は不要である。

この機能は、CMake 2.8.11以降で利用可能である。

  • 目的
    QtのUIファイル (.ui) を自動的に処理して、対応するヘッダファイルを生成する。
  • 動作
    変数CMAKE_AUTOUICを有効にする時、CMakeはプロジェクト内の.uiファイルを自動的に検出して、UICを実行してヘッダファイルを生成する。
    生成されたファイルは、一般的に、ビルドディレクトリに配置される。
  • 利点
    手動でUICの実行を設定する必要がなくなり、ビルドプロセスが簡素化される。
    UIファイルが変更された場合、自動的に再処理される。
  • 対象ファイル
    プロジェクト内の全ての.uiファイルが処理の対象となる。
  • 関連する変数
    CMAKE_AUTOUIC_SEARCH_PATHS : UICが.uiファイルを検索するパスを指定する。
    CMAKE_AUTOUIC_OPTIONS : UICに渡す追加オプションを指定する。
  • パフォーマンス
    大規模プロジェクトでは、自動処理が若干のビルド時間の増加をもたらす可能性がある。


変数CMAKE_AUTOUICを無効にする場合、qt_wrap_ui()コマンドを使用して手動で.uiファイルを処理することもできる。

また、Qtプロジェクトによっては、特定のUIファイルのみを処理したい場合がある。
その場合は、この変数CMAKE_AUTOUICを無効にして手動で制御することも可能である。

※注意
変数CMAKE_AUTOUICは、Qt Widgetベースのアプリケーションで使用される.uiファイル (XML形式) を処理するためのものである。
QMLは独自の宣言的UIフォーマットを使用して、.qmlファイルで定義される。
したがって、QMLを使用したプロジェクトでは、この変数CMAKE_AUTOUICの設定は不要である。


set(CMAKE_AUTOMOC ON)コマンド

変数CMAKE_AUTOMOCは、CMakeにおいてQt Meta-Object Compiler (MOC) の自動実行を制御するための重要な設定である。

この変数は、ほとんどのQtプロジェクトで必須の設定である。
Qtのメタオブジェクトシステムに必要なメタデータを生成するために、MOCを自動的に実行する。
これにより、開発者はQtの高度な機能 (シグナル / スロット、プロパティシステム等) を簡単に利用できるようになり、同時にビルドプロセスも自動化される。

この機能はCMake 2.8.6以降で利用可能である。

  • 動作
    変数CMAKE_AUTOMOCを有効にする時、CMakeはプロジェクト内のQtクラス (Q_OBJECTマクロを使用しているクラス等) を自動的に検出して、
    必要に応じてMOCを実行する。
  • 処理対象
    • Q_OBJECTマクロを含むヘッダファイル
    • シグナルやスロットを使用しているクラス
    • プロパティシステムを使用しているクラス
    • その他のQt固有の機能をC++で使用する場合
  • メリット
    • 手動でMOCの実行を設定する必要がなくなり、開発プロセスが簡素化される。
    • ソースファイルの変更時に自動的にMOC処理が行われる。
  • 生成ファイル
    moc_*.cppファイルがビルドディレクトリに生成される。
  • 関連する変数
    • CMAKE_AUTOMOC_MACRO_NAMES
      追加のマクロ名を指定して、MOC処理の対象を拡張できる。
    • CMAKE_AUTOMOC_PATH_PREFIX
      生成されるmocファイルのパスプレフィックスを設定する。
  • パフォーマンスへの影響
    大規模プロジェクトでは、ビルド時間が若干増加する可能性がある。
  • デバッグ
    変数CMAKE_AUTOMOC_VERBOSEを有効にする時、MOC処理の詳細なログが出力され、問題のデバッグに役立つ。
  • QtとC++の統合
    この変数を有効にすることにより、QtのメタオブジェクトシステムとC++のコードがシームレスに統合される。


また、特定のファイルのみMOCを処理をしたい場合は、変数CMAKE_AUTOMOCを無効にして、qt_wrap_cpp()コマンドを使用して手動で制御できる。

※注意
プリコンパイル済みヘッダ (PCH、GCH等) を使用する場合、追加の設定が必要になることがある。


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)