]> git.0d.be Git - empathy.git/blob - tools/make-version-script.py
Add shave support to build process.
[empathy.git] / tools / make-version-script.py
1 #!/usr/bin/python
2
3 """Construct a GNU ld or Debian dpkg version-script from a set of
4 RFC822-style symbol lists.
5
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...]
11
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.
16
17 Comments (lines starting with whitespace + "#") are allowed and ignored.
18
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.
23
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.
28
29 This script originates in telepathy-glib <http://telepathy.freedesktop.org/> -
30 please send us any changes that are needed.
31 """
32
33 # Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
34 # Copyright (C) 2008 Nokia Corporation
35 #
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.
39
40 import sys
41 from getopt import gnu_getopt
42 from sets import Set as set
43
44
45 def e(format, *args):
46     sys.stderr.write((format + '\n') % args)
47
48
49 def main(abifiles, symbols=None, unreleased_version=None,
50          dpkg=False, dpkg_first_line=None, dpkg_build_depends_package=None):
51
52     gnuld = not dpkg
53     symbol_set = None
54
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)
59
60     versioned_symbols = set()
61
62     dpkg_symbols = []
63     dpkg_versions = []
64
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
70
71     for filename in abifiles:
72         lines = open(filename, 'r').readlines()
73
74         version = None
75         extends = None
76         release = None
77
78         for i, line in enumerate(lines):
79             line = line.strip()
80
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)
101
102         else:
103             e('No symbols in %s', filename)
104             raise SystemExit(1)
105
106         if version is None:
107             e('No Versions: header in %s', filename)
108             raise SystemExit(1)
109
110         if extends is None:
111             e('No Extends: header in %s', filename)
112             raise SystemExit(1)
113
114         if release is None and dpkg:
115             e('No Release: header in %s', filename)
116             raise SystemExit(1)
117
118         if dpkg:
119             dpkg_versions.append('%s@%s %s' % (version, version, release))
120
121         lines = lines[cut:]
122
123         if gnuld:
124             print "%s {" % version
125             print "    global:"
126
127         for symbol in lines:
128             symbol = symbol.strip()
129
130             if symbol.startswith('#'):
131                 continue
132
133             if gnuld:
134                 print "        %s;" % symbol
135             elif dpkg:
136                 dpkg_symbols.append('%s@%s %s' % (symbol, version, release))
137
138             versioned_symbols.add(symbol)
139
140         if gnuld:
141             if extends == '-':
142                 print "    local:"
143                 print "        *;"
144                 print "};"
145             else:
146                 print "} %s;" % extends
147                 print
148
149     if dpkg:
150         dpkg_symbols.sort()
151         dpkg_versions.sort()
152
153         for x in dpkg_versions:
154             print " %s" % x
155
156         for x in dpkg_symbols:
157             print " %s" % x
158
159     if symbol_set is not None:
160         missing = versioned_symbols - symbol_set
161
162         if missing:
163             e('These symbols have disappeared:')
164
165             for symbol in missing:
166                 e('    %s', symbol)
167
168             raise SystemExit(1)
169
170         unreleased = symbol_set - versioned_symbols
171
172         if unreleased:
173             if unreleased_version is None:
174                 e('Unversioned symbols are not allowed in releases:')
175
176                 for symbol in unreleased:
177                     e('    %s', symbol)
178
179                 raise SystemExit(1)
180
181             if gnuld:
182                 print "%s {" % unreleased_version
183                 print "    global:"
184
185                 for symbol in unreleased:
186                     print "        %s;" % symbol
187
188                 print "} %s;" % version
189
190
191 if __name__ == '__main__':
192     options, argv = gnu_getopt (sys.argv[1:], '',
193                                 ['symbols=', 'unreleased-version=',
194                                  'dpkg=', 'dpkg-build-depends-package='])
195
196     opts = {'dpkg': False}
197
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
204
205     main(argv, **opts)