1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
#-----------------------------------------------------------------------------
# Copyright (c) 2005-2023, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
# or later) with exception for distributing the bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------
import sys
import os
from setuptools import setup
from setuptools.command.bdist_wheel import bdist_wheel
#-- plug-in building the bootloader
from distutils.core import Command
from distutils.command.build import build
# Hack that prevents PyInstaller.compat from failing due to unmet run-time dependencies (importlib-metadata on
# python < 3.10, pywin32-ctypes on Windows). These dependencies are not required for the subset of functionality that is
# used here in the `setup.py`.
os.environ["_PYINSTALLER_SETUP_PY"] = "1"
class build_bootloader(Command):
"""
Wrapper for distutil command `build`.
"""
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def bootloader_exists(self):
# Checks if the console, non-debug bootloader exists
from PyInstaller import HOMEPATH, PLATFORM
exe = 'run'
pyi_platform = os.environ.get("PYI_PLATFORM", PLATFORM)
if "Windows" in pyi_platform:
exe = 'run.exe'
exe = os.path.join(HOMEPATH, 'PyInstaller', 'bootloader', pyi_platform, exe)
return os.path.isfile(exe)
def compile_bootloader(self):
import subprocess
from PyInstaller import HOMEPATH
src_dir = os.path.join(HOMEPATH, 'bootloader')
additional_args = os.getenv('PYINSTALLER_BOOTLOADER_WAF_ARGS', '').strip().split()
cmd = [sys.executable, './waf', 'configure', 'all']
cmd += additional_args
rc = subprocess.call(cmd, cwd=src_dir)
if rc:
raise SystemExit('ERROR: Failed compiling the bootloader. Please compile manually and rerun')
def run(self):
if getattr(self, 'dry_run', False):
return
if self.bootloader_exists() and not os.environ.get("PYINSTALLER_COMPILE_BOOTLOADER"):
return
print(
'No precompiled bootloader found or compile forced. Trying to compile the bootloader for you ...',
file=sys.stderr
)
self.compile_bootloader()
if not self.bootloader_exists():
raise SystemExit("ERROR: Bootloaders have been compiled for the wrong platform")
class MyBuild(build):
# plug `build_bootloader` into the `build` command
def run(self):
self.run_command('build_bootloader')
build.run(self)
# --- Builder class for separate per-platform wheels. ---
class Wheel(bdist_wheel):
"""
Base class for building a wheel for one platform, collecting only the relevant bootloaders for that platform.
"""
def finalize_options(self):
# Inject the platform name.
if os.environ.get("PYI_WHEEL_TAG"):
self.plat_name = os.environ["PYI_WHEEL_TAG"]
self.plat_name_supplied = True
self.pyi_platform = os.environ.get("PYI_PLATFORM")
if self.pyi_platform:
if "Darwin" in self.pyi_platform:
icons = ["icns"]
elif "Windows" in self.pyi_platform:
icons = ["ico"]
else:
icons = []
else:
icons = ["ico", "icns"]
self.distribution.package_data = {
"PyInstaller": [
# And add the correct bootloaders as data files.
f"bootloader/{self.pyi_platform or '*'}/*",
*(f"bootloader/images/*.{suffix}" for suffix in icons),
# These files need to be explicitly included as well.
"fake-modules/*.py",
"fake-modules/_pyi_rth_utils/*.py",
"hooks/rthooks.dat",
"lib/README.rst",
],
}
super().finalize_options()
def run(self):
# Note that 'clean' relies on clean::all=1 being set in the `setup.cfg` or the build cache "leaks" into
# subsequently built wheels.
self.run_command("clean")
super().run()
#--
# --- Prevent `python setup.py install` from building and installing eggs ---
if "bdist_egg" not in sys.argv:
from setuptools.command.bdist_egg import bdist_egg
class bdist_egg_disabled(bdist_egg):
"""
Disabled version of bdist_egg, which prevents `setup.py install` from performing setuptools' default
easy_install, which is deprecated and should be avoided.
"""
def run(self):
raise SystemExit(
"Error: Aborting implicit building of eggs. To install from source, use `pip install .` instead of "
"`python setup.py install`."
)
bdist_egg_override = {'bdist_egg': bdist_egg_disabled}
else:
bdist_egg_override = {}
#--
setup(
setup_requires=["setuptools >= 42.0.0"],
cmdclass={
'build_bootloader': build_bootloader,
'build': MyBuild,
'bdist_wheel': Wheel,
**bdist_egg_override,
},
)
|