3 """Construct a GNU ld or Debian dpkg version-script from a set of
4 RFC822-style symbol lists.
7 make-version-script.py [--symbols SYMBOLS] [--unreleased-version VER]
8 [--dpkg "LIBRARY.so.0 LIBRARY0 #MINVER#"]
9 [--dpkg-build-depends-package LIBRARY-dev]
12 Each FILE starts with RFC822-style headers "Version:" (the name of the
13 symbol version, e.g. FOO_1.2.3) and "Extends:" (either the previous
14 version, or "-" if this is the first version). Next there is a blank
15 line, then a list of C symbols one per line.
17 Comments (lines starting with whitespace + "#") are allowed and ignored.
19 If --symbols is given, SYMBOLS lists the symbols actually exported by
20 the library (one per line). If --unreleased-version is given, any symbols
21 in SYMBOLS but not in FILES are assigned to that version; otherwise, any
22 such symbols cause an error.
24 If --dpkg is given, produce a Debian dpkg-gensymbols file instead of a
25 GNU ld version-script. The argument to --dpkg is the first line of the
26 resulting symbols file, and --dpkg-build-depends-package can optionally
27 be used to set the Build-Depends-Package field.
29 This script originates in telepathy-glib <http://telepathy.freedesktop.org/> -
30 please send us any changes that are needed.
33 # Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
34 # Copyright (C) 2008 Nokia Corporation
36 # Copying and distribution of this file, with or without modification,
37 # are permitted in any medium without royalty provided the copyright
38 # notice and this notice are preserved.
41 from getopt import gnu_getopt
42 from sets import Set as set
46 sys.stderr.write((format + '\n') % args)
49 def main(abifiles, symbols=None, unreleased_version=None,
50 dpkg=False, dpkg_first_line=None, dpkg_build_depends_package=None):
55 if symbols is not None:
56 symbol_set = open(symbols, 'r').readlines()
57 symbol_set = map(str.strip, symbol_set)
58 symbol_set = set(symbol_set)
60 versioned_symbols = set()
66 assert dpkg_first_line is not None
68 if dpkg_build_depends_package is not None:
69 print "* Build-Depends-Package: %s" % dpkg_build_depends_package
71 for filename in abifiles:
72 lines = open(filename, 'r').readlines()
78 for i, line in enumerate(lines):
81 if line.startswith('#'):
84 # the transition betwen headers and symbols
87 elif line.lower().startswith('version:'):
88 line = line[8:].strip()
91 elif line.lower().startswith('extends:'):
92 line = line[8:].strip()
95 elif line.lower().startswith('release:'):
96 release = line[8:].strip()
99 e('Could not understand line in %s header: %s', filename, line)
103 e('No symbols in %s', filename)
107 e('No Versions: header in %s', filename)
111 e('No Extends: header in %s', filename)
114 if release is None and dpkg:
115 e('No Release: header in %s', filename)
119 dpkg_versions.append('%s@%s %s' % (version, version, release))
124 print "%s {" % version
128 symbol = symbol.strip()
130 if symbol.startswith('#'):
134 print " %s;" % symbol
136 dpkg_symbols.append('%s@%s %s' % (symbol, version, release))
138 versioned_symbols.add(symbol)
146 print "} %s;" % extends
153 for x in dpkg_versions:
156 for x in dpkg_symbols:
159 if symbol_set is not None:
160 missing = versioned_symbols - symbol_set
163 e('These symbols have disappeared:')
165 for symbol in missing:
170 unreleased = symbol_set - versioned_symbols
173 if unreleased_version is None:
174 e('Unversioned symbols are not allowed in releases:')
176 for symbol in unreleased:
182 print "%s {" % unreleased_version
185 for symbol in unreleased:
186 print " %s;" % symbol
188 print "} %s;" % version
191 if __name__ == '__main__':
192 options, argv = gnu_getopt (sys.argv[1:], '',
193 ['symbols=', 'unreleased-version=',
194 'dpkg=', 'dpkg-build-depends-package='])
196 opts = {'dpkg': False}
198 for option, value in options:
199 if option == '--dpkg':
201 opts['dpkg_first_line'] = value
203 opts[option.lstrip('-').replace('-', '_')] = value