5

我正在使用 git-svn,我正在尝试将我的修订号嵌入到我的 iOS 应用程序中。目前,我有一个运行以下脚本的构建阶段:

SVN_REVISION=$(git svn find-rev HEAD)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $SVN_REVISION" "$INFOPLIST_FILE"

问题在于,由于 repo 总是包含以前的版本,脚本总是让我的 Info.plist 变脏。

我是否可以在不弄脏源代码树的情况下动态设置应用程序的内部版本号?

4

2 回答 2

10

1) 为您的“聚合”类型的项目添加一个新目标,例如,您可以将其命名为“更新 Info.plist Prefix Header”;只需在对话框中将其用作“产品名称”。

2) 使用以下源代码向这个新目标添加一个运行脚本构建阶段:

#!/bin/sh
SVN_REVISION=$(git svn find-rev HEAD)
echo "#define SVN_REVISION $SVN_REVISION" > "$SCRIPT_OUTPUT_FILE_0"


3) 将输出文件添加到您的脚本中,为其命名

$(CONFIGURATION_TEMP_DIR)/InfoPlist.pch


4) 打开 iOS 应用程序的构建阶段。

5)将您之前创建的聚合目标添加为依赖目标(将其添加到“目标依赖项”)。这意味着 Xcode 将始终先构建此目标,然后再构建您的 iOS 目标。

6) 打开 iOS 应用程序的构建设置。

7)搜索设置“Info.plist Preprocessor Prefix File”并将其更改为与步骤(3)中用于输出文件的值完全相同的值。

8) 搜索设置“Preprocess Info.plist File”并确保它已启用。

9) 打开您当前的 Info.plist 文件并将 CFBundleVersion 的值更改为SVN_REVISION. 不要使用$(SVN_REVISION) 或 ${SVN_REVISION};这不是构建设置或环境变量替换,这是预处理器替换,所以只需使用 SVN_REVISION。


就是这样。每次构建 iOS 应用时,Xcode 首先构建聚合目标,它会更新 PCH 文件,当它构建 iOS 应用时,它会通过 C 预处理器运行 Info.plist 文件(使用 PCH 文件作为前缀header) 在将其复制到您的应用程序之前。预处理器将替换 SVN_REVISION,因为它在您的 PCH 文件中定义为宏。

重要笔记

有些人可能认为使用$(DERIVED_FILE_DIR)而不是$(CONFIGURATION_TEMP_DIR). 好吧,理论上他们是对的,但实际上只有一个问题:每个目标的派生文件目录不同,而配置临时目录是相同的(只是每个构建配置不同)。使用派生文件目录时,PCH 文件被写入聚合目标的派生文件目录,但在构建 iOS 应用程序时,Xcode 会在 iOS 应用程序的派生文件目录中搜索此文件,因此找不到文件。

有些人可能还认为将更新前缀标头的运行脚本阶段添加为 iOS 应用程序的第一个构建阶段而不是为其创建单独的目标是一个更好的主意(这也将解决提到的派生文件目录问题多于)。再一次,理论上的好主意,但在实践中不能工作:如果请求预处理,Info.plist 在第一个脚本阶段甚至执行之前被预处理,所以如果 PCH 文件不存在或尚未更新,要么构建因错误而终止,或者将过时的 SVN 修订版写入 plist 文件。这就是为什么您需要一个单独的目标来保证在您的实际目标之前构建此任务。

于 2013-01-10T13:53:38.903 回答
2

Mecki感谢您的出色回答!我应用相同的概念来设置版本时间戳和构建的当前 git SHA。仅供参考,我只是遇到了一个小问题。似乎,至少在 Xcode 5 中,如果您指定一个输出文件,脚本步骤会将其用作缓存,因此无论我对实际应用程序代码所做的更改,脚本报告它已经运行但值不是当前的...我不得不将输出文件声明移动到脚本本身来解决问题,即添加

SCRIPT_OUTPUT_FILE_0="$CONFIGURATION_TEMP_DIR/InfoPlist.pch"

到我脚本的顶部。此外,还应该触摸原始 plist,以便构建步骤复制新值,所以我还添加了

`touch $SCRIPT_INPUT_FILE_0`

在上一个输出文件声明之后。此触摸操作不会使 git 将更改检测为可提交。

干杯

于 2013-09-30T11:08:28.340 回答