hook-clr.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. # ------------------------------------------------------------------
  2. # Copyright (c) 2020 PyInstaller Development Team.
  3. #
  4. # This file is distributed under the terms of the GNU General Public
  5. # License (version 2.0 or later).
  6. #
  7. # The full license is available in LICENSE, distributed with
  8. # this software.
  9. #
  10. # SPDX-License-Identifier: GPL-2.0-or-later
  11. # ------------------------------------------------------------------
  12. # There is a name clash between pythonnet's clr module/extension (which this hooks is for) and clr package that provides
  13. # the terminal styling library (https://pypi.org/project/clr/). Therefore, we must first check if pythonnet is actually
  14. # available...
  15. from PyInstaller.utils.hooks import is_module_satisfies
  16. from PyInstaller.compat import is_win
  17. if is_module_satisfies("pythonnet"):
  18. # pythonnet requires both clr.pyd and Python.Runtime.dll, but the latter isn't found by PyInstaller.
  19. import ctypes.util
  20. from PyInstaller.log import logger
  21. from _pyinstaller_hooks_contrib.compat import importlib_metadata
  22. collected_runtime_files = []
  23. # Try finding Python.Runtime.dll via distribution's file list
  24. dist_files = importlib_metadata.files('pythonnet') or []
  25. runtime_dll_files = [f for f in dist_files if f.match('Python.Runtime.dll')]
  26. if len(runtime_dll_files) == 1:
  27. runtime_dll_file = runtime_dll_files[0]
  28. collected_runtime_files = [(runtime_dll_file.locate(), runtime_dll_file.parent.as_posix())]
  29. logger.debug("hook-clr: Python.Runtime.dll discovered via metadata.")
  30. elif len(runtime_dll_files) > 1:
  31. logger.warning("hook-clr: multiple instances of Python.Runtime.dll listed in metadata - cannot resolve.")
  32. # Fall back to the legacy way
  33. if not collected_runtime_files:
  34. runtime_dll_file = ctypes.util.find_library('Python.Runtime')
  35. if runtime_dll_file:
  36. collected_runtime_files = [(runtime_dll_file, '.')]
  37. logger.debug('hook-clr: Python.Runtime.dll discovered via legacy method.')
  38. if not collected_runtime_files:
  39. raise Exception('Python.Runtime.dll not found')
  40. # On Windows, collect runtime DLL file(s) as binaries; on other OSes, collect them as data files, to prevent fatal
  41. # errors in binary dependency analysis.
  42. if is_win:
  43. binaries = collected_runtime_files
  44. else:
  45. datas = collected_runtime_files
  46. # These modules are imported inside Python.Runtime.dll
  47. hiddenimports = ["platform", "warnings"]