From 1de3ceccb54eb098350110f9c26fc0feba44de75 Mon Sep 17 00:00:00 2001 From: Pyry Haulos Date: Thu, 20 Nov 2014 14:29:20 -0800 Subject: [PATCH] Use git commit id as release identifier in development builds This change adds support for using latest git commit id as release name and id. This is done only if: 1) No existing release info file is detected. Release script will generate that file so actual release builds won't accidentally use development identifiers. 2) .git dir is detected. 3) Python binary is found, so this change doesn't add mandatory build-time dependency to python. Bug: 18445909 Change-Id: I3253b8b05f14e507774bb43331872607ffe6c1d0 --- framework/qphelper/CMakeLists.txt | 26 +++++++ framework/qphelper/gen_release_info.py | 94 ++++++++++++++++++++++++++ framework/qphelper/qpInfo.c | 8 ++- scripts/make_release.py | 42 ++++++------ 4 files changed, 148 insertions(+), 22 deletions(-) create mode 100644 framework/qphelper/gen_release_info.py diff --git a/framework/qphelper/CMakeLists.txt b/framework/qphelper/CMakeLists.txt index 56ec7fb4f..72878196a 100644 --- a/framework/qphelper/CMakeLists.txt +++ b/framework/qphelper/CMakeLists.txt @@ -36,3 +36,29 @@ endif () add_library(qphelper STATIC ${QPHELPER_SRCS}) target_link_libraries(qphelper ${QPHELPER_LIBS}) + +# Should qpInfo.c attempt to include qpReleaseInfo.inl +set(USE_RELEASE_INFO_FILE OFF) + +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/qpReleaseInfo.inl") + set(USE_RELEASE_INFO_FILE ON) + +elseif (EXISTS "${CMAKE_SOURCE_DIR}/.git") + find_program(PYTHON_BIN python) + + if (PYTHON_BIN) + message(STATUS "Using git revision as release identifier") + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/qpReleaseInfo.inl + COMMAND ${PYTHON_BIN} -B ${CMAKE_CURRENT_SOURCE_DIR}/gen_release_info.py --git --out=${CMAKE_CURRENT_BINARY_DIR}/qpReleaseInfo.inl + DEPENDS gen_release_info.py ${CMAKE_SOURCE_DIR}/.git/HEAD ${CMAKE_SOURCE_DIR}/.git/index) # \note HEAD updated only when changing branches + add_custom_target(git-rel-info DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/qpReleaseInfo.inl) + add_dependencies(qphelper git-rel-info) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) + set(USE_RELEASE_INFO_FILE ON) + endif () +endif () + +if (USE_RELEASE_INFO_FILE) + add_definitions(-DDEQP_USE_RELEASE_INFO_FILE) +endif () diff --git a/framework/qphelper/gen_release_info.py b/framework/qphelper/gen_release_info.py new file mode 100644 index 000000000..d2ba3a425 --- /dev/null +++ b/framework/qphelper/gen_release_info.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +import os +import re +import sys +import argparse + +def readFile (filename): + f = open(filename, 'rb') + d = f.read() + f.close() + return d + +def writeFile (filename, data): + f = open(filename, 'wb') + f.write(data) + f.close() + +COMMIT = 0 +REF = 1 + +def getCommitOrRef (filename): + src = readFile(filename) + m = re.search(r'^[a-zA-Z0-9]{40}', src) + if m: + return (COMMIT, m.group(0)) + m = re.search(r'^ref:\s+([^\s]+)', src) + if m: + return (REF, m.group(1)) + raise Exception("Coulnd't parse %s" % filename) + +def getHead (gitDir): + curFile = os.path.join(gitDir, "HEAD") + while True: + type, ptr = getCommitOrRef(curFile) + if type == COMMIT: + return ptr + else: + assert type == REF + curFile = os.path.join(gitDir, ptr) + +def makeReleaseInfo (name, id): + return """ +/* WARNING: auto-generated file, use {genFileName} to modify */ + +#define DEQP_RELEASE_NAME "{releaseName}" +#define DEQP_RELEASE_ID {releaseId} +"""[1:].format( + genFileName = os.path.basename(__file__), + releaseName = name, + releaseId = id) + +def parseArgs (): + parser = argparse.ArgumentParser(description="Generate release info for build") + parser.add_argument('--name', dest='releaseName', default=None, help="Release name") + parser.add_argument('--id', dest='releaseId', default=None, help="Release ID (must be C integer literal)") + parser.add_argument('--git', dest='git', action='store_true', default=False, help="Development build, use git HEAD to identify") + parser.add_argument('--git-dir', dest='gitDir', default=None, help="Use specific git dir for extracting info") + parser.add_argument('--out', dest='out', default=None, help="Output file") + + args = parser.parse_args() + + if (args.releaseName == None) != (args.releaseId == None): + print "Both --name and --id must be specified" + parser.print_help() + sys.exit(-1) + + if (args.releaseName != None) == args.git: + print "Either --name and --id, or --git must be specified" + parser.print_help() + sys.exit(-1) + + return args + +if __name__ == "__main__": + curDir = os.path.dirname(__file__) + defaultGitDir = os.path.normpath(os.path.join(curDir, "..", "..", ".git")) + defaultDstFile = os.path.join(curDir, "qpReleaseInfo.inl") + + args = parseArgs() + + if args.git: + gitDir = args.gitDir if args.gitDir != None else defaultGitDir + head = getHead(gitDir) + releaseName = "git-%s" % head + releaseId = "0x%s" % head[0:8] + else: + releaseName = args.releaseName + releaseId = args.releaseId + + releaseInfo = makeReleaseInfo(releaseName, releaseId) + dstFile = args.out if args.out != None else defaultDstFile + + writeFile(dstFile, releaseInfo) diff --git a/framework/qphelper/qpInfo.c b/framework/qphelper/qpInfo.c index 49cc3d0a1..54c92062e 100644 --- a/framework/qphelper/qpInfo.c +++ b/framework/qphelper/qpInfo.c @@ -25,8 +25,12 @@ DE_BEGIN_EXTERN_C -#define DEQP_RELEASE_NAME "2014.x" -#define DEQP_RELEASE_ID 0xcafebabe +#if defined(DEQP_USE_RELEASE_INFO_FILE) +# include "qpReleaseInfo.inl" +#else +# define DEQP_RELEASE_NAME "unknown" +# define DEQP_RELEASE_ID 0xcafebabe +#endif const char* qpGetTargetName (void) { diff --git a/scripts/make_release.py b/scripts/make_release.py index d996b40bd..f31a189dd 100644 --- a/scripts/make_release.py +++ b/scripts/make_release.py @@ -96,21 +96,22 @@ class CopyFile (DstFile): die("%s already exists" % self.dstFile) shutil.copyfile(self.srcFile, self.dstFile) -class GenInfoFile (DstFile): - def __init__ (self, srcFile, dstFile): - super(GenInfoFile, self).__init__(dstFile) - self.srcFile = srcFile +class GenReleaseInfoFileTarget (DstFile): + def __init__ (self, dstFile): + super(GenReleaseInfoFileTarget, self).__init__(dstFile) def make (self, packageBuildInfo): self.makeDir() - print " GenInfoFile: %s" % removeLeadingPath(self.dstFile, packageBuildInfo.dstBasePath) - src = readFile(self.srcFile) - - for define, value in [("DEQP_RELEASE_NAME", "\"%s\"" % packageBuildInfo.getReleaseVersion()), - ("DEQP_RELEASE_ID", "0x%08x" % packageBuildInfo.getReleaseId())]: - src = re.sub('(#\s*define\s+%s\s+)[^\n\r]+' % re.escape(define), r'\1 %s' % value, src) - writeFile(self.dstFile, src) + scriptPath = os.path.normpath(os.path.join(packageBuildInfo.srcBasePath, "framework", "qphelper", "gen_release_info.py")) + execute([ + "python", + "-B", # no .py[co] + scriptPath, + "--name=%s" % packageBuildInfo.getReleaseVersion(), + "--id=0x%08x" % packageBuildInfo.getReleaseId(), + "--out=%s" % self.dstFile + ]) class GenCMake (DstFile): def __init__ (self, srcFile, dstFile, replaceVars): @@ -362,15 +363,13 @@ BASE = Module("Base", [ makeFileCopyGroup ("doc/testlog-stylesheet", "doc/testlog-stylesheet", ["*"]), # Non-optional parts of framework - # \note qpInfo.c must be processed! - FileTargetGroup ("framework", "src/framework", [ - # If file is qpInfo.c use GenInfoFile - (lambda f: f[-8:] == "qpInfo.c", lambda s, d: GenInfoFile(s, d)), - # Otherwise just CopyFile targets - copyFileFilter(SRC_FILE_PATTERNS, ["imagedifftester", "randomshaders", "simplereference", "referencerenderer"]) - ]), - - # Main modules CMakeLists.txt + makeFileCopy ("framework/CMakeLists.txt", "src/framework/CMakeLists.txt"), + makeFileCopyGroup ("framework/delibs", "src/framework/delibs", SRC_FILE_PATTERNS), + makeFileCopyGroup ("framework/common", "src/framework/common", SRC_FILE_PATTERNS), + makeFileCopyGroup ("framework/qphelper", "src/framework/qphelper", SRC_FILE_PATTERNS), + makeFileCopyGroup ("framework/platform", "src/framework/platform", SRC_FILE_PATTERNS), + makeFileCopyGroup ("framework/opengl", "src/framework/opengl", SRC_FILE_PATTERNS, ["simplereference"]), + makeFileCopyGroup ("framework/egl", "src/framework/egl", SRC_FILE_PATTERNS), # android sources makeFileCopyGroup ("android/package/src", "src/android/package/src", SRC_FILE_PATTERNS), @@ -384,6 +383,9 @@ BASE = Module("Base", [ "launch.py", "debug.py" ]), + + # Release info + GenReleaseInfoFileTarget("src/framework/qphelper/qpReleaseInfo.inl") ]) DOCUMENTATION = Module("Documentation", [ -- 2.34.1