125 Views
June 21, 14
スライド概要
ツイッターを眺めていたら Info.plist の書き換えについてのお話が流れてきました。
その話題の中心にあった agvtool と、そこから派生して Build 番号を Info.plist そのものは更新せずにビルド時に細工をしてバンドルに埋め込む方法に興味を惹かれ、それについて少し深追いしてみました。特に Info.plist Preprocessor はなかなか面白い仕組みでした。どのような場面で便利に使えるかは別としまして。
※ Docswell での公開に移行する直前の Slideshare での閲覧数は 6,751 でした。
正統派趣味人プログラマー。プログラミングとは幼馴染です。
ビルド番号の更更新について ネットで教えてもらったこと • • • Info.plist & Run Script agvtool Info.plist Preprocessor EZ-‐‑‒NET 熊⾕谷友宏 @es_̲kumagai http://program.station.ez-‐‑‒net.jp/
⾃自⼰己紹介 EZ-‐‑‒NET 熊⾕谷友宏 http://program.station.ez-‐‑‒net.jp/ @es_̲kumagai EZ-‐‑‒NET IP Phone ⾳音で再配達ゴッド ⾳音で再配達 ⾳音でダイヤル いつもの電卓 for iPad いつもの電卓 for iPhone
書籍 • • • • • • • • • Xcode 全機能を網羅羅 プロジェクトの作り⽅方 ソースコード編集の効率率率化 ショートカットキーの紹介 オートレイアウトの使い⽅方 ローカライズの設定⽅方法 バージョン管理理の使い⽅方 ビルド設定とスキーム設定 ほか、とにかくいろいろ こんなご時世ですが ぜひ⼿手に取ってパラパラめくってみてください。 特設サイト ̶— http://ez-‐‑‒net.jp/sp/xcode5/
話題 さて ツイッターを眺めていたところ
話題 興味深いツイートが舞い込んできました。 agvtool のお話とか。
話題 話題は @tokorom さん のこちらのスライド h"ps://speakerdeck.com/tokorom/agvtooldechao-‐katukoyokubaziyoningudekimasuka
Apple-‐‑‒Generic Versioning Tool agvtool
Apple-‐‑‒Generic Versioning Tool agvtool プロダクトのバージョン管理理を⾏行行えるツール Build Settings に関連する設定項⽬目がある
Apple-‐‑‒Generic Versioning Tool 準備
Apple-‐‑‒Generic Versioning Tool Current Project Version を設定 Versioning System で “Apple Generic” を選択
Apple-‐‑‒Generic Versioning Tool 準備完了了
Apple-‐‑‒Generic Versioning Tool あとは プロジェクトファイルのある ディレクトリで agvtool を実⾏行行する だけ
Apple-‐‑‒Generic Versioning Tool バージョンの確認 agvtool what-‐‑‒version Current version of project $(PROJECT_̲NAME) is: 1 プロジェクトファイル内の CURRENT_̲PROJECT_̲VERSION が対象
Apple-‐‑‒Generic Versioning Tool バージョンの確認(簡潔に表⽰示) agvtool what-‐‑‒version -‐‑‒terse 1 プロジェクトファイル内の CURRENT_̲PROJECT_̲VERSION が対象
Apple-‐‑‒Generic Versioning Tool バージョンの更更新 agvtool new-‐‑‒version 2 プロジェクトファイル内の CURRENT_̲PROJECT_̲VERSION が対象
Apple-‐‑‒Generic Versioning Tool CFBundleVersion も同時更更新 agvtool new-‐‑‒version -‐‑‒all 3 プロジェクト内の CURRENT_̲PROJECT_̲VERSION と 全ターゲット の Info.plist の CFBundleVersion が対象
Apple-‐‑‒Generic Versioning Tool 次のバージョン番号に更更新 agvtool next-‐‑‒version -‐‑‒all ⼩小数点以下がある場合は切切り捨てられる
Apple-‐‑‒Generic Versioning Tool ターゲットバージョンの確認 agvtool what-‐‑‒marketing-‐‑‒version No marketing version number (CFBundleShortVersionString) in native targets... Found CFBundleShortVersionString of “1.0” in “PROJ.xcodeproj/../PROJNAME/PROJ-‐‑‒Info.plist” Found CFBundleShortVersionString of “1.0” in “PROJ.xcodeproj/../PROJNAME/PROJTest-‐‑‒Info.plist” プロジェクト内の全ターゲットの Info.plist にある CFBundleShortVersionString が対象
Apple-‐‑‒Generic Versioning Tool ターゲットバージョンの確認(簡潔に表⽰示) agvtool what-‐‑‒marketing-‐‑‒version -‐‑‒terse “PROJ.xcodeproj/../PROJNAME/PROJ-‐‑‒Info.plist”=1.0 “PROJ.xcodeproj/../PROJNAME/PROJTest-‐‑‒Info.plist”=1.0 プロジェクト内の全ターゲットの Info.plist にある CFBundleShortVersionString が対象
Apple-‐‑‒Generic Versioning Tool ターゲットバージョンの確認(最初のひとつだけ) agvtool what-‐‑‒marketing-‐‑‒version -‐‑‒terse1 1.0 最初のひとつを何で決めているかは不不明
Apple-‐‑‒Generic Versioning Tool ターゲットバージョンの更更新 agvtool new-‐‑‒marketing-‐‑‒version 2.0 プロジェクト内の 全ターゲット の Info.plist にある CFBundleShortVersionString が対象
Apple-‐‑‒Generic Versioning Tool バージョン管理理システムと 連動できたりするらしい 詳細は未確認
Apple-‐‑‒Generic Versioning Tool CVS との連携機能もあるらしい defaults write agvtool CVSEnabled YES defaults write agvtool CVSSubmitByTag YES defaults write agvtool CVSToolPath PATH Subversion との連携機能もあるらしい defaults write agvtool SVNEnabled YES defaults write agvtool SVNSubmitByTag YES defaults write agvtool SVNToolPath PATH Git との連携機能があるかは不不明 有効にしたバージョン管理理システムへ コミットやタグ付けを連動して実⾏行行できるらしい。
Apple-‐‑‒Generic Versioning Tool 話題のスライド中にあった VERSIONING_̲INFO_̲PREFIX Versioning Name Prefix 話題のスライドとは挙動が違う様⼦子
Apple-‐‑‒Generic Versioning Tool VERSIONING_̲NAME_̲PREFIX に “dev-‐‑‒” を設定してみたところ …
Apple-‐‑‒Generic Versioning Tool ビルドエラーになりました。 ⾒見見知らぬ “$(PROJECT_̲NAME)_̲vers.c” ファイル内に double 型の “dev-‐‑‒” で始まるシンボルが定義されている
Apple-‐‑‒Generic Versioning Tool VERSIONING_̲NAME_̲PREFIX は CURRENT_̲PROJECT_̲VERSION の 値を保持するシンボル名のプレフィックス として使われる様⼦子
Apple-‐‑‒Generic Versioning Tool ちなみにこのファイルは Derived Data フォルダー内に 中間ファイル (Intermediates) として⾃自動⽣生成される
Apple-‐‑‒Generic Versioning Tool ちなみに $(PROJECT_̲NAME)_̲vers.c ファイルは ビルドされてアプリに組み込まれるようなので
Apple-‐‑‒Generic Versioning Tool “extern” すると使えたりします。
Apple-‐‑‒Generic Versioning Tool agvtool の設定項⽬目
Apple-‐‑‒Generic Versioning Tool VERSIONING_̲SYSTEM Versioning System 必ず “Apple Generic” を指定 する。 CURRENT_̲PROJECT_̲VERSION Current Project Version バージョン番号(この値を agvtool で操作する) VERSION_̲INFO_̲EXPORT_̲DECL Generated Versioning Variables 中間ファイル内で定義される 各変数の宣⾔言の先頭に付与す るキーワード (export 等) VERSION_̲INFO_̲FILE Generate Versioning Source Filename 中間ファイルとして⽣生成する ファイル名(拡張⼦子を含む) VERSION_̲INFO_̲PREFIX Versioning Name Prefix 中間ファイル内で定義される 各変数に付けるシンボル名の プレフィックス VERSION_̲INFO_̲SUFFIX Versioning Name Suffix 中間ファイル内で定義される 各変数に付けるシンボル名の サフィックス VERSION_̲INFO_̲BUILDER Versioning Username 未確認
Apple-‐‑‒Generic Versioning Tool agvtool を Run Script などで使えば ビルド番号を簡単操作できるのでしょう たぶん。
#ifdef DEBUG 話は変わって 話題のスライド中にあった記載 『Configuration で切切り替えられるおかげで #ifdef DEBUG を使う必要がなくなった』 それに対して …
#ifdef DEBUG ?! Info.plist プリプロセッサ…?
Info.plist Preprocessor Info.plist プリプロセッサ
Info.plist Preprocessor プリプロセッサと⾔言えば コンパイル前にソースコードを整える C ⾔言語でお馴染みの機能 Objective-‐‑‒C でもお馴染み
Info.plist Preprocessor たとえば、こういうものたち。 #import “MyClass.h” #define MyClassMaxValue 1000 #ifdef DEBUG NSLog(“Value = %d”, object.value); #endif
Info.plist Preprocessor Info.plist プリプロセッサの 有効化
Info.plist Preprocessor Preprocess Info.list File を Yes に設定 これで OK
Info.plist Preprocessor Build Settings 設定だけで Info.plist をプリプロセスする場合
Info.plist Preprocessor Info.list Preprocessor Definitions に KEY=VALUE の形式で値を定義 複数の値を設定したい場合は、 半⾓角スペースを挟んで記載する。
Info.plist Preprocessor Info.plist の置き換えたい部分で Info.plist Preprocessor Definitions で定義したキーを記載 ビルド時にキーの部分が値に置き換わる
Info.plist Preprocessor Configuration 毎に異異なる値も設定可能
Info.plist Preprocessor ヘッダーファイルを使って Info.plist をプリプロセスする場合
Info.plist Preprocessor 1. Info.plist Preprocessor Prefix File に プリプロセスで使う ヘッダーファイル名 を指定 2. Info.plist Preprocessor Definitions に $(GCC_̲PREPROCESSOR_̲DEFINITIONS) を指定 $(GCC_̲PREPROCESSOR_̲DEFINITIONS) を指定することで Preprocessor Macros で定義した値を使⽤用可能に
Info.plist Preprocessor Info.list Preprocessor Prefix File で指定したファイルに #define KEY VALUE の形式で値を定義 ここでプリプロセッサマクロを使⽤用可能
Info.plist Preprocessor Info.plist の置き換えたい部分で Info.plist Preprocessor Definitions で定義したキーを記載 ビルド時にキーの部分が値に置き換わる
Info.plist Preprocessor Info.list Preprocessor Prefix File で Info.plist をプリプロセスする際の留留意点 値の更更新時はヘッダーファイルだけを 更更新しても Info.plist が更更新されない 変更更を反映するには Info.plist ファイルの更更新が必要
Info.plist Preprocessor Info.plist プリプロセッサーで使⽤用できる設定項⽬目 INFOPLIST_̲PREPROCESS Preprocess Info.plist File これを “Yes” にすると Info.plist がプリプロセスされる INFOPLIST_̲PREFIX_̲HEADER Info.plist Preprocessor Prefix File プリプロセス時に使⽤用する キーと値が書かれたヘッダー ファイル名を指定(任意) INFOPLIST_̲PREPROCESSOR_̲DEFINITIONS プリプロセス時に使⽤用する キーと値を指定(半⾓角スペー スで分けて複数指定可能) Info.plist Preprocessor Definitions INFOPLIST_̲OTHER_̲PREPROCESSOR_̲FLAGS プリプロセッサに渡すフラグ Info.plist Other Preprocessor Flags を指定(-‐‑‒DDEBUG=1 など)
Info.plist Preprocessor Based on Configuration File と合わせて使えば Info.plist の複雑な調整もできるかも? ターゲットや Configuration 毎に 設定内容を調整できる機能
宣伝 Based on Configuration File については Xcode 5 徹底解説 9.10 Configuration 設定ファイルを使って ビルド設定をテキストファイルで管理理する をご覧下さい。
話題 いつしか話は次の展開へと進み …
話題 ひとつの解が⽰示されました。 h"ps://github.com/kishikawakatsumi/BuildNumber
ビルド番号の更更新についての話題の中で… 解答の中で挙げられていた 「問題点」の但し書き そこに意識識が留留まりました。
Info.plist 処理理のタイミング 『Compile Sources より前に Run Script を実⾏行行しても間に合わない』
Info.plist 処理理のタイミング 『間に合わない』 ⾃自分も書籍執筆中に体験
Info.plist 処理理のタイミング そのときは Info.plist を Run Script で 更更新してもビルドに間に合わない というもの
PlistBuddy Info.plist の更更新といえば /usr/libexec/PlistBuddy プロパティリストファイルを読み書きできるコマンド
PlistBuddy 使⽤用例例 infoPlistFile="${SRCROOT}/${INFOPLIST_̲FILE}” buildNumber=$(/usr/libexec/PlistBuddy -‐‑‒c "Print CFBundleVersion" "${infoPlistFile}") buildNumber=$((${buildNumber%%.*} + 1)) /usr/libexec/PlistBuddy -‐‑‒c “Set CFBundleVersion $buildNumber" "${infoPlistFile}" Info.plist の CFBundleVersion を更更新する例例
PlistBuddy 【書式】/usr/libexec/PlistBuddy –c “コマンド” “プロパティリストファイル” Print KEY KEY の値を出⼒力力 Set KEY VALUE KEY に VALUE を設定 Copy srcKEY dstKEY srcKEY とその値を dstKEY として複製 Delete KEY KEY とその値を削除 Add KEY TYPE [VALUE] TYPE 型の KEY を追加(値は任意) Clear TYPE TYPE 型の Root 要素として初期化(TYPE は Array や Dictionary を指定) Merge FILE [KEY] FILE で指定したプロパティリストの内容を KEY の値として追加(KEY の型は FILE の Root 要素と同じ型のものを指定, 省省略略時は Root 要素に追加) Import KEY FILE Data 型の KEY を作成してファイルの内容 を値として設定
Info.plist 処理理のタイミング なぜ 間に合わないのか
Info.plist 処理理のタイミング ビルドログを確認すると… 1 2 Target Dependencies [1] Compile Sources Link Binary With Libraries [2] Copy Bundle Resources 間に合いそうに ⾒見見えるのですが…
Info.plist 処理理のタイミング 今、試してみると 間に合うようなのですが …
Info.plist 処理理のタイミング 調査当時は なぜか 間に合いませんでした
Info.plist 処理理のタイミング それはさておき。
Info.plist 処理理のタイミング Info.plist プリプロセッサを有効にしたとき 1 2 Target Dependencies Preprocess Info.plist File [1] Compile Sources Link Binary With Libraries [2] Copy Bundle Resources Preprocessed-‐‑‒Info.plist を⽣生成して処理理する様⼦子
Info.plist 処理理のタイミング Target Dependencies Build Phase の直後に Info.plist のプリプロセスが完了了する Info.plist のプリプロセスに必要な情報を Run Script Build Phase で揃えても間に合わない
Info.plist 処理理のタイミング ただし プリプロセス済みの Info.plist ファイルは 従来どおりのタイミングで組み込まれる このプロジェクトの Info.plist ファイルは もともと Preprocessed-‐‑‒Info.plist だったとみなせる かも
Info.plist 書き換えの⼿手段 今回の話題のスライド中では 『Info.plist を直接書き換えずに調整したい』 が⽬目標に掲げられていました。
厳Info.plist 書き換えの⼿手段 それなら Preprocessed-‐‑‒Info.plist を 直接 書き換えたらどうなるか
Info.plist 書き換えの⼿手段 ログを⾒見見る限りでは … * Target Dependencies Preprocess Info.plist File [*] Compile Sources [*] Link Binary With Libraries Copy Bundle Resources Copy Bundle Resources までの間 編集する猶予が得られそう
Info.plist 書き換えの⼿手段 Run Script はこのような感じに infoPlistFile="${TEMP_̲DIR}/Preprocessed-‐‑‒Info.plist” buildNumber=$(/usr/libexec/PlistBuddy -‐‑‒c "Print CFBundleVersion" "${infoPlistFile}") buildNumber=$((${buildNumber%%.*} + 1)) /usr/libexec/PlistBuddy -‐‑‒c "Set:CFBundleVersion $buildNumber" "${infoPlistFile}" Preprocessed-‐‑‒Info.plist ファイルのパスは 事実から “${TEMP_̲DIR}/Preprocessed-‐‑‒Info.plist” と推定
Info.plist 書き換えの⼿手段 更更新できました。 ビルドにも間に合う様⼦子
Info.plist 書き換えの⼿手段 留留意点 Preprocess Info.plist File を有効化 した状態で $(SRCROOT)/${INFOPLIST_̲FILE} を書き換える と 更更新が間に合わず 次回のビルドに繰り越される
Info.plist 書き換えの⼿手段 ちなみに
Info.plist 書き換えの⼿手段 ⼀一応は … バンドルに組み込まれた Info.plist を 直接 書き換えることも可能
Info.plist 書き換えの⼿手段 Run Script はこのような感じに infoPlistFile=“${BUILT_̲PRODUCTS_̲DIR}/ ${FULL_̲PRODUCT_̲NAME}/Info.plist” buildNumber=$(/usr/libexec/PlistBuddy -‐‑‒c "Print CFBundleVersion" "${infoPlistFile}") buildNumber=$((${buildNumber%%.*} + 1)) /usr/libexec/PlistBuddy -‐‑‒c "Set:CFBundleVersion $buildNumber" "${infoPlistFile}" これを Copy Bundle Resources よりも後に実⾏行行
Info.plist 書き換えの⼿手段 実⾏行行タイミングは、ここ * Target Dependencies Compile Sources Link Binary With Libraries [*] Copy Bundle Resources Run Script Copy Bundle Resources で 組み込まれた Info.plist を扱う
Info.plist 書き換えの⼿手段 ただし、実機だと2回に1度度、 コード署名あたりでエラー が発⽣生する様⼦子 原因は不不明
Info.plist 書き換えの⼿手段 実機⽤用のビルドに限って Build Phases 終了了後に パッケージング と コード署名 が⾏行行われる様⼦子
Info.plist 書き換えの⼿手段 1. Run Script はパッケージングの前に処理理される 2. Info.plist が処理理されてから Run Script までには デバッグシンボルを⽣生成するログのみ
お詳しい⽅方へ! どの辺りが 影響しているものなのでしょう?
以上、 ツイッターでの Info.plist の話をきっかけに 分かったことの紹介でした。