LoginSignup
127
118

More than 1 year has passed since last update.

Mac用Installerの作り方

Last updated at Posted at 2014-01-28

表題についてまとめていきたい

作り方

PackageMakerは止めて、pkgbuild, productbuildでinstallerを作るのがよさそう
http://stackoverflow.com/questions/11487596/making-os-x-installer-packages-like-a-pro-xcode4-developer-id-mountain-lion-re

基本方針は上記linkと同じ

  1. pkgbuild pkgつくる
  2. productbuild distribution(といってもextensionは同じpkg)つくる
  3. productsign signする
    ここまでで ship可能な pkg をつくるところまで。

ここから、さらに 1. dmg をつくり、2. Notary Service に upload して公称をうけ、3. offline時でのinstallのための staple を貼る。ところまでmemoを残します。
4) dmg をつくる
5) Apple Notary Service に upload して公称してもらう。
6) staple をはる

1) pkgをつくる

.pkgファイルをつくります。.pkgには、installされるfileや、install時に走るscriptなどを入れます。また、どのようにinstallするのかについてのoptionを付けることも出来ます。
そのようなことを記述するplistファイルをまず用意する必要があります。
それにはanalyzeコマンドでひな形を作ってあげるのが楽です。

1.1) pkgbuild で plist(設定file)のひな形をつくる

pkgbuild --analyze --root root-path plist-output-path

このコマンドでまず、pkgを作るのに必要なplistのひな形をつくります。
rootで指定するdirにinstallするappなどを、"所定の位置に"おきます。
たとえば、Applications以下にFoo.appをinstallするつもりなら
/path/to/root/以下に、
Applications という擬似的なdir構造を作って、そこにFoo.appを置きます。
そして
pkgbuild --analyze --root /path/to/root foo.plistを実行すると
以下のようなplistが得られます。

        <dict>
                <key>BundleHasStrictIdentifier</key>
                <true/>
                <key>BundleIsRelocatable</key>
                <false/>
                <key>BundleIsVersionChecked</key>
                <true/>
                <key>BundleOverwriteAction</key>
                <string>upgrade</string>
                <key>RootRelativeBundlePath</key>
                <string>Applications/Foo.app</string>
                <key>BundlePostInstallScriptPath</key>
                <string></string>
                <key>BundlePreInstallScriptPath</key>
                <string></string>
        </dict>

dictはbundle(app, vst など) 毎に用意されます。
以下、key/valueについて;
Relocatableはfalseがいいと思います。developerの環境でこれをtrueにしてinstallかけると、install場所としてbuild dirが勝手に指定されちゃったりして困ることになると思います。

BundlePostInstallScriptPath, BundlePreInstallScriptPathはないのなら削除してください(その意味で上のは悪い例です)。削除しないとcurrent position が scriptだとinstallerに思われてしまうようです。このScriptPathはpkgのscriptとは別に走らせたい場合において記述します。

くわしくは
man pkgbuild してください(darwin manpage は公式からは手繰れなくなってしまった)。

さてでは実際にpkgを作ります。

1.2) pkgbuildでpkgファイルをつくる

pkgbuild --root rootDir --component-plist plistPath --scripts scriptDir --identifier id --version version --install-location location Foo.pkg

root はanalyzeしたときのrootと同じです。

component-plistはさっき作ったplist

scripts は script が入っているfolderを指定します。plist で ScriptPathを指定してる場合はこのfolderにscriptを置きます。また、implicit に このfolderに置いたpre/postInstall は pkgが走らせるものと決まっている模様。

identifier は installer/pkg の jp.co.somewhere... みたいなやつです。

versionはinstaller/pkg のversionです

これで flat pkgが出来上がります。
出来上がった後、中身を操作したい場合は
pkgutil --expand xx.pkg out で展開。のち、packageする場合は
pkgutil --flatten で出来ます。 .svnとか不必要に入ってたら 展開して削除してもよいかも。(root以下の.svnなどはpkgbuildがやってくれるのだが(--filter optionの解説を見よ), script folder とかはやってくれない。

2) 次に pkg を distibution形式にします。

distribution形式とはmpkgみたいな、中に1つ以上のpkgをもったpkgです。
pkgがひとつであっても、必ず包むと考えるべき。

まずは distributionを定義するxmlを作るところからstart。

2.1) 設定ファイル(xml)のひな形をつくる

productbuild --synthesize --package Foo.pkg Distribution.xml

