如何自动设置Watchkit应用程序目标的版本和内部版本号

时间:2015-04-01 20:16:33

标签: ios watchkit apple-watch

Watchkit应用和扩展程序的版本和内部版本号(或版本和简短版本)必须设置为与包含应用程序相同的值。

我使用环境变量在构建时动态设置Info.plist中的应用版本。这也适用于Watchkit扩展,但不适用于Watchkit应用程序。

我使用的环境变量必须在没有${}的主应用和扩展程序的plist中提供(对于变量${VERSION}我设置VERSION)。
如果我为Watchkit应用程序执行相同的操作,它将获取字符串本身,而不是值。如果我提供美元&括号中变量中没有数据。

知道如何设置Watchkit应用程序的变量吗?

9 个答案:

答案 0 :(得分:16)

我用它来更新所有目标:

#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$SRCROOT/Great WatchKit App/Info.plist"

答案 1 :(得分:13)

我的CFBundleVersion是我在git repo上的master分支上的提交次数。

在我的主应用目标上,Build Phases> + New Run Script Phase我已添加此脚本:

# Set the build number to the count of Git commits
buildNumber=$(git rev-list --count HEAD)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$SRCROOT/app WatchKit Extension/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$SRCROOT/app WatchKit App/Info.plist"

app WatchKit App起,app应该是您应用的名称,但请检查确切的路径。

答案 2 :(得分:4)

好吧,如果它不起作用,请使用Run Script Build Phase。做这样的事情:

#!/bin/sh
INFOPLIST="${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
echo "writing to $INFOPLIST"
PLISTCMD="Set :CFBundleVersion $(git rev-list --all|wc -l)"
echo -n "$INFOPLIST" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"

我没有适合您的WatchKit应用程序的路径,因此您必须自己更改。

答案 3 :(得分:4)

stk的答案是对的,但我也希望补充我的发现。

解决问题的一种方法是使用agvtools

OSX>中创建新目标其他>外部构建系统 添加与此类似的运行脚本:

#!/bin/bash

#read vesion number from version.txt in project root
VERSION=$(head -n 1 version.txt)
BUILD=`git rev-list $(git rev-parse --abbrev-ref HEAD) | wc -l | awk '{ print $1 }'`

echo "${VERSION} (${BUILD})"

agvtool new-marketing-version ${VERSION}
agvtool new-version -all ${BUILD}

exit 0

我有一个version.txt文件,其中只有我的版本号(营销版短包版),可以通过任何CI系统轻松调整并使用我的git SHA数作为内部版本号(捆绑版本) 调整VERSIONBUILD的来源以满足您的要求

在构建/存档之前运行为新目标创建的方案。

如果您需要将此作为主目标的依赖项 - 这将失败,因为它将停止执行以下目标(如果有人知道如何防止这种情况,我会感谢提示)< / p>

但你仍然可以通过为每个plist执行以下脚本来实现这一点(类似于stk提供的内容):

#!/bin/sh
#
# usage:
# set-version-in-plist.sh LIST VERSION BUILD
# LIST:      Info.plist path & name
# VERSION:   version number xxx.xxx.xxx
# BUILD:     build number xxxxx
#

# Location of PlistBuddy
PLISTBUDDY="/usr/libexec/PlistBuddy"

${PLISTBUDDY} -c "Set :CFBundleShortVersionString $2" "$1";
${PLISTBUDDY} -c "Set :CFBundleVersion $3" "$1";

将此脚本另存为文件,使其可执行(chmod +x SCRIPTNAME) 然后使用所有plist的上述参数执行它

此解决方案不如agvtools解决方案方便,但在依赖项中使用时不应停止构建...

答案 4 :(得分:4)

您可以在没有构建脚本的情况下更新所有目标的构建版本。 (您也可以使用它来更新营销/短版本版本;在这种情况下,忽略对CFBundleVersion的更改)。

打开项目设置并将CURRENT_PROJECT_VERSION(当前项目版本)设置为所需的版本号。在所有目标中,sur CURRENT_PROJECT_VERSION为空(以便其值从项目继承)。然后在所有Info.plist文件中将CFBundleShortVersionString(Bundle versions string,short)和CFBundleVersion(Bundle version / build version)设置为$(CURRENT_PROJECT_VERSION)。

