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-2010 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
45 sys.stderr.write((format + '\n') % args)
48 def main(abifiles, symbols=None, unreleased_version=None,
49 dpkg=False, dpkg_first_line=None, dpkg_build_depends_package=None):
54 if symbols is not None:
55 symbol_set = open(symbols, 'r').readlines()
56 symbol_set = map(str.strip, symbol_set)
57 symbol_set = set(symbol_set)
59 versioned_symbols = set()
65 assert dpkg_first_line is not None
66 print(dpkg_first_line)
67 if dpkg_build_depends_package is not None:
68 print("* Build-Depends-Package: %s" % dpkg_build_depends_package)
70 for filename in abifiles:
71 lines = open(filename, 'r').readlines()
77 for i, line in enumerate(lines):
80 if line.startswith('#'):
83 # the transition betwen headers and symbols
86 elif line.lower().startswith('version:'):
87 line = line[8:].strip()
90 elif line.lower().startswith('extends:'):
91 line = line[8:].strip()
94 elif line.lower().startswith('release:'):
95 release = line[8:].strip()
98 e('Could not understand line in %s header: %s', filename, line)
102 e('No symbols in %s', filename)
106 e('No Versions: header in %s', filename)
110 e('No Extends: header in %s', filename)
113 if release is None and dpkg:
114 e('No Release: header in %s', filename)
118 dpkg_versions.append('%s@%s %s' % (version, version, release))
123 print("%s {" % version)
127 symbol = symbol.strip()
129 if symbol.startswith('#'):
133 print(" %s;" % symbol)
135 dpkg_symbols.append('%s@%s %s' % (symbol, version, release))
137 if symbol in versioned_symbols:
138 raise AssertionError('Symbol %s is in version %s and an '
139 'earlier version' % (symbol, version))
141 versioned_symbols.add(symbol)
149 print("} %s;" % extends)
156 for x in dpkg_versions:
159 for x in dpkg_symbols:
162 if symbol_set is not None:
163 missing = versioned_symbols - symbol_set
166 e('These symbols have disappeared:')
168 for symbol in missing:
173 unreleased = symbol_set - versioned_symbols
176 if unreleased_version is None:
177 e('Unversioned symbols are not allowed in releases:')
179 for symbol in unreleased:
185 print("%s {" % unreleased_version)
188 for symbol in unreleased:
189 print(" %s;" % symbol)
191 print("} %s;" % version)
194 if __name__ == '__main__':
195 options, argv = gnu_getopt (sys.argv[1:], '',
196 ['symbols=', 'unreleased-version=',
197 'dpkg=', 'dpkg-build-depends-package='])
199 opts = {'dpkg': False}
201 for option, value in options:
202 if option == '--dpkg':
204 opts['dpkg_first_line'] = value
206 opts[option.lstrip('-').replace('-', '_')] = value