Qt 5 と Qt 6 の互換性

Qt 5 と Qt 6 の CMake API のセマンティクスはほぼ互換性がありますが、後者のバージョンでのみ、これらのコマンドや追加インターフェースの動作に若干の違いがあります。このガイドは、主にメジャーリリースから別のメジャーリリースへの段階的な移行を検討しているプロジェクトのためのものです。

Qt 5.14 までは、インポートされた Qt ライブラリのターゲットやコマンドには、qt5_add_library のように、名前の一部としてバージョン番号が含まれていました。このため、Qt 5 と Qt 6 の両方で動作する CMake コードを書くのはやや面倒です。そのため、Qt 5.15 ではバージョンレスのターゲットとコマンド、つまりqt_add_library を導入し、異なる Qt バージョンにほとんど依存しない CMake コードを記述できるようにしました。

バージョンレスターゲット

既存のインポートターゲットに加えて、Qt 5.15ではバージョンレスターゲットが導入されました。つまり Qt Coreに対してリンクするために、Qt6::Core 、またはQt::Core の両方を参照することができます:

find_package(Qt6 COMPONENTS Core)
if (NOT Qt6_FOUND)
    find_package(Qt5 5.15 REQUIRED COMPONENTS Core)
endif()

add_executable(helloworld
    ...
)

target_link_libraries(helloworld PRIVATE Qt::Core)

上記のスニペットは、まず Qt 6 のインストールを探します。失敗した場合は、Qt 5.15パッケージを探します。Qt 6 と Qt 5 のどちらに関係なく、インポートされたQt::Core ターゲットを使うことができます。Qt 6のチェックをスキップするには CMAKE_DISABLE_FIND_PACKAGE_Qt6find_package をセットしてください。

バージョンレスターゲットはデフォルトで定義されています。無効にするには、最初のfind_package() 呼び出しの前にQT_NO_CREATE_VERSIONLESS_TARGETS を設定してください。

バージョンレスコマンド

Qt 5.15以降、Qtモジュールはバージョンレスコマンドも提供します。例えば、Qt 5 と Qt 6 のどちらを使用していても、qt_add_translation を使用して翻訳ファイルをコンパイルすることができます。

QT_NO_CREATE_VERSIONLESS_FUNCTIONS を最初のfind_package() 呼び出しの前に設定することで、バージョンレスコマンドの作成を防ぐことができます。

Qt 5 と Qt 6 の混在

Qt 5 と Qt 6 の両方を 1 つの CMake コンテキストでロードする必要があるプロジェクトがあるかもしれません(ただし、1 つのライブラリや実行ファイルで Qt のバージョンを混在させることはサポートされていませんので、注意が必要です)。

このようなセットアップでは、バージョンレスのターゲットやコマンドは、find_package を介して最初に見つかった Qt のバージョンを暗黙的に参照することになります。バージョンを明示的にするには、最初のfind_package 呼び出しの前に CMake 変数QT_DEFAULT_MAJOR_VERSIONを設定してください。

5.15 より古いバージョンの Qt 5 をサポートする

Qt 5.15より古いQt 5のバージョンもサポートする必要がある場合、CMake変数(QT_VERSION_MAJOR)に現在のバージョンを格納することで対応できます:

find_package(Qt6 COMPONENTS Core)
if(Qt6_FOUND)
    set(QT_VERSION_MAJOR 6)
else()
    find_package(Qt5 REQUIRED COMPONENTS Core)
    set(QT_VERSION_MAJOR 5)
endif()

add_executable(helloworld
    ...
)

target_link_libraries(helloworld PRIVATE Qt${QT_VERSION_MAJOR}::Core)

バージョンレスアプローチと比較すると、ターゲットはQt${QT_VERSION_MAJOR}::Core を指し、target_link_libraries の呼び出し時にQt5::Core またはQt6::Core のいずれかに解決されます。

可能であれば、CMakeコマンドのバージョンレスバリアントを使用してください。

同じプロジェクトで Qt 5 と Qt 6 をサポートする必要がない限り、バージョン付きターゲットを使用してください。

バージョンレスターゲットを使用しなければならない場合は、バージョンレスターゲットを使用する際の落とし穴に注意してください。

Qt 5.15より古いバージョンのQt 5をサポートする必要がある場合や、QT_NO_CREATE_VERSIONLESS_FUNCTIONSや QT_NO_CREATE_VERSIONLESS_TARGETSが定義されているコンテキストでCMakeコードがロードされるかどうかを制御できない場合は、バージョン管理されたバージョンのCMakeコマンドやターゲットを使用してください。この場合でも、変数を通して実際のコマンドやターゲット名を決定することで、コードを簡素化することができます。

バージョンレスターゲット使用時の落とし穴

バージョンレスターゲットを使うことには、いくつかの欠点がある。

バージョンレスターゲットは通常ALIASALIAS ターゲットを指すALIAS ターゲットを作ることはできません。代わりに ALIASED_TARGETプロパティを使用してください。

Qt 6 の古いバージョンでは、インポートされたQt::Core ターゲットは、Qt6::Core で公開されているすべてのターゲットプロパティを備えていませんでした。これは、CMake 3.18 以降で Qt 6.8 以降とリンクする場合に修正されます。

プロジェクトは、バージョンレスターゲットを公開するターゲットをエクスポートしてはいけません。例えば、他のプロジェクトによって消費されるライブラリーは、バージョンレスターゲットに対して公にリンクするターゲットをエクスポートしてはいけません。そうしないと、推移的依存関係が壊れたり、そのライブラリのユーザーが Qt5 と Qt6 のターゲットを不本意に混在させたりする可能性があります。

Windows での Unicode サポート

Qt 6 では、Qt モジュールに対してリンクするターゲットに対して、UNICODE_UNICODE のコンパイラ定義がデフォルトで設定されます。これは qmake の動作と同じですが、Qt 5 の CMake API の動作と比べると変更されています。

ターゲット上でqt_disable_unicode_defines()を呼び、定義を設定しないようにします。

find_package(Qt6 COMPONENTS Core)

add_executable(helloworld
    ...
)

qt_disable_unicode_defines(helloworld)

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.