修正了种子编译器的错误

This commit is contained in:
2026-07-22 21:55:36 +08:00
parent 135aa05485
commit ca7c2120b8
1185 changed files with 12056 additions and 2673 deletions

View File

@@ -59,6 +59,10 @@ class Phase1Generator:
self._manifest: dict[str, dict] = {}
self._typedef_map_cache: dict[str, ast.AST] | None = None
self._manifest_path: str = os.path.join(self.temp_dir, '_phase1_manifest.json')
# includes 依赖图:{module_name: set[dep_module_name]},用于 .stub.ll 缓存依赖校验
self._include_dep_graph: dict[str, set[str]] = {}
# include 文件映射:{module_name: (src_path, rel_from_inc, includes_dir)}
self._include_file_map: dict[str, tuple[str, str, str]] = {}
self._load_manifest()
def _load_manifest(self) -> None:
@@ -174,6 +178,7 @@ class Phase1Generator:
pass
needed: set[str] = set()
dep_graph: dict[str, set[str]] = {}
queue: list[str] = list(imported_from_src)
while queue:
mod_name: str = queue.pop(0)
@@ -184,6 +189,7 @@ class Phase1Generator:
src_path: str = include_file_map[mod_name][0]
includes_dir: str = include_file_map[mod_name][2]
deps: set[str] = get_file_dependencies(src_path, includes_dir)
dep_graph[mod_name] = deps
for dep in deps:
if dep in include_file_map and dep not in needed:
queue.append(dep)
@@ -195,6 +201,10 @@ class Phase1Generator:
if info not in needed_infos:
needed_infos.append(info)
# 存储依赖图和文件映射,供 .stub.ll 缓存依赖校验使用
self._include_dep_graph = dep_graph
self._include_file_map = include_file_map
return needed_infos
def run(self) -> None:
@@ -356,6 +366,58 @@ class Phase1Generator:
_vlog().warning(f"收集 typedef 映射失败: {_e}", "Exception")
return typedef_map
def _ComputeDepSha1Signature(self, module_name: str) -> str:
"""计算 module_name 的所有传递依赖的 SHA1 签名。
用于 .stub.ll 缓存依赖校验:当依赖的 include SHA1 变化时,
当前 include 的 .stub.ll 缓存应失效(因为类型引用的 SHA1 前缀会变化)。
"""
if not self._include_dep_graph or not self._include_file_map:
return ''
Result: set[str] = set()
Visited: set[str] = set()
Queue: list[str] = list(self._include_dep_graph.get(module_name, set()))
while Queue:
DepMod: str = Queue.pop(0)
if DepMod in Visited:
continue
Visited.add(DepMod)
if DepMod in self._include_file_map:
DepSrc: str = self._include_file_map[DepMod][0]
DepSha1: str = self._get_sha1(DepSrc)
if DepSha1:
Result.add(DepSha1)
Queue.extend(self._include_dep_graph.get(DepMod, set()))
return '|'.join(sorted(Result))
def _ReadStubDep(self, stub_path: str) -> str:
"""读取 .stub.ll 的依赖签名 sidecar不存在返回空字符串。"""
DepPath: str = stub_path + '.dep'
try:
with open(DepPath, 'r', encoding='utf-8') as f:
return f.read()
except Exception:
return ''
def _WriteStubDep(self, stub_path: str, dep_sig: str) -> None:
"""写入 .stub.ll 的依赖签名 sidecar 到 temp_dir 和全局缓存。"""
# temp_dir
DepPath: str = stub_path + '.dep'
try:
with open(DepPath, 'w', encoding='utf-8') as f:
f.write(dep_sig)
except Exception:
pass
# 全局缓存
Sha1: str = os.path.basename(stub_path).replace('.stub.ll', '')
GlobalDepPath: str = os.path.join(_GLOBAL_CACHE_DIR, f"{Sha1}.stub.ll.dep")
try:
os.makedirs(_GLOBAL_CACHE_DIR, exist_ok=True)
with open(GlobalDepPath, 'w', encoding='utf-8') as f:
f.write(dep_sig)
except Exception:
pass
def _process_include_py_files_stub(self, struct_names: set[str], needed_includes: list[tuple[str, str, str]] | None = None, enum_names: set[str] | None = None, struct_sha1_map: dict[str, str] | None = None, exception_names: set[str] | None = None, class_def_map: dict[str, ast.ClassDef] | None = None) -> None:
include_py_files: list[tuple[str, str, str]]
if needed_includes is not None:
@@ -374,15 +436,43 @@ class Phase1Generator:
if not sha1:
continue
# 计算依赖签名(用于 .stub.ll 缓存依赖校验)
# 当依赖的 include SHA1 变化时,.stub.ll 中类型引用的 SHA1 前缀会变化,缓存应失效
DepSig: str = self._ComputeDepSha1Signature(module_name)
stub_path: str = os.path.join(self.temp_dir, f"{sha1}.stub.ll")
if os.path.isfile(stub_path):
_vlog().info(f" 缓存命中: {rel_from_inc} -> {sha1}.stub.ll")
continue
# 依赖校验temp_dir 中的 .stub.ll 可能是上次编译残留,引用旧 SHA1
if self._ReadStubDep(stub_path) == DepSig:
_vlog().info(f" 缓存命中: {rel_from_inc} -> {sha1}.stub.ll")
continue
else:
_vlog().info(f" 缓存失效(依赖变更): {rel_from_inc} -> {sha1}.stub.ll")
try:
os.remove(stub_path)
except Exception:
pass
# 全局缓存检查(不被 --clean 清除)
if _TryGlobalCache(sha1, 'stub.ll', stub_path):
_vlog().info(f" 缓存命中(全局): {rel_from_inc} -> {sha1}.stub.ll")
continue
# 从全局缓存复制 sidecar .dep 文件
GlobalDepPath: str = os.path.join(_GLOBAL_CACHE_DIR, f"{sha1}.stub.ll.dep")
TempDepPath: str = stub_path + '.dep'
if os.path.isfile(GlobalDepPath):
try:
shutil.copy2(GlobalDepPath, TempDepPath)
except Exception:
pass
# 依赖校验:全局缓存中的 .stub.ll 可能引用旧 SHA1
if self._ReadStubDep(stub_path) == DepSig:
_vlog().info(f" 缓存命中(全局): {rel_from_inc} -> {sha1}.stub.ll")
continue
else:
_vlog().info(f" 缓存失效(依赖变更): {rel_from_inc} -> {sha1}.stub.ll")
try:
os.remove(stub_path)
except Exception:
pass
sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi")
if not os.path.isfile(sig_path):
@@ -392,6 +482,8 @@ class Phase1Generator:
self._generate_decl_ll(sig_content, stub_path, src_path, struct_names, enum_names=enum_names, module_sha1=sha1, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map, class_def_map=class_def_map)
_SaveToGlobalCache(sha1, 'stub.ll', stub_path)
# 写入依赖签名 sidecartemp_dir 和全局缓存)
self._WriteStubDep(stub_path, DepSig)
_vlog().info(f" 生成声明: {rel_from_inc} -> {sha1}.stub.ll")
except Exception as e:
_vlog().error(f"处理 include 文件失败 {rel_from_inc}: {e}")