📖

qmakeからcmakeへの移行(挫折)

2022/06/08に公開

Apple SiliconでQt6 の続きです。

cmake への移行

前回までで一応qmakeでビルドも通って動いているのですが、Qt6 は cmake をデフォルトに持って行きたいようなので cmake への移行を試みます。
結論から言うと、うまく行っていません。

参考: Building a QML application | Build with CMake 6.3.0

とりあえずできたもの

なんか、target_link_libraries のところのコードハイライトが変ですが。

cmake_minimum_required(VERSION 3.16)

project(ComicsViewer LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 COMPONENTS Quick Widgets LinguistTools REQUIRED)
find_package(QuaZip-Qt6)

qt_standard_project_setup()
set(CMAKE_AUTORCC ON)

if(APPLE)
    set(MACOSX_BUNDLE_ICON_FILE ComicsViewer.icns)
    set(app_icon "${CMAKE_CURRENT_SOURCE_DIR}/ComicsViewer.icns")
    set_source_files_properties(${app_icon} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
elseif(MINGW)
    set(app_icon "${CMAKE_CURRENT_SOURCE_DIR}/ComicsViewer.rc")
endif()

add_executable(ComicsViewer
    main.cpp 
    comicmodel.cpp 
    pageitem.cpp
    qml.qrc
    ${app_icon}
)

qt_add_translations(ComicsViewer
    TS_FILES i18n/ComicsViewer_ja.ts)

target_link_libraries(ComicsViewer PRIVATE Qt6::Widgets Qt6::Quick QuaZip::QuaZip)

set_target_properties(ComicsViewer PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

悩んだところとか

  • ドキュメントのQMLアプリでは Quick と Gui を Qt の COMPONENT として find_packageしろと書いてあるのですが、それだと QApplicationが使えないので Gui の代わりに Widgets を使います。
  • qt_add_translations をただ書くと、そんなの知らないって言われるので、LinguistTools も find_package します。
    • qt_add_translations を使わずに、add_executable に Qt5 から使っている i18n.qrc を書いても動きます。
  • qml.qrc も、add_executable に書く代わりに qt_add_qml_module を使うことができる(この場合linterとかかけてくれるらしい)のですが、URI が空にできないのでソースを修正する必要があります。なので、今回は qrc ファイルをそのまま使うことにしました。
  • deploy とかも cmakeで対応できるようですが、面倒なので今回はそこまでやっていません。
  • Macでしか動作確認していません。

駄目なところ

翻訳リソースの ComicsViewer_ja.qm が読み込めません。

読んでいるところ

    QTranslator myappTranslator;
    if (myappTranslator.load(":/i18n/ComicsViewer_" + QLocale::system().name())) {
        app.installTranslator(&myappTranslator);
    } else {
        qDebug() << "can't load translator for" << QLocale::system().name();
    }

ここで、QLocale::system().name()ja_JP を返してくれることを期待しているのですが、cmakeでビルドすると何故か en_JP になります。qmake でビルドしたときは正しく ja_JP が返ります。
また、直接 myappTranslator.load(":/i18n/ComicsViewer_ja") とか書くと読むことができます。

qmake したときのビルドコマンドラインと cmake したときのものを比較したり一部入れ換えたりしたのですが、どうしても解決できませんでした。
ちょっとお手上げなのでcmake対応はここで止まっている状態です。

ここまでの内容は引き続き github のqt6ブランチに入っています。

追記

今どきはi18nの作法が変わっているのかも知れないと思って、公式ドキュメントを確認してみました。

https://doc.qt.io/qt-6/internationalization.html

すると、実装例が以下のようになっています。

    QTranslator myappTranslator;
    if (myappTranslator.load(QLocale::system(), u"myapp"_qs, u"_"_qs, u":/i18n"_qs))
        app.installTranslator(&myappTranslator);

これに合わせて、上のリソースのロード部分を以下のように変えてみました。

    if (myappTranslator.load(QLocale::system(), "ComicsViewer", "_", ":/i18n")) {
        app.installTranslator(&myappTranslator);
    } else {
        qDebug() << "can't load translator for" << QLocale::system().name();
    }

ちなみに、ドキュメントでは文字列リテラルをQStringにするのに u"myapp"_qs のように書いていますが、普通に文字列リテラルを書いても暗黙で変換してくれるようです。(ASCIIの範囲外の文字とかあると違うのかも。面倒なので未確認)

これで、無事に日本語リソースを読んでくれました。
これは、文字列として ComicsViewer_ja を渡すのではなく QLocale を渡すことで、en_JP の JP の部分から適当に補完してくれるんだと思います。
その証拠に、日本語のリソースは読めるようになりましたが、ファイルダイアログを開くと qmake の方は日本語UIなのに、cmake の方は英語UIで表示されます。
ん〜、謎は深い。

追記その2

試しに、QtCreator でコンソールアプリを新規作成して実行してみたところ、普通に ja_JP と表示されました。

main.cpp
#include <QCoreApplication>
#include <QLocale>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << QLocale::system().name();
    return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.14)

project(localetest2 LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)

add_executable(localetest2
  main.cpp
)
target_link_libraries(localetest2 Qt${QT_VERSION_MAJOR}::Core)

もう何もわからない・・・。

追記その3

この後、QtCreatorが作った CMakeLists.txt を少しずつ自分のものに似せていって、何が悪いのかを調べる作業に。

いろいろ試していって、最終的に以下があるとまずいことがわかりました。

set_target_properties(ComicsViewer PROPERTIES
    MACOSX_BUNDLE ON
)

これがあると、ComicsViewer.app/Contents/Info.plist が作られるのですが、中に以下の記述があります。

        <key>CFBundleDevelopmentRegion</key>
        <string>English</string>

qmakeで作った方には CFBundleDevelopmentRegion はありません。
この2行を消してあげると、QLocale::system() は ja_JP になりました。
しかし、QMLから開くファイルダイアログは英語のまま・・・。
試しに MACOSX_BUNDLE を消して実行ファイルを作っても、ファイルダイアログは英語のままでした。
奥が深い。

Discussion