我一直在使用shell脚本作为我的Xcode构建过程的一部分来增加 plist 文件中的内部版本号,但是它使Xcode 4.2.1频繁崩溃(关于目标的错误)不属于某个项目;我猜测更改 plist 文件会让Xcode以某种方式混淆。)
shell脚本执行此操作,以便当文件比 plist 文件更新时,内部版本号仅增加agvtool
(因此只是构建时没有增加值):
if [ -n \"`find ProjDir -newer ProjDir/Project-Info.plist`\" ]; then agvtool -noscm next-version -all; else echo \"Version not incremented\"; fi
有没有办法增加不破坏Xcode的内部版本号(在 plist 文件中或其他任何地方)?
最终编辑:我现在使用我刚刚在github公开的python脚本来做这种事情。它没有很好的记录,但不应该很难解决。作为奖励,此repo还包含一个有用的脚本,可自动将第三方库捆绑到应用程序包中。
答案 0 :(得分:69)
我在这个问题上已经搞砸了许多答案,但他们都没有让我满意。然而,我终于想出了一个我非常喜欢的混合物!
有两个步骤,一个在构建阶段,一个在构建阶段结束。
一开始:
# Set the build number to the count of Git commits
buildNumber=$(git rev-list HEAD | wc -l | tr -d ' ')
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
最后:
# Set the build number to "DEVELOPMENT"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion DEVELOPMENT" "${PROJECT_DIR}/${INFOPLIST_FILE}"
查看Xcode中的Info.plist,您会看到版本号是“开发”,但构建的应用程序将具有不断增加的内部版本号。 (只要你总是在同一个分支上进行构建。)
最后将版本号设置回常量字符串可防止通过构建应用程序来更改Info.plist文件。
为什么我喜欢这种方法:
答案 1 :(得分:38)
我使用了这个神奇的怪物并且按照预期的方式工作。 https://gist.github.com/sekati/3172554 (所有功劳归于原作者)
我随时修改的剪贴画。
xcode-versionString-generator.sh,
xcode-build-number-generator.sh
因为这些要点正在帮助开发社区。我想从中做出了github项目。所以让我们把它发展好吧。 这是github项目: https://github.com/alokc83/Xcode-build-and-version-generator
我更新了两个脚本增强的代码。 而不是使用下面的抓取最新的github
版本:
# xcode-version-bump.sh
# @desc Auto-increment the version number (only) when a project is archived for export.
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Build Phases Tab
# 3. Select: Add Build Phase -> Add Run Script
# 4. Paste code below in to new "Run Script" section
# 5. Check the checkbox "Run script only when installing"
# 6. Drag the "Run Script" below "Link Binaries With Libraries"
# 7. Insure your starting version number is in SemVer format (e.g. 1.0.0)
# This splits a two-decimal version string, such as "0.45.123", allowing us to increment the third position.
VERSIONNUM=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${PROJECT_DIR}/${INFOPLIST_FILE}")
NEWSUBVERSION=`echo $VERSIONNUM | awk -F "." '{print $3}'`
NEWSUBVERSION=$(($NEWSUBVERSION + 1))
NEWVERSIONSTRING=`echo $VERSIONNUM | awk -F "." '{print $1 "." $2 ".'$NEWSUBVERSION'" }'`
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $NEWVERSIONSTRING" "${PROJECT_DIR}/${INFOPLIST_FILE}"
对于构建:
# xcode-build-bump.sh
# @desc Auto-increment the build number every time the project is run.
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Build Phases Tab
# 3. Select: Add Build Phase -> Add Run Script
# 4. Paste code below in to new "Run Script" section
# 5. Drag the "Run Script" below "Link Binaries With Libraries"
# 6. Insure that your starting build number is set to a whole integer and not a float (e.g. 1, not 1.0)
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
答案 2 :(得分:29)
如果我理解你的问题,你想要修改Project-Info.plist
文件,它是Xcode标准项目模板的一部分吗?
我问这个的原因是Project-Info.plist
通常处于版本控制之下,修改它意味着它将被标记为,修改好。
如果你没问题,那么下面的代码片段将更新内部版本号并在过程中将文件标记为已修改,其中get_build_number
是某个脚本(即本例中的占位符)以获取(可能递增)您要使用的内部版本号:
#!/bin/sh
# get_build_number is a placeholder for your script to get the latest build number
build_number = `get_build_number`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${build_number}" ProjDir/Project-Info.plist
PlistBuddy允许您在plist文件中设置任何键,而不仅仅是版本号。您可以创建所需的所有plist文件,并在需要时将它们包含在资源中。然后可以从捆绑中读入它们。
至于您需要在关注窗格和其他位置显示版本,您还可以查看设置CFBundleGetInfoString
和CFBundleShortVersionString
。
答案 3 :(得分:14)
我不知道哪种方式最好,但我会发布Apple的答案,万一有人在搜索它......
版本号和内部版本号键分别指定应用程序的营销和内部版本。 agvtool是一个命令行工具,允许您自动将这些数字增加到下一个最高数字或特定数字。
内部版本号标识应用程序的未发布或已发布版本。它作为CFBundleVersion
(Bundle版本)存储在应用程序的Info.plist中。
您必须在Xcode项目中完成以下步骤:
导航到目标的“构建设置”窗格,然后按以下步骤更新所有构建配置:
您的Xcode项目数据文件project.pbxproj包含CURRENT_PROJECT_VERSION
(当前项目版本)构建设置,该设置指定项目的当前版本。 agvtool在project.pbxproj中搜索CURRENT_PROJECT_VERSION
。如果CURRENT_PROJECT_VERSION
存在则继续运行并停止运行,否则。其值用于更新内部版本号。
默认情况下,Xcode不使用任何版本控制系统。将版本控制系统设置为Apple Generic可确保Xcode在项目中包含所有agvtool生成的版本信息。
agvtool在您的应用程序的Info.plist中搜索您的版本和内部版本号。如果它们存在则更新它们,否则不执行任何操作。确保Info.plist中存在CFBundleVersion
(Bundle版本)和CFBundleShortVersionString
(Bundle版本字符串,简称)密钥,如下图所示:
退出Xcode,然后在运行以下任何命令之前导航到终端应用程序中包含.xcodeproj项目文件的目录。 .xcodeproj项目文件包含project.pbxproj,由agvtool使用。 (这是您可以在脚本而不是命令行中运行的部分。)
更新版本号
要将版本号更新为特定版本,请运行
xcrun agvtool new-marketing-version <your_specific_version>
例如:将版本号更新为2.0
xcrun agvtool new-marketing-version 2.0
更新内部版本号
要自动增加内部版本号,请运行
xcrun agvtool next-version -all
要将应用程序的内部版本号设置为特定版本,请运行
xcrun agvtool new-version -all <your_specific_version>
例如:将内部版本号设置为2.6.9
xcrun agvtool new-version -all 2.6.9
<强>加成:强>
要查看当前版本号,请运行
xcrun agvtool what-marketing-version
要查看当前的内部版本号,请运行
xcrun agvtool what-version
答案 4 :(得分:14)
整个条目非常有帮助。我使用了这个技巧但是将我的脚本设置为GIT中的提交后挂钩,因此CFBundleVersion在每次成功提交后都会递增。钩子脚本进入.git / hooks。日志保留在项目目录中。
这符合我最基本的标准。我希望能够从GIT中提取一个版本并重建我以前的确切构建。在构建过程中完成的任何增量都不会这样做。
这是我的剧本:
#!/bin/sh
#
# post-commit
#
# This script increments the CFBundleVersion for each successful commit
#
plist="./XYZZY/XYZZY-Info.plist"
buildnum=$(/usr/libexec/Plistbuddy -c "Print CFBundleVersion" "$plist")
if [ -z "$buildnum" ]; then
exit 1
fi
buildnumplus=$(expr $buildnum + 1)
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnumplus" "$plist"
echo $(date) "- Incremented CFBundleVersion to" $buildnumplus >> hookLog.txt
答案 5 :(得分:11)
FWIW - 这就是我目前用来增加版本号仅用于发布版本(包括存档)。在Xcode 5.1下正常工作。
直接在Xcode中将代码段复制/粘贴到运行脚本构建阶段:
buildnum=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$PRODUCT_SETTINGS_PATH")
if [ "$CONFIGURATION" = "Release" ]; then
buildnum=$((buildnum + 1))
echo "Build number updated to $buildnum"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildnum" "$PRODUCT_SETTINGS_PATH"
fi;
答案 6 :(得分:7)
感谢您的脚本。它很棒。
我的Info.plist位于一个子目录中,其名称中包含空格,因此我必须使用plist路径周围的引号修改Run Script:
${PROJECT_DIR}/tools/bump_build_number.sh "${PROJECT_DIR}/${INFOPLIST_FILE}"
和shell脚本以相同的方式引用所有路径:
#!/bin/sh
if [ $# -ne 1 ]; then
echo usage: $0 plist-file
exit 1
fi
plist=$1
dir=$(dirname "$plist")
# Only increment the build number if source files have changed
if [ -n "$(find "$dir" \! -path "*xcuserdata*" \! -path "*.git" -newer "$plist")" ]; then
buildnum=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$plist")
if [ -z "$buildnum" ]; then
echo "No build number in $plist"
exit 2
fi
buildnum=$(expr $buildnum + 1)
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnum" "$plist"
echo "Incremented build number to $buildnum"
else
echo "Not incrementing build number as source files have not changed"
fi
答案 7 :(得分:6)
我目前使用的脚本非常基于上面的Alix's。我在下面的修改中添加了一个检查,仅对发布/存档构建进行自动增量。
如果没有这种更改,将会出现版本控制冲突,因为每个开发人员都会按照自己的速率增加版本号。事实上,随着内部版本号的不断变化,git历史将受到不必要的污染。
# xcode-build-bump.sh
# @desc Auto-increment Xcode target build number every time the project is archived
# @src stackoverflow.com/a/15483906
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Build Phases Tab
# 3. Select: Add Build Phase -> Add Run Script
# 4. Paste code below in to new "Run Script" section
# 5. Drag the "Run Script" below "Link Binaries With Libraries"
# 6. Insure that your starting build number is set to a whole integer and not a float (e.g. 1, not 1.0)
if [ "Release" != "${CONFIGURATION}" ]
then
exit 0
fi
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
它也可以{更简单地复制和粘贴格式)GitHub gist。
答案 8 :(得分:5)
我建议使用autorevision。
Xcode允许一个头文件(可以在构建时自动生成而不是在自己的vcs中生成)来提供将在构建时在info.plist中展开的值。您可以在autorevision website上找到有关设置的演练。
Autorevision有一个适合这些类型头文件的输出类型,可以帮助解决这些问题。
答案 9 :(得分:4)
您可以使用Apple's generic versioning。基本上您所要做的就是从承载.xcproj文件的目录中调用agvtool next-version -all
。有关详细信息,请查看上面的网址。
答案 10 :(得分:4)
其中一些解决方案的一个问题是Launch Services only recognizes four five major digits in the bundle version。我有一个项目的内部版本号数以千计,所以我想使用一些不太重要的数字。
此Perl脚本会增加项目中的所有Info.plists,而不仅仅是当前目标的Info.plists,因此构建数字都保持锁定状态。它还使用一个补丁数字和两个次要数字,因此build 1234的版本为1.23.4。我将它用作预构建行为,因此它适用于我构建的所有项目。
脚本非常强大,但它对我有用。
#!/usr/bin/perl
use strict;
use warnings;
use v5.12.0;
use Dir::Iterate;
for my $plist_file(grepdir { /-Info.plist$/ } '.') {
my $build = `/usr/libexec/PlistBuddy -c "Print CFBundleVersion" '$plist_file'`;
chomp $build;
next unless $build;
# Strip dots
$build =~ s/\.//g;
$build =~ s/^0//g;
# Increment
$build++;
# Re-insert dots
$build =~ s/^(\d{0,4}?) (\d{0,2}?) (\d{0,1}?)$/$1.$2.$3/x;
# Insert zeroes
$build =~ s{(^|\.)\.}{${1}0.}g;
system qq(/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $build" '$plist_file');
}
答案 11 :(得分:3)
在Wil Gieseler's solution的基础上,我只想做一个改变。他的解决方案将git提交的数量放入构建号。有用,但仍然很难找到创建该构建的实际提交。我不太关心构建号是否单调增加,所以我放弃了这个要求,这样我就可以更轻松地访问生成给定二进制文件的提交。
为此,我将他的第一个脚本修改为以下内容:
# Set the build number to the decimal conversion of the short version of the current git SHA
# Get the short version of the current git SHA in hexadecimal
SHA=$(git rev-parse --short @)
# Uppercase any alphabetic chars in SHA (bc doesn't like lowercase hex numbers)
UPPERCASE_SHA=$(tr '[:lower:]' '[:upper:]' <<< "$SHA")
# Use bc to convert the uppercase SHA from hex to decimal
BUILD_NUM=$(bc <<< "ibase=16;obase=A;$UPPERCASE_SHA")
# Set our build number to that
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BUILD_NUM" "${PROJECT_DIR}/${INFOPLIST_FILE}"
# To convert a build number back to a usable git SHA, run the following, substituting the build number for <build number>
# bc <<< "ibase=10;obase=16;<build number>"
这会将当前git SHA的短版本转换为十进制。十六进制字符不能很好地满足Apple的内部版本号要求,这就是我必须这样做的原因。要将其转换回来,您只需运行以下内容:
SHA=$(bc <<< "ibase=10;obase=16;<build number>")
在bash中,其中<build number>
是您从二进制文件中获取的内部版本号。然后,只需运行git checkout $SHA
,就可以了。
因为这是Wil Gieseler's solution的改编,如上所述,您还需要以下后期构建脚本:
# Set the build number to "DEVELOPMENT"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion DEVELOPMENT" "${PROJECT_DIR}/${INFOPLIST_FILE}"
可以保持你的git历史清洁。
答案 12 :(得分:2)
我觉得自己找到了我的部落。部落,希望您对VersionX感到满意。
十年前,当我在一个包含25个Xcode项目的工作区中工作时,我借此机会将版本自动化并构建字符串更新到某种程度的荒谬,如果您只维护一个或两个项目,偶尔更新。
版本X:
制作起来很有趣。我学到了有关Xcode构建系统的内容。
这是一个花哨的版本类型和版本X可以自动生成的构建字符串的示例。
VersionX 1.0.1β7(c5959a3“干净”)
营销版本: VersionX 1.0.1β7 “ 1.0.1派生自提交标记,而 “ Beta 7”由提交计数或构建计数自动生成(例如)。
内部版本:(c5959a3“干净”) 显示短提交哈希,并通知您构建目录的未提交更改为零。
答案 13 :(得分:2)
我使用最后一个SVN版本来构建编号。如果更改构建目录中的Info.plist,则不会影响源Info.plist:
# use the last SVN revision as the build number:
Info_plist="$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Info.plist"
defaults write "${Info_plist}" CFBundleVersion `svn stat -u | awk '/'"Status against revision:"'/ {print $4}'`
答案 14 :(得分:2)
您可能只想在存档(并上传到TF)时才这样做。 否则你的版本号可能会很快上升..
在方案(产品/编辑方案/存档/预操作)中,您可以添加仅在存档时执行的脚本。
此外,您可能希望每次增加应用版本时重置内部版本号。
最后,如果您使用存档,则可以安全地禁用:
# if [ -n "$(find "$dir" \! -path "*xcuserdata*" \! -path "*.git" -newer "$plist")" ]; then
...
# else
# echo "Not incrementing build number as source files have not changed"
# fi
由于只有在存档 ...
时,内部版本号才会增加 编辑:纠正我所说的,存档中的预操作发生在构建之后(但在存档之前),因此构建编号将为下一个存档增加...但是您可以创建一个新方案并在构建中添加此操作这项新计划的(行动前)部分。当您想要创建新版本时使用此方案答案 15 :(得分:2)
我尝试了修改后的程序但没有用,因为: -
Xcode 4.2.1更改.xcodeproj中的xcuserdata子目录
git注意到Project-Info.plist中的上一个更改
以下修改会导致忽略这些修改并仅标记真正的更改: -
if [ -n "$(find $dir \! -path "*xcuserdata*" \! -path "*.git" -newer $plist)" ]; then
答案 16 :(得分:1)
您可能想要查看我正在开发的名为Xcodebump的新工具。它可以处理更新CFBundleShortVersionString和CFBundleVersion。作为最后一步,它还将签入git并标记提交以匹配那些CFBundle值。
Xcodebump project位于此处:
答案 17 :(得分:1)
我通过以下方法更新build number
。
$INFO_FILE
是plist文件的路径。
$build_number
是此建筑的新版本号。
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $build_number" "${INFO_FILE}"
通常,我的$build_number
由major
和minor
部分组成。
minor
来自项目信息。所以我描述了如何生成major
部分。
## Composed by `major` and `minor`.
## `minor` is parsed from project information. It's another story.
## Examples: `21.1`, or `21.1.3`
build_number="${major_number}.${minor_number}"
我有2个策略来决定$build_number
。
此策略使用git tag
计数来决定major
的{{1}}。如果项目有build number
个标记,则会通过以下shell脚本返回53
。
一般来说,它正在增加。它会迫使开发人员在发布之前添加一个git标签。
53
让Jenkins CI系统决定major_number=$(git tag -l | wc -l | grep -oE "\d+")
部分。它有一个环境变量major
。在CI系统上构建时,它会自动增加。此信息对于跟踪CI系统上的项目历史记录非常有用。
BUILD_NUMBER
答案 18 :(得分:0)
我发现使用Automating Version and Build Numbers Using agvtool最方便。
尝试一下:
<your_app_target>
脚本(第一行是可选的):
exec > ${PROJECT_DIR}/prebuild.log 2>&1
cd ${PROJECT_DIR}
xcrun agvtool next-version -all
cd -
答案 19 :(得分:0)
让我们以苹果自己的方式做到这一点。 每次成功构建后,它将增加内部版本号
我将指导您浏览5张图像,只需浏览一下即可。
当您选择位于Stop_build_button右侧的项目名称时,从下拉列表中选择“ Edit Scheme ...”。 Check First Step
从左侧菜单中展开“构建”选项,然后选择“后操作” Check Second Step
在这里,您可以添加成功构建程序后要执行的所需代码(脚本)。在这里,我们必须添加少量代码以使我们的自动化完美运行。 >> 1.从左侧选择“添加(+)”按钮以添加新的脚本文件>> 2.现在从下拉列表中选择“新建运行脚本操作” Check Third Step
它具有3个字段>> 1.已经为您分配了外壳>> 2.现在用于“从以下位置提供构建设置”中选择您的项目名称。 >> 3.有一个大字段可以添加您的脚本,只需将以下代码复制并粘贴到此处即可:Check Fourth Step
PLIST =“ $ {PROJECT_DIR} / $ {INFOPLIST_FILE}” PLB = / usr / libexec / PlistBuddy LAST_NUMBER = $($ PLB -c“打印CFBundleVersion”“ $ PLIST”) NEW_VERSION = $((($ LAST_NUMBER + 1)) $ PLB -c“设置:CFBundleVersion $ NEW_VERSION”“ $ PLIST”
完成第4步后,只需选择“关闭”以关闭窗口,我们就要做最后一步,在“项目”文件菜单中转到“ plist.info”文件,并确保在“ “键”部分最多包含一个数字值Check Fifth Step
答案 20 :(得分:0)
这是一个更新版本。这适用于Xcode 9.3.1,iOS 11。
点击&#39;构建阶段&#39;从您的应用程序目标中,单击+图标以添加新的运行脚本,然后在框中粘贴此代码。
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
进入Info.plist文件并设置&#39; Bundle版本&#39;到1,以及&#39; Bundle版本字符串,简短&#39;到1,你应该被设置。
在视图中使用Info.plist构建项目,您应该看到Bundle版本(内部版本号)更改。
答案 21 :(得分:0)
这是我的解决方案。 如果你像我一样:终端友好,像ruby,就像语义版本一样,试试这个。
创建一个名为Rakefile
的文件,其中包含以下内容:
require "xcodeproj"
require "versionomy"
XCODEPROJECT = "MyProject.xcodeproj"
INFOPLISTFILE = "MyProject/MyProject-Info.plist"
$UPDATES = [:major,:minor,:tiny]
$UPDATES.each { |part|
desc "increment #{part} part of version"
task "increment:#{part}" do |task|
version=`/usr/libexec/Plistbuddy -c "Print CFBundleVersion" #{INFOPLISTFILE}`.chomp
version=Versionomy.parse(version)
version=version.bump(part)
# I use the same string for CFBundleVersion and CFBundleShortVersionString for now
`/usr/libexec/PlistBuddy -c "Set :CFBundleVersion #{version}" #{INFOPLISTFILE}`
`/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString #{version}" #{INFOPLISTFILE}`
print "version upgraded to #{version}\n"
end
}
准备:gem install xcodeproj versionomy
随时运行:rake increment:major
或rake increment:minor
或rake increment:tiny
。