feat: strengthen BSP and PSP validation and handoff

This commit is contained in:
tangfahong committed 2026-09-24 11:52:22 +08:00
1 parent bcea35a91e
commit 1641fac631
39 files changed
+2695 -90

No files matched your search

@@ -49,6 +49,64 @@ def detects_dual_os(config_dir: Path) -> bool:
return False
def resolve_board_layout(project: Path, chip: str | None = None) -> dict[str, object]:
"""Keep the existing CV184X layout; recognize CV181X split configuration."""
config_dirs = config_directories(project)
if chip and chip.upper().startswith("CV181"):
kernel = project / "configs" / "kernel"
uboot = project / "configs" / "uboot"
if {path.name for path in config_dirs} != {"kernel", "uboot"}:
return {
"board_build_type": None,
"system_form": None,
"config_directory": None,
"layout": "unknown",
"error": "CV181X 项目需要 configs/kernel 和 configs/uboot 两个配置目录",
}
candidates = sorted(
path for path in uboot.glob("*_defconfig")
if path.is_file() and not path.is_symlink() and not path.name.startswith("cvitek_")
)
if len(candidates) == 1:
build_type = candidates[0].name.removesuffix("_defconfig")
sdk_config = uboot / f"cvitek_{build_type}_defconfig"
kernel_config = kernel / f"cvitek_{build_type}_defconfig"
if (sdk_config.is_file() and not sdk_config.is_symlink()
and kernel_config.is_file() and not kernel_config.is_symlink()):
return {
"board_build_type": build_type,
"system_form": "dual-os" if detects_dual_os(uboot) else "single-os",
"config_directory": str(uboot),
"layout": "split-kernel-uboot",
"error": None,
}
return {
"board_build_type": None,
"system_form": None,
"config_directory": None,
"layout": "split-kernel-uboot",
"error": "CV181X kernel/uboot 结构未能唯一定位完整的板级 defconfig 组",
}
if len(config_dirs) == 1 and config_dirs[0].name not in {"kernel", "uboot"}:
config_dir = config_dirs[0]
return {
"board_build_type": config_dir.name,
"system_form": "dual-os" if detects_dual_os(config_dir) else "single-os",
"config_directory": str(config_dir),
"layout": "board-directory",
"error": None,
}
return {
"board_build_type": None,
"system_form": None,
"config_directory": None,
"layout": "unknown",
"error": f"无法识别配置布局:configs/ 下有 {[path.name for path in config_dirs]}",
}
def project_preflight(reference_name: str, target_name: str, root: Path) -> dict[str, object]:
errors: list[str] = []
warnings: list[str] = []
@@ -64,13 +122,19 @@ def project_preflight(reference_name: str, target_name: str, root: Path) -> dict
errors.append(f"缺少 buildEnvConfig.sh: {build_env}")
else:
assignments = parse_assignments(build_env)
config_dirs = config_directories(reference)
if len(config_dirs) != 1:
errors.append(f"参考项目必须唯一定位一个配置目录,实际为 {len(config_dirs)} 个")
config_dir = config_dirs[0] if len(config_dirs) == 1 else None
sync_script = reference / "configs" / "EPSYNCSDKConfig.sh"
if not sync_script.is_file():
warnings.append(f"未找到项目同步脚本: {sync_script}")
layout = resolve_board_layout(reference, assignments.get("EP_CHIP"))
if layout["error"]:
errors.append(str(layout["error"]))
if layout["layout"] == "split-kernel-uboot":
sync_scripts = [reference / "configs" / part / script for part, script in (
("kernel", "ep_kernel.sh"), ("uboot", "ep_uboot.sh"))]
sync_script = None
else:
sync_script = reference / "configs" / "EPSYNCSDKConfig.sh"
sync_scripts = [sync_script]
for path in sync_scripts:
if not path.is_file() or path.is_symlink():
warnings.append(f"未找到普通项目同步脚本: {path}")
imgs = reference / "imgs"
imgs_target = os.readlink(imgs) if imgs.is_symlink() else None
@@ -94,13 +158,15 @@ def project_preflight(reference_name: str, target_name: str, root: Path) -> dict
"architecture": assignments.get("EP_ARCH"),
"flash": assignments.get("EP_FLASH_TYPE"),
"nand_flash_id": assignments.get("NAND_FLASH_ID"),
"board_build_type": config_dir.name if config_dir else None,
"system_form": "dual-os" if config_dir and detects_dual_os(config_dir) else "single-os",
"board_build_type": layout["board_build_type"],
"system_form": layout["system_form"],
"config_layout": layout["layout"],
},
"bounded_paths": {
"build_env": str(build_env),
"config_directory": str(config_dir) if config_dir else None,
"sync_script": str(sync_script),
"config_directory": layout["config_directory"],
"sync_script": str(sync_script) if sync_script else None,
"sync_scripts": [str(path) for path in sync_scripts],
"reference_imgs_target": imgs_target,
"target_imgs_target": project_guard.expected_imgs_target(target_name),
},
@@ -115,6 +181,14 @@ def build_preflight(project_name: str, version: str, root: Path, output_root: Pa
if not VERSION_RE.fullmatch(version):
errors.append("构建版本必须为 YYYYMMDD_N,且 N 为正整数")
build_env = project / "buildEnvConfig.sh"
assignments = parse_assignments(build_env) if build_env.is_file() and not build_env.is_symlink() else {}
if not assignments.get("EP_CHIP"):
errors.append(f"构建前无法确认 EP_CHIP: {build_env}")
layout = resolve_board_layout(project, assignments.get("EP_CHIP"))
if layout["error"]:
errors.append(str(layout["error"]))
completion_script = root / "tools" / "script_completion.sh"
if not completion_script.is_file():
errors.append(f"统一构建入口不存在: {completion_script}")
@@ -137,6 +211,9 @@ def build_preflight(project_name: str, version: str, root: Path, output_root: Pa
f"EMX2_BuildSDKTool {project_name} {version} all"
)
warnings.append("统一构建可能同步配置到项目外 SDK,并按工具实现执行 git fetch origin")
requires_patch_precheck = assignments.get("EP_CHIP", "").upper().startswith("CV184")
if requires_patch_precheck:
warnings.append("CV184X 构建补丁检查失败可能触发 --applypatch --force;本预检未验证补丁环境,不能单凭 passed=true 自动构建")
return {
"schema_version": 1,
"kind": "build-preflight",
@@ -145,6 +222,9 @@ def build_preflight(project_name: str, version: str, root: Path, output_root: Pa
"warnings": warnings,
"project": project_name,
"project_path": str(project),
"config_layout": layout["layout"],
"board_build_type": layout["board_build_type"],
"requires_patch_precheck": requires_patch_precheck,
"build_version": version,
"working_directory": str(root),
"completion_script": str(completion_script),