XCode 4.4 捆绑包版本更新直到后续构建才获得

Posted

技术标签:

【中文标题】XCode 4.4 捆绑包版本更新直到后续构建才获得【英文标题】:XCode 4.4 bundle version updates not picked up until subsequent build 【发布时间】:2012-08-02 20:20:03 【问题描述】:

我可能在这里遗漏了一些简单的东西。我试图仅在归档我的应用程序(为 TestFlight 部署做准备)时自动增加 XCode 4.4 中的内部版本号。我有一个在目标上运行并成功更新每个构建的 info.plist 文件的工作 shell 脚本。我用于归档的构建配置名称为“Ad-Hoc”。

这是脚本:

if [ $CONFIGURATION == Ad-Hoc ]; then
    echo "Ad-Hoc build. Bumping build#..."
    plist=$PROJECT_DIR/$INFOPLIST_FILE
    buildnum=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$plist")

    if [[ "$buildnum" == "" ]]; then
        echo "No build number in $plist"
        exit 2
    fi

    buildnum=$(expr $buildnum + 1)
    /usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnum" "$plist"
    echo "Bumped build number to $buildnum"
else
    echo $CONFIGURATION " build - Not bumping build number."
fi

此脚本会适当地更新 plist 文件,并在我每次存档时反映在 XCode 中。问题是归档过程中产生的 .ipa 文件仍然显示以前的内部版本号。我尝试了以下解决方案但没有成功:

构建前清理 构建前清理构建文件夹 将运行脚本阶段直接移到构建阶段中的目标依赖项步骤之后 在我的方案中将脚本作为运行脚本操作添加为预操作

无论我做什么,当我查看构建日志时,我发现 info.plist 文件正在作为最初的步骤之一进行处理。它总是在我的脚本运行和更新内部版本号之前,我假设这就是为什么内部版本号在 .ipa 文件中永远不会是最新的。

有没有办法强制运行脚本阶段在处理 info.plist 文件之前运行?

【问题讨论】:

我认出了那个脚本的一些片段 ;-) 你还没有说你是如何把这个脚本挂接到构建过程中的吗?您是否编辑过项目方案并添加到Archive 阶段? 【参考方案1】:

在 Xcode 4.4.1 中,我创建新目标并将“运行自定义脚本”添加到此目标构建阶段,这会更新主目标 Plist。此外,您应该将此目标添加到主要目标的依赖项中

【讨论】:

【参考方案2】:

发生这种情况的原因是,当您的“运行脚本”运行时,XCode 构建过程已经处理了项目的 plist 文件以提取捆绑版本号等。

您可以通过转到 XCode 中的日志导航器(查看/导航器/显示日志导航器)并选择“存档”构建来查看这一点(可能更详细)。

构建操作的详细列表应该出现在您的主窗口中,靠近顶部的内容之一应该是名为 Process <projectname>-Info.plist 的内容。如果您使用右侧的图标展开它,您可以看到实际运行的构建命令。

我解决这个问题的方法是更新原始 plist 文件和处理后的文件。通过这样做,您可以在当前构建中获得更新的构建版本,而不是下一个。

这是我用来执行此操作的脚本(这是 Ruby,因此您需要将“/usr/bin/ruby”放入解释器框中才能使用它,但这个概念与 shell 脚本或任何其他脚本语言):

def incrementBundleVersion(file)
    oldVersion = `/usr/libexec/Plistbuddy -c "print :CFBundleVersion" #file`.strip
    components = oldVersion.split('.')
    newBuild = components.pop.to_i + 1
    version = components.push(newBuild).join('.')
    print "Updating version: #oldVersion -> #version : #file\n"
    system("/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion #version\" #file")
end

incrementBundleVersion("#ENV['PROJECT_DIR']/#ENV['INFOPLIST_FILE']")
incrementBundleVersion("#ENV['CODESIGNING_FOLDER_PATH']/Info.plist")

请注意,处理后的文件#ENV['CODESIGNING_FOLDER_PATH']/Info.plist 是二进制 plist 文件,因此您将无法使用简单的文本工具处理它 - 使用 plistbuddy 是处理此问题的最简单方法,它会自动处理文本和二进制 plist 文件。

【讨论】:

【参考方案3】:

Mark (et al),我相信我也遇到了同样的问题,我会试着用一句话来描述它,然后解释:

我认为 /usr/libexec/PlistBuddy 在从 Xcode 内部运行时,可以处理 Info.plist 数据的缓存版本,因此最终编写以在设备或模拟器上执行的内容并不总是您想要的。

我曾尝试写后 Copy Resource Bundle “Run Scripts”,以便以一种不会导致它在我的本地 git repo 中更改的方式更改此信息,只是发现了这一点,而信息会在以下情况下正常工作PlistBuddy 命令在 Xcode 旁边的 terminal.app 窗口中执行,如果不这样做,缓存的值将被写入。

我终于让自己在复制捆绑资源阶段之前运行版本信息生成脚本,并在另一个运行脚本中自动提交更改,对 git 消息和自动获取的 git 标记使用相同的标签-创建。对于 Settings.bundle/Root.plist 文件,而不是每次都提交,我宁愿只运行一个完成脚本来执行“git checkout -- $PROJECT/Resources/Settings.bundle/Root.plist” (这是我存在的地方,但可能不是每个人都放置自己的系统设置资源文件的地方)。

在检查更改、安装时运行部分内容和每次运行部分内容以及最后完成最终脚本之间,一些目标有 6 个脚本,另一个目标有 7 个……

…但对我来说重要的是,它终于正确地自动化了…并且在 Xcode 内部处理时,可以绕过 PlistBuddy 对我的 plist 文件所做的任何事情。

【讨论】:

以上是关于XCode 4.4 捆绑包版本更新直到后续构建才获得的主要内容,如果未能解决你的问题,请参考以下文章

XCode 4.4 iOS 5.1 模拟器问题

此捆绑包无效。 Apple 目前不接受使用此版本 SDK 构建的应用程序

传递 iOS 应用更新时出错。 “此捆绑包无效。Apple 目前不接受使用此版本 SDK 构建的应用程序。”

传递 iOS 应用更新时出错。 “此捆绑包无效。Apple 目前不接受使用此版本 SDK 构建的应用程序。”

捆绑包无效 Mac OS X

xcode更改捆绑标识符以覆盖旧应用程序