configure.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #-----------------------------------------------------------------------------
  2. # Copyright (c) 2005-2023, PyInstaller Development Team.
  3. #
  4. # Distributed under the terms of the GNU General Public License (version 2
  5. # or later) with exception for distributing the bootloader.
  6. #
  7. # The full license is in the file COPYING.txt, distributed with this software.
  8. #
  9. # SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
  10. #-----------------------------------------------------------------------------
  11. """
  12. Configure PyInstaller for the current Python installation.
  13. """
  14. import os
  15. import subprocess
  16. from PyInstaller import compat
  17. from PyInstaller import log as logging
  18. logger = logging.getLogger(__name__)
  19. def _check_upx_availability(upx_dir):
  20. logger.debug('Testing UPX availability ...')
  21. upx_exe = "upx"
  22. if upx_dir:
  23. upx_exe = os.path.normpath(os.path.join(upx_dir, upx_exe))
  24. # Check if we can call `upx -V`.
  25. try:
  26. output = subprocess.check_output(
  27. [upx_exe, '-V'],
  28. stdin=subprocess.DEVNULL,
  29. stderr=subprocess.DEVNULL,
  30. encoding='utf-8',
  31. )
  32. except Exception:
  33. logger.debug('UPX is not available.')
  34. return False
  35. # Read the first line to display version string
  36. try:
  37. version_string = output.splitlines()[0]
  38. except IndexError:
  39. version_string = 'version string unavailable'
  40. logger.debug('UPX is available: %s', version_string)
  41. return True
  42. def _get_pyinstaller_cache_dir():
  43. old_cache_dir = None
  44. if compat.getenv('PYINSTALLER_CONFIG_DIR'):
  45. cache_dir = compat.getenv('PYINSTALLER_CONFIG_DIR')
  46. elif compat.is_win:
  47. cache_dir = compat.getenv('LOCALAPPDATA')
  48. if not cache_dir:
  49. cache_dir = os.path.expanduser('~\\Application Data')
  50. elif compat.is_darwin:
  51. cache_dir = os.path.expanduser('~/Library/Application Support')
  52. else:
  53. # According to XDG specification: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
  54. old_cache_dir = compat.getenv('XDG_DATA_HOME')
  55. if not old_cache_dir:
  56. old_cache_dir = os.path.expanduser('~/.local/share')
  57. cache_dir = compat.getenv('XDG_CACHE_HOME')
  58. if not cache_dir:
  59. cache_dir = os.path.expanduser('~/.cache')
  60. cache_dir = os.path.join(cache_dir, 'pyinstaller')
  61. # Move old cache-dir, if any, to new location.
  62. if old_cache_dir and not os.path.exists(cache_dir):
  63. old_cache_dir = os.path.join(old_cache_dir, 'pyinstaller')
  64. if os.path.exists(old_cache_dir):
  65. parent_dir = os.path.dirname(cache_dir)
  66. if not os.path.exists(parent_dir):
  67. os.makedirs(parent_dir)
  68. os.rename(old_cache_dir, cache_dir)
  69. return cache_dir
  70. def get_config(upx_dir=None):
  71. config = {}
  72. config['cachedir'] = _get_pyinstaller_cache_dir()
  73. config['upx_dir'] = upx_dir
  74. # Disable UPX on non-Windows. Using UPX (3.96) on modern Linux shared libraries (for example, the python3.x.so
  75. # shared library) seems to result in segmentation fault when they are dlopen'd. This happens in recent versions
  76. # of Fedora and Ubuntu linux, as well as in Alpine containers. On macOS, UPX (3.96) fails with
  77. # UnknownExecutableFormatException on most .dylibs (and interferes with code signature on other occasions). And
  78. # even when it would succeed, compressed libraries cannot be (re)signed due to failed strict validation.
  79. upx_available = _check_upx_availability(upx_dir)
  80. if upx_available:
  81. if compat.is_win or compat.is_cygwin:
  82. logger.info("UPX is available and will be used if enabled on build targets.")
  83. elif os.environ.get("PYINSTALLER_FORCE_UPX", "0") != "0":
  84. logger.warning(
  85. "UPX is available and force-enabled on platform with known compatibility problems - use at own risk!"
  86. )
  87. else:
  88. upx_available = False
  89. logger.info("UPX is available but is disabled on non-Windows due to known compatibility problems.")
  90. config['upx_available'] = upx_available
  91. return config