hook-usb.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. import ctypes.util
  13. import os
  14. from PyInstaller.depend.utils import _resolveCtypesImports
  15. from PyInstaller.compat import is_cygwin, getenv
  16. from PyInstaller.utils.hooks import logger
  17. # Include glob for library lookup in run-time hook.
  18. hiddenimports = ['glob']
  19. # https://github.com/walac/pyusb/blob/master/docs/faq.rst
  20. # https://github.com/walac/pyusb/blob/master/docs/tutorial.rst
  21. binaries = []
  22. # Running usb.core.find() in this script crashes Ubuntu 14.04LTS,
  23. # let users circumvent pyusb discovery with an environment variable.
  24. skip_pyusb_discovery = \
  25. bool(getenv('PYINSTALLER_USB_HOOK_SKIP_PYUSB_DISCOVERY'))
  26. # Try to use pyusb's library locator.
  27. if not skip_pyusb_discovery:
  28. import usb.core
  29. import usb.backend
  30. try:
  31. # get the backend symbols before find
  32. backend_contents_before_discovery = set(dir(usb.backend))
  33. # perform find, which will load a usb library if found
  34. usb.core.find()
  35. # get the backend symbols which have been added (loaded)
  36. backends = set(dir(usb.backend)) - backend_contents_before_discovery
  37. for usblib in [getattr(usb.backend, be)._lib for be in backends]:
  38. if usblib is not None:
  39. if os.path.isabs(usblib._name):
  40. binaries.append((os.path.basename(usblib._name), usblib._name, "BINARY"))
  41. else:
  42. # OSX returns the full path, Linux only the filename.
  43. # try to resolve the library names to absolute paths.
  44. backend_lib_full_paths = _resolveCtypesImports([os.path.basename(usblib._name)])
  45. if backend_lib_full_paths:
  46. binaries.append(backend_lib_full_paths[0])
  47. except (ValueError, usb.core.USBError) as exc:
  48. logger.warning("%s", exc)
  49. # If pyusb didn't find a backend, manually search for usb libraries.
  50. if not binaries:
  51. # NOTE: Update these lists when adding further libs.
  52. if is_cygwin:
  53. libusb_candidates = ['cygusb-1.0-0.dll', 'cygusb0.dll']
  54. else:
  55. libusb_candidates = [
  56. # libusb10
  57. 'usb-1.0',
  58. 'usb',
  59. 'libusb-1.0',
  60. # libusb01
  61. 'usb-0.1',
  62. 'libusb0',
  63. # openusb
  64. 'openusb',
  65. ]
  66. backend_library_basenames = []
  67. for candidate in libusb_candidates:
  68. libname = ctypes.util.find_library(candidate)
  69. if libname is not None:
  70. if os.path.isabs(libname):
  71. binaries.append((os.path.basename(libname), libname, "BINARY"))
  72. else:
  73. backend_lib_full_paths = _resolveCtypesImports([os.path.basename(libname)])
  74. if backend_lib_full_paths:
  75. binaries.append(backend_lib_full_paths[0])
  76. # Validate and normalize the first found usb library.
  77. if binaries:
  78. # `_resolveCtypesImports` returns a 3-tuple, but `binaries` are only
  79. # 2-tuples, so remove the last element:
  80. assert len(binaries[0]) == 3
  81. binaries = [(binaries[0][1], '.')]