From 347998664eb4f9c252603d775df53f31d6e558f3 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 23 Aug 2026 15:52:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv):=20phase2command=20=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=20Phase=20C=20=E4=B8=8D=E5=86=8D=E5=9B=A0=20.obj=20=E7=BC=BA?= =?UTF-8?q?=E5=A4=B1=E4=B8=AD=E6=AD=A2=E2=80=94=E2=80=94=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E6=AD=A3=E7=A1=AE=E5=86=99=E5=85=A5=20bat=20?= =?UTF-8?q?-=20=E6=A0=B9=E5=9B=A0=EF=BC=9Aphase2command=20=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E4=B8=8B=20llc=20=E6=9C=AA=E6=89=A7=E8=A1=8C=EF=BC=88?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E5=86=99=E5=85=A5=20bat=EF=BC=89=EF=BC=8CPha?= =?UTF-8?q?se=20C=20=E7=9A=84'=E5=8F=AF=E8=BE=BE=E6=A8=A1=E5=9D=97=20.obj?= =?UTF-8?q?=20=E5=AD=98=E5=9C=A8=E6=80=A7=E6=A3=80=E6=9F=A5'=E5=AF=B9?= =?UTF-8?q?=E6=89=80=E6=9C=89=E5=AE=9E=E7=8E=B0=E6=A8=A1=E5=9D=97=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=20VLogger.error=E2=86=92sys.exit(1)=EF=BC=8C=E8=BF=9B?= =?UTF-8?q?=E7=A8=8B=E5=9C=A8=E8=B0=83=E7=94=A8=20link=5Fobjs=5Fto=5Fexe?= =?UTF-8?q?=20=E4=B9=8B=E5=89=8D=E7=BB=88=E6=AD=A2=EF=BC=8Cclang=20?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E5=91=BD=E4=BB=A4=E6=B0=B8=E8=BF=9C=E5=86=99?= =?UTF-8?q?=E4=B8=8D=E8=BF=9B=20bat=20-=20=E4=BF=AE=E5=A4=8D=EF=BC=9APhase?= =?UTF-8?q?=20C=20=E5=8F=AF=E8=BE=BE=E6=94=B6=E9=9B=86=E5=9C=A8=20=5Fphase?= =?UTF-8?q?2=5Fcmd=5Fpath=20=E9=9D=9E=E7=A9=BA=E6=97=B6=E8=B7=B3=E8=BF=87?= =?UTF-8?q?=E7=BC=BA=E5=A4=B1=E6=8A=A5=E9=94=99=EF=BC=8C=E5=B9=B6=E6=8A=8A?= =?UTF-8?q?=E5=8F=AF=E8=BE=BE=20includes=20.obj=20=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E7=85=A7=E5=B8=B8=E5=8A=A0=E5=85=A5=20final=5Fobj=5Fpaths?= =?UTF-8?q?=EF=BC=88bat=20=E6=89=8B=E5=B7=A5=E6=89=A7=E8=A1=8C=E5=90=8E?= =?UTF-8?q?=E5=8D=B3=E5=AD=98=E5=9C=A8=EF=BC=89=EF=BC=8C=E4=BF=9D=E8=AF=81?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E5=91=BD=E4=BB=A4=E5=AE=8C=E6=95=B4=20-=20?= =?UTF-8?q?=E9=99=84=E5=B8=A6=EF=BC=9A--run=20=E5=9C=A8=20phase2command=20?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=B8=8B=E8=B7=B3=E8=BF=87=EF=BC=88exe=20?= =?UTF-8?q?=E5=B0=9A=E6=9C=AA=E9=93=BE=E6=8E=A5=EF=BC=8C=E5=A4=9A=E6=96=87?= =?UTF-8?q?=E4=BB=B6+=E5=8D=95=E6=96=87=E4=BB=B6=E4=B8=A4=E5=A4=84?= =?UTF-8?q?=EF=BC=89=EF=BC=9BBuildPipeline.=5Fphase2=5Fwrite=5Fcmd=20?= =?UTF-8?q?=E8=A1=A5=20global=20=5Fphase2=5Fbat=5Finit=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E6=AF=8F=E6=AC=A1=E8=B0=83=E7=94=A8=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E5=86=99=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/Phase/BuildPipeline.vp | 47 ++++++++++++++++---------------- App/lib/Phase/Phase2/__init__.vp | 21 ++++++++++++-- App/main.vp | 3 +- 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/App/lib/Phase/BuildPipeline.vp b/App/lib/Phase/BuildPipeline.vp index f63e358..bb8674b 100644 --- a/App/lib/Phase/BuildPipeline.vp +++ b/App/lib/Phase/BuildPipeline.vp @@ -485,29 +485,30 @@ def free_llc_task(task: LlcTask | t.CPtr): task.ModuleSha1 = None -def _phase2_write_cmd(cmd: str) -> None: - """--phase2command 模式:把命令追加写入 bat(不执行) - - 首次调用写入 header(@echo off + 说明),后续命令以 \r\n 分行追加, - 与 cmd.exe 批处理格式一致。bat 路径由模块级 _phase2_cmd_path 指定。 - """ - if _phase2_cmd_path is None or cmd is None: - return - f: fileio.File | t.CPtr = fileio.File(_phase2_cmd_path, fileio.MODE.A) - if f.closed: - VLogger.error("phase2command: bat 打开失败", "phase2cmd") - return - if _phase2_bat_init == 0: - _phase2_bat_init = 1 - hdr1: str = "@echo off\r\n" - hdr2: str = "rem TransPyV --phase2command generated commands\r\n" - f.write(hdr1, string.strlen(hdr1)) - f.write(hdr2, string.strlen(hdr2)) - f.write(cmd, string.strlen(cmd)) - f.write("\r\n", 2) - f.close() - - +def _phase2_write_cmd(cmd: str) -> None: + """--phase2command 模式:把命令追加写入 bat(不执行) + + 首次调用写入 header(@echo off + 说明),后续命令以 \r\n 分行追加, + 与 cmd.exe 批处理格式一致。bat 路径由模块级 _phase2_cmd_path 指定。 + """ + global _phase2_bat_init + if _phase2_cmd_path is None or cmd is None: + return + f: fileio.File | t.CPtr = fileio.File(_phase2_cmd_path, fileio.MODE.A) + if f.closed: + VLogger.error("phase2command: bat 打开失败", "phase2cmd") + return + if _phase2_bat_init == 0: + _phase2_bat_init = 1 + hdr1: str = "@echo off\r\n" + hdr2: str = "rem TransPyV --phase2command generated commands\r\n" + f.write(hdr1, string.strlen(hdr1)) + f.write(hdr2, string.strlen(hdr2)) + f.write(cmd, string.strlen(cmd)) + f.write("\r\n", 2) + f.close() + + def _run_cmd_wait(cmd: str) -> int: """CreateProcessA 同步执行命令并等待退出,返回退出码。 diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index 1b0a4e1..90fca2e 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -1408,7 +1408,18 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, else: # .obj 缺失:纯声明模块(text.ll 无 define 行,如 stdio.vp 全 pass) # 无需 .obj,静默跳过;实现文件缺失才是编译产物异常(fail-fast) - if StubMergerIR.IsDeclOnlyModule(temp_dir, td_len_pc, rsha1_pc) != 1: + # phase2command 模式:.obj 尚未生成(由手工执行 bat 产生), + # 缺失属预期——路径照常加入链接命令,跳过缺失报错。 + if BuildPipeline._phase2_cmd_path is not None: + op_len_p2: t.CSizeT = string.strlen(obj_path_pc) + if fop_pos + op_len_p2 + 2 < OBJ_PATHS_SIZE + 512: + if fop_pos > 0: + final_obj_paths[fop_pos] = ' ' + fop_pos += 1 + string.strcpy(final_obj_paths + fop_pos, obj_path_pc) + fop_pos += op_len_p2 + final_obj_paths[fop_pos] = '\0' + elif StubMergerIR.IsDeclOnlyModule(temp_dir, td_len_pc, rsha1_pc) != 1: fb_pc: str = VLogger.fmt_buf() if fb_pc is not None: viperlib.snprintf(fb_pc, 1024, "可达模块 .obj 缺失: %s", obj_path_pc) @@ -1434,7 +1445,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, if fb is not None: viperlib.snprintf(fb, 1024, "输出: %s", exe_path) VLogger.success(fb, "PhaseC") - if args.get_bool("run"): + if args.get_bool("run") and BuildPipeline._phase2_cmd_path is not None: + # phase2command 模式:exe 尚未链接(命令在 bat 中),跳过 --run + fb_p2run: str = VLogger.fmt_buf() + if fb_p2run is not None: + viperlib.snprintf(fb_p2run, 1024, "phase2command 模式:跳过 --run(exe 尚未链接)") + VLogger.info(fb_p2run, "phase2cmd") + elif args.get_bool("run"): fb: str = VLogger.fmt_buf() if fb is not None: viperlib.snprintf(fb, 1024, "执行: %s", exe_path) diff --git a/App/main.vp b/App/main.vp index eb3f22b..80ba002 100644 --- a/App/main.vp +++ b/App/main.vp @@ -633,7 +633,8 @@ Target: %s viperlib.snprintf(fb8, 1024, "输出: %s/%s", output_dir, linker_output) log.info(fb8) # --run 模式:执行生成的可执行文件 - if args.get_bool("run"): + # phase2command 模式:exe 尚未链接(命令在 bat 中),跳过 --run + if args.get_bool("run") and BuildPipeline._phase2_cmd_path is None: exe_path: bytes = stdlib.malloc(string.strlen(output_dir) + string.strlen(linker_output) + 2) if exe_path is not None: viperlib.snprintf(exe_path, 256, "%s/%s", output_dir, linker_output)