_shared_with_waf.py 4.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. Code to be shared by PyInstaller and the bootloader/wscript file.
  13. This code must not assume that either PyInstaller or any of its dependencies installed. I.e., the only imports allowed
  14. in here are standard library ones. Within reason, it is preferable that this file should still run under Python 2.7 as
  15. many compiler docker images still have only Python 2 installed.
  16. """
  17. import re
  18. def _pyi_machine(machine, system):
  19. # type: (str, str) -> str
  20. """
  21. Choose an intentionally simplified architecture identifier to be used in the bootloader's directory name.
  22. Args:
  23. machine:
  24. The output of ``platform.machine()`` or any known architecture alias or shorthand that may be used by a
  25. C compiler.
  26. system:
  27. The output of ``platform.system()`` on the target machine.
  28. Returns:
  29. Either a string tag or, on platforms that don't need an architecture tag, ``None``.
  30. Ideally, we would just use ``platform.machine()`` directly, but that makes cross-compiling the bootloader almost
  31. impossible, because you need to know at compile time exactly what ``platform.machine()`` will be at run time, based
  32. only on the machine name alias or shorthand reported by the C compiler at the build time. Rather, use a loose
  33. differentiation, and trust that anyone mixing armv6l with armv6h knows what they are doing.
  34. """
  35. # See the corresponding tests in tests/unit/test_compat.py for examples.
  36. if system == "Windows":
  37. if machine.lower().startswith("arm"):
  38. return "arm"
  39. else:
  40. return "intel"
  41. if system == "SunOS":
  42. if machine.lower() in ("x86_64", "x86", "i86pc"):
  43. return "intel"
  44. else:
  45. return "sparc"
  46. # Fold Android back into Linux. Currently, Termux environment is the only way to run PyInstaller on Android.
  47. # Starting with python 3.13, `platform.system()` reports 'Android' (see PEP-738); earlier versions reported 'Linux'.
  48. # The compiler-based target platform identification in `waf`, however, identifies target platform as Linux on all
  49. # python versions.
  50. if system == "Android":
  51. system = "Linux"
  52. if system != "Linux":
  53. # No architecture specifier for anything par Linux.
  54. # - macOS is on two 64 bit architectures, but they are merged into one "universal2" bootloader.
  55. # - BSD supports a wide range of architectures, but according to PyPI's download statistics, every one of our
  56. # BSD users are on x86_64. This may change in the distant future.
  57. return
  58. if machine.startswith(("arm", "aarch")):
  59. # ARM has a huge number of similar and aliased sub-versions, such as armv5, armv6l armv8h, aarch64.
  60. return "arm"
  61. if machine in ("thumb"):
  62. # Reported by waf/gcc when Thumb instruction set is enabled on 32-bit ARM. The platform.machine() returns "arm"
  63. # regardless of the instruction set.
  64. return "arm"
  65. if machine in ("x86_64", "x64", "x86"):
  66. return "intel"
  67. if re.fullmatch("i[1-6]86", machine):
  68. return "intel"
  69. if machine.startswith(("ppc", "powerpc")):
  70. # PowerPC comes in 64 vs 32 bit and little vs big endian variants.
  71. return "ppc"
  72. if machine in ("mips64", "mips"):
  73. return "mips"
  74. if machine.startswith("riscv"):
  75. return "riscv"
  76. if machine.startswith(("sw_", "sunway")):
  77. return "sunway"
  78. if machine.startswith("loongarch"):
  79. return "loongarch"
  80. # Machines with no known aliases :)
  81. if machine in ("s390x",):
  82. return machine
  83. # Unknown architectures are allowed by default, but will all be placed under one directory. In theory, trying to
  84. # have multiple unknown architectures in one copy of PyInstaller will not work, but that should be sufficiently
  85. # unlikely to ever happen.
  86. return "unknown"