diff --git a/src/chongming/scripts/build.py b/src/chongming/scripts/build.py index 1f1ae51..f1b2f99 100644 --- a/src/chongming/scripts/build.py +++ b/src/chongming/scripts/build.py @@ -96,11 +96,12 @@ def _run_cmd( cwd: str | None = None, capture: bool = True, shell: bool | None = None, + echo_on_error: bool = True, ) -> subprocess.CompletedProcess: """统一执行外部命令""" if shell is None: shell = is_windows - return subprocess.run( + result = subprocess.run( cmd, cwd=cwd, capture_output=capture, @@ -109,6 +110,30 @@ def _run_cmd( encoding="utf-8", errors="replace", ) + # 命令失败时自动回显捕获的输出,便于定位失败原因 + if echo_on_error and capture and result.returncode != 0: + _echo_captured_output(cmd, result) + return result + + +def _echo_captured_output( + cmd: list[str], result: subprocess.CompletedProcess +) -> None: + """命令失败时回显被捕获的输出(截取末尾若干行,避免刷屏)""" + max_lines = 40 + print(f"\n ── 命令执行失败 (exit={result.returncode}): {' '.join(cmd)} ──") + for stream_name, stream in (("stdout", result.stdout), ("stderr", result.stderr)): + if not stream or not stream.strip(): + continue + lines = stream.rstrip("\n").splitlines() + tail = lines[-max_lines:] + header = f" [{stream_name}]" + if len(lines) > max_lines: + header += f" (共 {len(lines)} 行,显示末尾 {len(tail)} 行)" + print(header) + for line in tail: + print(f" {line}") + print(" ────────────────────────────────────────\n") def _format_size(path: str | Path) -> str: @@ -270,7 +295,7 @@ def _stage_pyinstaller(config: Config) -> tuple[str, str]: result = _run_cmd(cmd, cwd="build", capture=True) if result.returncode != 0: - return f"❌ PyInstaller 失败", "" + return f"❌ PyInstaller 失败 (exit={result.returncode}),详情见上方输出", "" exe_path = Path("build/chongming") if is_windows: @@ -336,10 +361,13 @@ def _stage_nuitka(config: Config) -> tuple[str, str]: if icon.exists(): cmd.append(f"--windows-icon-from-ico={icon}") - try: - _run_cmd(cmd, cwd="build", capture=False) - except subprocess.CalledProcessError: + result = _run_cmd(cmd, cwd="build", capture=False) + if result.returncode != 0: # 降级重试(移除可能不兼容的参数) + print( + f" ⚠️ Nuitka 首次编译失败 (exit={result.returncode})," + f"尝试移除不兼容参数重试..." + ) fallback = [ arg for arg in cmd if arg not in ("--lto=yes", "--enable-plugin=upx") ]