empathy-roster-model, empathy-roster-model-manager: Now deals with groups-changed...
[empathy-mirror.git] / tools / make-version-script.py
blob91306a0147f09d72c2a91c4234f5702a58010395
1 #!/usr/bin/python
3 """Construct a GNU ld or Debian dpkg version-script from a set of
4 RFC822-style symbol lists.
6 Usage:
7 make-version-script.py [--symbols SYMBOLS] [--unreleased-version VER]
8 [--dpkg "LIBRARY.so.0 LIBRARY0 #MINVER#"]
9 [--dpkg-build-depends-package LIBRARY-dev]
10 [FILES...]
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.
31 """
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.
40 import sys
41 from getopt import gnu_getopt
42 from sets import Set as set
45 def e(format, *args):
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):
52 gnuld = not dpkg
53 symbol_set = 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()
62 dpkg_symbols = []
63 dpkg_versions = []
65 if dpkg:
66 assert dpkg_first_line is not None
67 print dpkg_first_line
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()
74 version = None
75 extends = None
76 release = None
78 for i, line in enumerate(lines):
79 line = line.strip()
81 if line.startswith('#'):
82 continue
83 elif not line:
84 # the transition betwen headers and symbols
85 cut = i + 1
86 break
87 elif line.lower().startswith('version:'):
88 line = line[8:].strip()
89 version = line
90 continue
91 elif line.lower().startswith('extends:'):
92 line = line[8:].strip()
93 extends = line
94 continue
95 elif line.lower().startswith('release:'):
96 release = line[8:].strip()
97 continue
98 else:
99 e('Could not understand line in %s header: %s', filename, line)
100 raise SystemExit(1)
102 else:
103 e('No symbols in %s', filename)
104 raise SystemExit(1)
106 if version is None:
107 e('No Versions: header in %s', filename)
108 raise SystemExit(1)
110 if extends is None:
111 e('No Extends: header in %s', filename)
112 raise SystemExit(1)
114 if release is None and dpkg:
115 e('No Release: header in %s', filename)
116 raise SystemExit(1)
118 if dpkg:
119 dpkg_versions.append('%s@%s %s' % (version, version, release))
121 lines = lines[cut:]
123 if gnuld:
124 print "%s {" % version
125 print " global:"
127 for symbol in lines:
128 symbol = symbol.strip()
130 if symbol.startswith('#'):
131 continue
133 if gnuld:
134 print " %s;" % symbol
135 elif dpkg:
136 dpkg_symbols.append('%s@%s %s' % (symbol, version, release))
138 versioned_symbols.add(symbol)
140 if gnuld:
141 if extends == '-':
142 print " local:"
143 print " *;"
144 print "};"
145 else:
146 print "} %s;" % extends
147 print
149 if dpkg:
150 dpkg_symbols.sort()
151 dpkg_versions.sort()
153 for x in dpkg_versions:
154 print " %s" % x
156 for x in dpkg_symbols:
157 print " %s" % x
159 if symbol_set is not None:
160 missing = versioned_symbols - symbol_set
162 if missing:
163 e('These symbols have disappeared:')
165 for symbol in missing:
166 e(' %s', symbol)
168 raise SystemExit(1)
170 unreleased = symbol_set - versioned_symbols
172 if unreleased:
173 if unreleased_version is None:
174 e('Unversioned symbols are not allowed in releases:')
176 for symbol in unreleased:
177 e(' %s', symbol)
179 raise SystemExit(1)
181 if gnuld:
182 print "%s {" % unreleased_version
183 print " global:"
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':
200 opts['dpkg'] = True
201 opts['dpkg_first_line'] = value
202 else:
203 opts[option.lstrip('-').replace('-', '_')] = value
205 main(argv, **opts)