web-dev-qa-db-ja.com

プロジェクトをビルドするたびに、Xcodeにプロジェクト内のInfo.plistファイルを再構築させるにはどうすればよいですか?

どうやらファイルはキャッシュされるので、変更されたときにのみビルドされます。ただし、バージョン番号などを増やすように環境変数を設定し、plistとは独立して(実際にはプロジェクトのビルド設定で)環境変数を更新しています。 Info.plistを強制的に更新するスクリプトビルドフェーズとして使用できるスクリプトはありますか?他の便利な方法はありますか?

25
TraxusIV

[スキームの編集]を選択し、左側のコントロールから[ビルド]を選択します。

次に、事前アクションステップを追加し、[ビルド設定の提供元]プルダウンで問題のスキームが選択されていることを確認してから、これを下の編集ウィンドウに追加します。

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"

これにより、キャッシュされたバージョンのInfo.plistが削除され、ビルドを実行するたびにXCodeが再ビルドします。

または、XcodeにテンプレートのInfo.plistファイルを前処理させる場合は、テンプレートにタッチするだけです。

touch ${PROJECT_DIR}/${INFOPLIST_FILE}

も動作します。

アクション前スクリプトのデバッグ

間違いがあった場合、事前アクションのステップでは情報が提供されません。この行をスクリプトに追加することで、ビルド変数の使用をデバッグできます。

echo "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}" > ~/debug.txt

次に、~/debug.txtの内容をチェックして、プレアクションスクリプトが実行されたことを確認し、正しいパスを使用したかどうかを確認します。

17
LeeH

私もバージョン番号を自動設定しています。 スクリプトの実行ビルドフェーズを作成しました。重要なのは、Info.plistのターゲットビルドディレクトリコピーを更新することであり、ビルドディレクトリコピーを更新することではありません。また、コピーバンドルフェーズの後に実行スクリプトを用意する必要があります。コード署名の前なので、バンドルファイルを直接編集してもかまいません。車輪を再発明するファイルを生成する必要はありません。

これが私のスクリプトです:

# ---------------------------- IMPORTANT ----------------------------
# You must set GITHash to something like 'Set by build script' in the file
# file '<Project Name>-Info.plist' in the 'Supporting Files' group
# -------------------------------------------------------------------
#
# Get the version number from the tag in git and the number of commits as the build number
#
appVersion=$(git describe --long | cut -f 1 -d "-") 
appBuild=$(git describe --long | cut -f 2 -d "-") 
gitHash=$(git describe --long | cut -f 3 -d "-")
echo "From GIT Version = $appVersion Build = $appBuild"

#
# Set the version info in plist file
#
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $appVersion" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $appBuild" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
/usr/libexec/PlistBuddy -c "Set :GITHash $gitHash" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
echo "Updated ${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"

