如何在不污染源代码的情况下动态设置应用程序的构建号?

5

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

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

这样做的问题在于,由于仓库总是包含之前的版本,脚本总是使我的 Info.plist 变得脏乱。

我是否可以动态设置应用程序的构建号而不弄脏我的源代码树?

2个回答

10

1) 给你的项目添加一个新的目标,类型为“Aggregate”,例如你可以将其命名为“Update Info.plist Prefix Header”,只需在对话框中将其用作“Product Name”即可。

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应用程序的Build Phases。

5) 将之前创建的聚合目标添加为依赖目标(将其添加到“Target Dependencies”中)。这意味着Xcode在构建iOS目标之前始终会首先构建此目标。

6) 打开您的iOS应用程序的Build Settings。

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文件,然后在将其复制到应用程序之前,它将通过C预处理器(使用PCH文件作为前缀头)运行Info.plist文件。预处理器将替换SVN_REVISION,因为它在您的PCH文件中定义为宏。

重要提示

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

有些人可能也认为只需将更新前缀头的Run Script阶段作为您的iOS应用程序的第一个构建阶段而不是创建单独的目标会更好(这也将解决上述派生文件目录问题)。在理论上很好的想法,在实践中却行不通:如果要求预处理,则Info.plist在执行第一个脚本阶段之前就已被预处理了,因此如果PCH文件不存在或尚未更新,则构建将以错误终止或过时的SVN版本将写入plist文件。这就是为什么需要一个单独的目标来完成这项任务,并保证在实际目标之前进行构建。


2

Mecki非常感谢你提供的出色答案!我将相同的概念应用于设置版本时间戳和当前Git SHA的构建。 顺便说一下,我遇到了一个小问题。至少在Xcode 5中,如果指定输出文件,则脚本步骤将其用作缓存,因此无论我对实际应用程序代码进行了哪些更改,脚本都会报告它已运行,但是值并不是当前值... 我不得不将输出文件声明移动到脚本本身来解决这个问题,即添加

SCRIPT_OUTPUT_FILE_0="$CONFIGURATION_TEMP_DIR/InfoPlist.pch"

将以下代码添加到我的脚本顶部。此外,为了使构建步骤能够复制新值,还应该修改原始plist文件,因此我也添加了如下内容。

`touch $SCRIPT_INPUT_FILE_0`

在之前的输出文件声明后,执行这个touch操作不会被git识别为可提交的更改。

祝好


你的失败在于你的脚本阶段有一个输入文件。而我的回复中的脚本阶段只有一个输出文件,因为所有文件内容都是由脚本动态生成的。只有具有输入或输出文件的脚本会在每次构建时运行,而同时具有输入和输出的脚本只有在输入文件的最新修改日期早于输出文件时才会运行。 - Mecki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接