Xcode项目的“Build number”

31

什么是构建号,它有什么用途?它和版本号是一样的吗?


2
根据@cdashers的代码,我添加了一个简单的脚本到Github供大家使用。https://github.com/rbosch/Xcode-BuildNumber - Roger
9个回答

20

另外,如果你将CFBuildDate作为字符串和CFBuildNumber作为字符串添加到你的info.plist中,以下shell脚本(当添加到你的运行脚本编译阶段/bin/bash时)将自动更新你的构建号码和日期:

    # Auto Increment Version Script
buildPlist=${INFOPLIST_FILE}
CFBuildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBuildNumber" $buildPlist)
CFBuildNumber=$(($CFBuildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBuildNumber $CFBuildNumber" $buildPlist
CFBuildDate=$(date +%Y%m%d%H%M%S)
/usr/libexec/PlistBuddy -c "Set :CFBuildDate $CFBuildDate" $buildPlist

1
在Xcode 4中,我将CFBuildNumber更改为CFBundleVersion,以便数字显示在目标摘要编辑器的“构建”字段中。 - Ross
3
我将把CFBuildNumber在plist文件中的递增改为设置CFBundleVersion为buildNum=\git log --oneline | wc -l``,从Git中获取一个构建标识符。 - Kenny Winker
1
@KennyWinker 最好使用 git rev-list HEAD --count - pronebird
当我将CFBuildDate设置为字符串时,存储的是空字符串。当我将CFBuildDate设置为Rogier建议的日期格式时,日期被保存,但它不会被下一次构建覆盖 - 它只显示第一个构建日期 - 是否有人遇到了相同的问题? - Lukasz 'Severiaan' Grela
嗯?为什么这个答案开头是“另外”?它如何回答这个问题? - Mark Amery
显示剩余2条评论

17

我正在使用Xcode 4.3.3 (4E3002),成功实现了以下步骤以在每次构建时自动递增版本号(CFBundleVersion):

  1. 选择菜单项Product/Edit Scheme... (Command+<)
  2. 展开Build阶段
  3. 选择Pre-actions
  4. 点击加号添加"New Run Script Action"
  5. 将"Shell"设置为"/bin/bash"
  6. 从"Provide build settings from"中选择一个目标
  7. 输入以下代码:

    buildPlist=$SRCROOT/$INFOPLIST_FILE
    PlistBuddy="/usr/libexec/PlistBuddy"
    
    CFBundleVersion=`$PlistBuddy -c "Print CFBundleVersion" $buildPlist`
    CFBundleVersion=$(($CFBundleVersion + 1))
    $PlistBuddy -c "Set :CFBundleVersion $CFBundleVersion" $buildPlist
    

玩得开心!


哇!!!这对我的问题来说太完美了:自动增加CFBundleVersion并通过代码检索它而不会出现奇怪的行为... +1和非常感谢!!! - Giuseppe Garassino
在 OS X 10.8 上的 XCode 4.5 中,我发现 $SRCROOT/$INFOPLIST_FILE 不起作用,而 $INFOPLIST_FILE 是可以的。 - helioz

13

很多人使用构建号来跟踪项目“构建”的总次数(对于小型项目仅编译,对于较大的项目可能涉及一些更复杂的过程)。

构建号是每次构建时递增的绝对值。另一方面,版本号是一个任意的“标签”或“标记”,用作特定构建号的简写。

例如,假设您已经构建了123次项目,您的构建号为“123”,但为了便于理解,您可能决定将其称为“1.0版本”。如果您再建立20次以修复错误,则您的构建号为143,而您的版本号为“1.01”或“1.1”或您决定命名的任何内容。

我也看到一些项目将其构建号基于源代码控制。因此,CVS/SVN团队可能使用修订号作为其构建号。我也见过使用最新提交的SHA作为构建号的git项目(尽管一些管理工具假定构建号是递增的值 - 显然,在SHA的情况下,它不是)。


你是否有一个构建阶段脚本,用于将“CFBundleVersion”设置为当前SVN修订版本? - jowie
这应该是被接受的答案,因为它实际上回答了OP的问题。 - Desmond
同意,这就是我正在寻找的答案,并回答了问题。 - Zenman C

5
构建号是一个内部编号,表示应用程序的当前状态。 它与版本号不同,通常不面向用户,并且不像版本号通常会标示任何差异/功能/升级。
可以这样想:
- 构建(CFBundleVersion):构建的数字。通常您从1开始,并随着每个应用程序的构建而增加1。它可以快速比较哪个构建更近期,并表示代码库的进展状态。当与QA一起工作并需要确保错误记录在正确的构建中时,这些可以非常有价值。 - 市场版本(CFBundleShortVersionString) - 用户界面数字,用于表示您的应用程序的此版本。通常,这遵循主要.次要版本方案(例如MyAwesomeApp 1.2),以让用户知道哪些发布是较小的维护更新,哪些是新功能。
为了在项目中有效使用它,Apple提供了一个名为agvtool的绝佳工具。它允许您轻松设置构建号和市场版本。在脚本编写时特别有用(例如,在每个构建中轻松更新构建号甚至查询当前构建号时)。它甚至可以执行更多奇特的操作,例如在更新构建号时为您标记SVN。
使用方法如下:
- 在Xcode中将项目设置为“Apple Generic”版本控制。 - 在终端中: - agvtool new-version 1(将构建号设置为1) - agvtool new-marketing-version 1.0(将市场版本设置为1.0)
有关大量好信息,请参见agvtool的手册页面

我必须确保的一件事情是,也许使用 avgtool new-version 可以做到这一点,那就是如果你想让 agvtool 设置 CFBundleVersion(“摘要”选项卡中的“构建”或“信息”选项卡中的“Bundle Version”),并且你想让它设置 CURRENT_PROJECT_VERSION,那么它们两个都必须已经定义为某些值。否则,agvtool 将不会设置它们。 - devguydavid

4

构建号用于小型更新(通常从1开始逐渐增加到1000),例如:如果您在更新中更改了几行代码但未更改逻辑或添加新功能。版本号用于较大的更新,例如:应用程序中的新功能。然后您可以将其从1.8更改为2.0。


4
如果你想使用一个日期字段作为CFBuildDate,那么请使用:
# get UTC date
CFBuildDate=$(date -u +"%a %b %d %T GMT %Y")

顺便说一句,cdasher给出了一个很棒的技巧


2

这个在Xcode 6中对我有效:

cd ${SOURCE_ROOT}
buildPlist=${SOURCE_ROOT}/${PROJECT_NAME}/${PROJECT_NAME}-Info.plist
PlistBuddy="/usr/libexec/PlistBuddy"

buildNumber=`git rev-list HEAD --count`
buildNumber=$(($buildNumber + 1))

$PlistBuddy -c "Set :CFBundleVersion $buildNumber" $buildPlist

当PROJECT_NAME或SOURCE_ROOT包含空格时,无法正常工作,请参见我的改进答案。 - edwardmp
只有在删除第一行并将第二行替换为 buildPlist=${INFOPLIST_FILE} 后,此方法才对我有效。 - Mohannad A. Hassan

2

这个方法适用于Xcode 6,只有在归档时才会修改dSYM信息字典:

if [ "${CONFIGURATION}" = "Release" ]; then

buildPlist="${SOURCE_ROOT}/${PROJECT_NAME}/${PROJECT_NAME}-Info.plist"

PlistBuddy="/usr/libexec/PlistBuddy"

CFBundleVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}")
CFBundleVersion=$(($CFBundleVersion + 1))

$PlistBuddy -c "Set :CFBundleVersion $CFBundleVersion" "$buildPlist"
$PlistBuddy -c "Set :CFBundleVersion $CFBundleVersion" "$INFOPLIST_FILE"
$PlistBuddy -c "Set :CFBundleVersion $CFBundleVersion" "${DWARF_DSYM_FOLDER_PATH}/${WRAPPER_NAME}.dSYM/Contents/Info.plist"
fi

一条评论就足够了,没有必要新建一个回答去添加引用。 - trojanfoe
我无法将此整齐地粘贴在评论中,当换行符被剥离时,可读性较差。 - edwardmp
我修改了一些其他的东西。 - edwardmp
有一种更简单的方法:创建一个构建目标并使用它来运行原始脚本以修改 Info.plist 文件。然后使正常的 Xcode 项目目标依赖于这个新的脚本目标。这将避免你试图避免的问题。这在 Xcode 4.2 早期就被使用了,如果你使用 Build Phase 脚本来搞乱 Info.plist,Xcode 4.2 将会崩溃。相关 - trojanfoe
这篇博客文章是2014年的,所以我怀疑它只在Xcode 4.2及更早版本中才是必需的... - edwardmp
@edwardmp,我猜测dsym是在编译期间生成的。假设这个脚本是在编译后运行的,那么dsym包的构建号码不会比实际版本高一位吗? - Electro-Bunny

1

CFBundleVersion (Bundle版本) - 也称为营销版本,将显示在您的产品在Appstore上的页面上。

CFBundleShortVersionString (Bundle版本字符串, 简短版) - Bundle号码,通常作为次要版本,只能由TestFlight用户看到

以下是如何在Swift (4+)中以编程方式获取它们:

let buildNumber = Bundle.main.infoDictionary?[kCFBundleVersionKey as String] as? String,
let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")

我曾经需要在我的shell脚本中使用营销版本,以下是我使用xcode构建工具获取它的方法:

xcodebuild -showBuildSettings -project ${SDK_PROJECT} | sed '1d;s/^ *//;s/"/\\"/g;s/ = \(.*\)/="\1"/;s/ = /=/;s/UID.*//' > xcodebuild-env.tmp
source xcodebuild-env.tmp

echo "${MARKETING_VERSION}"

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