Fixed
This commit is contained in:
@@ -19,6 +19,7 @@ import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
@@ -207,6 +208,19 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
BuildPipeline.ensure_dir(temp_dir)
|
||||
BuildPipeline.ensure_dir(output_dir)
|
||||
|
||||
# === 0.5 扫描 includes 目录填充 Sha1Store(消除 Phase1 依赖)===
|
||||
# Phase2 不依赖 Phase1 的副作用:如果 Sha1Store 为空(Phase1 未运行或提前返回),
|
||||
# 自行扫描 includes 目录并填充 Sha1Store,确保后续"编译缺失 includes"逻辑能正常工作
|
||||
if includes_dir is not None:
|
||||
if StubMerger.GetSha1StoreCount() == 0:
|
||||
inc_scan_result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir)
|
||||
if inc_scan_result is not None:
|
||||
inc_filled: int = StubMerger.PopulateSha1MapStore(inc_scan_result)
|
||||
fb_inc: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_inc is not None:
|
||||
viperlib.snprintf(fb_inc, 1024, "Phase2 自主填充 includes Sha1Store: %d 个", inc_filled)
|
||||
VLogger.info(fb_inc, "project")
|
||||
|
||||
# 追加 App 源文件 SHA1 到 _sha1_map.txt(人类可读输出,程序内部不读取此文件)
|
||||
# 格式: {sha1}:{rel_path}\n (保留目录结构,如 lib/core/VLogger.py)
|
||||
# 同步追加到内存存储器(AppendToSha1MapStore,供跨模块 CDefine 查找)
|
||||
@@ -296,10 +310,62 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
|
||||
|
||||
# === 2. Phase A: 为每个文件生成 stub + text ===
|
||||
# app_deps_buf: 收集所有 App 源文件的直接依赖模块名(空格分隔)
|
||||
# 供 Phase B+ 的 _BuildReachableSha1Set 作为初始 worklist,实现按需编译
|
||||
# 声明在 if 块外,确保 Phase B+ 和清理代码能访问
|
||||
APP_DEPS_BUF_SIZE: t.CSizeT = 8192
|
||||
app_deps_buf: bytes = None
|
||||
app_deps_len: t.CSizeT = 0
|
||||
if do_phase1 != 0:
|
||||
if log is not None:
|
||||
log.banner("Phase A: 生成 stub + text")
|
||||
|
||||
# === Phase A-pre-inc: includes 预注册 struct + 依赖填充 ===
|
||||
# 必须在 App 源文件预注册之前执行:App 源文件(strict_mode=1)可能继承
|
||||
# 或引用 includes 中的 struct(如 ast.AST)。若 includes struct 未注册,
|
||||
# App 源文件翻译会失败 → .obj 缺失 → undefined reference。
|
||||
# 同时填充 PopulateIncludesDeps,供 Phase B+ 的 _BuildReachableSha1Set 使用。
|
||||
# 多遍扫描:解决跨文件继承问题(如 Constant(AST) 在 AST 未注册时被跳过)。
|
||||
if includes_dir is not None and includes_binary_dir is not None:
|
||||
store_count_inc_pre: int = StubMerger.GetSha1StoreCount()
|
||||
if store_count_inc_pre > 0:
|
||||
store_sha1_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
|
||||
store_rel_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
|
||||
inc_dir_len_pre: t.CSizeT = string.strlen(includes_dir)
|
||||
deps_filled_pre: int = 0
|
||||
PHASE_A_INC_MAX_PASSES: t.CInt = 3
|
||||
for pass_inc_i in range(PHASE_A_INC_MAX_PASSES):
|
||||
struct_count_before_inc: int = HandlesStruct.get_struct_count()
|
||||
for si_inc in range(store_count_inc_pre):
|
||||
inc_sha1_pre: str = store_sha1_inc_pre + t.CSizeT(si_inc) * 17
|
||||
inc_rel_pre: str = store_rel_inc_pre + t.CSizeT(si_inc) * StubMerger.MAX_REL_PATH_LEN
|
||||
if inc_rel_pre is None or inc_rel_pre[0] == '\0':
|
||||
continue
|
||||
rel_len_pre: t.CSizeT = string.strlen(inc_rel_pre)
|
||||
full_path_pre: bytes = stdlib.malloc(inc_dir_len_pre + rel_len_pre + 2)
|
||||
if full_path_pre is None:
|
||||
continue
|
||||
viperlib.snprintf(full_path_pre, inc_dir_len_pre + rel_len_pre + 2,
|
||||
"%s/%s", includes_dir, inc_rel_pre)
|
||||
pkg_inc_pre: str = HandlesImports.compute_package_from_relpath(mb, inc_rel_pre)
|
||||
tr_inc_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(
|
||||
mb, full_path_pre, inc_sha1_pre, pkg_inc_pre, 1)
|
||||
stdlib.free(full_path_pre)
|
||||
if tr_inc_pre is not None:
|
||||
# 依赖填充只在第一遍执行(PopulateIncludesDeps 内部有去重)
|
||||
if pass_inc_i == 0:
|
||||
if tr_inc_pre._imported_modules is not None:
|
||||
if StubMerger.PopulateIncludesDeps(inc_sha1_pre, tr_inc_pre._imported_modules) == 0:
|
||||
deps_filled_pre = deps_filled_pre + 1
|
||||
struct_count_after_inc: int = HandlesStruct.get_struct_count()
|
||||
# 收敛检查:本遍没有新结构体注册 → 所有类已注册
|
||||
if struct_count_after_inc == struct_count_before_inc:
|
||||
break
|
||||
fb_inc_pre: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_inc_pre is not None:
|
||||
viperlib.snprintf(fb_inc_pre, 1024, "includes 预注册 + 依赖填充: %d/%d", deps_filled_pre, store_count_inc_pre)
|
||||
VLogger.info(fb_inc_pre, "prePhaseA")
|
||||
|
||||
# === Phase A-pre: 预注册所有源文件的 struct/enum/union ===
|
||||
# 解决循环引用问题:circ_a 翻译时需要知道 circ_b.ClassB 的 struct 定义
|
||||
# 仅注册 struct/enum/union(declare_only=1),不翻译方法体
|
||||
@@ -334,6 +400,14 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
PHASE_A_IR_SIZE: t.CSizeT = 1048576
|
||||
td_len_pa: t.CSizeT = string.strlen(temp_dir)
|
||||
|
||||
# app_deps_buf: 收集所有 App 源文件的直接依赖模块名(空格分隔)
|
||||
# 供 Phase B+ 的 _BuildReachableSha1Set 作为初始 worklist 使用
|
||||
# 声明已在 if 块外,此处仅赋值
|
||||
app_deps_buf = stdlib.malloc(APP_DEPS_BUF_SIZE)
|
||||
app_deps_len = 0
|
||||
if app_deps_buf is not None:
|
||||
app_deps_buf[0] = '\0'
|
||||
|
||||
for i in range(file_count):
|
||||
ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
|
||||
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
|
||||
@@ -394,8 +468,21 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
df_a.close()
|
||||
stdlib.free(deps_path_a)
|
||||
|
||||
# 收集 _imported_modules 到 app_deps_buf(供 Phase B+ 按需编译)
|
||||
if tr_a._imported_modules is not None and app_deps_buf is not None:
|
||||
im_len_a: t.CSizeT = string.strlen(tr_a._imported_modules)
|
||||
if im_len_a > 0 and app_deps_len + im_len_a + 1 < APP_DEPS_BUF_SIZE:
|
||||
if app_deps_len > 0:
|
||||
app_deps_buf[app_deps_len] = ' '
|
||||
app_deps_len = app_deps_len + 1
|
||||
string.strcpy(app_deps_buf + app_deps_len, tr_a._imported_modules)
|
||||
app_deps_len = app_deps_len + im_len_a
|
||||
app_deps_buf[app_deps_len] = '\0'
|
||||
|
||||
if do_phase2 == 0:
|
||||
VLogger.info("Phase A 完成(仅 stub 生成)", "project")
|
||||
if app_deps_buf is not None:
|
||||
stdlib.free(app_deps_buf)
|
||||
stdlib.free(entries)
|
||||
return 0
|
||||
|
||||
@@ -404,8 +491,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
if log is not None:
|
||||
log.banner("Phase B: 编译 .obj")
|
||||
|
||||
# 收集 .obj 路径
|
||||
OBJ_PATHS_SIZE: t.CSizeT = 8192
|
||||
# 收集 .obj 路径(增大到 64KB,避免 includes .obj 路径溢出导致链接丢失符号)
|
||||
# reachable_set/reachable_count: Phase B+ 填充,Phase C 用于按需链接
|
||||
reachable_set: bytes = None
|
||||
reachable_count: int = 0
|
||||
OBJ_PATHS_SIZE: t.CSizeT = 65536
|
||||
obj_paths: bytes = stdlib.malloc(OBJ_PATHS_SIZE)
|
||||
if obj_paths is None:
|
||||
return 1
|
||||
@@ -457,6 +547,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
sys.exit(1)
|
||||
|
||||
compiled_count += 1
|
||||
# 显示编译完成的文件
|
||||
fb_comp: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_comp is not None:
|
||||
viperlib.snprintf(fb_comp, 1024, "[%d/%d] 编译完成: %s", i + 1, file_count, ent.Path)
|
||||
VLogger.info(fb_comp, "PhaseB")
|
||||
# 构造 .obj 路径,检测是否是 main 模块(test_main.py 或 main.py)
|
||||
od_len: t.CSizeT = string.strlen(output_dir)
|
||||
is_main_mod: int = 0
|
||||
@@ -497,39 +592,85 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
stdlib.free(entries)
|
||||
return 1
|
||||
|
||||
# === 3.5 编译缺失的 includes 文件 ===
|
||||
# includes.binary 可能缺少某些 includes .obj(如 testcheck.py),
|
||||
# 这些文件被用户项目导入但未被 TransPyV 自身依赖,Projectrans.py 未编译它们。
|
||||
# 检测并编译缺失的 includes 文件到 output_dir,加入链接命令。
|
||||
# 数据来源:StubMerger 全局内存存储器(不读取 _sha1_map.txt 文件)
|
||||
# === 3.5 编译缺失的 includes 文件(按依赖图按需编译)===
|
||||
# 只编译被 App 源文件直接/间接引用的 includes 文件(可达集合),
|
||||
# 而非遍历整个 includes 目录。通过 _BuildReachableSha1Set 构建依赖图。
|
||||
if includes_dir is not None and includes_binary_dir is not None:
|
||||
inc_compiled: int = 0
|
||||
td_len_mi: t.CSizeT = string.strlen(temp_dir)
|
||||
|
||||
# 诊断日志:确认 Phase B+ 入口和 Sha1Store 状态
|
||||
fb_pbp_enter: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_pbp_enter is not None:
|
||||
viperlib.snprintf(fb_pbp_enter, 1024,
|
||||
"PhaseB+ 入口: store_count=%d includes_binary_dir=%s",
|
||||
StubMerger.GetSha1StoreCount(), includes_binary_dir)
|
||||
VLogger.info(fb_pbp_enter, "PhaseB+")
|
||||
|
||||
# 创建 includes_binary_dir 目录(确保 .obj 能写入和 collect_obj_files 能扫描)
|
||||
BuildPipeline.ensure_dir(includes_binary_dir)
|
||||
|
||||
# declare_only 预处理已移至 Phase A 之前(Phase A-pre-inc),
|
||||
# 确保 Phase A 翻译 App 源文件时 includes struct 已注册。
|
||||
# PopulateIncludesDeps 已在 Phase A-pre-inc 中填充。
|
||||
|
||||
# 构建可达 SHA1 集合(依赖图遍历)
|
||||
# app_deps_buf 为 None 时回退到扫描 source_dir(非递归)
|
||||
REACHABLE_SET_SIZE: t.CSizeT = t.CSizeT(StubMerger.MAX_INCLUDES_SHA1) * 17
|
||||
reachable_set: bytes = stdlib.malloc(REACHABLE_SET_SIZE)
|
||||
reachable_count: int = 0
|
||||
if reachable_set is not None:
|
||||
string.memset(reachable_set, 0, REACHABLE_SET_SIZE)
|
||||
reachable_count = StubMerger._BuildReachableSha1Set(
|
||||
mb, source_dir, temp_dir, reachable_set, app_deps_buf)
|
||||
fb_reach: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_reach is not None:
|
||||
viperlib.snprintf(fb_reach, 1024, "可达 includes SHA1: %d 个", reachable_count)
|
||||
VLogger.info(fb_reach, "PhaseB+")
|
||||
# fast-fail: 可达集合构建失败(依赖未找到),永不回退,直接终止
|
||||
if reachable_count < 0:
|
||||
VLogger.error("可达集合构建失败(fast-fail),终止编译", "PhaseB+")
|
||||
return 1
|
||||
else:
|
||||
VLogger.error("reachable_set 分配失败,终止编译", "PhaseB+")
|
||||
return 1
|
||||
|
||||
# 释放 app_deps_buf(已构建完 reachable_set,不再需要)
|
||||
if app_deps_buf is not None:
|
||||
stdlib.free(app_deps_buf)
|
||||
app_deps_buf = None
|
||||
|
||||
# 从全局存储器获取 SHA1/模块名/rel_path 数组(直接访问器,避免 box 解引用问题)
|
||||
store_count_mi: int = StubMerger.GetSha1StoreCount()
|
||||
if store_count_mi > 0:
|
||||
store_sha1_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
|
||||
store_mod_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreModArrPtr()
|
||||
store_rel_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
|
||||
|
||||
for si_mi in range(store_count_mi):
|
||||
# 获取当前条目的 SHA1 和 rel_path
|
||||
inc_sha1_mi: str = store_sha1_arr_mi + t.CSizeT(si_mi) * 17
|
||||
inc_rel_mi: str = store_rel_arr_mi + t.CSizeT(si_mi) * StubMerger.MAX_REL_PATH_LEN
|
||||
# 检查 .obj 是否已存在于 includes.binary
|
||||
# 按需编译过滤:只处理 reachable_set 中的 includes
|
||||
# 永不回退:reachable_count > 0 时严格按可达集合过滤
|
||||
if reachable_count > 0:
|
||||
if StubMerger._is_in_sha1_set(inc_sha1_mi, reachable_set, reachable_count) == 0:
|
||||
continue
|
||||
# 检查 .obj 是否已存在于 includes.binary(切片子目录)
|
||||
ibd_len_mi: t.CSizeT = string.strlen(includes_binary_dir)
|
||||
check_pat_mi: bytes = stdlib.malloc(ibd_len_mi + 35)
|
||||
if check_pat_mi is None:
|
||||
continue
|
||||
viperlib.snprintf(check_pat_mi, ibd_len_mi + 35, "%s/%s*.obj", includes_binary_dir, inc_sha1_mi)
|
||||
check_pat_mi: str = StubMerger._sliced_path(includes_binary_dir, ibd_len_mi, inc_sha1_mi, "obj")
|
||||
check_fd_mi: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
obj_exists_mi: int = 0
|
||||
if check_fd_mi is not None:
|
||||
if check_pat_mi is not None and check_fd_mi is not None:
|
||||
string.memset(check_fd_mi, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
check_h_mi: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(check_pat_mi, check_fd_mi)
|
||||
if check_h_mi != w32.win32base.INVALID_HANDLE_VALUE:
|
||||
w32.win32file.FindClose(check_h_mi)
|
||||
obj_exists_mi = 1
|
||||
if obj_exists_mi != 0:
|
||||
if check_pat_mi is not None:
|
||||
stdlib.free(check_pat_mi)
|
||||
stdlib.free(check_fd_mi)
|
||||
continue
|
||||
|
||||
# .obj 不存在,需要编译
|
||||
@@ -538,6 +679,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
inc_dir_len_mi: t.CSizeT = string.strlen(includes_dir)
|
||||
src_fp_mi: bytes = stdlib.malloc(inc_dir_len_mi + 1 + rel_path_len_mi + 1)
|
||||
if src_fp_mi is None:
|
||||
stdlib.free(check_pat_mi)
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
continue
|
||||
viperlib.snprintf(src_fp_mi, inc_dir_len_mi + 1 + rel_path_len_mi + 1,
|
||||
"%s/%s", includes_dir, inc_rel_mi)
|
||||
@@ -571,20 +715,35 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
tpos_mi += 1
|
||||
if tll_mi >= 7 and string.strncmp(tbuf_mi + tls_mi, "define ", 7) == 0:
|
||||
# 临时在行尾加 \0 供 strstr 使用
|
||||
saved_mi: t.CChar = tbuf_mi[tls_mi + tll_mi]
|
||||
tbuf_mi[tls_mi + tll_mi] = '\0'
|
||||
# 仅当行尾不在缓冲区末尾时才需保存/恢复
|
||||
# (缓冲区末尾已在上方 read_all 后截断为 '\0',直接用即可)
|
||||
# 避免 tls_mi + tll_mi == tbr_mi 时越界写
|
||||
end_pos_mi: t.CSizeT = tls_mi + tll_mi
|
||||
saved_mi: t.CChar = '\0'
|
||||
need_restore_mi: int = 0
|
||||
if end_pos_mi < tbr_mi:
|
||||
saved_mi = tbuf_mi[end_pos_mi]
|
||||
tbuf_mi[end_pos_mi] = '\0'
|
||||
need_restore_mi = 1
|
||||
if string.strstr(tbuf_mi + tls_mi, "@\"") is not None:
|
||||
tbuf_mi[tls_mi + tll_mi] = saved_mi
|
||||
if need_restore_mi != 0:
|
||||
tbuf_mi[end_pos_mi] = saved_mi
|
||||
is_decl_mi = 0
|
||||
break
|
||||
tbuf_mi[tls_mi + tll_mi] = saved_mi
|
||||
if need_restore_mi != 0:
|
||||
tbuf_mi[end_pos_mi] = saved_mi
|
||||
stdlib.free(tbuf_mi)
|
||||
tf_mi.close()
|
||||
stdlib.free(tpath_mi)
|
||||
# is_decl_mi == -1: text.ll 不存在(Phase1 未翻译此文件,可能不被项目导入)
|
||||
# is_decl_mi == -1: text.ll 不存在(Phase1 未翻译此文件)
|
||||
# is_decl_mi == 1: 声明文件(仅 declare 无 define)
|
||||
# 两种情况都跳过:不编译未被 Phase1 翻译的 includes 文件
|
||||
if is_decl_mi != 0:
|
||||
# is_decl_mi == 0: 实现文件(有 define)
|
||||
# 只跳过声明文件(is_decl_mi == 1);text.ll 不存在时继续,让后续翻译逻辑处理
|
||||
if is_decl_mi == 1:
|
||||
stdlib.free(check_pat_mi)
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
stdlib.free(src_fp_mi)
|
||||
continue
|
||||
|
||||
# 尝试 BuildCombinedIR(stub/text 应已由 Phase1 生成)
|
||||
@@ -633,19 +792,43 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
inc_combined_len_mi = StubMerger.BuildCombinedIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE)
|
||||
|
||||
if inc_combined_len_mi == 0:
|
||||
# 诊断:检查 stub.ll/text.ll 是否存在
|
||||
diag_stub: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "stub.ll")
|
||||
diag_text: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll")
|
||||
diag_stub_ex: int = 0
|
||||
diag_text_ex: int = 0
|
||||
if diag_stub is not None:
|
||||
df_diag_s: fileio.File | t.CPtr = fileio.File(diag_stub, fileio.MODE.R)
|
||||
if not df_diag_s.closed:
|
||||
diag_stub_ex = 1
|
||||
df_diag_s.close()
|
||||
stdlib.free(diag_stub)
|
||||
if diag_text is not None:
|
||||
df_diag_t: fileio.File | t.CPtr = fileio.File(diag_text, fileio.MODE.R)
|
||||
if not df_diag_t.closed:
|
||||
diag_text_ex = 1
|
||||
df_diag_t.close()
|
||||
stdlib.free(diag_text)
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "BuildCombinedIR 失败: %s", src_fp_mi)
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"BuildCombinedIR 失败: %s (stub=%d text=%d is_decl=%d)",
|
||||
src_fp_mi, diag_stub_ex, diag_text_ex, is_decl_mi)
|
||||
VLogger.error(fb, "PhaseB+")
|
||||
if inc_combined_mi is not None:
|
||||
stdlib.free(inc_combined_mi)
|
||||
stdlib.free(check_pat_mi)
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
stdlib.free(src_fp_mi)
|
||||
continue
|
||||
|
||||
# 编译为 .obj
|
||||
# 编译为 .obj(输出到 includes_binary_dir,与存在性检查和链接收集一致)
|
||||
inc_cret_mi: int = BuildPipeline.compile_module_to_obj(
|
||||
inc_combined_mi, inc_combined_len_mi, temp_dir, output_dir, inc_sha1_mi,
|
||||
inc_combined_mi, inc_combined_len_mi, temp_dir, includes_binary_dir, inc_sha1_mi,
|
||||
cc_cmd, cc_flags)
|
||||
stdlib.free(inc_combined_mi)
|
||||
|
||||
if inc_cret_mi != 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
@@ -654,10 +837,16 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
sys.exit(1)
|
||||
|
||||
inc_compiled += 1
|
||||
# 显示编译完成的 includes 文件
|
||||
fb_inc_comp: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_inc_comp is not None:
|
||||
viperlib.snprintf(fb_inc_comp, 1024, "[includes %d] 编译完成: %s", inc_compiled, src_fp_mi)
|
||||
VLogger.info(fb_inc_comp, "PhaseB+")
|
||||
|
||||
# 添加到 obj_paths (切片路径,从 includes_binary_dir 取)
|
||||
ibd_len_mi2: t.CSizeT = string.strlen(includes_binary_dir)
|
||||
inc_obj_sliced: str = StubMerger._sliced_path(includes_binary_dir, ibd_len_mi2, inc_sha1_mi, "obj")
|
||||
|
||||
# 添加到 obj_paths (切片路径)
|
||||
od_len_mi: t.CSizeT = string.strlen(output_dir)
|
||||
inc_obj_sliced: str = StubMerger._sliced_path(output_dir, od_len_mi, inc_sha1_mi, "obj")
|
||||
if inc_obj_sliced is not None:
|
||||
inc_obj_len: t.CSizeT = string.strlen(inc_obj_sliced)
|
||||
if obj_pos + inc_obj_len + 2 < OBJ_PATHS_SIZE:
|
||||
@@ -669,11 +858,25 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
obj_paths[obj_pos] = '\0'
|
||||
stdlib.free(inc_obj_sliced)
|
||||
|
||||
# 释放本次迭代的临时内存
|
||||
if check_pat_mi is not None:
|
||||
stdlib.free(check_pat_mi)
|
||||
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
|
||||
stdlib.free(src_fp_mi)
|
||||
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "编译缺失 includes: %d 个", inc_compiled)
|
||||
VLogger.info(fb, "PhaseB+")
|
||||
|
||||
# 释放 app_deps_buf(Phase B+ 块未执行时此处兜底释放)
|
||||
if app_deps_buf is not None:
|
||||
stdlib.free(app_deps_buf)
|
||||
app_deps_buf = None
|
||||
|
||||
# === 4. Phase C: 链接所有 .obj → .exe ===
|
||||
if log is not None:
|
||||
log.banner("Phase C: 链接")
|
||||
@@ -708,6 +911,18 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
final_obj_paths[fop_pos] = '\0'
|
||||
|
||||
obj_paths_len: t.CSizeT = fop_pos
|
||||
|
||||
# 暂时禁用按图链接:始终全量链接 includes.binary 中的 .obj
|
||||
# 按图链接在 --clean 后 deps.txt 缺失时无法正确工作(跨包传递依赖丢失)
|
||||
# 按图编译(Phase B+)仍保留:只编译 reachable_set 中的缺失 includes
|
||||
# TODO: 待 deps.txt 生成机制完善后(如 Phase A 翻译所有 includes 的 imports),重新启用按图链接
|
||||
|
||||
# 释放 reachable_set(Phase B+ 已使用完毕)
|
||||
if reachable_set is not None:
|
||||
stdlib.free(reachable_set)
|
||||
reachable_set = None
|
||||
|
||||
# 始终传 includes_binary_dir 给 link_objs_to_exe,由其全量收集 .obj
|
||||
lret: int = BuildPipeline.link_objs_to_exe(
|
||||
final_obj_paths, obj_paths_len,
|
||||
linker_cmd, linker_flags, exe_path,
|
||||
|
||||
Reference in New Issue
Block a user