comparison OrthancFramework/Resources/CheckOrthancFrameworkSymbols.py @ 4520:f5cb0c0ffbed

added unit test OrthancFramework.SizeOf to dump sizeof all the public classes in the Orthanc framework
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 22 Feb 2021 18:30:31 +0100
parents d9473bd5ed43
children 1de2fc0363cb
comparison
equal deleted inserted replaced
4519:a3c6678aa7b1 4520:f5cb0c0ffbed
51 51
52 parser = argparse.ArgumentParser(description = 'Parse WebAssembly C++ source file, and create a basic JavaScript wrapper.') 52 parser = argparse.ArgumentParser(description = 'Parse WebAssembly C++ source file, and create a basic JavaScript wrapper.')
53 parser.add_argument('--libclang', 53 parser.add_argument('--libclang',
54 default = '', 54 default = '',
55 help = 'manually provides the path to the libclang shared library') 55 help = 'manually provides the path to the libclang shared library')
56 parser.add_argument('--target-cpp-size',
57 default = '',
58 help = 'where to store C++ source to display the size of each public class')
56 59
57 args = parser.parse_args() 60 args = parser.parse_args()
58 61
59 62
60 if len(args.libclang) != 0: 63 if len(args.libclang) != 0:
105 ]) 108 ])
106 109
107 110
108 FILES = [] 111 FILES = []
109 COUNT = 0 112 COUNT = 0
113 ALL_TYPES = []
110 114
111 def ReportProblem(message, fqn, cursor): 115 def ReportProblem(message, fqn, cursor):
112 global FILES, COUNT 116 global FILES, COUNT
113 FILES.append(os.path.normpath(str(cursor.location.file))) 117 FILES.append(os.path.normpath(str(cursor.location.file)))
114 COUNT += 1 118 COUNT += 1
139 visible = True 143 visible = True
140 144
141 if not visible: 145 if not visible:
142 return 146 return
143 147
148 global ALL_TYPES
149 ALL_TYPES.append('::'.join(fqn))
150
144 151
145 ## 152 ##
146 ## Ignore pure abstract interfaces, by checking the following 153 ## Ignore pure abstract interfaces, by checking the following
147 ## criteria: 154 ## criteria:
148 ## - It must be a C++ class (not a struct) 155 ## - It must be a C++ class (not a struct)
204 ## We are facing a standard C++ class or struct 211 ## We are facing a standard C++ class or struct
205 ## 212 ##
206 213
207 isPublic = (child.kind == clang.cindex.CursorKind.STRUCT_DECL) 214 isPublic = (child.kind == clang.cindex.CursorKind.STRUCT_DECL)
208 215
216 membersCount = 0
217 membersSize = 0
218
209 for i in child.get_children(): 219 for i in child.get_children():
210 if (i.kind == clang.cindex.CursorKind.VISIBILITY_ATTR or # "default" 220 if (i.kind == clang.cindex.CursorKind.VISIBILITY_ATTR or # "default"
211 i.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER): # base class 221 i.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER): # base class
212 pass 222 pass
213 223
230 240
231 if hasImplementation: 241 if hasImplementation:
232 ReportProblem('Exported public method with an implementation', fqn, i) 242 ReportProblem('Exported public method with an implementation', fqn, i)
233 243
234 elif i.kind == clang.cindex.CursorKind.VAR_DECL: 244 elif i.kind == clang.cindex.CursorKind.VAR_DECL:
235 if isPublic: 245 raise Exception('Unsupported: %s, %s' % (i.kind, i.location))
236 ReportProblem('Exported public member variable', fqn, i)
237 246
238 elif i.kind == clang.cindex.CursorKind.FUNCTION_TEMPLATE: 247 elif i.kind == clang.cindex.CursorKind.FUNCTION_TEMPLATE:
239 # An inline function template is OK, as it is not added to 248 # An inline function template is OK, as it is not added to
240 # a shared library, but compiled by the client of the library 249 # a shared library, but compiled by the client of the library
241 if isPublic: 250 if isPublic:
259 not children[0].displayname in [ 268 not children[0].displayname in [
260 # This is supported for ABI compatibility with Orthanc <= 1.8.0 269 # This is supported for ABI compatibility with Orthanc <= 1.8.0
261 'operator<<(std::ostream &, const Orthanc::DicomTag &)', 270 'operator<<(std::ostream &, const Orthanc::DicomTag &)',
262 ])): 271 ])):
263 raise Exception('Unsupported: %s, %s' % (i.kind, i.location)) 272 raise Exception('Unsupported: %s, %s' % (i.kind, i.location))
273
274 elif i.kind == clang.cindex.CursorKind.FIELD_DECL:
275 # TODO
276 if i.type.get_size() > 0:
277 membersSize += i.type.get_size()
278 membersCount += 1
264 279
265 else: 280 else:
266 if isPublic: 281 if isPublic:
267 raise Exception('Unsupported: %s, %s' % (i.kind, i.location)) 282 raise Exception('Unsupported: %s, %s' % (i.kind, i.location))
283
284 #print('Size of %s => (%d,%d)' % ('::'.join(fqn), membersCount, membersSize))
268 285
269 286
270 def ExploreNamespace(node, namespace): 287 def ExploreNamespace(node, namespace):
271 for child in node.get_children(): 288 for child in node.get_children():
272 fqn = namespace + [ child.spelling ] 289 fqn = namespace + [ child.spelling ]
299 if (node.kind == clang.cindex.CursorKind.NAMESPACE and 316 if (node.kind == clang.cindex.CursorKind.NAMESPACE and
300 node.spelling == 'Orthanc'): 317 node.spelling == 'Orthanc'):
301 ExploreNamespace(node, [ 'Orthanc' ]) 318 ExploreNamespace(node, [ 'Orthanc' ])
302 319
303 320
321 if args.target_cpp_size != '':
322 with open(args.target_cpp_size, 'w') as f:
323 for t in sorted(ALL_TYPES):
324 f.write(' printf("sizeof(::%s) == %%d\\n", static_cast<int>(sizeof(::%s)));\n' % (t, t))
325
326
304 print('\nTotal of possibly problematic methods: %d' % COUNT) 327 print('\nTotal of possibly problematic methods: %d' % COUNT)
305 328
306 print('\nProblematic files:\n') 329 print('\nProblematic files:\n')
307 for i in sorted(list(set(FILES))): 330 for i in sorted(list(set(FILES))):
308 print(i) 331 print(i)