-#! /usr/bin/python
+#! /usr/bin/python -B
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 and later: Unicode, Inc. and others.
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
# 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
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',
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]
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
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:
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
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")
"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__":