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_PATHCMAKE_FIND_ROOT_PATHQT_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 の呼び出しで、CoreWidgets に置き換えている。これにより、Qt6Widgets モジュールの場所が特定され、後でリンクするQt6::Widgets ターゲットが提供される。

Qt6::WidgetsQt6::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

AUTOUICよりもqt_add_uiを優先する場合

#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_packageadd_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.tshelloworld_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_lupdateqt_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.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。