forked from include-what-you-use/include-what-you-use
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgenerate_qt_mappings.py
executable file
·170 lines (137 loc) · 4.99 KB
/
generate_qt_mappings.py
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
#!/usr/bin/env python
##===--- generate_qt_mappings.py ------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
"""
This script generates the Qt mapping file according to given Qt include
directory
Example usage :
$ ./generate_qt_mappings.py /usr/include/x86_64-linux-gnu/qt5 qt5_11.imp
"""
from __future__ import print_function
import argparse
import glob
import json
import os
import re
import sys
OUTFILEHDR = ("# Do not edit! This file was generated by the script %s." %
os.path.basename(__file__))
QOBJECT_SYMBOLS = [
"QObjectList",
"qFindChildren",
"qobject_cast",
"QT_NO_NARROWING_CONVERSIONS_IN_CONNECT",
"Q_CLASSINFO",
"Q_DISABLE_COPY",
"Q_DISABLE_COPY_MOVE",
"Q_DISABLE_MOVE",
"Q_EMIT",
"Q_ENUM",
"Q_ENUM_NS",
"Q_FLAG",
"Q_FLAG_NS",
"Q_GADGET",
"Q_INTERFACES",
"Q_INVOKABLE",
"Q_NAMESPACE",
"Q_NAMESPACE_EXPORT",
"Q_OBJECT",
"Q_PROPERTY",
"Q_REVISION",
"Q_SET_OBJECT_NAME",
"Q_SIGNAL",
"Q_SIGNALS",
"Q_SLOT",
"Q_SLOTS",
"emit",
"slots",
"signals",
"SIGNAL",
"SLOT",
]
class QtHeader(object):
""" Carry data associated with a Qt header """
def __init__(self, headername):
self.headername = headername
self.classname = os.path.basename(headername)
self.modulename = os.path.basename(os.path.dirname(headername))
self._private_headers = None
def get_private_headers(self):
""" Return a list of headernames included by this header """
if self._private_headers is None:
with open(self.headername, 'r') as headerfile:
included = re.findall(r'#include "(.*)\.h"', headerfile.read())
self._private_headers = list(included)
return self._private_headers
def build_imp_lines(symbols_map, includes_map):
""" Generate a big string containing the mappings in .imp format.
This should ideally return a jsonable structure instead, and use json.dump
to write it to the output file directly. But there doesn't seem to be a
simple way to convince Python's json library to generate a "packed"
formatting, it always prefers to wrap dicts onto multiple lines.
Cheat, and use json.dumps for escaping and build a string instead.
"""
root = []
def jsonline(mapping):
return " " + json.dumps(mapping)
for symbol, header in symbols_map:
map_to = "<" + header + ">"
root.append(jsonline({"symbol": [symbol, "private", map_to, "public"]}))
for module, include, header in includes_map:
# Use regex map-from to match both quoted and angled includes and
# optional directory prefix (e.g. <QtCore/qnamespace.h> is equivalent to
# "qnamespace.h").
map_from = r'@["<](%s/)?%s\.h[">]' % (module, include)
map_to = "<" + header + ">"
root.append(jsonline({"include": [map_from, "private",
map_to, "public"]}))
lines = "[\n"
lines += ",\n".join(root)
lines += "\n]\n"
return lines
def add_mapping_rules(header, symbols_map, includes_map):
""" Add symbol and include mappings for a Qt module. """
symbols_map += [(header.classname, header.classname)]
for include in header.get_private_headers():
includes_map += [(header.modulename, include, header.classname)]
def main(qt_include_dir, output_file):
""" Entry point. """
symbols_map = []
includes_map = []
deferred_headers = []
# Add manual overrides.
symbols_map += [("qDebug", "QtGlobal")]
symbols_map += [(symbol, "QObject") for symbol in QOBJECT_SYMBOLS]
includes_map += [("QtCore", "qnamespace", "Qt")]
# Collect mapping information from Qt directory tree.
headers = glob.glob(os.path.join(qt_include_dir, '**/*[!.h]'))
for header in headers:
if os.path.isdir(header):
continue
header = QtHeader(header)
if header.classname == "QInternal":
continue
if header.classname == header.modulename:
deferred_headers.append(header)
else:
add_mapping_rules(header, symbols_map, includes_map)
for header in deferred_headers:
add_mapping_rules(header, symbols_map, includes_map)
# Transform to .imp-style format and write to output file.
lines = build_imp_lines(symbols_map, includes_map)
with open(output_file, 'w') as outfile:
print(OUTFILEHDR, file=outfile)
print(lines, file=outfile)
return 0
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("qt_include_dir", help="Qt include directoy")
parser.add_argument("output_file", help="Generated output mapping file")
args = parser.parse_args()
sys.exit(main(args.qt_include_dir, args.output_file))