diff OrthancFramework/Resources/CheckOrthancFrameworkSymbols.py @ 4277:c5ca798b158a

CheckOrthancFrameworkSymbols.py
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 03 Nov 2020 18:45:32 +0100
parents
children ab4d015af660
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancFramework/Resources/CheckOrthancFrameworkSymbols.py	Tue Nov 03 18:45:32 2020 +0100
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+
+# Orthanc - A Lightweight, RESTful DICOM Store
+# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+# Department, University Hospital of Liege, Belgium
+# Copyright (C) 2017-2020 Osimis S.A., Belgium
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+##
+## This maintenance script detects all the public methods in the
+## Orthanc framework that come with an inlined implementation in the
+## header file. Such methods can break the ABI of the shared library,
+## as the actual implementation might change over versions.
+##
+
+
+# Ubuntu 20.04:
+# sudo apt-get install python-clang-6.0
+# ./ParseWebAssemblyExports.py --libclang=libclang-6.0.so.1 ./Test.cpp
+
+# Ubuntu 18.04:
+# sudo apt-get install python-clang-4.0
+# ./ParseWebAssemblyExports.py --libclang=libclang-4.0.so.1 ./Test.cpp
+
+# Ubuntu 14.04:
+# ./ParseWebAssemblyExports.py --libclang=libclang-3.6.so.1 ./Test.cpp
+
+
+import os
+import sys
+import clang.cindex
+import argparse
+
+##
+## Parse the command-line arguments
+##
+
+parser = argparse.ArgumentParser(description = 'Parse WebAssembly C++ source file, and create a basic JavaScript wrapper.')
+parser.add_argument('--libclang',
+                    default = '',
+                    help = 'manually provides the path to the libclang shared library')
+
+args = parser.parse_args()
+
+
+if len(args.libclang) != 0:
+    clang.cindex.Config.set_library_file(args.libclang)
+
+index = clang.cindex.Index.create()
+
+
+ROOT = os.path.abspath(os.path.dirname(sys.argv[0]))
+SOURCES = []
+
+for root, dirs, files in os.walk(os.path.join(ROOT, '..', 'Sources')):
+    for name in files:
+        if os.path.splitext(name)[1] == '.h':
+            SOURCES.append(os.path.join(root, name))
+
+AMALGAMATION = '/tmp/CheckOrthancFrameworkSymbols.cpp'
+            
+with open(AMALGAMATION, 'w') as f:
+    f.write('#include "%s"\n' % os.path.join(ROOT, '..', 'Sources', 'OrthancFramework.h'))
+    for source in SOURCES:
+        f.write('#include "%s"\n' % source)
+            
+
+tu = index.parse(AMALGAMATION,
+                 [ '-DORTHANC_BUILDING_FRAMEWORK_LIBRARY=1' ])
+
+
+
+def ExploreNamespace(node, namespace):
+    for child in node.get_children():
+        fqn = namespace + [ child.spelling ]
+        
+        if child.kind == clang.cindex.CursorKind.NAMESPACE:
+            ExploreNamespace(child, fqn)
+
+        elif (child.kind == clang.cindex.CursorKind.CLASS_DECL or
+              child.kind == clang.cindex.CursorKind.STRUCT_DECL):
+            visible = False
+            
+            for i in child.get_children():
+                if (i.kind == clang.cindex.CursorKind.VISIBILITY_ATTR and
+                    i.spelling == 'default'):
+                    visible = True
+
+            if visible:
+                isPublic = (child.kind == clang.cindex.CursorKind.STRUCT_DECL)
+                
+                for i in child.get_children():
+                    if i.kind == clang.cindex.CursorKind.CXX_ACCESS_SPEC_DECL:
+                        isPublic = (i.access_specifier == clang.cindex.AccessSpecifier.PUBLIC)
+                        
+                    elif (i.kind == clang.cindex.CursorKind.CXX_METHOD or
+                          i.kind == clang.cindex.CursorKind.CONSTRUCTOR):
+                        if isPublic:
+                            hasImplementation = False
+                            for j in i.get_children():
+                                if j.kind == clang.cindex.CursorKind.COMPOUND_STMT:
+                                    hasImplementation = True
+
+                            if hasImplementation:
+                                print('Exported public method with an implementation: %s::%s()' %
+                                      ('::'.join(fqn), i.spelling))
+
+
+for node in tu.cursor.get_children():
+    if (node.kind == clang.cindex.CursorKind.NAMESPACE and
+        node.spelling == 'Orthanc'):
+        ExploreNamespace(node, [ 'Orthanc' ])