nvidia_cuda.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. # ------------------------------------------------------------------
  2. # Copyright (c) 2023 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. import os
  13. import re
  14. from PyInstaller import compat
  15. from PyInstaller.utils.hooks import (
  16. logger,
  17. is_module_satisfies,
  18. )
  19. # Helper for collecting shared libraries from NVIDIA CUDA packages on linux.
  20. def collect_nvidia_cuda_binaries(hook_file):
  21. # Find the module underlying this nvidia.something hook; i.e., change ``/path/to/hook-nvidia.something.py`` to
  22. # ``nvidia.something``.
  23. hook_name, hook_ext = os.path.splitext(os.path.basename(hook_file))
  24. assert hook_ext.startswith('.py')
  25. assert hook_name.startswith('hook-')
  26. module_name = hook_name[5:]
  27. # `search_patterns` was added to `collect_dynamic_libs` in PyInstaller 5.8, so that is the minimum required version.
  28. binaries = []
  29. if is_module_satisfies('PyInstaller >= 5.8'):
  30. from PyInstaller.utils.hooks import collect_dynamic_libs, PY_DYLIB_PATTERNS
  31. binaries = collect_dynamic_libs(
  32. module_name,
  33. # Collect fully-versioned .so files (not included in default search patterns).
  34. search_patterns=PY_DYLIB_PATTERNS + ["lib*.so.*"],
  35. )
  36. else:
  37. logger.warning("hook-%s: this hook requires PyInstaller >= 5.8!", module_name)
  38. return binaries
  39. # Helper to turn list of requirements (e.g., ['nvidia-cublas-cu12', 'nvidia-nccl-cu12', 'nvidia-cudnn-cu12']) into
  40. # list of corresponding nvidia.* module names (e.g., ['nvidia.cublas', 'nvidia.nccl', 'nvidia-cudnn']), while ignoring
  41. # unrecognized requirements. Intended for use in hooks for frameworks, such as `torch` and `tensorflow`.
  42. def infer_hiddenimports_from_requirements(requirements):
  43. # All nvidia-* packages install to nvidia top-level package, so we cannot query top-level module via
  44. # metadata. Instead, we manually translate them from dist name to package name.
  45. _PATTERN = r'^nvidia-(?P<subpackage>.+)-cu[\d]+$'
  46. nvidia_hiddenimports = []
  47. for req in requirements:
  48. m = re.match(_PATTERN, req)
  49. if m is not None:
  50. # Convert
  51. package_name = "nvidia." + m.group('subpackage').replace('-', '_')
  52. nvidia_hiddenimports.append(package_name)
  53. return nvidia_hiddenimports
  54. def create_symlink_suppression_patterns(hook_file):
  55. hook_name, hook_ext = os.path.splitext(os.path.basename(hook_file))
  56. assert hook_ext.startswith('.py')
  57. assert hook_name.startswith('hook-')
  58. module_name = hook_name[5:]
  59. # Applicable only to Linux
  60. if not compat.is_linux:
  61. return []
  62. # Pattern: **/{module_dir}/lib/lib*.so*
  63. return [os.path.join('**', *module_name.split('.'), 'lib', 'lib*.so*')]