Unity アプリに Sparkle を組み込む

Unity で macOS アプリを作成する際、Xcode プロジェクトを出力し改変を加えることで Unity が持たない機能を追加することができます。そこで、macOS アプリのアップデートフレームワークとして定番の Sparkle を導入する方法を記録します。

なお筆者は Xcode がからっきし、Unity は多少わかるくらいの者です。

環境

Unity で Xcode プロジェクトを作成

まずは Unity で Xcode プロジェクトを作成します。

ここで重要なのがバージョン番号です。Sparkle はビルドナンバー(CFBundleVersion)を見てバージョンの上下を判定しますが、初期設定の 0 から 1 への変更はアップデートとして認識されません。そのため、初回リリース時にはバージョン番号を 1 などにしておく必要があります。Unity 側では Player Settings - Other Settings でビルドナンバーを設定できます。

Build Settings で「Create Xcode Project」を選択し、ビルドします。

Sparkle の組み込み

パッケージを追加

生成されたプロジェクトを Xcode で開いたら、Sparkle を追加します。

  1. File/Add Package Dependencies… を開く。
  2. 右上のボックスに https://github.com/sparkle-project/Sparkle と入力し、Add Package をクリックする。
  3. 追加先のターゲットが表示されるので、もう 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 プロジェクトに加えた変更が元に戻っています。これなんとかならないものか……仕方がないので以下の作業をやり直します。

Info.plist はバージョン番号の変更のみを残し、他は元に戻します。

メニュー設定などは残っているので、修正作業は以上です。

appcast.xml を更新する

アプリをビルドして、新しい appcast.xml を生成し、<item> タグを公開用の appcast.xml に追記します。

zip をアップロードする

zip を適当な場所にアップロードします。今回は GitHub Releases に配置し、appcast.xml に記載された URL を置き換えます。

appcast.xml を公開する

appcast.xml を公開します。これでアップデートが無事に行えるはずです。

アップデートを確認する

アップデートが正常に行えるか確認します。

最後に

結構大変なので、慣れてきたら省力化したいですね。

参考資料

2024年5月11日