Unity アプリに Sparkle を組み込む
Unity で macOS アプリを作成する際、Xcode プロジェクトを出力し改変を加えることで Unity が持たない機能を追加することができます。そこで、macOS アプリのアップデートフレームワークとして定番の Sparkle を導入する方法を記録します。
なお筆者は Xcode がからっきし、Unity は多少わかるくらいの者です。
環境
- Unity 2022.3.25f1
- macOS Sonoma 14.4.1
- Xcode 15.3
Unity で Xcode プロジェクトを作成
まずは Unity で Xcode プロジェクトを作成します。
ここで重要なのがバージョン番号です。Sparkle はビルドナンバー(CFBundleVersion)を見てバージョンの上下を判定しますが、初期設定の 0 から 1 への変更はアップデートとして認識されません。そのため、初回リリース時にはバージョン番号を 1 などにしておく必要があります。Unity 側では Player Settings - Other Settings でビルドナンバーを設定できます。
Build Settings で「Create Xcode Project」を選択し、ビルドします。
Sparkle の組み込み
パッケージを追加
生成されたプロジェクトを Xcode で開いたら、Sparkle を追加します。
- File/Add Package Dependencies… を開く。
- 右上のボックスに
https://github.com/sparkle-project/Sparkle
と入力し、Add Package をクリックする。 - 追加先のターゲットが表示されるので、もう 1 度 Add Package をクリックする。
メニューを追加
アプリケーションメニューに「Check for Updates…」を追加します。
MainMenu.nib を開き、Object を追加します。
追加した Object の Class を SPUStandardUpdaterController
に設定します。
メニューアイテムを追加し、名前を「Check for Updates…」に変更します。
Standard Updater Controller となった Object のコンテキストメニューから、メニューアイテムと Object を接続します。
ここで試しにビルドして実行すると、メニューが表示されることを確認できます。現時点ではメニューをクリックしてもエラーが表示されます。
鍵の生成
Xcode プロジェクトのフォルダ/DerivedData/Xcode/SourcePackages/artifacts/sparkle/Sparkle/bin
に Sparkle の鍵生成や署名に使えるツールが入っています。
この中にある generate_keys
を実行すると、秘密鍵がキーチェーンに登録され、公開鍵がコンソールに出力されます。
./generate_keys
この公開鍵を Info.plist に SUPublicEDKey
として追加します。何もないところのコンテキストメニューから「Add Row」で追加できます。
フレームワーク探索パスの修正
おそらく Unity が生成する Xcode プロジェクトの問題だと思うのですが、Xcode で追加したフレームワークを探索するパスが誤っているため、Xcode を通さずダブルクリックした場合アプリケーションが起動しません。これを修正するには、Build Settings で Runpath Search Paths を @executable_path/../Frameworks
に変更します。
おそらく Xcode の再生ボタンを押した場合はプロジェクトに含まれるフレームワークを見ているため起動するのではないかと思いますが、ちょっと謎。
appcast.xml
Sparkle は、appcast.xml を読み取ってアップデートの有無を判定します。先ほどの generate_keys
と同じフォルダに生成用の generate_appcast
があるので、これを利用します。
生成
まずは、現在のバージョンのアプリの情報を含む appcast.xml を生成します。generate_appcast
は .zip, .dmg, .tar.gz などをを検出して appcast.xml を生成してくれるようになっています。
今回は、試しに .app を Finder で .zip にして、次のコマンドを実行します。
./generate_appcast /path/to/directory/includes/zip
無事に appcast.xml が生成されました。
配置
appcast.xml を自分が編集・公開しやすい場所に配置します。良い場所が思いつかないのでとりあえず GitHub に置きます。
配置先の指定
アプリケーションが appcast.xml をどこへ読みに行くかは、Info.plist に SUFeedURL
を追加することで設定できます。
動作確認
ここで再びアプリを実行し、アップデートを確認してみましょう。アプリケーションが appcast.xml を読み込んで、最新だよという旨のメッセージが表示されます。
.zip をどこにもアップロードしていないので厳密には正しくありませんが、初版が Sparkle 経由でダウンロードされることはないので、気にしないことにします。
バージョンを上げる際の対応
いよいよアップデートを配信する際の対応です。
Unity で新しいバージョンをビルドする
バージョンとビルドナンバーを上げてビルドします。2つ罠があります。
- ビルドナンバーだけを変更しても Xcode プロジェクトが更新されない。
- ビルド時に Replace を選択しないと更新されない。
Xcode プロジェクトを修正する
上でやむを得ず Replace を選択したことで、Xcode プロジェクトに加えた変更が元に戻っています。これなんとかならないものか……仕方がないので以下の作業をやり直します。
- Sparkle を追加する
- Runpath Search Paths を修正する
- Info.plist を修正する
Info.plist はバージョン番号の変更のみを残し、他は元に戻します。
メニュー設定などは残っているので、修正作業は以上です。
appcast.xml を更新する
アプリをビルドして、新しい appcast.xml を生成し、<item>
タグを公開用の appcast.xml に追記します。
zip をアップロードする
zip を適当な場所にアップロードします。今回は GitHub Releases に配置し、appcast.xml に記載された URL を置き換えます。
appcast.xml を公開する
appcast.xml を公開します。これでアップデートが無事に行えるはずです。
アップデートを確認する
アップデートが正常に行えるか確認します。
最後に
結構大変なので、慣れてきたら省力化したいですね。
参考資料
- Sparkle ドキュメント
- macOSアプリケーションの更新フレームワークSparkleの使い方
- MacApp用アップデート管理システムSparkleの使い方
- CotEditor の appcast.xml
2024年5月11日