📖

Apple SiliconでQt5

2022/05/26に公開

Qtアプリのサンプル - Qiita の続き(?)です。

前置き

2019年モデルのMacBook Pro 16インチが、熱くて使えないことが増えてきたので、Apple SiliconのMacに買い換えることにしました。
最近はゲームのためにメインマシンをWindowsに乗り換えたので、Macにはあまりお金をかけたくないと言うことで、2020年モデルのMacBook Airを買いました。(なんで2022年に2020年モデルを、しかも2019年モデルからの乗り換えで、と言う気はしますが)
x86_64からarm64に変わるので、今回はマシンの引継を行わずに初期設定して使うことにしました。
ほとんどのアプリはApple Silicon対応が終わっているのですが、一部今まで使っていたアプリでx86_64しか提供されていないものもあります。(DMMブックスとか、Skitchとか)
上に挙げたQtのアプリも、そのままではarm64で動かないので、新しいマシンでビルドし直してあげる必要があります。

Qt

ここのところずっとQtから離れていて、今の事情が良くわかりません。
公式サイト https://www.qt.io/ に行くと最新版は 6.3 のようですが、OpenSourceのページ https://www.qt.io/download-open-source から Source Code に飛ぶと Qt5 の説明になります。
また、Download the Qt Online Installer のリンクを踏むと x86_64のバイナリがダウンロードされます。
しょうがないので、ソースから5系の最新をビルドすることにします。(上の記事を書いたときは5.4でした)

ソースを持ってくる

% mkdir ~/qt
% cd ~/qt
% git clone https://code.qt.io/qt/qt5.git

5系のブランチに切り替えて、ビルド

5系の最新は5.15.2のようです。init-repositoryでsubmoduleを持ってきます。

% cd qt
% git switch 5.15.2
% perl init-repository
% cd ..
% mkdir 5.15.2
% cd 5.15.2
% ../qt5/configure -developer-build -opensource -nomake examples -nomake tests
% make -j4

※ make -j でCPUコアを全部使ってくれるのですが、ファンがない MacBook Air だとCPU温度が上がって大変なことになったので、気温と相談してどのくらいコアを使うか決めてください。

configureの途中でライセンスの同意を求められるので、yを押します。面倒な場合は -confirm-license をつけます。
configureは無事に終わったかに見えたのですが、makeがエラーで止まりました。
(この後の手順でXcodeをインストールしたときにRosettaが入ってしまったため、エラーが再現できませんが、x86_64のバイナリは実行できないよ的なエラーです。)
qtbase/bin/mocが実行できないようです。

