feat(linker): TPV 支持 project.vpj 静态链接 .a/.obj

- Config.vp 新增 LinkerStaticLibs(读取 linker.static_libs 数组并基于 project_dir 解析绝对路径)

- BuildPipeline link_obj_to_exe/link_objs_to_exe/run_pipeline 支持 static_libs(位于 .obj 之后、-l 之前)

- main.vp/Phase2.RunMultiFileProject 全链传递 linker_static_libs
This commit is contained in:
TermiNexus committed 2026-09-01 20:15:26 +08:00
1 parent 9b46e1da78
commit 29667672e4
4 files changed
+553 -27

No files matched your search

+39 -2
View File
@@ -33,6 +33,7 @@ CompilerFlags: str = None # 编译器参数(空格分隔,从 compile
LinkerCmd: str = None
LinkerFlags: str = None # 链接器参数(空格分隔,从 linker.flags 数组拼接)
LinkerOutput: str = None
LinkerStaticLibs: str = None # 显式静态链接文件(空格分隔绝对路径,从 linker.static_libs 数组)
TargetTriple: str = None
TargetDataLayout: str = None
ProjectDir: str = None # project.vpj 所在目录(resolve_paths 设置)
@@ -57,7 +58,7 @@ def Load_project_config(path: str) -> int:
0 表示成功,非 0 表示失败
"""
global SourceDir, BuildDir, TempDir, OutputDir, ProjectName, ProjectVersion
global CompilerCmd, CompilerFlags, LinkerCmd, LinkerFlags, LinkerOutput
global CompilerCmd, CompilerFlags, LinkerCmd, LinkerFlags, LinkerOutput, LinkerStaticLibs
global TargetTriple, TargetDataLayout, Sha1SliceLevel, StrictMode
global IncludesDir, IncludesDirs
@@ -119,6 +120,10 @@ def Load_project_config(path: str) -> int:
# 读取 linker.flags 数组,拼接成空格分隔的字符串
ld_flags_val: JsonValue | t.CPtr = linker["flags"]
LinkerFlags = _join_flags_array(ld_flags_val)
# 读取 linker.static_libs 数组:显式静态链接文件(.a/.obj),
# 先拼接原样字符串,resolve_paths 中再基于 project_dir 解析绝对路径
sl_val: JsonValue | t.CPtr = linker["static_libs"]
LinkerStaticLibs = _join_flags_array(sl_val)
# 读取 target 子对象
target: JsonValue | t.CPtr = root["target"]
@@ -392,7 +397,7 @@ def resolve_paths(project_dir: str) -> int:
0 表示成功,非 0 表示失败
"""
global SourceDir, BuildDir, TempDir, OutputDir, IncludesDir, IncludesDirs
global ProjectDir
global ProjectDir, LinkerStaticLibs
if project_dir is None:
return 1
if _mbuddy is None:
@@ -451,6 +456,38 @@ def resolve_paths(project_dir: str) -> int:
IncludesDirs = id_out
if IncludesDir is not None:
IncludesDir = _join_path(IncludesDir, project_dir)
# linker.static_libs 显式静态链接文件路径基于 project_dir 逐段解析为绝对路径
if LinkerStaticLibs is not None:
sl_total: t.CSizeT = string.strlen(LinkerStaticLibs)
sl_out: str = _mbuddy.alloc(sl_total * 3 + 64)
if sl_out is not None:
sl_out[0] = '\0'
sl_pos: t.CSizeT = 0
sl_i: t.CSizeT = 0
while sl_i < sl_total:
while sl_i < sl_total and LinkerStaticLibs[sl_i] == ' ':
sl_i += 1
if sl_i >= sl_total:
break
sl_start: t.CSizeT = sl_i
while sl_i < sl_total and LinkerStaticLibs[sl_i] != ' ':
sl_i += 1
seg_len: t.CSizeT = sl_i - sl_start
if seg_len > 0:
seg_buf: str = _mbuddy.alloc(seg_len + 1)
if seg_buf is not None:
string.strncpy(seg_buf, LinkerStaticLibs + sl_start, seg_len)
seg_buf[seg_len] = '\0'
joined: str = _join_path(seg_buf, project_dir)
if joined is not None:
jl: t.CSizeT = string.strlen(joined)
if sl_pos > 0:
sl_out[sl_pos] = ' '
sl_pos += 1
string.strcpy(sl_out + sl_pos, joined)
sl_pos += jl
sl_out[sl_pos] = '\0'
LinkerStaticLibs = sl_out
# linker.flags 中 `-T <脚本>` 的链接脚本路径同样基于 project_dir 解析,
# 否则 subprocess 按进程 cwd(TransPyC/)找 linker.ld → ld.lld 报
# "cannot find linker script linker.ld"