|
| 1 | +import os |
| 2 | +import shutil |
| 3 | +import subprocess |
| 4 | +import sys |
| 5 | +import time |
| 6 | + |
| 7 | +# TODO strip |
| 8 | +# pyinstaller ? |
| 9 | +# sudo pacman -S ccache |
| 10 | + |
| 11 | +# --- Конфигурация сборки Nuitka --- |
| 12 | + |
| 13 | +# Имя основного скрипта вашего приложения |
| 14 | +main_script = "xmlgenerator/bootstrap.py" |
| 15 | + |
| 16 | +# Имя выходного исполняемого файла (без расширения) |
| 17 | +output_filename_base = "xmlgenerator" |
| 18 | + |
| 19 | +# Директория для собранного файла |
| 20 | +output_dir = "dist_native" |
| 21 | + |
| 22 | +# Собрать в один файл? (True/False) |
| 23 | +use_onefile = True |
| 24 | + |
| 25 | +build_time = time.time() |
| 26 | +build_time = str(int(build_time)) |
| 27 | + |
| 28 | +file_ver = f"{build_time[-4]}.{build_time[-3]}.{build_time[-2]}.{build_time[-1]}" |
| 29 | + |
| 30 | +print(file_ver) |
| 31 | + |
| 32 | +# Дополнительные опции Nuitka (добавляйте сюда нужные флаги) |
| 33 | +extra_nuitka_options = [ |
| 34 | + # "--show-progress", |
| 35 | + "--no-deployment-flag=self-execution", # Флаг для исправления ошибки |
| 36 | + "--standalone", |
| 37 | + # "--python-flag=no_site", |
| 38 | + # "--onefile-no-compression", |
| 39 | + "--follow-stdlib", |
| 40 | + # "--nofollow-import-to=tkinter", |
| 41 | + # "--include-package=some_package", |
| 42 | + |
| 43 | + "--product-name=xmlgenerator", |
| 44 | + "--product-version=0.1.0", |
| 45 | + f"--file-version={file_ver}", |
| 46 | + "--onefile-tempdir-spec={CACHE_DIR}/{PRODUCT}/{VERSION}", |
| 47 | + |
| 48 | + "--lto=yes", # Use link time optimizations (MSVC, gcc, clang). |
| 49 | + # "--static-libpython=yes", # Use static link library of Python undefined symbol: PyList_New |
| 50 | + |
| 51 | + # "--plugin-list", |
| 52 | + "--enable-plugin=anti-bloat", |
| 53 | + "--enable-plugin=pylint-warnings", |
| 54 | + "--enable-plugin=no-qt", |
| 55 | +] |
| 56 | + |
| 57 | +# --- Логика сборки --- |
| 58 | + |
| 59 | +# Определяем базовое имя скрипта для имени директории сборки |
| 60 | +main_script_basename = os.path.splitext(os.path.basename(main_script))[0] |
| 61 | + |
| 62 | +# Определяем ПОТЕНЦИАЛЬНЫЕ имена сборочных директорий Nuitka |
| 63 | +possible_temp_dirs = [ |
| 64 | + # os.path.join(output_dir, f"{main_script_basename}.build"), |
| 65 | + # os.path.join(output_dir, f"{main_script_basename}.onefile-build"), |
| 66 | +] |
| 67 | + |
| 68 | +# Определяем полное имя выходного файла с расширением для текущей ОС |
| 69 | +if sys.platform == "win32": |
| 70 | + output_filename = f"{output_filename_base}.exe" |
| 71 | +elif sys.platform == "darwin": |
| 72 | + output_filename = output_filename_base |
| 73 | +else: # Linux и другие |
| 74 | + output_filename = output_filename_base |
| 75 | + |
| 76 | +# Формируем команду Nuitka |
| 77 | +command = [ |
| 78 | + sys.executable, # Используем тот же python, что и для запуска скрипта |
| 79 | + "-m", |
| 80 | + "nuitka", |
| 81 | + f"--output-dir={output_dir}", |
| 82 | + f"--output-filename={output_filename}", # Указываем имя выходного файла |
| 83 | +] |
| 84 | + |
| 85 | +if use_onefile: |
| 86 | + command.append("--onefile") |
| 87 | + |
| 88 | +# Добавляем дополнительные опции |
| 89 | +command.extend(extra_nuitka_options) |
| 90 | + |
| 91 | +# Добавляем главный скрипт в конец команды |
| 92 | +command.append(main_script) |
| 93 | + |
| 94 | +print("Запуск Nuitka со следующей командой:") |
| 95 | +print(" ".join(command)) |
| 96 | +print("-" * 30) |
| 97 | + |
| 98 | +# Запускаем сборку с Popen для потокового вывода |
| 99 | +try: |
| 100 | + # --- Очистка выходной директории перед сборкой --- |
| 101 | + if os.path.exists(output_dir): |
| 102 | + print(f"Очистка существующей директории: {output_dir}") |
| 103 | + try: |
| 104 | + shutil.rmtree(output_dir) |
| 105 | + print("Директория успешно очищена.") |
| 106 | + except OSError as e: |
| 107 | + print(f"Ошибка при очистке директории {output_dir}: {e}") |
| 108 | + # Решаем, прерывать ли сборку, если очистка не удалась. |
| 109 | + # В данном случае, продолжим, т.к. makedirs может сработать. |
| 110 | + # ------------------------------------------------ |
| 111 | + |
| 112 | + # Убедимся, что директория существует (или создаем ее после очистки) |
| 113 | + os.makedirs(output_dir, exist_ok=True) |
| 114 | + |
| 115 | + # Используем Popen и перенаправляем stderr в stdout для единого потока |
| 116 | + process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding='utf-8', errors='replace', bufsize=1) |
| 117 | + |
| 118 | + print("--- Вывод Nuitka --- ") |
| 119 | + # Читаем вывод построчно в реальном времени |
| 120 | + if process.stdout: |
| 121 | + for line in iter(process.stdout.readline, ''): |
| 122 | + # Выводим каждую строку немедленно |
| 123 | + sys.stdout.write(line) |
| 124 | + sys.stdout.flush() |
| 125 | + process.stdout.close() |
| 126 | + |
| 127 | + # Ждем завершения процесса и получаем код возврата |
| 128 | + return_code = process.wait() |
| 129 | + print("-" * 30) |
| 130 | + |
| 131 | + if return_code == 0: |
| 132 | + print(f"Сборка успешно завершена! Исполняемый файл: {os.path.join(output_dir, output_filename)}") |
| 133 | + |
| 134 | + # --- Удаление ВСЕХ известных сборочных директорий --- |
| 135 | + print("Попытка удаления временных сборочных директорий...") |
| 136 | + for temp_dir_path in possible_temp_dirs: |
| 137 | + if os.path.exists(temp_dir_path): |
| 138 | + print(f"Найден и удаляется: {temp_dir_path}") |
| 139 | + try: |
| 140 | + shutil.rmtree(temp_dir_path) |
| 141 | + print(f"Успешно удалено: {temp_dir_path}") |
| 142 | + except OSError as e: |
| 143 | + print(f"Ошибка при удалении {temp_dir_path}: {e}") |
| 144 | + # else: |
| 145 | + # Можно раскомментировать для отладки: |
| 146 | + # print(f"Директория не найдена: {temp_dir_path}") |
| 147 | + print("Очистка временных директорий завершена.") |
| 148 | + # -------------------------------------------------- |
| 149 | + else: |
| 150 | + print(f"Ошибка во время сборки Nuitka (код возврата {return_code})") |
| 151 | + sys.exit(return_code) # Выходим с кодом ошибки Nuitka |
| 152 | + |
| 153 | +except FileNotFoundError: |
| 154 | + print(f"Ошибка: Не удалось найти '{sys.executable} -m nuitka'. Убедитесь, что Nuitka установлена в вашем окружении.") |
| 155 | + sys.exit(1) |
| 156 | +except Exception as e: |
| 157 | + print(f"Произошла непредвиденная ошибка: {e}") |
| 158 | + sys.exit(1) |
0 commit comments