blob: c3a83b015ed73189d73e731c8e6df5355a82d4e8 [file] [log] [blame]
Kevin O'Connora6c87742015-10-13 15:09:40 -04001#!/usr/bin/env python
2# Generate version information for a program
3#
4# Copyright (C) 2015 Kevin O'Connor <kevin@koconnor.net>
5#
6# This file may be distributed under the terms of the GNU GPLv3 license.
Kevin O'Connorefd70a52015-10-13 15:44:25 -04007import sys, os, subprocess, time, socket, optparse, re
Kevin O'Connora6c87742015-10-13 15:09:40 -04008
9VERSION_FORMAT = """
10/* DO NOT EDIT! This is an autogenerated file. See scripts/buildversion.py. */
11#define BUILD_VERSION "%s"
Kevin O'Connorefd70a52015-10-13 15:44:25 -040012#define BUILD_TOOLS "%s"
Kevin O'Connora6c87742015-10-13 15:09:40 -040013"""
14
15# Obtain version info from "git" program
16def git_version():
17 if not os.path.exists('.git'):
18 return ""
19 params = "git describe --tags --long --dirty".split()
20 try:
21 ver = subprocess.check_output(params).decode().strip()
22 except:
23 return ""
24 return ver
25
26# Look for version in a ".version" file
27def file_version():
28 if not os.path.isfile('.version'):
29 return ""
30 try:
31 f = open('.version', 'r')
32 ver = f.readline().strip()
33 f.close()
34 except:
35 return ""
36 return ver
37
38# Generate an output file with the version information
Kevin O'Connorefd70a52015-10-13 15:44:25 -040039def write_version(outfile, version, toolstr):
Kevin O'Connora6c87742015-10-13 15:09:40 -040040 sys.stdout.write("Version: %s\n" % (version,))
41 f = open(outfile, 'w')
Kevin O'Connorefd70a52015-10-13 15:44:25 -040042 f.write(VERSION_FORMAT % (version, toolstr))
Kevin O'Connora6c87742015-10-13 15:09:40 -040043 f.close()
44
Kevin O'Connorefd70a52015-10-13 15:44:25 -040045re_gcc = re.compile(r'^(?P<prog>.*) \(GCC\) (?P<version>.*)$')
46re_binutils = re.compile(r'^GNU (?P<prog>.*) version (?P<version>.*)$')
47
48# Run "tool --version" for each specified tool and extract versions
49def tool_versions(tools):
50 tools = [t.strip() for t in tools.split(';')]
51 gcc = binutils = ""
52 success = 0
53 for tool in tools:
54 try:
55 ver = subprocess.check_output([tool, '--version']).decode()
56 except:
57 continue
58 ver = ver.split('\n')[0]
59 m = re_gcc.match(ver)
60 if m:
61 ver = m.group('version')
62 if gcc and gcc != ver:
63 gcc = "mixed"
64 continue
65 gcc = ver
66 success += 1
67 continue
68 m = re_binutils.match(ver)
69 if m:
70 ver = m.group('version')
71 if binutils and binutils != ver:
72 binutils = "mixed"
73 continue
74 binutils = ver
75 success += 1
76 cleanbuild = binutils and gcc and success == len(tools)
77 return cleanbuild, "gcc: %s binutils: %s" % (gcc, binutils)
78
Kevin O'Connora6c87742015-10-13 15:09:40 -040079def main():
80 usage = "%prog [options] <outputheader.h>"
81 opts = optparse.OptionParser(usage)
82 opts.add_option("-e", "--extra", dest="extra", default="",
83 help="extra version string to append to version")
Kevin O'Connorefd70a52015-10-13 15:44:25 -040084 opts.add_option("-t", "--tools", dest="tools", default="",
85 help="list of build programs to extra version from")
Kevin O'Connora6c87742015-10-13 15:09:40 -040086
87 options, args = opts.parse_args()
88 if len(args) != 1:
89 opts.error("Incorrect arguments")
90 outfile = args[0]
91
Kevin O'Connorefd70a52015-10-13 15:44:25 -040092 cleanbuild, toolstr = tool_versions(options.tools)
93
Kevin O'Connora6c87742015-10-13 15:09:40 -040094 ver = git_version()
Kevin O'Connora1b4dd02015-10-13 15:49:03 -040095 cleanbuild = cleanbuild and ver and 'dirty' not in ver
Kevin O'Connora6c87742015-10-13 15:09:40 -040096 if not ver:
97 ver = file_version()
98 if not ver:
99 ver = "?"
Kevin O'Connora1b4dd02015-10-13 15:49:03 -0400100 if not cleanbuild:
101 btime = time.strftime("%Y%m%d_%H%M%S")
102 hostname = socket.gethostname()
103 ver = "%s-%s-%s" % (ver, btime, hostname)
104 write_version(outfile, ver + options.extra, toolstr)
Kevin O'Connora6c87742015-10-13 15:09:40 -0400105
106if __name__ == '__main__':
107 main()