[〜#〜] fyi [〜#〜]バージョンを自動設定し、次のコードを使用して[バージョン情報]タブでビルドします

NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *appDisplayName = infoDictionary[@"CFBundleDisplayName"];
NSString *majorVersion = infoDictionary[@"CFBundleShortVersionString"];
NSString *minorVersion = infoDictionary[@"CFBundleVersion"];

self.appDescription.text = [NSString stringWithFormat:@"Dirty Dog Software\n%@\nVersion: %@(%@)",
                       appDisplayName, majorVersion, minorVersion];                           
15
GayleDDS

touchコマンドを使用してタイムスタンプを更新してみることもできます。これは、Xcodeが再構築する必要があるかどうかを判断するために使用しているものだと思います。

$ touch Info.plist
12
bosmacs

これを行う1つの方法は、スクリプトの実行ビルドフェーズでInfo.plistファイルからInfo.plist.templateを生成し、バンドルの作成後にrm Info.plistを生成することです。コメントからのアイデア Dave DeLong 彼のブログに投稿 ここ

それがかなりひどくキャッシュしている場合(つまり、ファイル履歴でInfo.plistを開いていない場合でもキャッシュする)、このスクリプトでキャッシュされたバージョンをrmすることもできます。

9
user244343

Xcode 4では、事前ビルドアクションを使用してinfo plistを操作できます。

注:これは、スクリプトの実行ビルドフェーズと同じではありません。 Xcodeがinfo plistをチェックする前にビルド前のアクションが発生し、Xcodeがinfo plistをすでにチェックした後に実行スクリプトのビルドフェーズが発生するようです(そのため、1回おきにしか機能しません)。

  1. [スキームの編集]> [ビルド]> [事前アクション]に移動します
  2. 「+」ボタンをクリックし、「新しいスクリプト実行アクション」を選択します
  3. [ビルド設定の提供元]ドロップダウンでターゲットを選択します
  4. 追加 touch "${SRCROOT}/${INFOPLIST_FILE}"スクリプトボックス内
5
lukelutman

ターゲットの[情報を見る]ウィンドウの[ビルド]タブの[パッケージ]にある[Info.plistファイルの前処理]というラベルの付いたオプションがあり、確認できます。ビルドごとにファイルが更新されると思います。

1
ExitToShell

Xcode 8.3.2での作業

2013年の@LeeHの回答に触発されて、Info.plistを再構築するための2つのソリューションを考え出しました。

解決策1:最もシンプルでエレガント

最も簡単な解決策は、ターゲットをInfo.plisttouchingして、Xcodeにカスタム変数を読み取らせることです。

ビルドフェーズを追加します。以下のスクリーンショット(元々はSolution 2のスクリーンショット)を参照して、次の行を追加してください。

touch $INFOPLIST_FILE

以上です!これで、Xcodeはカスタム変数をInfo.plistファイルに強制的に再ロードする必要があります。

このソリューションは@lukelutmanが提案したものと同じですが、ビルドフェーズを使用します。プレアクションスクリプトは私には機能しませんでした。

解決策2:より複雑でハッキー

別の解決策は、ビルドディレクトリのcachedInfo.plistを削除することです

この超シンプルな小さなbashスクリプトを書きました

#!/bin/bash
info_plist="$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME.app/Info.plist"
echo "Removing Info.plist from build dir in order to force rebuild of it and reading of correct xcconfig variables, plist path $info_plist"
rm "$info_plist"

それを保存して、ターゲットのビルドフェーズから呼び出しました。最初のビルドフェーズとして配置します。

enter image description here

バックグラウンド:

私は3つの異なる構成:ConfigAlphaAppStoreを使用しており、ユニバーサルリンク、プッシュ通知、および資格ファイルの使用を必要とするその他のものを使用しています。しかし、構成ごとに1つずつ、合計3つのエンタイトルメントファイルを作成したくありませんでした。

私のプロジェクトはすでに設定ファイル(.xcconfig)に大きく依存しています。私は実際にカスタム構成変数を使用して資格ファイル(MyAppsProductName.entitlements)を設定しました。

しかし、同じ構成変数のランタイムを読みたかったので、それらがターゲットのInfo.plistに追加されれば、それができると考えました。うまくいった!

しかし、.xcconfigファイルの値を変更しても、Info.plistファイルの値が変更されていないことに気付きました。クリーンビルドを実行すると、Info.plistの値が.xcconfigファイル内の値に従って更新されることに気付きました。 Xcodeは確かにInfo.plistファイルをキャッシュします。

したがって、上記のこれらのソリューションはこの問題を修正します。それが役に立てば幸い! :)

討論

Solution 2Solution 1...よりも有利かどうかはわかりません...おそらく誰か入力はありますか?

0
Sajjon

プロジェクトで自動バージョン管理を行うのに苦労している人のために、@ GayleDDSとDanielのアイデアのおかげで、非常に簡単で簡単な方法でプロジェクトを実装する方法を示す macOS GitHubプロジェクト を作成しました。 Farrellyと彼のブログで、バージョン管理と自分の実装について説明しています。手間をかけずに、他のプラットフォームのプロジェクトに変換できると思います。

