如何在不污染源树的情况下动态设置应用程序的内部版本号?

时间:2013-01-10 10:13:52

标签: xcode version-control

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

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

问题在于,由于repo总是包含之前的版本,因此该脚本总是使我的Info.plist变脏。

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

2 个答案:

答案 0 :(得分:9)

1)将新目标添加到“Aggregate”类型的项目中,例如你可以命名为“Update 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)将您之前创建的聚合目标添加为依赖目标(将其添加到“Target Dependencies”)。这意味着Xcode将始终首先构建此目标,然后才能构建您的iOS目标。

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

7)搜索“Info.plist预处理器前缀文件”设置,并将其更改为与步骤(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文件作为前缀)在将其复制到您的应用程序之前。预处理器将取代SVN_REVISION,因为它被定义为PCH文件中的宏。

重要提示

有些人可能认为使用$(DERIVED_FILE_DIR)代替$(CONFIGURATION_TEMP_DIR)更好。好吧,理论上它们是正确的,但实际上只有一个问题:派生文件dir对于每个目标都是不同的,而配置temp dir是相同的(它对每个构建配置只是不同的)。使用派生文件目录时,PCH文件将写入聚合目标的派生文件目录,但在构建iOS应用程序时,Xcode将在iOS应用程序的派生文件目录中搜索此文件,因此无法找到文件。

有些人可能还认为最好只添加更新前缀标题的Run Script阶段作为iOS应用的第一个构建阶段,而不是为它创建一个单独的目标(这也会解析派生文件)上面提到的dir问题)。同样,理论上的好主意但在实践中无法工作:如果请求预处理,则在第一个脚本阶段执行之前对Info.plist进行预处理,因此如果PCH文件尚未存在或尚未更新,则要么构建以错误终止,或者将过时的SVN修订写入plist文件。这就是为什么你需要一个单独的目标来完成这个任务,保证在你的实际目标之前建立。

答案 1 :(得分:2)

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

SCRIPT_OUTPUT_FILE_0="$CONFIGURATION_TEMP_DIR/InfoPlist.pch"

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

`touch $SCRIPT_INPUT_FILE_0`

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

干杯