blob: d61fc9e331377760b74cd756fd64e85fe253857a [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'Connor23421012015-10-21 20:35:50 -04007import sys, os, subprocess, time, socket, optparse
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
Kevin O'Connor98a100c2015-10-22 11:59:47 -040026# Look for version in a ".version" file. Official release tarballs
27# have this file (see scripts/tarball.sh).
Kevin O'Connora6c87742015-10-13 15:09:40 -040028def file_version():
29 if not os.path.isfile('.version'):
30 return ""
31 try:
32 f = open('.version', 'r')
33 ver = f.readline().strip()
34 f.close()
35 except:
36 return ""
37 return ver
38
39# Generate an output file with the version information
Kevin O'Connorefd70a52015-10-13 15:44:25 -040040def write_version(outfile, version, toolstr):
Kevin O'Connora6c87742015-10-13 15:09:40 -040041 sys.stdout.write("Version: %s\n" % (version,))
42 f = open(outfile, 'w')
Kevin O'Connorefd70a52015-10-13 15:44:25 -040043 f.write(VERSION_FORMAT % (version, toolstr))
Kevin O'Connora6c87742015-10-13 15:09:40 -040044 f.close()
45
Kevin O'Connorefd70a52015-10-13 15:44:25 -040046# Run "tool --version" for each specified tool and extract versions
47def tool_versions(tools):
48 tools = [t.strip() for t in tools.split(';')]
Kevin O'Connor23421012015-10-21 20:35:50 -040049 versions = ['', '']
Kevin O'Connorefd70a52015-10-13 15:44:25 -040050 success = 0
51 for tool in tools:
Kevin O'Connor23421012015-10-21 20:35:50 -040052 # Extract first line from "tool --version" output
Kevin O'Connorefd70a52015-10-13 15:44:25 -040053 try:
54 ver = subprocess.check_output([tool, '--version']).decode()
55 except:
56 continue
Kevin O'Connor23421012015-10-21 20:35:50 -040057 verstr = ver.split('\n')[0]
58 # Check if this tool looks like a binutils program
59 isbinutils = 0
60 if verstr.startswith('GNU '):
61 isbinutils = 1
62 verstr = verstr[4:]
63 # Extract version information and exclude program name
64 if ' ' not in verstr:
Kevin O'Connorefd70a52015-10-13 15:44:25 -040065 continue
Kevin O'Connor23421012015-10-21 20:35:50 -040066 prog, ver = verstr.split(' ', 1)
67 if not prog or not ver:
68 continue
69 # Check for any version conflicts
70 if versions[isbinutils] and versions[isbinutils] != ver:
71 vers[isbinutils] = "mixed"
72 continue
73 versions[isbinutils] = ver
74 success += 1
75 cleanbuild = versions[0] and versions[1] and success == len(tools)
76 return cleanbuild, "gcc: %s binutils: %s" % (versions[0], versions[1])
Kevin O'Connorefd70a52015-10-13 15:44:25 -040077
Kevin O'Connora6c87742015-10-13 15:09:40 -040078def main():
79 usage = "%prog [options] <outputheader.h>"
80 opts = optparse.OptionParser(usage)
81 opts.add_option("-e", "--extra", dest="extra", default="",
82 help="extra version string to append to version")
Kevin O'Connorefd70a52015-10-13 15:44:25 -040083 opts.add_option("-t", "--tools", dest="tools", default="",
Kevin O'Connor23421012015-10-21 20:35:50 -040084 help="list of build programs to extract version from")
Kevin O'Connora6c87742015-10-13 15:09:40 -040085
86 options, args = opts.parse_args()
87 if len(args) != 1:
88 opts.error("Incorrect arguments")
89 outfile = args[0]
90
Kevin O'Connorefd70a52015-10-13 15:44:25 -040091 cleanbuild, toolstr = tool_versions(options.tools)
92
Kevin O'Connora6c87742015-10-13 15:09:40 -040093 ver = git_version()
Kevin O'Connor98a100c2015-10-22 11:59:47 -040094 cleanbuild = cleanbuild and 'dirty' not in ver
Kevin O'Connora6c87742015-10-13 15:09:40 -040095 if not ver:
96 ver = file_version()
Kevin O'Connor98a100c2015-10-22 11:59:47 -040097 # We expect the "extra version" to contain information on the
98 # distributor and distribution package version (if
99 # applicable). It is a "clean" build if this is a build from
100 # an official release tarball and the above info is present.
101 cleanbuild = cleanbuild and ver and options.extra != ""
Kevin O'Connora6c87742015-10-13 15:09:40 -0400102 if not ver:
103 ver = "?"
Kevin O'Connora1b4dd02015-10-13 15:49:03 -0400104 if not cleanbuild:
105 btime = time.strftime("%Y%m%d_%H%M%S")
106 hostname = socket.gethostname()
107 ver = "%s-%s-%s" % (ver, btime, hostname)
108 write_version(outfile, ver + options.extra, toolstr)
Kevin O'Connora6c87742015-10-13 15:09:40 -0400109
110if __name__ == '__main__':
111 main()