fix(compiler): 支持多 includes 目录,修复 G4 g4node 未注册 SHA1
- Config.vp 解析 includes 数组全部元素为空格分隔 IncludesDirs(首元素仍存 IncludesDir 兼容单目录) - IncludesScanner 逐目录递归扫描合并,FileEntry.IncDir 记录所属 includes 根目录 - StubMerger 存储新增 IncDir 并行数组(MAX_INC_DIR_LEN=512),容量 256→1024 - Phase2 预注册/3.5 按需编译改用逐条目 IncDir 拼接源路径(空串回退 includes_dir) - HandlesImports import 未注册错误显示行内内容 + App 兄弟模块文件豁免 - 新增 TransPyV 自身 project.vpj
This commit is contained in:
1 parent
ea8bb0b3a4
commit
60493d6ae5
7 files changed
+257
-35
No files matched your search
@@ -34,7 +34,8 @@ TargetTriple: str
|
||||
TargetDataLayout: str
|
||||
Sha1SliceLevel: t.CInt # SHA1 切片层数(目录分散等级)
|
||||
StrictMode: t.CInt
|
||||
IncludesDir: str # includes 目录路径(从 includes 数组首元素)
|
||||
IncludesDir: str # includes 目录路径(从 includes 数组首元素,兼容单目录场景)
|
||||
IncludesDirs: str # 全部 includes 目录(空格分隔,多 includes 目录支持)
|
||||
|
||||
|
||||
def Load_project_config(path: str) -> int:
|
||||
@@ -49,7 +50,7 @@ def Load_project_config(path: str) -> int:
|
||||
global SourceDir, BuildDir, TempDir, OutputDir, ProjectName, ProjectVersion
|
||||
global CompilerCmd, CompilerFlags, LinkerCmd, LinkerFlags, LinkerOutput
|
||||
global TargetTriple, TargetDataLayout, Sha1SliceLevel, StrictMode
|
||||
global IncludesDir
|
||||
global IncludesDir, IncludesDirs
|
||||
|
||||
if path is None:
|
||||
return 1
|
||||
@@ -141,14 +142,33 @@ def Load_project_config(path: str) -> int:
|
||||
if sm is not None and sm.is_bool():
|
||||
StrictMode = 1 if sm.as_bool() else 0
|
||||
|
||||
# 读取 includes 数组(取首个元素作为 includes 目录)
|
||||
# 读取 includes 数组(支持多目录:首元素存 IncludesDir,全部拼接存 IncludesDirs)
|
||||
includes_val: JsonValue | t.CPtr = root.__getitem__("includes")
|
||||
if includes_val is not None and includes_val.is_array():
|
||||
arr_len: t.CSizeT = includes_val.__len__()
|
||||
if arr_len > 0:
|
||||
first_inc: JsonValue | t.CPtr = includes_val.get_item(0)
|
||||
if first_inc is not None and first_inc.is_string():
|
||||
IncludesDir = first_inc.as_string()
|
||||
inc_buf: bytes = stdlib.malloc(2048)
|
||||
if inc_buf is not None:
|
||||
inc_buf[0] = '\0'
|
||||
inc_pos: t.CSizeT = 0
|
||||
for inc_i in range(arr_len):
|
||||
inc_item: JsonValue | t.CPtr = includes_val.get_item(inc_i)
|
||||
if inc_item is None or not inc_item.is_string():
|
||||
continue
|
||||
inc_str: str = inc_item.as_string()
|
||||
inc_slen: t.CSizeT = string.strlen(inc_str)
|
||||
if inc_i == 0:
|
||||
IncludesDir = inc_str
|
||||
# 拼接进 IncludesDirs(空格分隔)
|
||||
if inc_pos + inc_slen + 1 < 2048:
|
||||
if inc_pos > 0:
|
||||
inc_buf[inc_pos] = ' '
|
||||
inc_pos += 1
|
||||
string.strcpy(inc_buf + inc_pos, inc_str)
|
||||
inc_pos += inc_slen
|
||||
inc_buf[inc_pos] = '\0'
|
||||
IncludesDirs = inc_buf
|
||||
if IncludesDir is None:
|
||||
IncludesDir = inc_buf
|
||||
|
||||
return 0
|
||||
|
||||
@@ -367,7 +387,7 @@ def resolve_paths(project_dir: str) -> int:
|
||||
Returns:
|
||||
0 表示成功,非 0 表示失败
|
||||
"""
|
||||
global SourceDir, BuildDir, TempDir, OutputDir, IncludesDir
|
||||
global SourceDir, BuildDir, TempDir, OutputDir, IncludesDir, IncludesDirs
|
||||
if project_dir is None:
|
||||
return 1
|
||||
if _mbuddy is None:
|
||||
@@ -390,6 +410,38 @@ def resolve_paths(project_dir: str) -> int:
|
||||
OutputDir = output_buf
|
||||
|
||||
# includes 路径可能是 ../includes 形式,需要基于 project_dir 解析
|
||||
# IncludesDir(首元素)与 IncludesDirs(全部,空格分隔)逐项规范化
|
||||
if IncludesDirs is not None:
|
||||
id_total: t.CSizeT = string.strlen(IncludesDirs)
|
||||
id_out: str = _mbuddy.alloc(id_total * 3 + 64)
|
||||
if id_out is not None:
|
||||
id_out[0] = '\0'
|
||||
id_pos: t.CSizeT = 0
|
||||
id_i: t.CSizeT = 0
|
||||
while id_i < id_total:
|
||||
while id_i < id_total and IncludesDirs[id_i] == ' ':
|
||||
id_i += 1
|
||||
if id_i >= id_total:
|
||||
break
|
||||
id_start: t.CSizeT = id_i
|
||||
while id_i < id_total and IncludesDirs[id_i] != ' ':
|
||||
id_i += 1
|
||||
seg_len: t.CSizeT = id_i - id_start
|
||||
if seg_len > 0:
|
||||
seg_buf: str = _mbuddy.alloc(seg_len + 1)
|
||||
if seg_buf is not None:
|
||||
string.strncpy(seg_buf, IncludesDirs + id_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 id_pos > 0:
|
||||
id_out[id_pos] = ' '
|
||||
id_pos += 1
|
||||
string.strcpy(id_out + id_pos, joined)
|
||||
id_pos += jl
|
||||
id_out[id_pos] = '\0'
|
||||
IncludesDirs = id_out
|
||||
if IncludesDir is not None:
|
||||
IncludesDir = _join_path(IncludesDir, project_dir)
|
||||
return 0
|
||||
|
||||
@@ -7,6 +7,7 @@ import stdlib
|
||||
import viperlib
|
||||
import stdio
|
||||
import sys
|
||||
import w32.fileio as fileio
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
@@ -507,6 +508,27 @@ def _report_import_error(node: ast.AST | t.CPtr, msg: str) -> None:
|
||||
if file_name is None:
|
||||
file_name = "<unknown>"
|
||||
stdio.printf(' File "%s", line %d\n', file_name, lineno)
|
||||
# 显示行内内容(读源文件第 lineno 行的实际代码,便于快速定位)
|
||||
if lineno > 0 and file_name is not None:
|
||||
f_err: fileio.File | t.CPtr = fileio.File(file_name, fileio.MODE.R)
|
||||
if not f_err.closed:
|
||||
line_buf_err: bytes = stdlib.malloc(512)
|
||||
if line_buf_err is not None:
|
||||
cur_ln: int = 0
|
||||
while cur_ln < lineno:
|
||||
r_err: LONG = f_err.readline(line_buf_err, 511)
|
||||
if r_err <= 0:
|
||||
break
|
||||
cur_ln += 1
|
||||
if cur_ln == lineno:
|
||||
ll_err: t.CSizeT = string.strlen(line_buf_err)
|
||||
while ll_err > 0 and (line_buf_err[ll_err - 1] == '\n' or line_buf_err[ll_err - 1] == '\r'):
|
||||
ll_err -= 1
|
||||
line_buf_err[ll_err] = '\0'
|
||||
stdio.printf(" %s\n", line_buf_err)
|
||||
break
|
||||
stdlib.free(line_buf_err)
|
||||
f_err.close()
|
||||
stdio.printf("ImportError: %s\n", msg)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -522,6 +544,54 @@ def _report_import_error(node: ast.AST | t.CPtr, msg: str) -> None:
|
||||
#
|
||||
# t/c 是内部库,不参与 includes 扫描,豁免检查。
|
||||
# ============================================================
|
||||
def _is_local_module_file(mod_name: str) -> int:
|
||||
"""当前文件同目录存在 {mod_name}.vp/.py → 项目内兄弟模块
|
||||
|
||||
多文件项目(如 Test/G4/App 的 caller1.vp import g4node)的兄弟模块
|
||||
不在 includes 扫描存储器中(SHA1 在项目源文件列表),检查应豁免。
|
||||
"""
|
||||
cur: str = _g_current_file
|
||||
if cur is None or mod_name is None:
|
||||
return 0
|
||||
cur_len: t.CSizeT = string.strlen(cur)
|
||||
if cur_len == 0:
|
||||
return 0
|
||||
sep_pos: t.CSizeT = cur_len
|
||||
while sep_pos > 0:
|
||||
sep_pos -= 1
|
||||
ch: t.CChar = cur[sep_pos]
|
||||
if ch == '/' or ch == '\\':
|
||||
sep_pos += 1
|
||||
break
|
||||
mod_len: t.CSizeT = string.strlen(mod_name)
|
||||
path_len: t.CSizeT = sep_pos + mod_len + 5
|
||||
path_buf: bytes = stdlib.malloc(path_len + 1)
|
||||
if path_buf is None:
|
||||
return 0
|
||||
# .vp 文件
|
||||
string.strncpy(path_buf, cur, sep_pos)
|
||||
path_buf[sep_pos] = '\0'
|
||||
string.strcat(path_buf, mod_name)
|
||||
string.strcat(path_buf, ".vp")
|
||||
fex: fileio.File | t.CPtr = fileio.File(path_buf, fileio.MODE.R)
|
||||
if not fex.closed:
|
||||
fex.close()
|
||||
stdlib.free(path_buf)
|
||||
return 1
|
||||
# .py 文件(Python 模块可能无 .vp)
|
||||
string.strncpy(path_buf, cur, sep_pos)
|
||||
path_buf[sep_pos] = '\0'
|
||||
string.strcat(path_buf, mod_name)
|
||||
string.strcat(path_buf, ".py")
|
||||
fex2: fileio.File | t.CPtr = fileio.File(path_buf, fileio.MODE.R)
|
||||
if not fex2.closed:
|
||||
fex2.close()
|
||||
stdlib.free(path_buf)
|
||||
return 1
|
||||
stdlib.free(path_buf)
|
||||
return 0
|
||||
|
||||
|
||||
def _check_import_sha1(node: ast.AST | t.CPtr, mod_name: str) -> int:
|
||||
"""导入时校验模块 SHA1 是否已注册,未注册则立即报错退出
|
||||
|
||||
@@ -539,6 +609,11 @@ def _check_import_sha1(node: ast.AST | t.CPtr, mod_name: str) -> int:
|
||||
return 1
|
||||
mod_sha1: str = StubMerger.LookupSha1ByModName(mod_name)
|
||||
if mod_sha1 is None:
|
||||
# App 兄弟模块豁免:当前文件同目录存在 {mod_name}.vp/.py
|
||||
# (如 Test/G4/App/caller1.vp import g4node——同项目源文件,
|
||||
# SHA1 在项目文件列表而非 includes 扫描存储器,不应报错)
|
||||
if _is_local_module_file(mod_name) != 0:
|
||||
return 1
|
||||
err_buf: t.CChar | t.CPtr = stdlib.malloc(256)
|
||||
if err_buf is not None:
|
||||
viperlib.snprintf(err_buf, 256,
|
||||
|
||||
@@ -27,7 +27,7 @@ _mbuddy: memhub.MemBuddy | t.CPtr
|
||||
# 文件路径最大长度
|
||||
MAX_PATH_LEN: t.CDefine = 512
|
||||
# 单次扫描最大文件数
|
||||
MAX_FILES: t.CDefine = 256
|
||||
MAX_FILES: t.CDefine = 1024
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -40,6 +40,7 @@ class FileEntry:
|
||||
Sha1: str # SHA1 前16字符(16字节+null)
|
||||
RelPath: str # 相对于 includes 根目录的路径
|
||||
ModuleName: str # 模块名(如 "ast.parser")
|
||||
IncDir: str # 所属 includes 根目录(多 includes 目录支持)
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -83,8 +84,8 @@ def create_scan_result(pool: memhub.MemBuddy | t.CPtr) -> ScanResult | t.CPtr:
|
||||
def add_file_entry(result: ScanResult | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
abs_path: str, rel_path: str,
|
||||
sha1: str) -> int:
|
||||
"""添加文件条目到扫描结果,返回 0 成功"""
|
||||
sha1: str, inc_dir: str) -> int:
|
||||
"""添加文件条目到扫描结果,返回 0 成功(inc_dir 为所属 includes 根目录)"""
|
||||
if result is None or pool is None:
|
||||
return 1
|
||||
if result.Count >= result.Capacity:
|
||||
@@ -127,6 +128,15 @@ def add_file_entry(result: ScanResult | t.CPtr,
|
||||
# 复制模块名
|
||||
entry.ModuleName = mod_buf
|
||||
|
||||
# 复制所属 includes 根目录(多 includes 目录支持,Phase2 拼路径用)
|
||||
if inc_dir is not None:
|
||||
inc_len: t.CSizeT = string.strlen(inc_dir)
|
||||
inc_buf: str = stdlib.malloc(inc_len + 1)
|
||||
if inc_buf is None:
|
||||
return 1
|
||||
string.strcpy(inc_buf, inc_dir)
|
||||
entry.IncDir = inc_buf
|
||||
|
||||
result.Count += 1
|
||||
return 0
|
||||
|
||||
@@ -193,8 +203,9 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
|
||||
def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
|
||||
root_dir: str,
|
||||
rel_prefix: str,
|
||||
result: ScanResult | t.CPtr) -> int:
|
||||
"""递归扫描目录,收集 .vp/.py 文件"""
|
||||
result: ScanResult | t.CPtr,
|
||||
inc_dir: str) -> int:
|
||||
"""递归扫描目录,收集 .vp/.py 文件(inc_dir 为所属 includes 根目录)"""
|
||||
if pool is None or root_dir is None or result is None:
|
||||
return 1
|
||||
|
||||
@@ -262,7 +273,7 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
|
||||
|
||||
if is_dir != 0:
|
||||
# 递归扫描子目录
|
||||
scan_directory_recursive(pool, full_path, rel_path, result)
|
||||
scan_directory_recursive(pool, full_path, rel_path, result, inc_dir)
|
||||
else:
|
||||
# 检查是否为 .vp 或 .py 文件(.vp 为 Viper 源,.py 向后兼容)
|
||||
is_py: int = 0
|
||||
@@ -280,7 +291,7 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 计算 SHA1
|
||||
sha1: str = compute_file_sha1(pool, full_path)
|
||||
if sha1 is not None:
|
||||
add_file_entry(result, pool, full_path, rel_path, sha1)
|
||||
add_file_entry(result, pool, full_path, rel_path, sha1, inc_dir)
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "扫描: %s -> %s", rel_path, sha1)
|
||||
@@ -300,16 +311,36 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 扫描指定的 includes 目录,返回所有 .vp/.py 文件的路径和 SHA1。
|
||||
# ============================================================
|
||||
def scan_includes(pool: memhub.MemBuddy | t.CPtr,
|
||||
includes_dir: str) -> ScanResult | t.CPtr:
|
||||
"""扫描 includes 目录,返回所有 .vp/.py 文件的扫描结果"""
|
||||
if pool is None or includes_dir is None:
|
||||
includes_dirs: str) -> ScanResult | t.CPtr:
|
||||
"""扫描 includes 目录(支持空格分隔的多目录),返回所有 .vp/.py 文件的扫描结果"""
|
||||
if pool is None or includes_dirs is None:
|
||||
return None
|
||||
|
||||
result: ScanResult | t.CPtr = create_scan_result(pool)
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
scan_directory_recursive(pool, includes_dir, None, result)
|
||||
# 解析空格分隔的多 includes 目录(如 "../../includes ./includes"),逐目录递归扫描合并
|
||||
dirs_total: t.CSizeT = string.strlen(includes_dirs)
|
||||
d_i: t.CSizeT = 0
|
||||
while d_i < dirs_total:
|
||||
while d_i < dirs_total and includes_dirs[d_i] == ' ':
|
||||
d_i += 1
|
||||
if d_i >= dirs_total:
|
||||
break
|
||||
d_start: t.CSizeT = d_i
|
||||
while d_i < dirs_total and includes_dirs[d_i] != ' ':
|
||||
d_i += 1
|
||||
d_len: t.CSizeT = d_i - d_start
|
||||
if d_len == 0:
|
||||
continue
|
||||
dir_buf: bytes = stdlib.malloc(d_len + 1)
|
||||
if dir_buf is None:
|
||||
continue
|
||||
string.strncpy(dir_buf, includes_dirs + d_start, d_len)
|
||||
dir_buf[d_len] = '\0'
|
||||
scan_directory_recursive(pool, dir_buf, None, result, dir_buf)
|
||||
stdlib.free(dir_buf)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
+16
-7
@@ -281,7 +281,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
if store_count_inc_pre > 0:
|
||||
store_sha1_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
|
||||
store_rel_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
|
||||
inc_dir_len_pre: t.CSizeT = string.strlen(includes_dir)
|
||||
store_incdir_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreIncdirArrPtr()
|
||||
deps_filled_pre: int = 0
|
||||
PHASE_A_INC_MAX_PASSES: t.CInt = 3
|
||||
# [修复] 记录预注册失败的 includes:多遍后仍失败 → 报错终止编译。
|
||||
@@ -320,11 +320,16 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
inc_fail_flags[si_inc] = 0
|
||||
continue
|
||||
rel_len_pre: t.CSizeT = string.strlen(inc_rel_pre)
|
||||
full_path_pre: bytes = stdlib.malloc(inc_dir_len_pre + rel_len_pre + 2)
|
||||
# 所属 includes 根目录(多目录逐条取自 IncDir 数组,空串回退 includes_dir)
|
||||
incdir_pre: str = store_incdir_inc_pre + t.CSizeT(si_inc) * StubMerger.MAX_INC_DIR_LEN
|
||||
if incdir_pre is None or incdir_pre[0] == '\0':
|
||||
incdir_pre = includes_dir
|
||||
incdir_len_pre: t.CSizeT = string.strlen(incdir_pre)
|
||||
full_path_pre: bytes = stdlib.malloc(incdir_len_pre + rel_len_pre + 2)
|
||||
if full_path_pre is None:
|
||||
continue
|
||||
viperlib.snprintf(full_path_pre, inc_dir_len_pre + rel_len_pre + 2,
|
||||
"%s/%s", includes_dir, inc_rel_pre)
|
||||
viperlib.snprintf(full_path_pre, incdir_len_pre + rel_len_pre + 2,
|
||||
"%s/%s", incdir_pre, inc_rel_pre)
|
||||
pkg_inc_pre: str = HandlesImports.compute_package_from_relpath(mb, inc_rel_pre)
|
||||
tr_inc_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(
|
||||
mb, full_path_pre, inc_sha1_pre, pkg_inc_pre, 1)
|
||||
@@ -652,6 +657,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
store_sha1_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
|
||||
store_mod_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreModArrPtr()
|
||||
store_rel_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
|
||||
store_incdir_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreIncdirArrPtr()
|
||||
|
||||
for si_mi in range(store_count_mi):
|
||||
# 获取当前条目的 SHA1 和 rel_path
|
||||
@@ -680,9 +686,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
continue
|
||||
|
||||
# .obj 不存在,需要编译
|
||||
# 构造源文件路径: {includes_dir}/{rel_path}
|
||||
# 构造源文件路径: {所属 includes 根目录}/{rel_path}(多目录逐条取 IncDir,空串回退 includes_dir)
|
||||
rel_path_len_mi: t.CSizeT = string.strlen(inc_rel_mi)
|
||||
inc_dir_len_mi: t.CSizeT = string.strlen(includes_dir)
|
||||
incdir_mi: str = store_incdir_arr_mi + t.CSizeT(si_mi) * StubMerger.MAX_INC_DIR_LEN
|
||||
if incdir_mi is None or incdir_mi[0] == '\0':
|
||||
incdir_mi = includes_dir
|
||||
inc_dir_len_mi: t.CSizeT = string.strlen(incdir_mi)
|
||||
src_fp_mi: bytes = stdlib.malloc(inc_dir_len_mi + 1 + rel_path_len_mi + 1)
|
||||
if src_fp_mi is None:
|
||||
stdlib.free(check_pat_mi)
|
||||
@@ -690,7 +699,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
stdlib.free(check_fd_mi)
|
||||
continue
|
||||
viperlib.snprintf(src_fp_mi, inc_dir_len_mi + 1 + rel_path_len_mi + 1,
|
||||
"%s/%s", includes_dir, inc_rel_mi)
|
||||
"%s/%s", incdir_mi, inc_rel_mi)
|
||||
|
||||
# 检查是否为声明文件(只有 declare 没有实质 define)
|
||||
# 判断方法: text.ll 中若有混淆函数 define(含 @")则为实现文件
|
||||
|
||||
@@ -39,17 +39,18 @@ import lib.Projectrans.Config as Config
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 最大 includes SHA1 数(用于过滤)
|
||||
MAX_INCLUDES_SHA1: t.CDefine = 256
|
||||
MAX_INCLUDES_SHA1: t.CDefine = 1024
|
||||
# stub 读取缓冲区大小
|
||||
STUB_READ_BUF_SIZE: t.CDefine = 1048576
|
||||
# 最大 includes 条目数
|
||||
MAX_INCLUDES: t.CDefine = 256
|
||||
MAX_INCLUDES: t.CDefine = 1024
|
||||
|
||||
# 全局 SHA1 映射存储器(内存中,不依赖 _sha1_map.txt 文件)
|
||||
# Phase1 扫描完成后填充,供所有函数使用
|
||||
_sha1_store_arr: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_mod: bytes # 模块名数组(每个 64 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_rel: bytes # 相对路径数组(每个 256 字节,MAX_INCLUDES 个)
|
||||
_sha1_store_incdir: bytes # 所属 includes 根目录数组(每个 512 字节,MAX_INCLUDES 个,多 includes 支持)
|
||||
_sha1_store_count: int # 条目数
|
||||
|
||||
# includes 依赖内存存储(不依赖 deps.txt 过程文件)
|
||||
@@ -64,6 +65,8 @@ MAX_DEPS_STR_LEN: t.CDefine = 512
|
||||
|
||||
# rel_path 最大长度
|
||||
MAX_REL_PATH_LEN: t.CDefine = 256
|
||||
# includes 根目录最大长度(绝对路径,多 includes 支持)
|
||||
MAX_INC_DIR_LEN: t.CDefine = 512
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -345,7 +348,7 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in
|
||||
模块名通过 _PathToModuleName(includes/rel_path) 计算。
|
||||
内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
|
||||
"""
|
||||
global _sha1_store_arr, _sha1_store_mod, _sha1_store_rel, _sha1_store_count
|
||||
global _sha1_store_arr, _sha1_store_mod, _sha1_store_rel, _sha1_store_incdir, _sha1_store_count
|
||||
if scan_result is None:
|
||||
return -1
|
||||
# 释放旧存储器
|
||||
@@ -355,14 +358,18 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in
|
||||
stdlib.free(_sha1_store_mod)
|
||||
if _sha1_store_rel is not None:
|
||||
stdlib.free(_sha1_store_rel)
|
||||
if _sha1_store_incdir is not None:
|
||||
stdlib.free(_sha1_store_incdir)
|
||||
_sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
_sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
|
||||
_sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
if _sha1_store_arr is None or _sha1_store_mod is None or _sha1_store_rel is None:
|
||||
_sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
if _sha1_store_arr is None or _sha1_store_mod is None or _sha1_store_rel is None or _sha1_store_incdir is None:
|
||||
return -1
|
||||
string.memset(_sha1_store_arr, 0, MAX_INCLUDES * 17)
|
||||
string.memset(_sha1_store_mod, 0, MAX_INCLUDES * 64)
|
||||
string.memset(_sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
string.memset(_sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
_sha1_store_count = 0
|
||||
entry_size_p: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
|
||||
for i in range(scan_result.Count):
|
||||
@@ -398,6 +405,15 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in
|
||||
else:
|
||||
string.strncpy(_sha1_store_rel + idx3, ent.RelPath, MAX_REL_PATH_LEN - 1)
|
||||
_sha1_store_rel[idx3 + MAX_REL_PATH_LEN - 1] = '\0'
|
||||
# 保存所属 includes 根目录(Phase2 预注册/按需编译拼路径用)
|
||||
idx_inc: t.CSizeT = t.CSizeT(_sha1_store_count) * MAX_INC_DIR_LEN
|
||||
if ent.IncDir is not None:
|
||||
icd_len: t.CSizeT = string.strlen(ent.IncDir)
|
||||
if icd_len < MAX_INC_DIR_LEN:
|
||||
string.strcpy(_sha1_store_incdir + idx_inc, ent.IncDir)
|
||||
else:
|
||||
string.strncpy(_sha1_store_incdir + idx_inc, ent.IncDir, MAX_INC_DIR_LEN - 1)
|
||||
_sha1_store_incdir[idx_inc + MAX_INC_DIR_LEN - 1] = '\0'
|
||||
_sha1_store_count += 1
|
||||
return _sha1_store_count
|
||||
|
||||
@@ -424,7 +440,7 @@ def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> in
|
||||
# ============================================================
|
||||
def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
|
||||
"""追加条目到全局 SHA1 映射存储器(Phase2 用)"""
|
||||
global _sha1_store_arr, _sha1_store_mod, _sha1_store_rel, _sha1_store_count
|
||||
global _sha1_store_arr, _sha1_store_mod, _sha1_store_rel, _sha1_store_incdir, _sha1_store_count
|
||||
if sha1 is None or rel_path is None:
|
||||
return 1
|
||||
# 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用)
|
||||
@@ -432,11 +448,13 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
|
||||
_sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
|
||||
_sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
|
||||
_sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
if _sha1_store_arr is None or _sha1_store_mod is None or _sha1_store_rel is None:
|
||||
_sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
if _sha1_store_arr is None or _sha1_store_mod is None or _sha1_store_rel is None or _sha1_store_incdir is None:
|
||||
return 1
|
||||
string.memset(_sha1_store_arr, 0, MAX_INCLUDES * 17)
|
||||
string.memset(_sha1_store_mod, 0, MAX_INCLUDES * 64)
|
||||
string.memset(_sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
|
||||
string.memset(_sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
|
||||
_sha1_store_count = 0
|
||||
if _sha1_store_count >= MAX_INCLUDES:
|
||||
return 1
|
||||
@@ -474,6 +492,9 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
|
||||
else:
|
||||
string.strncpy(_sha1_store_rel + idx_r, rel_path, MAX_REL_PATH_LEN - 1)
|
||||
_sha1_store_rel[idx_r + MAX_REL_PATH_LEN - 1] = '\0'
|
||||
# App 源文件不属于任何 includes 目录:IncDir 留空(Phase2 回退 includes_dir 参数)
|
||||
idx_inc_a: t.CSizeT = t.CSizeT(_sha1_store_count) * MAX_INC_DIR_LEN
|
||||
_sha1_store_incdir[idx_inc_a] = '\0'
|
||||
_sha1_store_count += 1
|
||||
return 0
|
||||
|
||||
@@ -639,6 +660,11 @@ def GetSha1StoreRelArrPtr() -> bytes | t.CPtr:
|
||||
return _sha1_store_rel
|
||||
|
||||
|
||||
def GetSha1StoreIncdirArrPtr() -> bytes | t.CPtr:
|
||||
"""返回所属 includes 根目录数组指针(每个条目 MAX_INC_DIR_LEN 字节,空串表示不属于任何 includes 目录)"""
|
||||
return _sha1_store_incdir
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GetSha1StoreArr - 获取全局存储器数组指针(直接遍历用)
|
||||
#
|
||||
|
||||
+3
-3
@@ -304,11 +304,11 @@ def main() -> int:
|
||||
|
||||
# === Phase1: 扫描 includes(按需翻译)===
|
||||
# 对 includes 目录中每个 .vp/.py 文件,若 stub 不存在则翻译并分离 stub
|
||||
if do_phase1 != 0 and Config.IncludesDir is not None:
|
||||
if do_phase1 != 0 and Config.IncludesDirs is not None:
|
||||
ph1_temp: str = Config.TempDir
|
||||
if ph1_temp is None:
|
||||
ph1_temp = "."
|
||||
Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log)
|
||||
Phase1.RunPhase1(mb, Config.IncludesDirs, ph1_temp, log)
|
||||
# 如果仅 Phase1(不执行 Phase2),直接退出
|
||||
if do_phase2 == 0:
|
||||
if log is not None:
|
||||
@@ -333,7 +333,7 @@ def main() -> int:
|
||||
mf_ret: int = Phase2.RunMultiFileProject(
|
||||
mb, Config.SourceDir, mf_temp, mf_output,
|
||||
mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out,
|
||||
mf_includes_bin, Config.IncludesDir, do_phase1, do_phase2, log, args)
|
||||
mf_includes_bin, Config.IncludesDirs, do_phase1, do_phase2, log, args)
|
||||
argparse.release(args)
|
||||
if log is not None:
|
||||
log.success("TransPyV 完成")
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
|
||||
"name": "TransPyV",
|
||||
"version": "1.0.0",
|
||||
"source_dir": "./App",
|
||||
"build_dir": "./.tpv_build",
|
||||
"compiler": {
|
||||
"cmd": "llc",
|
||||
"flags": ["-filetype=obj", "-relocation-model=pic"]
|
||||
},
|
||||
"linker": {
|
||||
"cmd": "clang++",
|
||||
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition", "-Wl,--stack,0x1000000"],
|
||||
"output": "TransPyV.exe"
|
||||
},
|
||||
"includes": [
|
||||
"../includes"
|
||||
],
|
||||
"target": {
|
||||
"triple": "x86_64-pc-windows-gnu",
|
||||
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
},
|
||||
"options": {
|
||||
"slice_level": 3,
|
||||
"sha1_slice_level": 1,
|
||||
"target": "llvm",
|
||||
"strict_mode": true
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user