CMakeを始める
CMake
は、アプリケーションをビルド、テスト、パッケージ化するためのツール群です。Qt と同様に、すべての主要な開発プラットフォームで利用可能です。また、Qt Creatorを含む様々なIDEでサポートされています。
このセクションでは、CMake プロジェクトで Qt を使用する最も基本的な方法を紹介します。まず、基本的なコンソールアプリケーションを作成します。次に、Qtウィジェットを使用するGUIアプリケーションに拡張します。
既存のCMakeプロジェクトをQtでビルドする方法を知りたい場合は、コマンドラインでCMakeを使ってプロジェクトをビルドする方法のドキュメントを参照してください。
CMake を使い始めるための基礎を学ぶには、Building with Cmakeを受講してください:Getting Started with CMake and Qt」コースを受講してください。
C++ コンソールアプリケーションのビルド
CMake
プロジェクトは、CMake 言語で書かれたファイルによって定義されます。メインファイルはCMakeLists.txt
と呼ばれ、通常、実際のプログラムソースと同じディレクトリに置かれます。
以下は、Qtを使ってC++で書かれたコンソール・アプリケーションの典型的なCMakeLists.txt
ファイルです:
cmake_minimum_required(VERSION 3.16) project(helloworld VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Core) qt_standard_project_setup() qt_add_executable(helloworld main.cpp ) target_link_libraries(helloworld PRIVATE Qt6::Core)
内容を見ていきましょう。
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required()
は、プロジェクトを正常に設定するために必要なCMakeの最小バージョンを指定します。Qt が必要とする最小バージョンについては、サポートされる CMake のバージョンを参照してください。
project(helloworld VERSION 1.0.0 LANGUAGES CXX)
project()
は、プロジェクト名とデフォルトのプロジェクトバージョンを設定します。 引数は、プログラムが C++ で書かれていることを CMake に伝えます。LANGUAGES
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)
Qt 6 では、C++ バージョン 17 以降をサポートするコンパイラが必要です。CMAKE_CXX_STANDARD
,CMAKE_CXX_STANDARD_REQUIRED
変数を設定することで、コンパイラが古すぎる場合にCMakeがエラーを表示するようになります。
find_package(Qt6 REQUIRED COMPONENTS Core)
これはCMakeにQt 6を検索し、Core
モジュールをインポートするように指示します。CMake
、モジュールの場所を特定できない場合、続行する意味がないので、REQUIRED
フラグを設定し、この場合にCMakeを中断させます。
成功すれば、モジュールはModule variables で説明したいくつかの CMake 変数を設定します。さらに、以下で使用するQt6::Core
ターゲットをインポートします。
find_package
が成功するためには、CMake が Qt のインストールを見つける必要があります。Qt Creatorと qt-cmake
(Windowsではqt-cmake.bat
)は、これを透過的に処理します。
バニラCMakeを直接使用する場合、CMakeにQtについて伝える方法はさまざまですが、最も一般的で推奨される方法は、CMakeのキャッシュ変数CMAKE_PREFIX_PATH
、Qt 6のインストールプレフィックスを含めるように設定することです。これはQtバイナリがインストールされるディレクトリです。Linuxでは、通常次のようになります:"~/Qt/6.8.0/gcc_64"
そして、これをコマンドラインで-DCMAKE_PREFIX_PATH=$HOME/Qt/6.8.0/gcc_64
として渡します。
注意: クロスコンパイル(WebAssembly や Android など、使用しているプラットフォーム以外のためにコンパイルすること)するときや、バニラcmake
を使用するときは、CMAKE_PREFIX_PATH
の代わりにCMAKE_TOOLCHAIN_FILE
を設定してください。 Linux では、ツールチェーンファイル(特定のターゲットプラットフォーム専用)は、通常次のようなパスにあります:"~/Qt/6.8.0/wasm_singlethread/lib/cmake/Qt6/qt.toolchain.cmake"
。これは、CMAKE_PREFIX_PATH
、CMAKE_FIND_ROOT_PATH
、QT_HOST_PATH
のような必要な変数を設定します。
qt_standard_project_setup()
qt_standard_project_setupコマンドは、典型的な Qt アプリケーションのプロジェクト全体のデフォルトを設定します。
特に、このコマンドはCMAKE_AUTOMOC
変数をON
に設定し、Qt のMeta-Object Compiler (moc)が必要なときに透過的に呼び出されるように、CMake に自動的にルールを設定するように指示します。
詳細はqt_standard_project_setupのリファレンスを参照してください。
qt_add_executable(helloworld main.cpp )
qt_add_executable() は、helloworld
という実行ファイル(ライブラリではない)をターゲットとしてビルドしたいことを CMake に伝えます。これは組み込みのadd_executable()
コマンドのラッパーで、静的 Qt ビルドにおける Qt プラグインのリンクや、ライブラリ名のプラットフォーム固有のカスタマイズなどを自動的に処理するための追加ロジックを提供します。
ターゲットはC++ソースファイルmain.cpp
からビルドする必要があります。
通常、ここにはヘッダーファイルは記述しません。これはqmakeとは異なり、ヘッダーファイルはメタオブジェクトコンパイラ(moc)で処理されるように明示的にリストする必要があります。
ライブラリの作成についてはqt_add_library を参照してください。
target_link_libraries(helloworld PRIVATE Qt6::Core)
最後に、target_link_libraries
は、find_package()
の呼び出しによってインポートされたQt6::Core
ターゲットを参照することによって、helloworld
の実行ファイルがQt Core を使用することを CMake に伝えます。これはリンカに正しい引数を追加するだけでなく、正しいインクルードディレクトリとコンパイラ定義がC++コンパイラに渡されるようにします。実行可能なターゲットでは、PRIVATE
キーワードは厳密には必要ではありませんが、指定しておくとよいでしょう。helloworld
が実行可能ファイルではなくライブラリであった場合、PRIVATE
またはPUBLIC
のどちらかを指定する必要があります(ライブラリのヘッダーにQt6::Core
の記述がある場合はPUBLIC
を、そうでない場合はPRIVATE
を指定します)。
C++GUIアプリケーションのビルド
前節では、単純なコンソール・アプリケーションの CMakeLists.txt ファイルを示しました。ここでは、Qt Widgetsモジュールを使用するGUIアプリケーションを作成します。
これがプロジェクトファイルです:
cmake_minimum_required(VERSION 3.16) project(helloworld VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) qt_standard_project_setup() qt_add_executable(helloworld mainwindow.ui mainwindow.cpp main.cpp ) target_link_libraries(helloworld PRIVATE Qt6::Widgets) set_target_properties(helloworld PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON )
それでは、変更したところを見ていきましょう。
find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package
の呼び出しで、Core
をWidgets
に置き換えている。これにより、Qt6Widgets
モジュールの場所が特定され、後でリンクするQt6::Widgets
ターゲットが提供される。
Qt6::Widgets
はQt6::Core
に依存しているため、アプリケーションはまだ に対してリンクしていることに注意してください。
qt_standard_project_setup()
CMAKE_AUTOMOC
に加えて、qt_standard_project_setup は CMAKE_AUTOUIC
変数をON
に設定します。これにより、.ui
ソースファイルに対して Qt のユーザーインターフェイスコンパイラ (uic) を起動するルールが自動的に作成されます。
qt_add_executable(helloworld mainwindow.ui mainwindow.cpp main.cpp )
Qt Widgets Designerファイル (mainwindow.ui
) と対応する C++ ソースファイル (mainwindow.cpp
) をアプリケーションターゲットのソースに追加します。
includeディレクティブが相対パスを使用している以下の例のような特定のケースでは、AUTOUICに依存する代わりに、qt_add_uiを使用してui_calculatorform.h
。
#include "src/files/ui_mainwindow.h"
qt_add_ui(calculatorform SOURCES mainwindow.ui INCLUDE_PREFIX src/files)
qt_add_ui
を使う場合、qt_add_executable
コマンドにmainwindow.ui
を渡す必要はない。
target_link_libraries(helloworld PRIVATE Qt6::Widgets)
target_link_libraries
コマンドでは、Qt6::Core
の代わりにQt6::Widgets
に対してリンクする。
set_target_properties(helloworld PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON )
最後に、アプリケーション・ターゲットにプロパティを設定します:
- Windowsでコンソール・ウィンドウが作成されないようにする。
- macOSでアプリケーション・バンドルを作成する。
これらのターゲットプロパティについての詳細は、CMakeドキュメントを参照してください。
プロジェクトの構造化
つ以上のターゲットを含むプロジェクトでは、プロジェクトのファイル構造を明確にすることが有益です。CMakeのサブディレクトリ機能を使います。
より多くのターゲットでプロジェクトを拡張する予定なので、アプリケーションのソースファイルをサブディレクトリに移動し、そこに新しいCMakeLists.txt
。
<project root> ├── CMakeLists.txt └── src └── app ├── CMakeLists.txt ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h └── mainwindow.ui
トップレベルのCMakeLists.txt
には、プロジェクト全体のセットアップ、find_package
とadd_subdirectory
の呼び出しが含まれています:
cmake_minimum_required(VERSION 3.16) project(helloworld VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) qt_standard_project_setup() add_subdirectory(src/app)
このファイルで設定された変数は、サブディレクトリのプロジェクト・ファイルで見ることができます。
アプリケーションのプロジェクト・ファイルsrc/app/CMakeLists.txt
には、実行可能なターゲットが含まれています:
qt_add_executable(helloworld mainwindow.ui mainwindow.cpp main.cpp ) target_link_libraries(helloworld PRIVATE Qt6::Widgets) set_target_properties(helloworld PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON )
このような構造にすることで、ライブラリやユニットテストのようなターゲットをプロジェクトに追加しやすくなります。
注意: システム上で動作するアンチウィルスアプリケーションの除外ディレクトリリストに、プロジェクトのビルドディレクトリを追加してください。
ライブラリのビルド
プロジェクトが大きくなるにつれて、アプリケーションコードの一部を、 アプリケーションや、場合によっては単体テストで使われるライブラリにしたいと思うかもしれません。このセクションでは、そのようなライブラリを作成する方法を示します。
現在、私たちのアプリケーションには、main.cpp
に直接ビジネスロジックが含まれています。前のセクションで説明したように、サブディレクトリ"src/businesslogic"
のbusinesslogic
という新しい静的ライブラリにコードを抽出します。
簡略化のため、ライブラリは1つのC++ソースファイルと、アプリケーションのmain.cpp
にインクルードされる対応するヘッダーファイルだけで構成されます:
<project root> ├── CMakeLists.txt └── src ├── app │ ├── ... │ └── main.cpp └── businesslogic ├── CMakeLists.txt ├── businesslogic.cpp └── businesslogic.h
ライブラリのプロジェクト・ファイル(src/businesslogic/CMakeLists.txt
)を見てみましょう。
qt_add_library(businesslogic STATIC businesslogic.cpp ) target_link_libraries(businesslogic PRIVATE Qt6::Core) target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
内容を見てみよう。
qt_add_library(businesslogic STATIC businesslogic.cpp )
add_libraryコマンドはライブラリbusinesslogic
を作成する。後で、このターゲットに対してアプリケーションをリンクさせます。
STATIC
キーワードは静的ライブラリを表します。共有ライブラリまたはダイナミック・ライブラリを作成する場合は、SHARED
キーワードを使用します。
target_link_libraries(businesslogic PRIVATE Qt6::Core)
私たちは静的ライブラリを持っているので、実際には他のライブラリをリンクする必要はありません。しかし、このライブラリはQtCore
のクラスを使用するため、Qt6::Core
にリンク依存を追加します。これにより、必要なQtCore
インクルード・パスとプリプロセッサ定義が取り込まれます。
target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
ライブラリーのAPIは、ヘッダーファイルbusinesslogic/businesslogic.h
で定義されています。target_include_directoriesを呼び出すことで、businesslogic
ディレクトリへの絶対パスが、当ライブラリを使用するすべてのターゲットのインクルード・パスとして自動的に追加されるようにします。
これにより、main.cpp
では、businesslogic.h
を見つけるために相対パスを使う必要がなくなる。代わりに、次のように書けばよい。
#include <businesslogic.h>
最後に、ライブラリーのサブディレクトリーをトップレベルのプロジェクト・ファイルに追加しなければならない:
add_subdirectory(src/app) add_subdirectory(src/businesslogic)
ライブラリを使う
前のセクションで作成したライブラリを使うために、CMakeにリンクするように指示します:
target_link_libraries(helloworld PRIVATE
businesslogic
Qt6::Widgets
)
これにより、main.cppがコンパイルされるときにbusinesslogic.h
。さらに、businesslogicスタティック・ライブラリーはhelloworld
実行ファイルの一部になります。
CMakeの用語では、ライブラリbusinesslogic
、ライブラリの消費者(アプリケーション)が満たさなければならない使用要件(インクルード・パス)を指定します。target_link_libraries
。
リソースの追加
アプリケーションに画像を表示したいので、Qt Resource Systemを使って画像を追加します。
qt_add_resources(helloworld imageresources PREFIX "/images" FILES logo.png splashscreen.png )
qt_add_resourcesコマンドは、参照する画像を含むQtリソースを自動的に作成します。C++のソースコードからは、指定したリソース接頭辞を先頭につけることで画像にアクセスできます:
logoLabel->setPixmap(QPixmap(":/images/logo.png"));
qt_add_resourcesコマンドは、変数名またはターゲット名を第一引数にとります。qt_add_resourcesコマンドは最初の引数として変数名かターゲット名を取ります。
翻訳の追加
Qt プロジェクト内の文字列の翻訳は.ts
ファイルにエンコードされます。これらの.ts
ファイルはバイナリの.qm
ファイルにコンパイルされ、Qt アプリケーションの実行時に読み込まれます。詳細はQt による国際化を参照してください。
このセクションでは、helloworld
アプリケーションにドイツ語とフランス語の翻訳を追加する方法について説明します。
qt_standard_project_setup で両方の言語を指定してください:
qt_standard_project_setup(I18N_TRANSLATED_LANGUAGES de fr)
それから、.qm
ファイルを読み込むターゲットでqt_add_translations を呼び出します:
qt_add_translations(helloworld)
最初の設定では、このコマンドはプロジェクトのソースディレクトリに helloworld_de.ts
とhelloworld_fr.ts
というファイルを作成します。これらのファイルには翻訳された文字列が含まれ、バージョン管理下に置かれます。
このコマンドは、.ts
ファイルから.qm
ファイルを自動的に生成するビルド・ルールも作成します。デフォルトでは、.qm
ファイルはリソースに埋め込まれ、"/i18n"
リソースのプレフィックスでアクセスできます。
.ts
ファイルのエントリーを更新するには、update_translations
ターゲットをビルドします:
$ cmake --build . --target update_translations
.qm
ファイルを手動で生成するには、release_translations
ターゲットをビルドします:
$ cmake --build . --target release_translations
.ts
ファイルの処理とリソースへの埋め込みに影響を与える方法の詳細については、qt_add_translations のドキュメントを参照してください。
qt_add_translationsコマンドは便利なラッパーです。.ts
ファイルや.qm
ファイルの扱い方をより細かく制御するには、基礎となるコマンドqt_add_lupdateとqt_add_lrelease を使用してください。
さらに読む
公式のCMakeドキュメントは、CMakeで作業するための貴重な情報源です。
公式のCMakeチュートリアルは、一般的なビルドシステムのタスクをカバーしています。
書籍Professional CMake: A Practical Guideは、最も関連性の高い CMake 機能の素晴らしい入門書です。
©2024 The Qt Company Ltd. ここに含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。