86 lines
3.8 KiB
Python
86 lines
3.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""builder.py - Handles the execution of the PyInstaller build process in a separate thread."""
|
|
|
|
import subprocess
|
|
import os
|
|
import traceback
|
|
from typing import Optional, List, Dict, Callable
|
|
|
|
def run_build_in_thread(
|
|
command: List[str],
|
|
working_dir: str,
|
|
output_queue: 'queue.Queue',
|
|
logger_func: Callable[..., None],
|
|
output_dir_name: str,
|
|
environment: Optional[Dict[str, str]] = None
|
|
):
|
|
"""
|
|
Executes the PyInstaller command using subprocess.Popen in the background.
|
|
Streams stdout/stderr to the output_queue for display in the GUI.
|
|
Notifies the main thread of success, failure, or completion via the queue.
|
|
"""
|
|
build_process = None
|
|
try:
|
|
logger_func("Build thread starting execution...", level="INFO")
|
|
command_str_for_log = " ".join([f'"{c}"' if " " in c else c for c in command])
|
|
logger_func(f"PyInstaller command to be executed: {command_str_for_log}", level="DEBUG")
|
|
logger_func(f"Working directory: {working_dir}", level="DEBUG")
|
|
|
|
env_log_msg = f"Using {'custom' if environment else 'inherited'} environment."
|
|
logger_func(f"PyInstaller process starting. {env_log_msg}", level="INFO")
|
|
|
|
build_process = subprocess.Popen(
|
|
command,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
cwd=working_dir,
|
|
text=True,
|
|
encoding="utf-8",
|
|
errors="replace",
|
|
bufsize=1,
|
|
env=environment,
|
|
)
|
|
logger_func(f"PyInstaller process launched (PID: {build_process.pid}).", level="INFO")
|
|
|
|
# Stream output
|
|
while True:
|
|
line = build_process.stdout.readline()
|
|
if not line:
|
|
if build_process.poll() is not None:
|
|
logger_func("End of PyInstaller output stream.", level="DEBUG")
|
|
break
|
|
else:
|
|
continue
|
|
# Messaggio per il logger della GUI
|
|
output_queue.put(("LOG_STREAM", "LOG", line))
|
|
|
|
return_code = build_process.wait()
|
|
logger_func(f"PyInstaller process finished with exit code: {return_code}", level="INFO")
|
|
|
|
if return_code == 0:
|
|
dist_path_abs = os.path.join(working_dir, output_dir_name)
|
|
if os.path.exists(dist_path_abs):
|
|
success_msg = f"Build completed successfully!\nOutput Directory: {dist_path_abs}"
|
|
# Messaggio per la GUI principale
|
|
output_queue.put(("MAIN_GUI_ACTION", "BUILD_SUCCESS", success_msg))
|
|
else:
|
|
warn_msg = f"Build finished with exit code 0, but output directory not found:\n{dist_path_abs}\nCheck the full log for potential issues."
|
|
logger_func(warn_msg, level="WARNING")
|
|
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", warn_msg))
|
|
else:
|
|
error_msg = f"Build failed! (Exit Code: {return_code})\nCheck the log for details."
|
|
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", error_msg))
|
|
|
|
except FileNotFoundError:
|
|
error_msg = "Error: 'pyinstaller' command not found.\nEnsure PyInstaller is installed correctly and in the system PATH."
|
|
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", error_msg))
|
|
logger_func(error_msg, level="CRITICAL")
|
|
except Exception as e:
|
|
error_msg = f"Unexpected error during build process execution: {e}"
|
|
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", error_msg))
|
|
logger_func(error_msg, level="CRITICAL")
|
|
logger_func(traceback.format_exc(), level="DEBUG")
|
|
finally:
|
|
# Segnala sempre la fine del tentativo di build
|
|
output_queue.put(("MAIN_GUI_ACTION", "BUILD_FINISHED", None))
|
|
logger_func("Build thread finished.", level="INFO") |