如果你想在每个版本上增加你的CFBundleVersion(或者让它反映你的git SHA)。如doggod所述使用agvtool或参见https://developer.apple.com/library/ios/qa/qa1827/_index.html

答案 5 :(得分:3)

如果用我个人的经验补充其他答案会有用。这些以ValidateEmbeddedBinary引起的构建失败为中心。

如果ValidateEmbeddedBinary在嵌入式WatchKit应用和父应用中不相同,

CFBundleVersion将会失败。

错误类似于:

  

(null):error:WatchKit应用程序中CFBundleVersion的值   Info.plist(1234)与您的随播广告应用中的值不匹配   Info.plist(7931)。这些值必须匹配。

在XCode 7.3中工作,以下内容将首先更新父应用程序的plist。然后它会在执行PBXCp之前更新Debug或Release WatchKit应用程序,以将其复制到父app目录:

#!/bin/sh

git=`sh /etc/profile; which git`
appBuild=`"$git" rev-list HEAD --count`

appPlistPath="${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
watchKitPlistPath="${BUILT_PRODUCTS_DIR}/../${CONFIGURATION}-watchos/${PRODUCT_NAME} WatchKit App.app/Info.plist"

echo "Setting App CFBundleVersion $appBuild at info plist path at ${appPlistPath}"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $appBuild" "${appPlistPath}"

echo "Setting WatchKit App CFBundleVersion $appBuild at ${watchKitPlistPath}"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $appBuild" "${watchKitPlistPath}"

以上使用git的提交计数为CFBundleVersion

答案 6 :(得分:2)

我有一个运行脚本,我附加到我的主应用目标。它将在构建应用程序时传播WatchKit扩展和WatchKit应用程序。

完全可以重复使用。享受!

buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")

buildNumberDec=$(($buildNumber + 1))

/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumberDec" "${PROJECT_DIR}/${INFOPLIST_FILE}"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumberDec" "$SRCROOT/${PRODUCT_NAME} WatchKit Extension/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumberDec" "$SRCROOT/${PRODUCT_NAME} WatchKit App/Info.plist"

答案 7 :(得分:1)

要扩展此主题,如果有人遇到与我类似的问题,希望下面的脚本会有所帮助。

例如,我在项目中有观看目标,观看扩展程序,应用程序共享扩展程序。

我按照建议使用运行阶段来更新项目的plist,如果我构建项目,它会起作用,.plist文件都按预期更新。

然而,问题是当您归档应用程序时(假设所有目标具有不同的内部版本号),归档项目中的信息plist未更新。 经过几次试用后,我发现扩展的plist文件在此运行阶段之前被复制,然后运行阶段脚本(更新项目的plist)将无法帮助存档的plist。 所以我最终更改了脚本以更新已编译目标的plist,它按预期工作,我对应用程序中的所有目标都有相同的内部版本号。 我是这样做的: 将此脚本添加到每个目标的构建阶段:

infoPlistPath="${TARGET_BUILD_DIR}/${EXECUTABLE_FOLDER_PATH}/Info.plist"
PLISTBUDDY="/usr/libexec/PlistBuddy"
buildNumber=$(git rev-list HEAD | wc -l | tr -d ' ')
$PLISTBUDDY -c "Set :CFBundleVersion $buildNumber" "${infoPlistPath}"

对于不同的目标,这个EXECUTABLE_FOLDER_PATH是不同的,它将更新编译目标的信息plist,而不是项目的信息plist。 只是一个注意事项我检查了“仅在安装时运行脚本”,因为我只需要将其运行以进行存档

答案 8 :(得分:0)

您还可以简单地将相同的构建阶段添加到目标的每个中。

#Update build number with number of git commits if in release mode
if [ ${CONFIGURATION} == "Release" ]; then
buildNumber=$(git rev-list HEAD | wc -l | tr -d ' ')
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
fi;

因此,如果您有Watch App,Watch App Extension,Widget扩展或其他任何扩展,请转到其每个构建阶段,添加一个 New Run Script Phase 并粘贴以上内容