こんな感じ。これで出来たxmlをひな形にして、titleやbg, versionなどを適宜変更する。逆に言うと さっきつくったpkgにはbgやtitleを独自に入れるinterfaceがなかった(=公開用のpkgではない)ってことです!

xmlの定義は以下を参照
https://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html#//apple_ref/doc/uid/TP40005370-CH100-SW14

で実際にdistribution形式にパッケージする。

2.2) pkgをdistribution形式にする

productbuild  --distribution "Distribution.xml" --package-path /path/to/pkgDir --resources "/path/to/rsrcDir" "Bar.pkg"

こんな感じ。parameterについてはみれば分かると思うので、割愛します。
ここで分かるのはscriptを指定する方法がdistributionにはないということですね。つまり、scriptは個別のpkgで持つしかない、です。
mpkgと比較していえば、mpkgにつけてたscriptどうすんの?てのがあるんですけど、1)使わないで何とかする, 2)裏技としてpayload=0 つまり、実際には何もinstallしないpkgをつくってこれにscriptだけを持たせるという方法があります。
僕のケースでいえば、使わないようにしました。

3)最後にsignしておわり

productsign  --sign "Developer ID Installer: Somewhere Inc."  "Bar.pkg" "Installer.pkg"

4)dmg をつくる

実際にuserに配るときにはdmgにするのが、macOSだと基本でしょうか。ということでつくったpkgをdmgに入れます。

hdiutil create -srcfolder "/path/to/folder" -fs HFS+ -format UDZO -volname "name_you_see_when_mounting_the_volume" "/path/to/filename.dmg"

このコマンドの前に、 srcfolder に必要なfileを入れておきます。 pkg とか readme とかそういうやつです。.DS_Storeを用意しておくと、imageをmountしたときに見える風景を調整できるのでぜひしましょう。(実際に finder で そのfolderをひらいて、fileをよい場所において、できる.DS_Storeを何らか保存しておき、それを /path/to/folderに配置する)
-fs とか -format は好きなものにしましょう。ここはなんかtipsあったかもなので、追記するかも。

5) 公称をうける。

https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/customizing_the_notarization_workflow?language=objc
ここを読んでね。なのですが、

#比較的新しい方法
notarytool submit --keychain-profile TOKEN_IN_KEYCHAIN --wait "/path/to/file.dmg"
#少し古い方法
xcrun altool --notarize-app -f "/path/to/file.dmg" --primary-bundle-id "jp.mycompany.myappname" -u me@mail.jp -p @keychain:PWD_IN_KEYCHAIN
  • primary-bundle-idはここでしか使われないidentifier。適宜名前をつけましょう。
  • Upload には AppleID が必要です。さらに2step validationしてる場合、tokenが必要になるので、appleid.apple.comにいってtokenをgetしましょう。
  • このtoken を keychain にて PWD_IN_KEYCHAIN (名前はもちろん自由) として store すれば、上記のような形式で呼び出し可能です。

notarization で error が出た場合

まずは、どんなerrorが出ているか調べます。

xcrun altool --notarization-info MAGIC_NUMBER_DISTRIBUTED_BY_APPLE -u me@mail.jp -p @keychain:PWD_IN_KEYCHAIN
  • app の場合、hardened してないから、と言われることがあります。xcodeで Hardened Runtime を on にします
  • code_sign してないから、といわれることがあります。Xcodeで Code Sign するように組みましょう (Developer ID Application)
  • 有効なtimestamp がついてないから、と言われることがあります。 Archive から、Exportするときには timestampが付くようですが、Release build して、それをpackagingするようになってたりする場合、OTHER_CODE_SIGN_FLAGS--timestamp をつけます
  • The executable requests the com.apple.security.get-task-allow entitlement. の場合は、release時のみ、CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO などして、回避しましょう

6) stapleをはります。

appなどを起動する際、初めての場合は公称を受けているのかappleのサーバーに確認に行くのですが、offlineの場合はできません。なので、package自体にラベルを貼って、公称済みかどうかを知らせます。これが staple です。

xcrun stapler staple /path/to/dmg

これは、Appleから公称を受けた後に行います。以上で作成された dmg を distribute します。

その他メモ

pkgbuildでつくったpkgのpayloadも開きたい。

pkgutil --expand-full [pkg] [dir]

pkgの内容物をunarchiveせずに閲覧したい

lsbom [options] /path/to/BOM

uninstaller をつくりたい

pkgutil --files ${PKG_ID}
でinstallしたfileリストはでるので、あとはお好みで削除してください

127
118
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
127
118