1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#!/usr/bin/python
"""Construct a GNU ld or Debian dpkg version-script from a set of
RFC822-style symbol lists.
Usage:
make-version-script.py [--symbols SYMBOLS] [--unreleased-version VER]
[--dpkg "LIBRARY.so.0 LIBRARY0 #MINVER#"]
[--dpkg-build-depends-package LIBRARY-dev]
[FILES...]
Each FILE starts with RFC822-style headers "Version:" (the name of the
symbol version, e.g. FOO_1.2.3) and "Extends:" (either the previous
version, or "-" if this is the first version). Next there is a blank
line, then a list of C symbols one per line.
Comments (lines starting with whitespace + "#") are allowed and ignored.
If --symbols is given, SYMBOLS lists the symbols actually exported by
the library (one per line). If --unreleased-version is given, any symbols
in SYMBOLS but not in FILES are assigned to that version; otherwise, any
such symbols cause an error.
If --dpkg is given, produce a Debian dpkg-gensymbols file instead of a
GNU ld version-script. The argument to --dpkg is the first line of the
resulting symbols file, and --dpkg-build-depends-package can optionally
be used to set the Build-Depends-Package field.
This script originates in telepathy-glib <http://telepathy.freedesktop.org/> -
please send us any changes that are needed.
"""
# Copyright (C) 2008-2010 Collabora Ltd. <http://www.collabora.co.uk/>
# Copyright (C) 2008 Nokia Corporation
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.
import sys
from getopt import gnu_getopt
def e(format, *args):
sys.stderr.write((format + '\n') % args)
def main(abifiles, symbols=None, unreleased_version=None,
dpkg=False, dpkg_first_line=None, dpkg_build_depends_package=None):
gnuld = not dpkg
symbol_set = None
if symbols is not None:
symbol_set = open(symbols, 'r').readlines()
symbol_set = map(str.strip, symbol_set)
symbol_set = set(symbol_set)
versioned_symbols = set()
dpkg_symbols = []
dpkg_versions = []
if dpkg:
assert dpkg_first_line is not None
print(dpkg_first_line)
if dpkg_build_depends_package is not None:
print("* Build-Depends-Package: %s" % dpkg_build_depends_package)
for filename in abifiles:
lines = open(filename, 'r').readlines()
version = None
extends = None
release = None
for i, line in enumerate(lines):
line = line.strip()
if line.startswith('#'):
continue
elif not line:
# the transition betwen headers and symbols
cut = i + 1
break
elif line.lower().startswith('version:'):
line = line[8:].strip()
version = line
continue
elif line.lower().startswith('extends:'):
line = line[8:].strip()
extends = line
continue
elif line.lower().startswith('release:'):
release = line[8:].strip()
continue
else:
e('Could not understand line in %s header: %s', filename, line)
raise SystemExit(1)
else:
e('No symbols in %s', filename)
raise SystemExit(1)
if version is None:
e('No Versions: header in %s', filename)
raise SystemExit(1)
if extends is None:
e('No Extends: header in %s', filename)
raise SystemExit(1)
if release is None and dpkg:
e('No Release: header in %s', filename)
raise SystemExit(1)
if dpkg:
dpkg_versions.append('%s@%s %s' % (version, version, release))
lines = lines[cut:]
if gnuld:
print("%s {" % version)
print(" global:")
for symbol in lines:
symbol = symbol.strip()
if symbol.startswith('#'):
continue
if gnuld:
print(" %s;" % symbol)
elif dpkg:
dpkg_symbols.append('%s@%s %s' % (symbol, version, release))
if symbol in versioned_symbols:
raise AssertionError('Symbol %s is in version %s and an '
'earlier version' % (symbol, version))
versioned_symbols.add(symbol)
if gnuld:
if extends == '-':
print(" local:")
print(" *;")
print("};")
else:
print("} %s;" % extends)
print("")
if dpkg:
dpkg_symbols.sort()
dpkg_versions.sort()
for x in dpkg_versions:
print(" %s" % x)
for x in dpkg_symbols:
print(" %s" % x)
if symbol_set is not None:
missing = versioned_symbols - symbol_set
if missing:
e('These symbols have disappeared:')
for symbol in missing:
e(' %s', symbol)
raise SystemExit(1)
unreleased = symbol_set - versioned_symbols
if unreleased:
if unreleased_version is None:
e('Unversioned symbols are not allowed in releases:')
for symbol in unreleased:
e(' %s', symbol)
raise SystemExit(1)
if gnuld:
print("%s {" % unreleased_version)
print(" global:")
for symbol in unreleased:
print(" %s;" % symbol)
print("} %s;" % version)
if __name__ == '__main__':
options, argv = gnu_getopt (sys.argv[1:], '',
['symbols=', 'unreleased-version=',
'dpkg=', 'dpkg-build-depends-package='])
opts = {'dpkg': False}
for option, value in options:
if option == '--dpkg':
opts['dpkg'] = True
opts['dpkg_first_line'] = value
else:
opts[option.lstrip('-').replace('-', '_')] = value
main(argv, **opts)
|