如何阻止Xcode 11将CFBundleVersion和CFBundleShortVersionString更改为$(CURRENT_PROJECT_VERSION)和$(MARKETING_VERSION)?

Mr.*_*tem 10 info.plist xcode11

从版本11开始,每当我在目标设置(选项卡“常规”)中输入“版本”或“构建”值时,Xcode就会将我的CFBundleVersion值设置为,$(CURRENT_PROJECT_VERSION)并将我CFBundleShortVersionString的值$(MARKETING_VERSION)设置为。

我输入的实际版本和构建值现在存储在project.pbxproj文件中。我不希望或不喜欢这种行为,因为我在构建时使用shell脚本来修改值。

我可以在Info.plist文件中手动设置正确的值,但是一旦在目标设置中更改了版本号或内部版本号,Xcode就会再次更改Info.plist文件。

如何停止Xcode 11执行此操作?

当我修改构建脚本以更改项目文件本身时,Xcode将在更改项目文件后立即取消构建。

KoC*_*BTa 5

到目前为止的路

我的用例是:

  1. 我正在同步版本并跨多个目标构建数字。
  2. 我正在同步版本和构建数字与目标的 Settigns.bundle
  3. 我正在从 CI 服务器读取和修改内部版本号。

我曾经将第 1 点和第 2 点作为目标构建脚本执行,将第 3 点作为 CI 本身的自定义脚本执行。

在 Xcode 构建设置中存储版本和构建的新方法导致脚本出现问题,因为它们不再能够有效地修改值。至少阅读是可能的。

不幸的是,我无法找到阻止 Xcode 将版本和构建编号存储到项目构建设置中的合法方法,但是我设法创建了一个解决方法。

事实证明,在进行构建或存档时,Info.plist会使用写入的值。这意味着该值在构建期间被替换,这不允许我们在同一构建时间内修改它。

我还尝试使用xcodeprojcli修改项目,但是对项目的任何更改都会导致任何构建停止,因此该解决方案不起作用。

最终,在我尝试了很多不同的方法之后,我终于找到了一个不违反 Xcode 新行为的折衷方案。

简答:

作为目标预操作,执行一个脚本,该脚本将相应的值写入CFBundleShortVersionString和写入CFBundleVersion目标的Info.plist

作为事实来源,我使用 Xcode 构建设置来读取所需目标的值MARKETING_VERSION和值CURRENT_PROJECT_VERSION

这样,当您修改项目设置中的值时 - 在下一次构建/归档时 - 它们将被写入 . Info.plist,允许任何现有的脚本逻辑继续工作。

详细解答

根据构建操作修改资源的唯一方法是使用pre-action脚本。如果您尝试从构建脚本执行此操作 - 更改不会立即生效,并且不会在构建/存档结束时出现。

为了添加预构建操作 - 转到编辑方案。

在此处输入图片说明

然后展开构建和存档部分。在 下Pre-action,单击Provide build and settings from下拉菜单并选择您希望从中读取值的真实来源目标。

在此处输入图片说明

添加以下脚本:

# 1) 
cd ${PROJECT_DIR}

# 2) 
exec > Pruvit-Int.prebuild.sync_project_version_and_build_with_info_plists.log 2>&1

# 3) 
./sync_project_version_and_build_with_info_plists.sh $MARKETING_VERSION $CURRENT_PROJECT_VERSION
Run Code Online (Sandbox Code Playgroud)

记录行执行以下操作:

  1. 转到同步脚本所在的目录以执行它
  2. 允许在预操作期间写入日志,否则默认情况下任何输出都将静音
  3. 通过提供MARKETING_VERSION和执行同步脚本CURRENT_PROJECT_VERSION

最后一步是编写您自己的同步脚本,该脚本读取所提供的值MARKETING_VERSIONCURRENT_PROJECT_VERSION相应的目标/s 以及您需要的任何其他时间。

在我的情况下,脚本如下:

#!/bin/bash

#IMPORTANT - this script must run as pre-action of each target's Build and Archive actions

version_number=$1
build_number=$2

echo "version_number is $version_number"
echo "build_number is $build_number"

#update Pruvit/Info.plist
pruvitInfoPlist="Pruvit/Info.plist"
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $version_number" $pruvitInfoPlist
/usr/libexec/PlistBuddy -c "Set CFBundleVersion $build_number" $pruvitInfoPlist

#update Pruvit/Settings.bundle
settingsPlist="Pruvit/Settings.bundle/Root.plist"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version_number" $settingsPlist
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $build_number" $settingsPlist

#update BadgeCounter/Info.plist
badgeCounterInfoPlist="BadgeCounter/Info.plist"
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $version_number" $badgeCounterInfoPlist
/usr/libexec/PlistBuddy -c "Set CFBundleVersion $build_number" $badgeCounterInfoPlist
Run Code Online (Sandbox Code Playgroud)

我在我的两个应用程序目标之间使用共享Info.plistSettings.bundle,所以我必须更新一次。

我还使用了通知服务扩展BadgeCounter,它必须具有完全相同的版本并构建为嵌入它的目标。所以我也更新了这个。