]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/depstest/depstest.py
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / depstest / depstest.py
index 2a542e787074897837d65bb1a25cc797d506aa33..83dbfc063cab22634467c60f8b042cff6c8a15ca 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/python -B
 # -*- coding: utf-8 -*-
 #
 # Copyright (C) 2016 and later: Unicode, Inc. and others.
@@ -16,10 +16,15 @@ This probably works only on Linux.
 
 The exit code is 0 if everything is fine, 1 for errors, 2 for only warnings.
 
-Sample invocation:
-  ~/svn.icu/trunk/src/source/test/depstest$ ./depstest.py ~/svn.icu/trunk/dbg
+Sample invocation with an in-source build:
+  ~/icu/icu4c/source/test/depstest$ ./depstest.py ../../
+
+Sample invocation with an out-of-source build:
+  ~/icu/icu4c/source/test/depstest$ ./depstest.py ~/build/
 """
 
+from __future__ import print_function
+
 __author__ = "Markus W. Scherer"
 
 import glob
@@ -40,12 +45,21 @@ _virtual_classes = set()
 # nm shows a symbol class of "W" rather than "T".
 _weak_destructors = set()
 
+def iteritems(items):
+  """Python 2/3-compatible iteritems"""
+  try:
+    for v in items.iteritems():
+      yield v
+  except AttributeError:
+    for v in items.items():
+      yield v
+
 def _ReadObjFile(root_path, library_name, obj_name):
   global _ignored_symbols, _obj_files, _symbols_to_files
   global _virtual_classes, _weak_destructors
   lib_obj_name = library_name + "/" + obj_name
   if lib_obj_name in _obj_files:
-    print "Warning: duplicate .o file " + lib_obj_name
+    print("Warning: duplicate .o file " + lib_obj_name)
     _return_value = 2
     return
 
@@ -56,7 +70,7 @@ def _ReadObjFile(root_path, library_name, obj_name):
   obj_imports = set()
   obj_exports = set()
   for line in nm_result.splitlines():
-    fields = line.split("|")
+    fields = line.decode().split("|")
     if len(fields) == 1: continue
     name = fields[0].strip()
     # Ignore symbols like '__cxa_pure_virtual',
@@ -87,6 +101,19 @@ def _ReadLibrary(root_path, library_name):
   for path in obj_paths:
     _ReadObjFile(root_path, library_name, os.path.basename(path))
 
+# Dependencies that would otherwise be errors, but that are to be allowed
+# in a limited (not transitive) context.  List of (file_name, symbol)
+# TODO: Move this data to dependencies.txt?
+allowed_errors = (
+  ("common/umutex.o", "std::__throw_system_error(int)"),
+  ("common/umutex.o", "std::uncaught_exception()"),
+  ("common/umutex.o", "std::__once_callable"),
+  ("common/umutex.o", "std::__once_call"),
+  ("common/umutex.o", "__once_proxy"),
+  ("common/umutex.o", "__tls_get_addr"),
+  ("common/unifiedcache.o", "std::__throw_system_error(int)"),
+)
+
 def _Resolve(name, parents):
   global _ignored_symbols, _obj_files, _symbols_to_files, _return_value
   item = dependencies.items[name]
@@ -120,7 +147,7 @@ def _Resolve(name, parents):
       dep_exports = dep_item["exports"]
       dep_system_symbols = dep_item["system_symbols"]
       if files and imports.isdisjoint(dep_exports) and imports.isdisjoint(dep_system_symbols):
-        print "Info:  %s %s  does not need to depend on  %s\n" % (item_type, name, dep)
+        print("Info:  %s %s  does not need to depend on  %s\n" % (item_type, name, dep))
       # We always include the dependency's exports, even if we do not need them
       # to satisfy local imports.
       exports |= dep_exports
@@ -130,6 +157,9 @@ def _Resolve(name, parents):
   imports -= exports | system_symbols
   for symbol in imports:
     for file_name in files:
+      if (file_name, symbol) in allowed_errors:
+         sys.stderr.write("Info:  ignoring %s imports %s\n\n" % (file_name, symbol))
+         continue
       if symbol in _obj_files[file_name]["imports"]:
         neededFile = _symbols_to_files.get(symbol)
         if neededFile in dependencies.file_to_item:
@@ -138,7 +168,7 @@ def _Resolve(name, parents):
           neededItem = "- is this a new system symbol?"
         sys.stderr.write("Error: in %s %s: %s imports %s %s\n" %
                          (item_type, name, file_name, symbol, neededItem))
-    _return_value = 1
+        _return_value = 1
   del parents[-1]
   return item
 
@@ -150,7 +180,7 @@ def Process(root_path):
   global _ignored_symbols, _obj_files, _return_value
   global _virtual_classes, _weak_destructors
   dependencies.Load()
-  for name_and_item in dependencies.items.iteritems():
+  for name_and_item in iteritems(dependencies.items):
     name = name_and_item[0]
     item = name_and_item[1]
     system_symbols = item.get("system_symbols")
@@ -189,11 +219,11 @@ def main():
              "need one argument with the root path to the built ICU libraries/*.o files."))
   Process(sys.argv[1])
   if _ignored_symbols:
-    print "Info: ignored symbols:\n%s" % sorted(_ignored_symbols)
+    print("Info: ignored symbols:\n%s" % sorted(_ignored_symbols))
   if not _return_value:
-    print "OK: Specified and actual dependencies match."
+    print("OK: Specified and actual dependencies match.")
   else:
-    print "Error: There were errors, please fix them and re-run. Processing may have terminated abnormally."
+    print("Error: There were errors, please fix them and re-run. Processing may have terminated abnormally.")
   return _return_value
 
 if __name__ == "__main__":