使用#define和clang为info.plist创建版本号变体? [英] Create version number variations for info.plist using #define and clang?

查看:287
本文介绍了使用#define和clang为info.plist创建版本号变体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

多年前,在使用GCC进行编译时,#include .h文件中的以下定义可以预处理以用于info.plist:

Years ago, when compiling with GCC, the following defines in a #include .h file could be pre-processed for use in info.plist:

#define MAJORVERSION 2
#define MINORVERSION 6 
#define MAINTVERSION 4

<key>CFBundleShortVersionString</key> <string>MAJORVERSION.MINORVERSION.MAINTVERSION</string>

...这将变成2.6.4。这是因为GCC支持-traditional标志。 (请参阅技术说明TN2175 Xcode中的Info.plist文件使用C预处理器<

...which would turn into "2.6.4". That worked because GCC supported the "-traditional" flag. (see Tech Note TN2175 Info.plist files in Xcode Using the C Preprocessor, under "Eliminating whitespace between tokens in the macro expansion process")

但是,快进到2016和Clang 7.0.2(Xcode 7.2.1)显然不支持-traditional或-traditional-cpp(或正确支持),产生以下字符串:

However, fast-forward to 2016 and Clang 7.0.2 (Xcode 7.2.1) apparently does not support either "-traditional" or "-traditional-cpp" (or support it properly), yielding this string:

"2 . 6 . 4"

(请参阅 Bug 12035 - 预处理程序在宏展开式中插入空格,注释4

因为有这么多不同的变体(CFBundleShortVersionString,CFBundleVersion,CFBundleGetInfoString),它将是很好的工作围绕这个铛问题,并定义这些一次,并连接/ stringify的片段在一起。现在这样做的普遍接受的模式是什么? (我目前正在MacOS上构建,但同样的模式将适用于IOS)

Because there are so many different variations (CFBundleShortVersionString, CFBundleVersion, CFBundleGetInfoString), it would be nice to work around this clang problem, and define these once, and concatenate / stringify the pieces together. What is the commonly-accepted pattern for doing this now? (I'm presently building on MacOS but the same pattern would work for IOS)

推荐答案

这里是我使用的Python脚本检测到源代码更改时增加我的构建号,并更新项目中的一个或多个 Info.plist 文件。

Here is the Python script I use to increment my build number, whenever a source code change is detected, and update one or more Info.plist files within the project.

这是为了解决此问题中提出的问题而创建的

It was created to solve the issue raised in this question I asked a while back.

您需要在源代码树中创建 buildnum.ver 文件,如下所示:

You need to create buildnum.ver file in the source tree that looks like this:

version 1.0
build 1

(当达到某些项目里程碑时,您需要手动增加版本,但 buildnum 会自动递增。)

(you will need to manually increment version when certain project milestones are reached, but buildnum is incremented automatically).

注意 .ver 文件必须在源代码树的根目录中(参见 SourceDir ),因为此脚本将在此目录中查找已修改的文件。如果发现任何内容,则内部版本号将递增。修改意味着在 .ver 文件最后更新后,源文件发生更改。

NOTE the location of the .ver file must be in the root of the source tree (see SourceDir, below) as this script will look for modified files in this directory. If any are found, the build number is incremented. Modified means source files changes after the .ver file was last updated.

然后创建一个新的Xcode目标外部构建工具并运行类似:

Then create a new Xcode target to run an external build tool and run something like:

tools/bump_buildnum.py SourceDir/buildnum.ver SourceDir/Info.plist

(使其在 $ {PROJECT_DIR} 中运行)

,然后使所有实际的Xcode目标依赖于这个目标,所以它们在任何一个构建之前运行。

and then make all the actual Xcode targets dependent upon this target, so it runs before any of them are built.

#!/usr/bin/env python
#
# Bump build number in Info.plist files if a source file have changed.
#
# usage: bump_buildnum.py buildnum.ver Info.plist [ ... Info.plist ]
#
# andy@trojanfoe.com, 2014.
#

import sys, os, subprocess, re

def read_verfile(name):
    version = None
    build = None
    verfile = open(name, "r")
    for line in verfile:
        match = re.match(r"^version\s+(\S+)", line)
        if match:
            version = match.group(1).rstrip()
        match = re.match(r"^build\s+(\S+)", line)
        if match:
            build = int(match.group(1).rstrip())
    verfile.close()
    return (version, build)

def write_verfile(name, version, build):
    verfile = open(name, "w")
    verfile.write("version {0}\n".format(version))
    verfile.write("build {0}\n".format(build))
    verfile.close()
    return True

def set_plist_version(plistname, version, build):
    if not os.path.exists(plistname):
        print("{0} does not exist".format(plistname))
        return False

    plistbuddy = '/usr/libexec/Plistbuddy'
    if not os.path.exists(plistbuddy):
        print("{0} does not exist".format(plistbuddy))
        return False

    cmdline = [plistbuddy,
        "-c", "Set CFBundleShortVersionString {0}".format(version),
        "-c", "Set CFBundleVersion {0}".format(build),
        plistname]
    if subprocess.call(cmdline) != 0:
        print("Failed to update {0}".format(plistname))
        return False

    print("Updated {0} with v{1} ({2})".format(plistname, version, build))
    return True

def should_bump(vername, dirname):
    verstat = os.stat(vername)
    allnames = []
    for dirname, dirnames, filenames in os.walk(dirname):
        for filename in filenames:
            allnames.append(os.path.join(dirname, filename))

    for filename in allnames:
        filestat = os.stat(filename)
        if filestat.st_mtime > verstat.st_mtime:
            print("{0} is newer than {1}".format(filename, vername))
            return True

    return False

def upver(vername):
    (version, build) = read_verfile(vername)
    if version == None or build == None:
        print("Failed to read version/build from {0}".format(vername))
        return False

    # Bump the version number if any files in the same directory as the version file
    # have changed, including sub-directories.
    srcdir = os.path.dirname(vername)
    bump = should_bump(vername, srcdir)

    if bump:
        build += 1
        print("Incremented to build {0}".format(build))
        write_verfile(vername, version, build)
        print("Written {0}".format(vername))
    else:
        print("Staying at build {0}".format(build))

    return (version, build)

if __name__ == "__main__":
    if os.environ.has_key('ACTION') and os.environ['ACTION'] == 'clean':
        print("{0}: Not running while cleaning".format(sys.argv[0]))
        sys.exit(0)

    if len(sys.argv) < 3:
        print("Usage: {0} buildnum.ver Info.plist [... Info.plist]".format(sys.argv[0]))
        sys.exit(1)
    vername = sys.argv[1]

    (version, build) = upver(vername)
    if version == None or build == None:
        sys.exit(2)

    for i in range(2, len(sys.argv)):
        plistname = sys.argv[i]
        set_plist_version(plistname, version, build)        

    sys.exit(0)

这篇关于使用#define和clang为info.plist创建版本号变体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