90 lines
3.0 KiB
Python
90 lines
3.0 KiB
Python
"""Build the Tk controller with Windows Python and PyInstaller.
|
|
|
|
Run `uv run --python 3.14 --group bundle python scripts/build_exe.py`.
|
|
Build output stays under dist/ and temporary files under build/. A Windows
|
|
executable must be built on Windows; this script never attempts cross-compiling.
|
|
"""
|
|
|
|
import argparse
|
|
import importlib.util
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def build_arguments(root, onefile=False, console=False):
|
|
"""Include the dynamically selected WinRT backend and its namespace modules."""
|
|
root = Path(root).resolve()
|
|
return [
|
|
"--noconfirm",
|
|
"--clean",
|
|
"--name",
|
|
"SoundTowerController",
|
|
"--console" if console else "--windowed",
|
|
"--onefile" if onefile else "--onedir",
|
|
"--distpath",
|
|
str(root / "dist"),
|
|
"--workpath",
|
|
str(root / "build" / "pyinstaller"),
|
|
"--specpath",
|
|
str(root / "build"),
|
|
"--paths",
|
|
str(root),
|
|
# Bleak chooses backends dynamically. WinRT's generated namespaces
|
|
# and extension modules must also be present in the frozen application.
|
|
"--collect-submodules",
|
|
"bleak.backends.winrt",
|
|
"--collect-all",
|
|
"winrt",
|
|
"--copy-metadata",
|
|
"bleak",
|
|
"--copy-metadata",
|
|
"winrt-runtime",
|
|
str(root / "controller" / "__main__.py"),
|
|
]
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument(
|
|
"--onefile",
|
|
action="store_true",
|
|
help="Make one self-extracting .exe instead of an application folder",
|
|
)
|
|
parser.add_argument(
|
|
"--console", action="store_true", help="Keep a console for diagnosing startup errors"
|
|
)
|
|
args = parser.parse_args(argv)
|
|
if sys.platform != "win32":
|
|
parser.error(
|
|
"Build with Windows Python in PowerShell, or Windows uv.exe from WSL. Linux Python cannot build a Windows executable."
|
|
)
|
|
if importlib.util.find_spec("PyInstaller") is None:
|
|
parser.error(
|
|
"PyInstaller is missing. Run with: uv run --group bundle python scripts/build_exe.py"
|
|
)
|
|
if importlib.util.find_spec("tkinter") is None:
|
|
parser.error(
|
|
"This Python installation lacks Tk. Use --python with a Windows Python installation that includes Tcl/Tk."
|
|
)
|
|
root = Path(__file__).resolve().parents[1]
|
|
subprocess.run(
|
|
[sys.executable, "-m", "PyInstaller", *build_arguments(root, args.onefile, args.console)],
|
|
cwd=root,
|
|
check=True,
|
|
)
|
|
executable = (
|
|
root / "dist" / "SoundTowerController.exe"
|
|
if args.onefile
|
|
else root / "dist" / "SoundTowerController" / "SoundTowerController.exe"
|
|
)
|
|
if not executable.is_file():
|
|
raise RuntimeError(f"Build finished without the expected executable: {executable}")
|
|
print(f"Built: {executable}")
|
|
if not args.onefile:
|
|
print("Keep the whole SoundTowerController folder together, including _internal.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|