diff --git a/lib/Projectrans/Config.py b/lib/Projectrans/Config.py index 60a10c2..88ac6d9 100644 --- a/lib/Projectrans/Config.py +++ b/lib/Projectrans/Config.py @@ -276,6 +276,11 @@ def main() -> None: static_libs: list[str] = [] for lib in resolved.get('linker', {}).get('static_libs', []) or []: static_libs.append(lib if os.path.isabs(lib) else os.path.normpath(os.path.join(project_dir, lib))) + # 显式动态链接文件列表(.dll/.so 等),相对 project.vpj 目录解析为绝对路径; + # 链接时作为输入文件(GNU ld 从 DLL/SO 提取导入符号),运行时需 DLL/SO 在搜索路径 + dynamic_libs: list[str] = [] + for lib in resolved.get('linker', {}).get('dynamic_libs', []) or []: + dynamic_libs.append(lib if os.path.isabs(lib) else os.path.normpath(os.path.join(project_dir, lib))) target_triple = resolved.get('target', {}).get('triple') target_datalayout = resolved.get('target', {}).get('datalayout') force_recompile_includes: bool = bool(resolved.get('options', {}).get('force_recompile_includes', False)) @@ -304,7 +309,7 @@ def main() -> None: except: pass _vlog().info(f"includes.binary: 已清空 {precompiled_dir} ({cleared} 个文件)") - trans: Phase2Translator = Phase2Translator(src, temp_dir, output_dir, compile_cmd=cc_cmd, compile_flags=cc_flags, linker_cmd=linker_cmd, linker_flags=linker_flags, linker_output=linker_output, static_libs=static_libs, include_dirs=project_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout, force_recompile_includes=force_recompile_includes, asan_mode=args.asan) + trans: Phase2Translator = Phase2Translator(src, temp_dir, output_dir, compile_cmd=cc_cmd, compile_flags=cc_flags, linker_cmd=linker_cmd, linker_flags=linker_flags, linker_output=linker_output, static_libs=static_libs, dynamic_libs=dynamic_libs, include_dirs=project_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout, force_recompile_includes=force_recompile_includes, asan_mode=args.asan) trans.sha1_map = Load_sha1_map(temp_dir) trans.slice_level = slice_level trans.run() diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index 014cd1a..1890225 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -516,7 +516,7 @@ class Phase2Translator: _include_sha1_cache: dict[str, str] = {} _include_exist_cache: dict[str, bool] = {} - def __init__(self, src_root: str, temp_dir: str, output_dir: str, compile_cmd: str = 'llc', compile_flags: list[str] | None = None, linker_cmd: str | None = None, linker_flags: list[str] | None = None, linker_output: str | None = None, static_libs: list[str] | None = None, include_dirs: list[str] | None = None, entry_files: list[str] | None = None, target_triple: str | None = None, target_datalayout: str | None = None, force_recompile_includes: bool = False, build_pyi_cache: bool = True, asan_mode: bool = False) -> None: + def __init__(self, src_root: str, temp_dir: str, output_dir: str, compile_cmd: str = 'llc', compile_flags: list[str] | None = None, linker_cmd: str | None = None, linker_flags: list[str] | None = None, linker_output: str | None = None, static_libs: list[str] | None = None, dynamic_libs: list[str] | None = None, include_dirs: list[str] | None = None, entry_files: list[str] | None = None, target_triple: str | None = None, target_datalayout: str | None = None, force_recompile_includes: bool = False, build_pyi_cache: bool = True, asan_mode: bool = False) -> None: self.src_root = os.path.abspath(src_root) self.temp_dir = os.path.abspath(temp_dir) self.output_dir = os.path.abspath(output_dir) @@ -562,6 +562,13 @@ class Phase2Translator: for lib in static_libs: if lib not in self.extra_link_files: self.extra_link_files.append(lib) + # project.vpj linker.dynamic_libs:显式动态链接文件(.dll/.so), + # 同样作为链接输入(GNU ld 从 DLL/SO 提取导入符号);运行时需 + # DLL/SO 位于 exe 同目录 / PATH / LD_LIBRARY_PATH。 + if dynamic_libs: + for lib in dynamic_libs: + if lib not in self.extra_link_files: + self.extra_link_files.append(lib) self._include_sha1s: set[str] = set() # 持有 ProcessPoolExecutor 引用,避免局部变量 GC 时 finalizer 阻塞 ~99s # (join_executor_internals 在 GC 时同步等待 worker 退出队列)