错误处理实现指南¶
版本:v3.0.10 | 更新时间:2026-01-21
概述¶
CCGO 增强的错误处理系统提供:
- 用户友好的错误消息,附带可执行的提示
- 优雅降级,当可选工具缺失时
- 全面的配置验证,附带有用的建议
- 更好的构建失败诊断
架构¶
src/
├── error.rs # 自定义错误类型和提示
├── config/
│ ├── ccgo_toml.rs # 配置解析(增强版)
│ └── validation.rs # 全面验证
└── utils/
└── tools.rs # 工具检测和验证
组件¶
1. 错误模块(src/error.rs)¶
带上下文提示的自定义错误类型:
use crate::error::{CcgoError, hints};
// 配置错误
CcgoError::config_error_with_hint(
"Invalid package name",
None,
"Package name must be a valid C++ identifier"
)
// 依赖错误
CcgoError::dependency_error_with_hint(
"fmt",
"Invalid version requirement",
"Version requirements support: ^1.0.0, ~1.2.0, >=1.0.0"
)
// 缺失工具错误
CcgoError::missing_tool(
"cmake",
"building projects",
hints::cmake() // 提供安装说明
)
// 带诊断信息的构建失败
CcgoError::build_failure_with_diagnostics(
"Android",
"NDK not found",
vec!["Check ANDROID_NDK environment variable"],
Some(hints::android_ndk())
)
可用提示¶
hints 模块为常见工具提供安装说明:
hints::cmake()- CMake 安装hints::git()- Git 安装hints::android_ndk()- Android NDK 设置hints::xcode()- Xcode 安装hints::visual_studio()- Visual Studio 设置hints::mingw()- MinGW 安装hints::gradle()- Gradle 安装hints::python()- Python 安装hints::doxygen()- Doxygen 安装
常见错误模式¶
// CCGO.toml 未找到
hints::ccgo_toml_not_found()
// 无效的 CCGO.toml
hints::invalid_ccgo_toml()
// 依赖解析失败
hints::dependency_resolution()
// 构建配置问题
hints::build_config()
// Lockfile 不同步
hints::lockfile_mismatch()
2. 配置验证(src/config/validation.rs)¶
附带有用错误消息的全面验证:
use crate::config::validate_config;
// 加载并验证配置
let config = CcgoConfig::load()?; // 自动验证
// 手动验证
validate_config(&config)?;
验证检查项¶
包元信息:
- ✅ 包名(必须是有效的 C++ 标识符,不能是关键字)
- ✅ 版本(必须是有效的 semver:1.0.0、2.3.4-alpha.1)
- ✅ 许可证(对非标准 SPDX 标识符发出警告)
工作区配置: - ✅ 仅工作区配置时成员列表非空 - ✅ 有效的解析器版本("1" 或 "2")
依赖项:
- ✅ 至少有一个有效来源(version、git 或 path)
- ✅ 有效的版本要求(^1.0.0、~1.2.0、>=1.0.0)
- ✅ 有效的 git URL(必须以 https://、git:// 等开头)
- ✅ 不存在冲突的 git refs(不能同时指定 branch 和 tag)
- ✅ 路径依赖存在(仅警告)
构建配置: - ✅ 并行任务数 > 0 - ✅ 合理的任务数量(超过 128 时发出警告)
平台配置:
- ✅ Android minSdk >= 16(低于推荐值时发出警告)
- ✅ 有效的 iOS 版本格式("12.0"、"14.0")
二进制和示例: - ✅ 有效的名称(C++ 标识符) - ✅ 源文件存在(仅警告)
3. 工具检测(src/utils/tools.rs)¶
通过优雅降级检测构建工具:
use crate::utils::tools::{
check_tool,
require_tool,
check_tool_with_requirement,
ToolRequirement,
PlatformTools,
};
// 检查工具是否存在
if let Some(tool_info) = check_tool("cmake") {
println!("CMake version: {:?}", tool_info.version);
}
// 要求某个工具(缺失则报错)
let cmake = require_tool("cmake", "building projects")?;
// 按需求级别检查
check_tool_with_requirement(
"doxygen",
ToolRequirement::Recommended,
"documentation generation"
)?;
// ⚠️ 缺失时发出警告,但继续执行
工具需求级别¶
pub enum ToolRequirement {
/// 必需 - 缺失时以有用的错误信息失败
Required,
/// 可选 - 缺失时静默
Optional,
/// 推荐 - 缺失时发出警告,继续执行
Recommended,
}
平台特定的工具检查¶
use crate::utils::tools::{
PlatformTools,
check_android_environment,
check_apple_environment,
check_windows_environment,
};
// 检查平台特定的工具
let checker = PlatformTools::new("android");
let (required, optional) = checker.check_all()?;
// Android 环境
check_android_environment()?; // 检查 ANDROID_NDK、ANDROID_HOME
// Apple 环境
check_apple_environment()?; // 检查 Xcode、命令行工具
// Windows 环境
check_windows_environment("msvc")?; // 检查 MSVC 或 MinGW
集成示例¶
示例 1:增强的构建命令¶
use crate::utils::tools::{PlatformTools, ToolRequirement};
use crate::error::CcgoError;
pub fn execute_build(platform: &str) -> Result<()> {
// 检查必需工具
let checker = PlatformTools::new(platform);
let (required_tools, optional_tools) = checker.check_all()?;
println!("✓ Required tools found:");
for tool in &required_tools {
println!(" • {}: {}", tool.name,
tool.version.as_deref().unwrap_or("installed"));
}
if !optional_tools.is_empty() {
println!("✓ Optional tools found:");
for tool in &optional_tools {
println!(" • {}", tool.name);
}
}
// 继续构建...
Ok(())
}
示例 2:增强的安装命令¶
use crate::error::{CcgoError, hints};
use crate::config::validate_config;
pub fn execute_install(dep_name: Option<&str>) -> Result<()> {
// 加载并验证配置
let config = CcgoConfig::load()?; // 自动验证
// 检查 git 依赖所需的 git
let has_git_deps = config.dependencies.iter()
.any(|d| d.git.is_some());
if has_git_deps {
require_tool("git", "installing git dependencies")?;
}
// 安装依赖...
Ok(())
}
示例 3:更好的错误消息¶
之前:
之后:
ERROR: Failed to parse CCGO.toml
Common issues:
• Invalid TOML syntax (check quotes, brackets, commas)
• Typo in section names (should be [package] or [workspace])
• Missing closing brackets or quotes
Validate your TOML at: https://www.toml-lint.com/
之前:
之后:
ERROR: Invalid version requirement '1.0' for dependency 'fmt'
HINT: Version requirements support:
• Exact: "1.2.3" or "=1.2.3"
• Range: ">=1.0.0, <2.0.0"
• Caret: "^1.0.0" (allows 1.x.x)
• Tilde: "~1.2.0" (allows 1.2.x)
• Wildcard: "1.*" or "1.2.*"
最佳实践¶
1. 始终提供上下文¶
// 错误
bail!("Tool not found");
// 正确
Err(CcgoError::missing_tool(
"cmake",
"building C++ projects",
hints::cmake()
).into())
2. 使用合适的错误类型¶
// 配置错误
CcgoError::config_error_with_hint(message, source, hint)
// 依赖错误
CcgoError::dependency_error_with_hint(dep_name, message, hint)
// 缺失工具
CcgoError::missing_tool(tool, required_for, hint)
// 构建失败
CcgoError::build_failure_with_diagnostics(platform, message, diagnostics, hint)
3. 尽早验证¶
4. 构建前检查工具¶
// 平台特定构建
let checker = PlatformTools::new("android");
checker.check_required()?; // 通过有用的错误快速失败
// 可选特性
check_tool_with_requirement(
"doxygen",
ToolRequirement::Recommended,
"documentation generation"
)?;
错误消息编写指南¶
编写错误消息时:
- 具体明确:说明发生了什么以及发生在哪里
- 可操作:告诉用户如何修复
- 简洁:让提示聚焦于最可能的解决方案
- 有帮助:包含示例、链接或可运行的命令
示例:
❌ 错误:"Invalid configuration"
✅ 正确:
ERROR: Invalid package name 'class' in CCGO.toml
HINT: Package name 'class' is a C++ reserved keyword.
Choose a different name, e.g., 'class_lib' or 'libclass'
测试¶
所有验证逻辑都包含单元测试:
当前状态¶
✅ 已完成: - 带提示的自定义错误类型 - 全面的配置验证 - 带优雅降级的工具检测 - 增强的 CCGO.toml 解析错误 - 平台特定的工具检查
📝 集成任务(后续):
- 将工具检查集成到 build 命令
- 将工具检查集成到 publish 命令
- 添加更多平台特定的验证
- 带常见解决方案的构建失败诊断
迁移指南¶
在现有代码中使用新的错误处理方式:
之前:¶
之后:¶
use crate::error::{CcgoError, hints};
use crate::utils::tools::require_tool;
// 选项 1:使用工具检测
require_tool("cmake", "building projects")?;
// 选项 2:手动构造错误
if tool_missing {
return Err(CcgoError::missing_tool(
"cmake",
"building projects",
hints::cmake()
).into());
}