1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#!/usr/bin/env python
# Generate version information for a program
#
# Copyright (C) 2015 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import sys, os, subprocess, shlex, time, socket, optparse, logging, traceback
VERSION_FORMAT = """
/* DO NOT EDIT! This is an autogenerated file. See scripts/buildversion.py. */
#define BUILD_VERSION "%s"
#define BUILD_TOOLS "%s"
"""
# Run program and return the specified output
def check_output(prog):
logging.debug("Running %s" % (repr(prog),))
try:
process = subprocess.Popen(shlex.split(prog), stdout=subprocess.PIPE)
output = process.communicate()[0]
retcode = process.poll()
except OSError:
logging.debug("Exception on run: %s" % (traceback.format_exc(),))
return ""
logging.debug("Got (code=%s): %s" % (retcode, repr(output)))
if retcode:
return ""
try:
return output.decode()
except UnicodeError:
logging.debug("Exception on decode: %s" % (traceback.format_exc(),))
return ""
# Obtain version info from "git" program
def git_version():
if not os.path.exists('.git'):
logging.debug("No '.git' file/directory found")
return ""
ver = check_output("git describe --tags --long --dirty").strip()
logging.debug("Got git version: %s" % (repr(ver),))
return ver
# Look for version in a ".version" file. Official release tarballs
# have this file (see scripts/tarball.sh).
def file_version():
if not os.path.isfile('.version'):
logging.debug("No '.version' file found")
return ""
try:
f = open('.version', 'r')
ver = f.readline().strip()
f.close()
except OSError:
logging.debug("Exception on read: %s" % (traceback.format_exc(),))
return ""
logging.debug("Got .version: %s" % (repr(ver),))
return ver
# Generate an output file with the version information
def write_version(outfile, version, toolstr):
logging.debug("Write file %s and %s" % (repr(version), repr(toolstr)))
sys.stdout.write("Version: %s\n" % (version,))
f = open(outfile, 'w')
f.write(VERSION_FORMAT % (version, toolstr))
f.close()
# Run "tool --version" for each specified tool and extract versions
def tool_versions(tools):
tools = [t.strip() for t in tools.split(';')]
versions = ['', '']
success = 0
for tool in tools:
# Extract first line from "tool --version" output
verstr = check_output("%s --version" % (tool,)).split('\n')[0]
# Check if this tool looks like a binutils program
isbinutils = 0
if verstr.startswith('GNU '):
isbinutils = 1
verstr = verstr[4:]
# Extract version information and exclude program name
if ' ' not in verstr:
continue
prog, ver = verstr.split(' ', 1)
if not prog or not ver:
continue
# Check for any version conflicts
if versions[isbinutils] and versions[isbinutils] != ver:
logging.debug("Mixed version %s vs %s" % (
repr(versions[isbinutils]), repr(ver)))
versions[isbinutils] = "mixed"
continue
versions[isbinutils] = ver
success += 1
cleanbuild = versions[0] and versions[1] and success == len(tools)
return cleanbuild, "gcc: %s binutils: %s" % (versions[0], versions[1])
def main():
usage = "%prog [options] <outputheader.h>"
opts = optparse.OptionParser(usage)
opts.add_option("-e", "--extra", dest="extra", default="",
help="extra version string to append to version")
opts.add_option("-t", "--tools", dest="tools", default="",
help="list of build programs to extract version from")
opts.add_option("-v", action="store_true", dest="verbose",
help="enable debug messages")
options, args = opts.parse_args()
if len(args) != 1:
opts.error("Incorrect arguments")
outfile = args[0]
if options.verbose:
logging.basicConfig(level=logging.DEBUG)
cleanbuild, toolstr = tool_versions(options.tools)
ver = git_version()
cleanbuild = cleanbuild and 'dirty' not in ver
if not ver:
ver = file_version()
# We expect the "extra version" to contain information on the
# distributor and distribution package version (if
# applicable). It is a "clean" build if this is a build from
# an official release tarball and the above info is present.
cleanbuild = cleanbuild and ver and options.extra != ""
if not ver:
ver = "?"
if not cleanbuild:
btime = time.strftime("%Y%m%d_%H%M%S")
hostname = socket.gethostname()
ver = "%s-%s-%s" % (ver, btime, hostname)
write_version(outfile, ver + options.extra, toolstr)
if __name__ == '__main__':
main()
|