Use git commit id as release identifier in development builds
authorPyry Haulos <phaulos@google.com>
Thu, 20 Nov 2014 22:29:20 +0000 (14:29 -0800)
committerPyry Haulos <phaulos@google.com>
Thu, 20 Nov 2014 23:50:27 +0000 (15:50 -0800)
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
framework/qphelper/gen_release_info.py [new file with mode: 0644]
framework/qphelper/qpInfo.c
scripts/make_release.py

index 56ec7fb4f3b0b47e0b16424eb618cac4ce892c9a..72878196a03477ad23ca5123bc416dba92681ca9 100644 (file)
@@ -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 (file)
index 0000000..d2ba3a4
--- /dev/null
@@ -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)
index 49cc3d0a1d94090edea7a6b7bd886f50360b0a3f..54c92062ec0a3fe00a4edaa793b1bb54f3bdd409 100644 (file)
 
 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)
 {
index d996b40bd54a25f37927097a60b8671c4d3323cd..f31a189dd878f105c3f86ae913abede7cedda73b 100644 (file)
@@ -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", [