"""
gen_full_flow_batch.py
对已有 03_参数定义.yaml 的接口批量执行完整 CPP 生成链:
st_to_fuzz_config → gen_fuzz_cpp(normal) → gen_non_contig_from_normal →
gen_error_scenarios+gen_error_cpp → gen_consistent_from_normal → gen_multithread_from_nc
并逐个编译校验(-fsyntax-only)。
用法:
python gen_full_flow_batch.py --apis <清单文件> # 每行一个 aclnnApiName
python gen_full_flow_batch.py --api aclnnXxx
"""
import argparse
import os
import subprocess
import sys
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
GEN = os.path.join(ROOT, "skills/ascendc-fuzz-cpp-gen/scripts")
CONS = os.path.join(ROOT, "skills/gen-consistent-from-normal/scripts")
ASCEND = "/usr/local/Ascend/ascend-toolkit/latest/x86_64-linux"
def sh(cmd, timeout=600):
r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, cwd=ROOT)
return r.returncode, (r.stdout + r.stderr)
def compile_check(cpp):
cmd = ["g++", "-fsyntax-only", "-w", "-DAscend950DT_9582",
"-I", "turing_sec/aclnnAPI_fuzz/inc/utils/",
"-I", "turing_sec/aclnnAPI_fuzz/fuzzlib/",
"-I", "turing_sec/aclnnAPI_fuzz/inc/acl/",
"-I", ASCEND + "/include/",
"-I", ASCEND + "/x86_64-linux/include/aclnnop/",
"-I", ASCEND + "/include", "-std=c++11", "-pthread", cpp]
rc, out = sh(cmd)
errs = [l for l in out.splitlines() if "error:" in l]
return len(errs), errs[:3]
def process(api):
d = os.path.join(ROOT, "output", api)
td = os.path.join(d, "test-design")
y03 = os.path.join(td, "03_参数定义.yaml")
if not os.path.isfile(y03):
return f"SKIP: 无 03_参数定义.yaml"
cfg = os.path.join(td, "fuzz_config.yaml")
rc, out = sh(["python3", os.path.join(GEN, "st_to_fuzz_config.py"),
"--param_def", y03, "--op_name", api, "--output", cfg])
if not os.path.isfile(cfg):
return f"FAIL st_to_fuzz_config: {out[-200:]}"
rc, out = sh(["python3", os.path.join(GEN, "gen_fuzz_cpp.py"),
"--op_name", api, "--config", cfg, "--output", d])
normal = os.path.join(d, f"{api}.cpp")
if not os.path.isfile(normal):
return f"FAIL gen_fuzz_cpp: {out[-200:]}"
nc = os.path.join(d, f"{api}_non_contig.cpp")
sh(["python3", os.path.join(GEN, "gen_non_contig_from_normal.py"), normal, nc, api])
es = os.path.join(td, "error_scenarios.yaml")
sh(["python3", os.path.join(GEN, "gen_error_scenarios.py"), "--param_yaml", y03, "--output", es])
ecp = os.path.join(d, f"{api}_error.cpp")
sh(["python3", os.path.join(GEN, "gen_error_cpp.py"), "--op_name", api,
"--scenarios", es, "--param_yaml", y03, "--output", ecp])
cst = os.path.join(d, f"{api}_consistent.cpp")
sh(["python3", os.path.join(CONS, "gen_consistent_from_normal.py"),
"--input", normal, "--output", cst, "--api", api])
mt = os.path.join(d, f"{api}_multithread.cpp")
sh(["python3", os.path.join(ROOT, "scripts/gen_multithread_from_nc.py"), nc, mt, api])
results = {}
for name, p in [("normal", normal), ("nc", nc), ("mt", mt), ("error", ecp), ("consistent", cst)]:
if os.path.isfile(p):
n, errs = compile_check(os.path.relpath(p, ROOT))
results[name] = n
if n:
results[name] = f"{n}({' | '.join(e.split(': error:')[0].split('/')[-1] for e in errs)})"
else:
results[name] = "缺文件"
ok = all(isinstance(v, int) and v == 0 for v in results.values())
return ("OK " if ok else "ERR ") + " ".join(f"{k}={v}" for k, v in results.items())
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--apis")
ap.add_argument("--api")
args = ap.parse_args()
apis = [args.api] if args.api else [l.strip() for l in open(args.apis) if l.strip()]
for i, api in enumerate(apis, 1):
r = process(api)
print(f"[{i}/{len(apis)}] {api}: {r}", flush=True)
if __name__ == "__main__":
main()