import subprocess import logging from pathlib import Path logger = logging.getLogger(__name__) def collect_gcov(cobol_src: Path, work_dir: Path) -> dict: try: gcda_files = list(work_dir.glob("*.gcda")) if not gcda_files: logger.warning("[gcov] 未找到 .gcda 文件,可能未启用插桩编译") return {"available": False, "reason": "no_gcda_files"} result = subprocess.run( ["gcov", cobol_src.name], capture_output=True, text=True, timeout=30, cwd=work_dir, ) if result.returncode != 0: logger.warning(f"[gcov] gcov 执行失败: {result.stderr[:200]}") return {"available": False, "reason": "gcov_failed"} gcov_file = work_dir / f"{cobol_src.stem}.cbl.gcov" if not gcov_file.exists(): gcov_file = work_dir / f"{cobol_src.stem}.gcov" if not gcov_file.exists(): logger.warning("[gcov] .gcov 文件未生成") return {"available": False, "reason": "no_gcov_output"} total_lines = 0 executed_lines = 0 with open(gcov_file) as f: for line in f: stripped = line.strip() if stripped and not stripped.startswith("-"): total_lines += 1 if not stripped.startswith("#"): executed_lines += 1 line_rate = executed_lines / max(total_lines, 1) return { "available": True, "line_rate": round(line_rate, 4), "total_lines": total_lines, "executed_lines": executed_lines, } except FileNotFoundError: logger.warning("[gcov] gcov 命令未找到,降级为仅静态分析") return {"available": False, "reason": "gcov_not_installed"} except Exception as e: logger.warning(f"[gcov] 采集异常: {e}") return {"available": False, "reason": str(e)[:100]}