feat(tpc): includes 只认项目配置;ASan 改为显式链接 clang64 运行库
includes 目录不再回退仓库硬编码 TransPyCRoot/includes:Phase2Translator 新增 PROJECT_INCLUDE_DIRS(INCLUDE_DIRS 置空以兼容旧引用),Config.py 从 project.vpj 的 includes 同步;HandlesImports 的模块搜索、TypeAnnotationResolver._builtins_include_dirs 一律只读项目目录。 ASan:mingw64 clang 没有 x86_64-w64-windows-gnu 目标的 ASan runtime,新增 _FindAsanRuntimeDir 定位 clang64 运行库并按 -l: 显式链接(asan_dynamic-x86_64.dll.a + runtime_thunk),定位失败即报错退出。HandlesExprFormat:i32 不再写 'l' 长度修饰符(LP64 下 printf 会按 64 位读实参)。
This commit is contained in:
1 parent
ab3873b038
commit
cc2f5d34eb
122 files changed
+89
-31
No files matched your search
@@ -37,6 +37,40 @@ def _CachedIsFile(path: str) -> bool:
|
||||
return r
|
||||
|
||||
|
||||
def _FindAsanRuntimeDir() -> str | None:
|
||||
"""定位 clang64 的 ASan 运行库目录(按 LLVM 大版本取最新的那个)
|
||||
|
||||
mingw64 的 clang 只为 x86_64-w64-windows-gnu 目标提供 builtins / fuzzer /
|
||||
profile / orc 运行库,**没有 ASan runtime**(<resource-dir>/lib/
|
||||
x86_64-w64-windows-gnu/ 是空目录),所以不能靠 `-fsanitize=address` 让驱动
|
||||
自动去找 —— 那只会得到
|
||||
"could not open .../libclang_rt.asan_dynamic.dll.a: No such file or directory"。
|
||||
clang64(MSVC ABI) 那边才有 libclang_rt.asan_dynamic-x86_64.dll.a 与
|
||||
libclang_rt.asan_dynamic_runtime_thunk-x86_64.a,只能借用这两份。
|
||||
|
||||
Returns:
|
||||
形如 D:\\msys64\\clang64\\lib\\clang\\22\\lib\\windows 的目录;找不到返回 None
|
||||
"""
|
||||
root = r'D:\msys64\clang64\lib\clang'
|
||||
if not os.path.isdir(root):
|
||||
return None
|
||||
found: list[str] = []
|
||||
for name in os.listdir(root):
|
||||
cand = os.path.join(root, name, 'lib', 'windows')
|
||||
if os.path.isfile(os.path.join(cand, 'libclang_rt.asan_dynamic-x86_64.dll.a')):
|
||||
found.append(cand)
|
||||
if not found:
|
||||
return None
|
||||
|
||||
def _Ver(path: str) -> int:
|
||||
# 目录名是 LLVM 大版本号(如 "22")——按数值比,否则 "9" 会排在 "22" 之后
|
||||
v = path.split(os.sep)[-3]
|
||||
return int(v) if v.isdigit() else 0
|
||||
|
||||
found.sort(key=_Ver)
|
||||
return found[-1]
|
||||
|
||||
|
||||
def _PickWorkerCount(n_files: int, per_worker_mb: int = 350) -> int:
|
||||
"""按可用物理内存动态限制并行 worker 数,避免多进程编译内存峰值 OOM。
|
||||
|
||||
@@ -565,9 +599,10 @@ class Phase2Translator:
|
||||
|
||||
INCLUDE_LIB_EXTENSIONS: tuple[str, ...] = ('.dll', '.ll', '.so', '.o', '.a', '.lib')
|
||||
INCLUDE_SRC_EXTENSIONS: tuple[str, ...] = ('.c', '.cpp', '.cc', '.cxx', '.m', '.mm')
|
||||
INCLUDE_DIRS: list[str] = [
|
||||
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'includes'),
|
||||
]
|
||||
# includes 只认项目配置(project.vpj includes),禁止仓库硬编码回退。
|
||||
# INCLUDE_DIRS 保留为空以兼容旧引用;实际目录由 __init__ 写入 PROJECT_INCLUDE_DIRS。
|
||||
INCLUDE_DIRS: list[str] = []
|
||||
PROJECT_INCLUDE_DIRS: list[str] = []
|
||||
# include 源文件 sha1/存在性缓存(_build_current_ModuleSha1Map):
|
||||
# 编译期间 include .vp/.py 源文件不变,避免每文件重复 isfile + open +
|
||||
# compute_sha1(PROF 显示 9306 isfile + 4653 open + TextIOWrapper.read
|
||||
@@ -595,13 +630,16 @@ class Phase2Translator:
|
||||
# ASan 模式:由 Config 的 --asan 参数直传(不再用 TPC_ASAN 环境变量,
|
||||
# 环境变量在 worker 子进程/外部调用链下不可靠)。
|
||||
# 检测 stdlib 堆/栈/全局越界与垃圾指针(MemBuddy pool 内部由 canary 覆盖)。
|
||||
# 注意:mingw64 的 clang 不提供 ASan runtime(libclang_rt.asan 缺失),
|
||||
# 必须使用 clang64 环境(自带 asan_dynamic runtime),PATH 前置 clang64/bin。
|
||||
# 注意:mingw64 的 clang 不提供 x86_64-w64-windows-gnu 目标的 ASan runtime,
|
||||
# 只能借用 clang64(MSVC ABI) 的那两份:PATH 前置 clang64/bin(运行期 DLL),
|
||||
# 链接时显式 -l: 那两份 .a/.dll.a(见 _FindAsanRuntimeDir 的说明)。
|
||||
self.asan_mode = asan_mode
|
||||
self.asan_rt_dir: str | None = None
|
||||
if self.asan_mode:
|
||||
_clang64_bin = r'D:\msys64\clang64\bin'
|
||||
if os.path.isdir(_clang64_bin):
|
||||
os.environ['PATH'] = _clang64_bin + os.pathsep + os.environ.get('PATH', '')
|
||||
self.asan_rt_dir = _FindAsanRuntimeDir()
|
||||
self.slice_level = 3
|
||||
self.sha1_map: dict[str, str] = {}
|
||||
self.sig_files: dict[str, str] = {}
|
||||
@@ -652,7 +690,7 @@ class Phase2Translator:
|
||||
self._shared_cross_module_vtable: set[str] = set()
|
||||
self._shared_class_methods: dict[str, list[str]] = {}
|
||||
self._shared_cross_module_novtable: set[str] = set()
|
||||
default_dirs = [d for d in self.INCLUDE_DIRS if os.path.isdir(d)]
|
||||
default_dirs: list[str] = []
|
||||
if include_dirs:
|
||||
seen = set()
|
||||
self.include_dirs = []
|
||||
@@ -663,6 +701,8 @@ class Phase2Translator:
|
||||
seen.add(d)
|
||||
else:
|
||||
self.include_dirs = default_dirs
|
||||
# 严格:只认项目 includes;供 builtins.vp 扫描等静态路径使用
|
||||
Phase2Translator.PROJECT_INCLUDE_DIRS = list(self.include_dirs)
|
||||
self._LoadSha1Map()
|
||||
|
||||
def _LoadSha1Map(self) -> None:
|
||||
@@ -1486,6 +1526,10 @@ class Phase2Translator:
|
||||
trans.translator._global_function_default_args = self.function_default_args
|
||||
trans.translator._global_function_param_names = self.function_param_names
|
||||
trans.translator._temp_dir = self.temp_dir
|
||||
# includes 只认 project.vpj 配置的 include 目录(不再回退仓库 TransPyCRoot/includes):
|
||||
# 目录重组/缺失时避免声明解析从仓库或 sig 回退路径产生错误时序(memhub 未注册→i32)
|
||||
_proj_inc = [os.path.abspath(d) for d in self.include_dirs if os.path.isdir(d)]
|
||||
trans.translator.LibraryPaths = _proj_inc if _proj_inc else ['.']
|
||||
trans.translator._shared_doc_meta = self._shared_doc_meta
|
||||
# 传递共享 vtable 状态
|
||||
trans.translator._shared_class_vtable = self._shared_class_vtable
|
||||
@@ -3655,9 +3699,23 @@ SECTIONS {
|
||||
# 其他所有标志(包括 -Wl, 选项)放在目标文件之前
|
||||
non_lib_flags.append(flag)
|
||||
i += 1
|
||||
# ASan 模式:链接 libasan(配合各 .ll 的 opt -passes=asan 插桩)
|
||||
# ASan 模式:链接 ASan 运行库(配合各 .ll 的 opt -passes=asan 插桩)
|
||||
# 不能传 -fsanitize=address:那会让 clang++ 驱动去找
|
||||
# <resource-dir>/lib/x86_64-w64-windows-gnu/libclang_rt.asan_dynamic.dll.a,
|
||||
# 而该目录是空的(上游 LLVM 不为这个 triple 构建 ASan runtime),
|
||||
# 直接报 "could not open ... No such file or directory"。
|
||||
# 改为显式链接 clang64 的那两份(与 TPV / README §8.1 同口径)。
|
||||
# 它们是库,必须排在目标文件之后,所以追加到 lib_flags 而不是 non_lib_flags。
|
||||
if self.asan_mode:
|
||||
non_lib_flags.append('-fsanitize=address')
|
||||
if self.asan_rt_dir is None:
|
||||
_vlog().error(
|
||||
"ASan 模式找不到 clang64 的 ASan 运行库目录 "
|
||||
r"(D:\msys64\clang64\lib\clang\<ver>\lib\windows)\n"
|
||||
" 请确认 msys2 的 mingw-w64-clang-x86_64-compiler-rt 已安装。")
|
||||
sys.exit(1)
|
||||
lib_flags.append('-L' + self.asan_rt_dir)
|
||||
lib_flags.append('-l:libclang_rt.asan_dynamic-x86_64.dll.a')
|
||||
lib_flags.append('-l:libclang_rt.asan_dynamic_runtime_thunk-x86_64.a')
|
||||
cmd = [self.linker_cmd] + non_lib_flags + ['-o', link_output] + all_link_files + lib_flags
|
||||
_vlog().info(f" 执行: {' '.join(cmd)}")
|
||||
result = subprocess.run(
|
||||
|
||||
Reference in new issue
Block a user