import subprocess import shutil import os from pathlib import Path import PySide2 from PyInstaller.utils.hooks import collect_data_files # install: pip install PySide2 lxml nuitka pyinstaller # - PyInstaller # - nuitka # - PySide2 # - clang # === Конфигурация === USE_NUITKA = True # True — сборка через Nuitka, False — через PyInstaller MAIN_SCRIPT_NAME = "mainterm" OUTPUT_NAME = "BusTerminal" USE_ICON = False # True — использовать иконку, False — без иконки SRC_PATH = Path("./") SCRIPT_PATH = SRC_PATH / (MAIN_SCRIPT_NAME + ".py") DIST_PATH = Path("./").resolve() WORK_PATH = Path("./build_temp").resolve() SPEC_PATH = WORK_PATH ICON_PATH = SRC_PATH / "icon.png" ICON_ICO_PATH = SRC_PATH / "icon.ico" TEMP_FOLDERS = [ "build_temp", "__pycache__", MAIN_SCRIPT_NAME + ".build", MAIN_SCRIPT_NAME + ".onefile-build", MAIN_SCRIPT_NAME + ".dist" ] # === Пути к DLL и прочим зависимостям === LIBS = { } # === PySide2 плагины === PySide2_path = Path(PySide2.__file__).parent datas = [] datas += collect_data_files('PySide2', includes=['plugins/platforms/*']) datas += collect_data_files('PySide2', includes=['plugins/styles/*']) datas += collect_data_files('PySide2', includes=['plugins/imageformats/*']) add_data_list = [f"{src};{dest}" for src, dest in datas] # Проверка наличия DLL и добавление add_binary_list = [] for name, path in LIBS.items(): if path.exists(): add_binary_list.append(f"{str(path)};{name}") else: print(f"WARNING: {path.name} не найден — он не будет включён в сборку") def clean_temp(): for folder in TEMP_FOLDERS: path = Path(folder) if path.exists(): shutil.rmtree(path, ignore_errors=True) if USE_NUITKA: # Формируем include-data-file только для DLL include_data_files = [f"--include-data-file={str(path)}={name}" for name, path in LIBS.items() if path.exists()] # Добавляем опциональную иконку как встроенный ресурс if USE_ICON and ICON_ICO_PATH.exists(): include_data_files.append(f"--include-data-file={ICON_ICO_PATH}=icon.ico") cmd = [ "python", "-m", "nuitka", "--standalone", "--onefile", "--enable-plugin=pyside2", "--windows-console-mode=disable", f"--output-dir={DIST_PATH}", f"--output-filename={OUTPUT_NAME}.exe", ] # Добавляем параметр иконки только если она нужна и существует if USE_ICON and ICON_ICO_PATH.exists(): cmd.append(f"--windows-icon-from-ico={ICON_ICO_PATH}") cmd.extend(include_data_files) cmd.append(str(SCRIPT_PATH)) else: # PyInstaller cmd = [ "pyinstaller", "--name", OUTPUT_NAME, "--distpath", str(DIST_PATH), "--workpath", str(WORK_PATH), "--specpath", str(SPEC_PATH), "--windowed", "--hidden-import=PySide2.QtWidgets", "--hidden-import=PySide2.QtGui", "--hidden-import=PySide2.QtCore", *[arg for b in add_binary_list for arg in ("--add-binary", b)], *[arg for d in add_data_list for arg in ("--add-data", d)], ] # Добавляем иконку только если она нужна и существует if USE_ICON and ICON_ICO_PATH.exists(): cmd.append(f"--icon={ICON_ICO_PATH}") else: print("WARNING: Иконка не используется или не найдена") cmd.append(str(SCRIPT_PATH)) # === Запуск сборки === print("Выполняется сборка с помощью " + ("Nuitka" if USE_NUITKA else "PyInstaller")) print(" ".join(cmd)) try: subprocess.run(cmd, check=True) print("\nСборка успешно завершена!") # Удаление временных папок после сборки clean_temp() except subprocess.CalledProcessError: print("\nОшибка при сборке.")