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
|
# pylint: disable=invalid-name,missing-docstring
#
# Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
#
# SPDX-License-Identifier: LGPL-2.1+
import sys
import xml.etree.ElementTree as ET
from pkg_resources import parse_version
XMLNS = '{http://www.gtk.org/introspection/core/1.0}'
XMLNS_C = '{http://www.gtk.org/introspection/c/1.0}'
def usage(return_code):
""" print usage and exit with the supplied return code """
if return_code == 0:
out = sys.stdout
else:
out = sys.stderr
out.write("usage: %s <NAME> <INPUT> <OUTPUT>\n" % sys.argv[0])
sys.exit(return_code)
class LdVersionScript:
""" Rasterize some text """
def __init__(self, library_name):
self.library_name = library_name
self.releases = {}
def _add_node(self, node):
identifier = node.attrib[XMLNS_C + 'identifier']
if 'version' not in node.attrib:
print('No version for', identifier)
sys.exit(1)
version = node.attrib['version']
if version not in self.releases:
self.releases[version] = []
release = self.releases[version]
if identifier not in release:
release.append(identifier)
return version
def _add_cls(self, cls):
# add all class functions
for node in cls.findall(XMLNS + 'function'):
self._add_node(node)
# choose the lowest version method for the _get_type symbol
version_lowest = None
# add all class methods
for node in cls.findall(XMLNS + 'method'):
version_tmp = self._add_node(node)
if version_tmp:
if not version_lowest or parse_version(version_tmp) < parse_version(version_lowest):
version_lowest = version_tmp
# add the constructor
for node in cls.findall(XMLNS + 'constructor'):
version_tmp = self._add_node(node)
if version_tmp:
if not version_lowest or parse_version(version_tmp) < parse_version(version_lowest):
version_lowest = version_tmp
if '{http://www.gtk.org/introspection/glib/1.0}get-type' not in cls.attrib:
return
type_name = cls.attrib['{http://www.gtk.org/introspection/glib/1.0}get-type']
# finally add the get_type symbol
if version_lowest:
self.releases[version_lowest].append(type_name)
def import_gir(self, filename):
tree = ET.parse(filename)
root = tree.getroot()
for ns in root.findall(XMLNS + 'namespace'):
for node in ns.findall(XMLNS + 'function'):
self._add_node(node)
for cls in ns.findall(XMLNS + 'record'):
self._add_cls(cls)
for cls in ns.findall(XMLNS + 'class'):
self._add_cls(cls)
def render(self):
# get a sorted list of all the versions
versions = []
for version in self.releases:
versions.append(version)
# output the version data to a file
verout = '# generated automatically, do not edit!\n'
oldversion = None
for version in sorted(versions, key=parse_version):
symbols = sorted(self.releases[version])
verout += '\n%s_%s {\n' % (self.library_name, version)
verout += ' global:\n'
for symbol in symbols:
verout += ' %s;\n' % symbol
verout += ' local: *;\n'
if oldversion:
verout += '} %s_%s;\n' % (self.library_name, oldversion)
else:
verout += '};\n'
oldversion = version
return verout
if __name__ == '__main__':
if {'-?', '--help', '--usage'}.intersection(set(sys.argv)):
usage(0)
if len(sys.argv) != 4:
usage(1)
ld = LdVersionScript(library_name=sys.argv[1])
ld.import_gir(sys.argv[2])
open(sys.argv[3], 'w').write(ld.render())
|