% file qtbase/bin/*
qtbase/bin/moc:      Mach-O 64-bit executable x86_64
qtbase/bin/qmake:    Mach-O 64-bit executable arm64
qtbase/bin/qt.conf:  ASCII text
qtbase/bin/rcc:      Mach-O 64-bit executable x86_64
qtbase/bin/tracegen: Mach-O 64-bit executable x86_64

qmakeはちゃんとarm64用なのに、他のバイナリがx86_64用にビルドされてしまっているようです。

なんでかな〜と思いつつconfig.logやconfig.summaryを見ると、以下の行があります。

Build type: macx-clang (x86_64, CPU features: cx16 mmx sse sse2 sse3 ssse3 sse4.1)

Apple Siliconだって言ってるじゃないですか!

しょうがないので、ソースの ~/qt/qt5/qtbase/mkspecs/common/macx.conf を書き換えます。

--- a/mkspecs/common/macx.conf
+++ b/mkspecs/common/macx.conf
@@ -6,7 +6,7 @@ QMAKE_PLATFORM         += macos osx macx
 QMAKE_MAC_SDK           = macosx

 QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.13
-QMAKE_APPLE_DEVICE_ARCHS = x86_64
+QMAKE_APPLE_DEVICE_ARCHS = arm64

 # Should be 10.15, but as long as the CI builds with
 # older SDKs we have to keep this.

気を取り直してconfigureからやり直して、ビルドを続けます。

またエラーが出ました。

/Users/false/qt/qt5/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm
In file included from /Users/false/qt/qt5/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm:40:
/Users/false/qt/qt5/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h:54:32: error: unknown type name 'CGColorSpaceRef'; did you mean 'QColorSpace'?
    void setColorSpace(QCFType<CGColorSpaceRef> colorSpace);
                               ^~~~~~~~~~~~~~~
                               QColorSpace
../../../../include/QtCore/../../../../qt5/qtbase/src/corelib/kernel/qmetatype.h:2090:1: note: 'QColorSpace' declared here
QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
^
../../../../include/QtCore/../../../../qt5/qtbase/src/corelib/kernel/qmetatype.h:178:24: note: expanded from macro 'QT_FOR_EACH_STATIC_GUI_CLASS'
    F(QColorSpace, 87, QColorSpace) \
                       ^
/Users/false/qt/qt5/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm:90:32: error: out-of-line definition of 'setColorSpace' does not match any declaration in 'QIOSurfaceGraphicsBuffer'
void QIOSurfaceGraphicsBuffer::setColorSpace(QCFType<CGColorSpaceRef> colorSpace)
                               ^~~~~~~~~~~~~
/Users/false/qt/qt5/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h:54:24: note: type of 1st parameter of member declaration does not match definition ('QCFType<QColorSpace>' vs 'QCFType<CGColorSpaceRef>')
    void setColorSpace(QCFType<CGColorSpaceRef> colorSpace);
                       ^

エラーメッセージの unknown type name 'CGColorSpaceRef' でググると、以下がひっかかりました。
[qt] fails to build on macOS 12 (Monterrey) · Issue #21055 · microsoft/vcpkg
このissueからリンクの張ってあった [qt] Fix missing Cocoa include by wrobelda · Pull Request #21056 · microsoft/vcpkg にpatchがあるので、同じように修正します。

~/qt/qt5/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h を修正します。

--- a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
+++ b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
@@ -40,6 +40,7 @@
 #ifndef QIOSURFACEGRAPHICSBUFFER_H
 #define QIOSURFACEGRAPHICSBUFFER_H

+#include <CoreGraphics/CGColorSpace.h>
 #include <qpa/qplatformgraphicsbuffer.h>
 #include <private/qcore_mac_p.h>

今度こそ、最後までビルドが走りきりました。
ドキュメント通り configure に -developer-build をつけていた場合、installせずにこのまま使います。
~/qt/5.15.2/qtbase/bin/qmake を使えば良いです。

が、ここでqmakeを動かしてみると、Xcode.appの下のclang++を探しに行って見つからないと怒られます。
原因を調べるのも面倒になったので、AppStoreでXcodeをインストールしてしまいました。
Xcodeを起動すると、Rosettaをインストールするか聞かれます。あまり良く見ずにOKを押してしまって、結局Rosettaが入ってしまいました。

インストールしてPATHを設定して使いたい場合は、configure の -prefix オプションでインストール先を指定して、make install すればインストールされると思います。(試してません)

quazip

0.7.1

Qt以外に依存ライブラリとして quazip を使っています。
以前は、quazip-0.7.1 を使っていました。

https://sourceforge.net/projects/quazip/ では、0.7.3 まで開発が行われ、その後 https://stachenov.github.io/quazip/ に移ったようです。

面倒になったので、まずは 0.7.1 をそのままビルドしてみました。(以前の記事のpatchが当たった状態)

% cd quazip-0.7.1/quazip
% ~/qt/5.15.2/qtbase/bin/qmake PREFIX=$HOME/qt/quazip
Project ERROR: Could not resolve SDK SDKVersion for 'macosx10.11' using --show-sdk-version

quazip.pro を修正します。

*** quazip.pro.orig2    2022-05-26 16:07:59.000000000 +0900
--- quazip.pro  2022-05-26 16:06:46.000000000 +0900
***************
*** 1,5 ****
  TEMPLATE = lib
! QMAKE_MAC_SDK=macosx10.11
  CONFIG += qt warn_on
  QT -= gui

--- 1,5 ----
  TEMPLATE = lib
! QMAKE_MAC_SDK=macosx12.3
  CONFIG += qt warn_on
  QT -= gui

※ これ、手元の環境で昔何かあって修正していたようで、本来の quazip.pro には QMAKE_MAC_SDK の行はなかったようです。単純にこの行を削除しても成功しますね。

% ~/qt/5.15.2/qtbase/bin/qmake PREFIX=$HOME/qt/quazip
% make
% make install

1.3

移行先のgithubリポジトリを見ると、1.3のソースアーカイブがダウンロードできます。
https://github.com/stachenov/quazip/releases

1.0以降で結構大きな変更があります。

  • qmakeのサポートをやめて、cmakeを使うようになっています。
  • include ディレクトリの変更
  • ライブラリ名の変更
  • その他

wikiの記述に従って、cmake を実行しますが、qtをdevelop-buildしていてインストールしていない場合は、cmakeがqtを見つけられないため、CMAKE_PREFIX_PATH で指定します。

# ~/qt 以外のどこか
% tar xf quazip-1.3.tar.gz
% CMAKE_PREFIX_PATH=~/qt/5.15.2/qtbase/lib/cmake/Qt5 cmake quazip-1.3 -B quazip-1.3-build
% cmake --build quazip-1.3-build
% cmake --install quazip-1.3-build --prefix ~/qt/quazip-1.3

これで、~/qt/quazip-1.3/include と ~/qt/quazip-1.3/lib ができます。

  • ~/qt/quazip/include は、直下に quazip ディレクトリがありますが、~/qt/quazip-1.3/include は QuaZip-Qt5-1.3/quazip のような階層になっています。
  • ~/qt/quazip/lib は、libquazip.dylib がありますが、~/qt/quazip-1.3/lib は libquazip1-qt5.dylib になっています。

この辺を全部対応したら ComicsViewer がビルドできたのですが、起動した瞬間に落ちたので、1.3の使用は諦めました。

ComicsViewer

修正なしでビルドが通り、無事に動いたようです。(気持ち遅いような気も・・・)

% ~/qt/5.15.2/qtbase/bin/qmake QUAZIP_DIR=~/qt/quazip
% make

これで、なんとか Intel Macと同じような環境が整ったようです。
下取りに出す前にやり忘れたことはないかなあ・・・。

追記

ふと思い立って brew search したら Qt も quazip も homebrew で入るみたいです。
試していないのでどう言うアーキテクチャのものが入るのかわかりませんが。

(searchの結果は抜粋)

% brew search qt
==> Formulae
pyqt                pyqt@5              qt                  qt@5

==> Casks
qt-creator

% brew search quazip
==> Formulae
quazip

% brew info qt
qt: stable 6.2.3 (bottled), HEAD
Cross-platform application and UI framework
https://www.qt.io/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/qt.rb
License: GFDL-1.3-only and GPL-2.0-only and GPL-3.0-only and LGPL-2.1-only and LGPL-3.0-only

% brew info qt@5
qt@5: stable 5.15.3 (bottled) [keg-only]
Cross-platform application and UI framework
https://www.qt.io/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/qt@5.rb
License: GFDL-1.3-only and GPL-2.0-only and GPL-3.0-only and LGPL-2.1-only and LGPL-3.0-only

% brew info quazip
quazip: stable 1.3 (bottled)
C++ wrapper over Gilles Vollant's ZIP/UNZIP package
https://github.com/stachenov/quazip/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/quazip.rb
License: LGPL-2.1-only

qt@5 のバージョンが5.15.2ではなく5.15.3であることに気づいたので、qt5のリポジトリでブランチではなくtagを見てみる。

% git tag
(中略)
v5.15.1
v5.15.2
v5.15.3-lts-lgpl
v5.15.4-lts-lgpl
(後略)

どうも、1.15.3とか1.15.4があるらしい。

% git log v5.15.4-lts-lgpl
commit 45624b631fffebe4d2cd1a28978c37304bea8d3c (HEAD -> 5.15, tag: v5.15.4-lts-lgpl, origin/5.15)
Author: Tarja Sundqvist <tarja.sundqvist@qt.io>
Date:   Mon May 9 19:30:14 2022 +0300

    Merge Qt 5.15.4 release to the public 5.15 branch

    Merge the Qt 5.15.4 release that is tagged with the v5.15.4-lts-lgpl tag.

    Change-Id: I6564af2fd851f5cebe88781153da53979244ca50

commit b78a4dc89344bd3069f75496b5978500ed124828 (tag: v5.15.3-lts-lgpl)
Author: Tarja Sundqvist <tarja.sundqvist@qt.io>
Date:   Wed Mar 2 18:04:45 2022 +0200

    Merge Qt 5.15.3 Opensource release

    Merge of the v5.15.3-lts-lgpl tag.

    Change-Id: I87eabbc5d9e960e2afb74574c603067480d0468f

これを見ると、5.15.2ブランチではなく5.15ブランチを選択するのが正しかったようだ。
ちゃんとドキュメントのブランチ戦略を見ないと駄目だな。(と言いつつ見ない)

Discussion