更新,可自举

This commit is contained in:
TermiNexus committed 2026-08-27 09:48:20 +08:00
1 parent 07db560510
commit ab0f37e1a8
35 files changed
+3759 -1518

No files matched your search

+102 -6
View File
@@ -35,6 +35,7 @@ LinkerFlags: str = None # 链接器参数(空格分隔,从 linker.
LinkerOutput: str = None
TargetTriple: str = None
TargetDataLayout: str = None
ProjectDir: str = None # project.vpj 所在目录(resolve_paths 设置)
Sha1SliceLevel: int = 0 # SHA1 切片层数(目录分散等级)
StrictMode: int = 0
IncludesDir: str = None # includes 目录路径(从 includes 数组首元素,兼容单目录场景)
@@ -146,7 +147,7 @@ def Load_project_config(path: str) -> int:
# 读取 includes 数组(支持多目录:首元素存 IncludesDir,全部拼接存 IncludesDirs)
includes_val: JsonValue | t.CPtr = root["includes"]
if includes_val is not None and includes_val.is_array():
arr_len: t.CSizeT = includes_val.__len__()
arr_len: t.CSizeT = len(includes_val)
inc_buf: bytes = stdlib.malloc(2048)
if inc_buf is not None:
inc_buf[0] = '\0'
@@ -186,12 +187,10 @@ def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str:
Returns:
空格分隔的字符串,或 None 如果 flags_val 为 None 或非数组或空数组
"""
if flags_val is None:
return None
if not flags_val.is_array():
return None
if flags_val is None: return None
if not flags_val.is_array(): return None
arr_len: t.CSizeT = flags_val.__len__()
arr_len: t.CSizeT = len(flags_val)
if arr_len == 0:
return None
@@ -385,11 +384,14 @@ def resolve_paths(project_dir: str) -> int:
0 表示成功,非 0 表示失败
"""
global SourceDir, BuildDir, TempDir, OutputDir, IncludesDir, IncludesDirs
global ProjectDir
if project_dir is None:
return 1
if _mbuddy is None:
return 1
ProjectDir = project_dir
SourceDir = _join_path(SourceDir, project_dir)
BuildDir = _join_path(BuildDir, project_dir)
@@ -441,9 +443,103 @@ def resolve_paths(project_dir: str) -> int:
IncludesDirs = id_out
if IncludesDir is not None:
IncludesDir = _join_path(IncludesDir, project_dir)
# linker.flags 中 `-T <脚本>` 的链接脚本路径同样基于 project_dir 解析,
# 否则 subprocess 按进程 cwd(TransPyC/)找 linker.ld → ld.lld 报
# "cannot find linker script linker.ld"
_resolve_linker_t_paths(project_dir)
return 0
def _join_path_abs(rel: str, project_dir: str) -> str:
"""将相对路径基于 project_dir 拼接为绝对路径(用于 -T 链接脚本等)
已为绝对路径(/ \\ 开头)或盘符形式(x:)时原样返回。
"""
if rel is None:
return None
rel_len: t.CSizeT = string.strlen(rel)
if rel_len == 0:
return rel
if rel[0] == '/' or rel[0] == '\\':
return rel
if rel_len >= 2 and rel[1] == ':':
return rel
dir_len: t.CSizeT = string.strlen(project_dir)
if dir_len == 0:
return rel
total_len: t.CSizeT = dir_len + 1 + rel_len + 1
buf: str = _mbuddy.alloc(total_len)
if buf is None:
return rel
viperlib.snprintf(buf, total_len, "%s/%s", project_dir, rel)
return buf
def _resolve_linker_t_paths(project_dir: str) -> None:
"""将 LinkerFlags 中 `-T <相对路径>` 的链接脚本路径解析为绝对路径
ld.lld 的 -T 参数若是相对路径,将按 subprocess 进程 cwd 解析而找不到
脚本。逐 token 扫描 LinkerFlags,遇 -T 其后 token 若非绝对路径则基于
project_dir 拼接(与 resolve_paths 对其他相对路径的处理保持一致)。
"""
global LinkerFlags
if LinkerFlags is None or project_dir is None:
return
fl_total: t.CSizeT = string.strlen(LinkerFlags)
if fl_total == 0:
return
out: str = _mbuddy.alloc(fl_total * 2 + 512)
if out is None:
return
out[0] = '\0'
out_pos: t.CSizeT = 0
i: t.CSizeT = 0
prev_is_t: int = 0 # 前一 token 是否为 -T
while i < fl_total:
# 跳过前导空格
while i < fl_total and LinkerFlags[i] == ' ':
i += 1
if i >= fl_total:
break
start: t.CSizeT = i
while i < fl_total and LinkerFlags[i] != ' ':
i += 1
tok_len: t.CSizeT = i - start
is_t_flag: int = 0
if tok_len == 2 and LinkerFlags[start] == '-' and LinkerFlags[start + 1] == 'T':
is_t_flag = 1
# 输出分隔符(前一 token 之后)
if out_pos > 0:
out[out_pos] = ' '
out_pos += 1
if is_t_flag:
string.strcpy(out + out_pos, "-T")
out_pos += 2
elif prev_is_t != 0:
# -T 后的脚本路径:非绝对路径则基于 project_dir 拼接
tok_buf: str = _mbuddy.alloc(tok_len + 1)
if tok_buf is not None:
string.memcpy(tok_buf, LinkerFlags + start, tok_len)
tok_buf[tok_len] = '\0'
abs_path: str = _join_path_abs(tok_buf, project_dir)
if abs_path is not None:
p_len: t.CSizeT = string.strlen(abs_path)
string.strcpy(out + out_pos, abs_path)
out_pos += p_len
else:
string.memcpy(out + out_pos, LinkerFlags + start, tok_len)
out_pos += tok_len
else:
string.memcpy(out + out_pos, LinkerFlags + start, tok_len)
out_pos += tok_len
else:
string.memcpy(out + out_pos, LinkerFlags + start, tok_len)
out_pos += tok_len
prev_is_t = is_t_flag
out[out_pos] = '\0'
LinkerFlags = out
def get_includes_binary_dir() -> str:
"""获取 includes.binary 目录路径(includes 目录 + 缓存后缀)
+10 -8
View File
@@ -89,16 +89,18 @@ def compute_sha1(pool: memhub.MemBuddy | t.CPtr, content: str) -> str:
# ============================================================
# is_vp_or_py_at - 检查路径段是否以 .vp/.py 后缀结尾
# is_vp_at - 检查路径段是否以 .vp 后缀结尾
# ============================================================
def is_vp_or_py_at(p: str, start: t.CSizeT, plen: t.CSizeT) -> int:
"""检查 p[start, start+plen) 是否以 .vp/.py 后缀结尾(1=是,0=否)"""
def is_vp_at(p: str, start: t.CSizeT, plen: t.CSizeT) -> int:
"""检查 p[start, start+plen) 是否以 .vp 后缀结尾(1=是,0=否)。
不再识别 .py(移除 vp -> py 后缀识别回退:Viper 源文件仅 .vp)。
"""
if p is None or plen <= 3:
return 0
base: t.CSizeT = start + plen - 3
if p[base] == '.':
if p[base + 1] == 'v' and p[base + 2] == 'p': return 1
if p[base + 1] == 'p' and p[base + 2] == 'y': return 1
if p[base] == '.' and p[base + 1] == 'v' and p[base + 2] == 'p':
return 1
return 0
@@ -167,8 +169,8 @@ def PathToModuleName(path: str, strip_includes_prefix: int) -> str:
if psep_ch == '/' or psep_ch == '\\':
path_start = prefix_len
plen = plen - prefix_len
# 去掉 .vp 或 .py 后缀(.vp 为 Viper 源,.py 向后兼容)
if is_vp_or_py_at(path, path_start, plen) != 0:
# 去掉 .vp 后缀(Viper 源文件仅 .vp,不再识别 .py)
if is_vp_at(path, path_start, plen) != 0:
plen -= 3
if plen == 0:
return None