xcode 增加内部版本号的更好方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9258344/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 04:14:08  来源:igfitidea点击:

Better way of incrementing build number?

xcodeshellversionxcrunagvtool

提问by trojanfoe

I have been using a shell script as part of my Xcode build process to increment the build number within the plistfile, however it's making Xcode 4.2.1 crash frequently (with an error about the target not belonging to a project; I'm guessing the changing of the plistfile is confusing Xcode in some way).

我一直在使用 shell 脚本作为我的 Xcode 构建过程的一部分来增加plist文件中的构建号,但是它使 Xcode 4.2.1 频繁崩溃(关于目标不属于项目的错误;我猜plist文件的更改在某种程度上使 Xcode 感到困惑)。

The shell script did this so that the build number is only incremented by agvtoolwhen a file is newer than the plistfile (so just building didn't increment the value):

shell 脚本这样做是为了使构建号仅agvtool在文件比plist文件更新时才增加(因此仅构建不会增加值):

if [ -n \"`find ProjDir -newer ProjDir/Project-Info.plist`\" ]; then agvtool -noscm next-version -all; else echo \"Version not incremented\"; fi

Is there a way to increment the build number (in the plistfile, or anywhere else) that doesn't break Xcode?

有没有办法增加不会破坏 Xcode的内部版本号(在plist文件中或其他任何地方)?

FINAL EDIT: I now do this kind of stuff using a python script which I have just made public on github. It's not well documented but shouldn't be difficult to work out. As a bonus this repo also contains a useful script to automatically bundle 3rd party library into an app bundle.

最终编辑:我现在使用刚刚在github 上公开的 python 脚本来做这种事情。它没有很好的记录,但应该不难解决。作为奖励,这个 repo 还包含一个有用的脚本,用于将 3rd 方库自动捆绑到应用程序包中。

采纳答案by Monolo

If I understand your question correctly, you want to modify the Project-Info.plistfile, which is a part of the standard project template of Xcode?

如果我正确理解你的问题,你想修改Project-Info.plist文件,它是 Xcode 标准项目模板的一部分?

The reason I ask this is that Project-Info.plistnormally is under version control, and modifying it means that it will be marked as, well, modified.

我问这个的原因是Project-Info.plist通常是在版本控制下,修改它意味着它将被标记为,好吧,修改。

If that is fine with you, then the following snippet will update the build number and mark the file as modified in the process, where get_build_numberis some script (i.e., a placeholder in this example) to get the (possibly incremented) build number that you want to use:

如果这对您没问题,那么以下代码段将更新内部版本号并将文件标记为在此过程中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 allows you to set any key in a plist file, not just the version number. You can create all the plist files you want, and include them in the resources if needed. They can then be read in from the bundle.

PlistBuddy 允许您在 plist 文件中设置任何键,而不仅仅是版本号。您可以创建所需的所有 plist 文件,并在需要时将它们包含在资源中。然后可以从包中读入它们。

As to your need to show the version in the about pane and other places, you can also look into setting CFBundleGetInfoStringand CFBundleShortVersionString.

至于您需要在关于窗格和其他地方显示版本,您还可以查看设置CFBundleGetInfoStringCFBundleShortVersionString.

回答by Wil Gieseler

I've messed around with a lot of the answers on this question, and none of them quite satisfied me. However, I finally came up with a mixture that I really like!

关于这个问题,我已经弄乱了很多答案,但没有一个让我满意。然而,我终于想出了一种我非常喜欢的混合物!

There are two steps, one at the beginning and one at the end of your build phases.

有两个步骤,一个在构建阶段的开始,一个在构建阶段的结束。

At the beginning:

一开始:

# Set the build number to the count of Git commits
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

At the end:

在末尾:

# Set the build number to "DEVELOPMENT"
if [ "${CONFIGURATION}" = "Release" ]; then
    /usr/libexec/PlistBuddy -c "Set :CFBundleVersion DEVELOPMENT" "${PROJECT_DIR}/${INFOPLIST_FILE}"
fi

Looking at the Info.plist in Xcode you'll see the version number is "DEVELOPMENT", but the built app will have a constantly increasing build number. (As long as you always do your builds off the same branch.)

查看 Xcode 中的 Info.plist,您会看到版本号是“DEVELOPMENT”,但构建的应用程序的版本号会不断增加。(只要你总是在同一个分支上进行构建。)

Setting the version number back to a constant string at the end prevents the Info.plist file from being changed by building the app.

最后将版本号设置回常量字符串可防止通过构建应用程序更改 Info.plist 文件。

Why I like this method:

为什么我喜欢这种方法:

  • Easy
  • Doesn't pollute Git version history
  • CFBundleVersion is totally automatic
  • The pretty version number can be modified whenever I want
  • 简单
  • 不污染 Git 版本历史
  • CFBundleVersion 是完全自动的
  • 漂亮的版本号可以随时修改

回答by Alix

I have used this glist. It works as expected. https://gist.github.com/sekati/3172554(all credit goes to the original author)

我用过这个 glist。它按预期工作。 https://gist.github.com/sekati/3172554(所有功劳归原作者所有)

Scripts that I modified over time.

我随着时间修改的脚本。

xcode-versionString-generator.sh,

xcode-versionString-generator.sh,

xcode-build-number-generator.sh

xcode-build-number-generator.sh

As these gist are helping the dev community, I made GitHub project out of it. So let's develop it well. Here is the GitHub project: https://github.com/alokc83/Xcode-build-and-version-generator

由于这些要点正在帮助开发社区,因此我制作了 GitHub 项目。所以让我们好好开发它。这是 GitHub 项目:https: //github.com/alokc83/Xcode-build-and-version-generator

I have updated the code for both script little bit of enhancement. instead of using below grab the latest from GitHub

我已经更新了两个脚本的代码,进行了一点点增强。而不是使用下面从 GitHub 获取最新信息

For Version :

对于版本:

# 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 }'`
NEWSUBVERSION=$(($NEWSUBVERSION + 1))
NEWVERSIONSTRING=`echo $VERSIONNUM | awk -F "." '{print  "."  ".'$NEWSUBVERSION'" }'`
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $NEWVERSIONSTRING" "${PROJECT_DIR}/${INFOPLIST_FILE}"

For build:

对于构建:

# 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 into new "Run Script" section
# 5. Drag the "Run Script" below "Link Binaries With Libraries"
# 6. Ensure 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}"

回答by LostInTheTrees

This whole entry was extremely helpful. I used this trick but set up my script as a post-commit hook in GIT, so CFBundleVersion is incremented after every successful commit. The hook script goes in .git/hooks. A log is left in the project directory.

整个条目非常有帮助。我使用了这个技巧,但将我的脚本设置为 GIT 中的提交后挂钩,因此每次成功提交后 CFBundleVersion 都会增加。钩子脚本在 .git/hooks 中。项目目录中会留下一个日志。

This meets my most basic criterion. I want to be able to pull a version from GIT and rebuild the exact build I had previously. Any increment done during the build process does not do this.

这符合我最基本的标准。我希望能够从 GIT 中提取一个版本并重建我以前的确切版本。在构建过程中完成的任何增量都不会这样做。

Here is my script:

这是我的脚本:

#!/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

回答by FormigaNinja

I don't know which way is the best, but I will post Apple's answer just in case anybody is searching for it...

我不知道哪种方式最好,但我会发布 Apple 的答案,以防万一有人在寻找它...

According to this Apple's Q&A post:

根据这个苹果的问答帖子

Automating Version and Build Numbers Using agvtool

使用 agvtool 自动化版本和内部版本号

The version and build number keys respectively specify the marketing and internal versions of your application. agvtool is a command-line tool that allows you to automatically increment these numbers to the next highest number or to a specific number.

version 和 build number 键分别指定应用程序的营销和内部版本。agvtool 是一个命令行工具,允许您自动将这些数字递增到下一个最高数字或特定数字。

The build number identifies an unreleased or released version of your application. It is stored in your application's Info.plist as CFBundleVersion(Bundle version).

内部版本号标识应用程序的未发布或已发布版本。它作为CFBundleVersion(捆绑版本)存储在应用程序的 Info.plist 中。

You must complete the following steps in your Xcode project:

您必须在 Xcode 项目中完成以下步骤:

  1. Enable agvtool
  1. 启用 agvtool

Navigate to the Build Settings pane of your target, then update it for all your build configurations as follows:

导航到目标的 Build Settings 窗格,然后为所有构建配置更新它,如下所示:

  • Set Current Project Version to a value of your choosing.
  • 将当前项目版本设置为您选择的值。

Your Xcode project data file, project.pbxproj, includes a CURRENT_PROJECT_VERSION(Current Project Version) build setting, which specifies the current version of your project. agvtool searches project.pbxproj for CURRENT_PROJECT_VERSION. It continues running if CURRENT_PROJECT_VERSIONexists and stops running, otherwise. Its value is used to update the build number.

您的 Xcode 项目数据文件 project.pbxproj 包含一个CURRENT_PROJECT_VERSION(当前项目版本)构建设置,用于指定项目的当前版本。agvtool 在 project.pbxproj 中搜索CURRENT_PROJECT_VERSION. 如果CURRENT_PROJECT_VERSION存在则继续运行,否则停止运行。它的值用于更新内部版本号。

  • Set Versioning System to Apple Generic.
  • 将版本系统设置为 Apple 通用。

By default, Xcode does not use any versioning system. Setting Versioning System to Apple Generic ensures that Xcode will include all agvtool-generated version information in your project.

默认情况下,Xcode 不使用任何版本控制系统。将 Versioning System 设置为 Apple Generic 可确保 Xcode 将在您的项目中包含所有 agvtool 生成的版本信息。

Set Versioning System to Apple Generic

将版本系统设置为 Apple 通用

  1. Set up your version and build numbers
  1. 设置您的版本和版本号

agvtool searches your application's Info.plist for your version and build numbers. It updates them if they exist and does nothing, otherwise. Make sure that the CFBundleVersion(Bundle version) and CFBundleShortVersionString(Bundle versions string, short) keys exist in your Info.plist as seen in the image below:

agvtool 在你的应用程序的 Info.plist 中搜索你的版本和内部版本号。如果它们存在,它会更新它们,否则什么都不做。确保CFBundleVersion(Bundle version) 和CFBundleShortVersionString(Bundle versions string, short) 键存在于您的 Info.plist 中,如下图所示:

Set up your version and build numbers

设置您的版本和版本号

Quit Xcode, then navigate to the directory containing your .xcodeproj project file in the Terminal application before running any of the following commands. The .xcodeproj project file contains project.pbxproj, which is used by agvtool. (This is the part you can run in a script instead of command line.)

退出 Xcode,然后在运行以下任何命令之前导航到终端应用程序中包含 .xcodeproj 项目文件的目录。.xcodeproj 项目文件包含 project.pbxproj,由 agvtool 使用。(这是您可以在脚本而不是命令行中运行的部分。)

Updating the Version Number

更新版本号

To update the version number to a specific version, run

要将版本号更新为特定版本,请运行

xcrun agvtool new-marketing-version <your_specific_version>

Ex:Update the version number to 2.0

例如:将版本号更新为 2.0

xcrun agvtool new-marketing-version 2.0

Updating the Build Number

更新内部版本号

To automatically increment your build number, run

要自动增加内部版本号,请运行

xcrun agvtool next-version -all

To set the build number of your application to a specific version, run

要将应用程序的内部版本号设置为特定版本,请运行

xcrun agvtool new-version -all <your_specific_version>

Ex:Set the build number to 2.6.9

例如:将内部版本号设置为 2.6.9

xcrun agvtool new-version -all 2.6.9

Bonus:

奖金:

To view the current version number, run

要查看当前版本号,请运行

xcrun agvtool what-marketing-version

To view the current build number, run

要查看当前版本号,请运行

xcrun agvtool what-version

回答by Jay

FWIW - this is what I'm currently using to increase the build number only for release builds(which includes archiving). Works fine under Xcode 5.1.

FWIW - 这是我目前用于增加仅用于发布版本(包括存档)的版本号的方法。在 Xcode 5.1 下工作正常。

Just copy/paste the snippet into a Run scriptbuild phase directly in Xcode:

只需直接在 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;

回答by massimobio

Thanks for the script. It works great.

谢谢你的剧本。它工作得很好。

My Info.plist is in a subdirectory with a name containing spaces so I had to modify the Run Script with quotes around the plist path:

我的 Info.plist 位于一个名称包含空格的子目录中,因此我不得不在 plist 路径周围用引号修改运行脚本:

${PROJECT_DIR}/tools/bump_build_number.sh "${PROJECT_DIR}/${INFOPLIST_FILE}"

and the shell script in the same way with quotes around all the paths:

和 shell 脚本以相同的方式在所有路径周围加上引号:

#!/bin/sh

if [ $# -ne 1 ]; then
    echo usage: 
# 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}"
plist-file exit 1 fi plist= 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

回答by Matthew

The script I'm currently using is very much based on Alix's, above. My adaptation, below, adds a check to only do the auto-increment on a release/archive build.

我目前使用的脚本很大程度上基于上面Alix 的。我的改编,在下面,添加了一个检查,只在发布/存档构建上进行自动增量。

Without that change there will be version control conflicts as each developer will be incrementing the build number at their own rate. And the fact that the git history would be unnecessarily polluted with the build number changing all the time.

如果没有这种变化,就会出现版本控制冲突,因为每个开发人员都会以自己的速度增加内部版本号。事实上,随着构建号一直在变化,git 历史会被不必要地污染。

#!/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}?)$/../x;

    # Insert zeroes
    $build =~ s{(^|\.)\.}{0.}g;

    system qq(/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $build" '$plist_file');
}

It's also available (in a slightly easier to copy and paste format) as a GitHub gist.

它也可以作为GitHub gist使用(以稍微容易复制和粘贴的格式)。

回答by dak180

I would recommend the use of autorevision.

我会推荐使用autorevision

Xcode allows for a header file (which can be auto generated at build time and not in the vcs its self) to provide values that will be expanded in the info.plist at build time. You can find a walkthrough for setting this up on the autorevision website.

Xcode 允许一个头文件(它可以在构建时自动生成,而不是在它自己的 vcs 中)来提供将在构建时在 info.plist 中扩展的值。您可以在autorevision 网站上找到有关设置的演练。

Autorevision has an output type geared towards these types header files to help in exactly these situations.

Autorevision 具有针对这些类型的头文件的输出类型,以在这些情况下提供帮助。

回答by Brent Royal-Gordon

One issue with some of these solutions is that Launch Services only recognizes fourfive major digits in the bundle version. I have a project with a build number that's in the thousands, so I wanted to use some of the less significant digits.

其中一些解决方案的一个问题是Launch Services 只能识别捆绑版本中的四个五个主要数字。我有一个项目的内部版本号数以千计,所以我想使用一些不太重要的数字。

This Perl script increments all Info.plists in the project, not just the one for the current target, so the build numbers all stay in lockstep. It also uses one patch digit and two minor digits, so build 1234 is given version 1.23.4. I use it as a pre-build behavior, so it applies to all projects I build.

这个 Perl 脚本增加了项目中的所有 Info.plist,而不仅仅是当前目标的那个,所以内部版本号都保持同步。它还使用一个补丁数字和两个次要数字,因此构建 1234 的版本为 1.23.4。我将它用作预构建行为,因此它适用于我构建的所有项目。

The script is pretty brute-force, but it does work for me.

该脚本非常暴力,但它确实对我有用。

##代码##