これは、プロジェクト(Xcode 8)でそれを複製する方法の簡単なガイドです。

  1. これを間違える可能性を減らすために、事前にすべてのターゲットをプロジェクトに追加していることを確認してください。
  2. メニューFile> New File ...に移動し、下にスクロールしてConfiguration Settings Fileを選択します。
  3. BuildNumberという名前を付け、忘れないでくださいこの構成ファイルをすべてのターゲットに追加同期を維持したい;このファイルを保存する前に、それぞれのチェックボックスをクリックしてください
  4. BuildNumber.xcconfigというファイルがプロジェクトに表示されるはずです
  5. このファイルに次のテキストを追加します:CURRENT_PROJECT_VERSION = 1。必要に応じて、別の番号から始めることができます。これは、ビルドするたびに増加するビルド番号になります。 ただし、変数の名前は変更しないでください
  6. 複数のターゲットがある場合は、プロジェクト>ターゲット>ビルドフェーズに移動してビルドされる最初のターゲットに次のスクリプトを追加します。
  7. メニューに移動Editor> Add Build Phase> Add Run Script Phase
  8. スクリプトの実行フェーズがターゲットに追加されているはずです。 Target Dependenciesの下になるまでドラッグします(この詳細は重要です!)。
  9. ここで興味深い部分があります。スクリプトをほぼ1行ずつ説明します。

スクリプトの最初の行にPlistBuddyへのパスを作成することから始めます。

plistbuddy="/usr/libexec/PlistBuddy"

2行目を追加して構成ファイルを読み取り、手順5で設定したCURRENT_PROJECT_VERSION変数を読み取ります。

OLD_VERSION=`cat "$SRCROOT/BuildNumber.xcconfig" | awk '/CURRENT_PROJECT_VERSION/ { print $3 }'`

3-11行目は、バンプされた値でNEW_VERSIONを設定し、新しいビルド番号で構成ファイルを保存します。残りの行は、マーケティングバージョンとビルド番号をplistに保存するためのものです。

NEW_VERSION=`cat "$SRCROOT/BuildNumber.xcconfig" | awk '/CURRENT_PROJECT_VERSION/ { print $3 + 1 }'`
sed -i '' "s/CURRENT_PROJECT_VERSION = .*/CURRENT_PROJECT_VERSION = $NEW_VERSION/" "$SRCROOT/BuildNumber.xcconfig"
CURRENT_PROJECT_VERSION=$NEW_VERSION
BUILD_STR="Build $NEW_VERSION"
COPYRIGHT_STR="© 2017 MyCompany.net"
APP_VERSION_STR="1.3.5"
$plistbuddy -c "Set :CFBundleShortVersionString $APP_VERSION_STR" "${SRCROOT}/$TARGETNAME/Info.plist"
$plistbuddy -c "Set :CFBundleVersion $BUILD_STR" "${SRCROOT}/$EXECUTABLE_NAME/Info.plist"
$plistbuddy -c "Set :NSHumanReadableCopyright $COPYRIGHT_STR" "$INFOPLIST_FILE"

Xcodeがスクリプト用にセットアップするさまざまな環境変数を使用する方法も8〜11行目に示します。追加の行を追加して、他のターゲットのinfo.plistを編集し、メインアプリのバージョンとそのヘルパーの同期を維持できます。 GitHub に移動し、プロジェクトをダウンロードして遊んでから、ニーズに合わせてください。 Xcodeによるハッピー自動バージョン管理。

0
jvarela

もう1つのアプローチは、ビルドフェーズのみを持つ「集約」ターゲットを作成することです。これを使用して、Info.plistファイルをタッチします。そのターゲットを、アプリを構築するターゲットの依存関係にします。

これは独立したターゲットであり、アプリターゲットの依存関係であるため、アプリターゲットのInfo.plistファイルがチェックされる前にビルドされます。 (他の場所で説明されているように、Info.plistファイルの変更時刻がすでに確認されているため、アプリターゲット自体のビルドフェーズは遅すぎます。)

0
Ken Thomases

Plistのビューも更新してください。
Xcodeでplistを表示するときは、plistのルート要素の横にある開示三角形をクリックするだけです(Information Property List)。そして、もう一度クリックして展開します。
値が更新されたことがわかります。私は同様のスクリプトを実行していて、plistビューが単に更新されていないことに気付くまで、断続的にしか機能していないと思いました。

0
Andrew