Team Ai
Modelpublic

cwenzi/neuroflow-cpp

sourceHugging Faceapache-2.0updated 3mo agoView on Hugging Face
1likes
stub_evaluator.py140 linesDownload Raw Back to scripts
1import os
2import re
3import json
4import argparse
5import logging
6
7logger = logging.getLogger(__name__)
8
9HEADER_ONLY_PROS = [
10    "无需编译.cpp文件,包含即可用",
11    "模板代码可内联优化",
12    "分发简单(单头文件)",
13    "适合小型模板库",
14    "避免链接顺序问题",
15]
16HEADER_ONLY_CONS = [
17    "编译时间随包含次数线性增长",
18    "二进制体积膨胀(重复实例化)",
19    "循环依赖风险高",
20    "调试困难(模板展开复杂)",
21    "IDE代码补全和跳转受限",
22    "修改头文件触发全量重编译",
23]
24COMPILED_SEP_PROS = [
25    "编译时间可控(修改cpp仅重编译单文件)",
26    "二进制体积小(单次实例化)",
27    "可隐藏实现细节(Pimpl模式)",
28    "循环依赖易解(前向声明)",
29    "调试友好(独立编译单元)",
30    "增量编译高效",
31]
32COMPILED_SEP_CONS = [
33    "需维护hpp/cpp文件对",
34    "模板代码仍需在头文件",
35    "构建系统更复杂",
36    "分发需同时提供头文件和库文件",
37    "链接顺序可能出错",
38]
39
40
41def analyze_stub_file(file_path):
42    with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
43        lines = f.readlines()
44    total = len(lines)
45    effective = sum(1 for l in lines if l.strip() and not l.strip().startswith("//"))
46    has_include = any("#include" in l for l in lines)
47    has_namespace = any("namespace" in l for l in lines)
48    has_impl = any(re.search(r'\w+::\w+', l) for l in lines if not l.strip().startswith("//"))
49    is_stub = effective <= 5 and not has_impl
50    return {
51        "path": file_path, "total_lines": total, "effective_lines": effective,
52        "is_stub": is_stub, "has_include": has_include, "has_namespace": has_namespace,
53        "has_implementation": has_impl,
54    }
55
56
57def analyze_hpp_template_ratio(hpp_dir):
58    reports = {}
59    for fname in os.listdir(hpp_dir):
60        if not fname.endswith(".hpp"):
61            continue
62        fpath = os.path.join(hpp_dir, fname)
63        with open(fpath, "r", encoding="utf-8", errors="ignore") as f:
64            lines = f.readlines()
65        total = len(lines)
66        template_lines = sum(1 for l in lines if "template" in l)
67        reports[fname] = {"total_lines": total, "template_lines": template_lines,
68                          "ratio": template_lines / total if total > 0 else 0}
69    return reports
70
71
72def make_mode_decision(stub_reports, template_reports):
73    decision = {"mode": "MIXED", "details": []}
74    for fname, info in template_reports.items():
75        if info["ratio"] > 0.05:
76            decision["details"].append((fname, "HEADER_ONLY", "模板占比高,保持Header-Only"))
77        else:
78            decision["details"].append((fname, "COMPILED_SEP", "模板占比低,迁移到编译分离"))
79    return decision
80
81
82def generate_cmake_patch(current_cmake_path):
83    patch_lines = [
84        "# === NeuroFlow 文件完整性补丁 ===",
85        "# 在neuroflow_core源文件列表中添加:",
86        "#   src/weight_io.cpp",
87        "# 新增训练可执行目标:",
88        "#   add_executable(neuroflow_train_v2 src/train_v2.cpp)",
89        "#   target_link_libraries(neuroflow_train_v2 PRIVATE neuroflow_core OpenMP::OpenMP_CXX)",
90    ]
91    return "\n".join(patch_lines)
92
93
94def generate_evaluation_report(stub_reports, template_reports, decision, cmake_patch):
95    lines = ["# NeuroFlow 空壳源文件评估报告\n"]
96    lines.append("## 空壳文件分析\n")
97    for r in stub_reports:
98        status = "✅ 空壳" if r["is_stub"] else "❌ 非空壳"
99        lines.append(f"- `{r['path']}`: {r['total_lines']}行, 有效{r['effective_lines']}行, {status}")
100    lines.append("\n## Header-Only vs 编译分离\n")
101    lines.append("### Header-Only 优点\n")
102    for p in HEADER_ONLY_PROS:
103        lines.append(f"- {p}")
104    lines.append("\n### Header-Only 缺点\n")
105    for c in HEADER_ONLY_CONS:
106        lines.append(f"- {c}")
107    lines.append("\n### 编译分离 优点\n")
108    for p in COMPILED_SEP_PROS:
109        lines.append(f"- {p}")
110    lines.append("\n### 编译分离 缺点\n")
111    for c in COMPILED_SEP_CONS:
112        lines.append(f"- {c}")
113    lines.append(f"\n## 混合模式决策: **{decision['mode']}**\n")
114    for fname, mode, reason in decision["details"]:
115        lines.append(f"- `{fname}`: **{mode}** — {reason}")
116    lines.append("\n## CMakeLists.txt 修改方案\n")
117    lines.append(f"```cmake\n{cmake_patch}\n```")
118    return "\n".join(lines)
119
120
121if __name__ == "__main__":
122    logging.basicConfig(level=logging.INFO)
123    parser = argparse.ArgumentParser(description="NeuroFlow空壳源文件评估器")
124    parser.add_argument("--source-dir", type=str, default="src", help="源文件目录")
125    parser.add_argument("--include-dir", type=str, default="include/neuroflow", help="头文件目录")
126    parser.add_argument("--cmake", type=str, default="CMakeLists.txt", help="CMakeLists.txt路径")
127    parser.add_argument("--output", type=str, default="report_stub_evaluation.md", help="输出报告路径")
128    args = parser.parse_args()
129
130    stub_reports = []
131    for f in os.listdir(args.source_dir):
132        if f.endswith(".cpp"):
133            stub_reports.append(analyze_stub_file(os.path.join(args.source_dir, f)))
134    template_reports = analyze_hpp_template_ratio(args.include_dir)
135    decision = make_mode_decision(stub_reports, template_reports)
136    cmake_patch = generate_cmake_patch(args.cmake)
137    report = generate_evaluation_report(stub_reports, template_reports, decision, cmake_patch)
138    with open(args.output, "w", encoding="utf-8") as f:
139        f.write(report)
140    logger.info(f"评估报告已保存到 {args.output}")