forked from pyinstaller/pyinstaller
-
Notifications
You must be signed in to change notification settings - Fork 2
/
setup.py
166 lines (134 loc) · 5.38 KB
/
setup.py
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
163
164
165
166
#-----------------------------------------------------------------------------
# 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
#-- 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"
try:
from wheel.bdist_wheel import bdist_wheel
except ImportError:
raise SystemExit("Error: Building wheels requires the 'wheel' package. Please `pip install wheel` then try again.")
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,
},
)