This commit is contained in:
crazywhalecc 2026-02-05 16:11:16 +08:00
parent 4d4b1a334f
commit 2a4959d973
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
6 changed files with 62 additions and 7 deletions

View File

@ -32,6 +32,7 @@ class ConfigValidator
'build-static' => ConfigType::BOOL,
'build-with-php' => ConfigType::BOOL,
'notes' => ConfigType::BOOL,
'display-name' => ConfigType::STRING,
// library and target fields
'headers' => ConfigType::LIST_ARRAY, // @
@ -75,6 +76,7 @@ class ConfigValidator
'build-static' => false,
'build-with-php' => false,
'notes' => false,
'display-name' => false,
];
public const array ARTIFACT_TYPE_FIELDS = [ // [required_fields, optional_fields]

View File

@ -58,7 +58,7 @@ class PackageBuilder
if ($package->getType() !== 'virtual-target') {
// patch before build
$package->patchBeforeBuild();
$package->emitPatchBeforeBuild();
}
// build

View File

@ -53,7 +53,7 @@ trait PackageCallbacksTrait
$this->patch_before_build_callbacks[] = $callback;
}
public function patchBeforeBuild(): void
public function emitPatchBeforeBuild(): void
{
if (file_exists("{$this->getSourceDir()}/.spc-patched")) {
return;

View File

@ -159,7 +159,7 @@ class PackageLoader
}
$package_type = PackageConfig::get($attribute_instance->name, 'type');
if ($package_type === null) {
throw new RegistryException("Package [{$attribute_instance->name}] not defined in config, please check your config files.");
throw new RegistryException("Package [{$attribute_instance->name}] not defined in config, but referenced from class {$class}, please check your config files.");
}
// if class has parent class and matches the attribute instance, use custom class
@ -277,6 +277,8 @@ class PackageLoader
foreach (self::$packages as $pkg) {
if ($pkg instanceof PhpExtensionPackage) {
$pkg->registerDefaultStages();
} elseif ($pkg instanceof LibraryPackage) {
$pkg->registerDefaultStages();
}
}
}

View File

@ -237,6 +237,9 @@ class Registry
// check BeforeStage, AfterStage is valid
PackageLoader::checkLoadedStageEvents();
// Validate package dependencies
self::validatePackageDependencies();
}
/**
@ -310,6 +313,54 @@ class Registry
return self::$current_registry_name;
}
/**
* Validate package dependencies to ensure all referenced dependencies exist.
* This helps catch configuration errors early in the registry loading process.
*
* @throws RegistryException
*/
private static function validatePackageDependencies(): void
{
$all_packages = PackageConfig::getAll();
$errors = [];
foreach ($all_packages as $pkg_name => $pkg_config) {
// Check depends field
$depends = PackageConfig::get($pkg_name, 'depends', []);
if (!is_array($depends)) {
$errors[] = "Package '{$pkg_name}' has invalid 'depends' field (expected array, got " . gettype($depends) . ')';
continue;
}
foreach ($depends as $dep) {
if (!isset($all_packages[$dep])) {
$config_info = self::getPackageConfigInfo($pkg_name);
$location = $config_info ? " (defined in {$config_info['config']})" : '';
$errors[] = "Package '{$pkg_name}'{$location} depends on '{$dep}' which does not exist in any loaded registry";
}
}
// Check suggests field
$suggests = PackageConfig::get($pkg_name, 'suggests', []);
if (!is_array($suggests)) {
$errors[] = "Package '{$pkg_name}' has invalid 'suggests' field (expected array, got " . gettype($suggests) . ')';
continue;
}
foreach ($suggests as $suggest) {
if (!isset($all_packages[$suggest])) {
$config_info = self::getPackageConfigInfo($pkg_name);
$location = $config_info ? " (defined in {$config_info['config']})" : '';
$errors[] = "Package '{$pkg_name}'{$location} suggests '{$suggest}' which does not exist in any loaded registry";
}
}
}
if (!empty($errors)) {
throw new RegistryException("Package dependency validation failed:\n - " . implode("\n - ", $errors));
}
}
/**
* Parse a class entry from the classes array.
* Supports two formats:

View File

@ -219,8 +219,8 @@ class DependencyResolver
return;
}
$visited[$pkg_name] = true;
// 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常)
foreach (array_merge($dep_list[$pkg_name]['depends'], $dep_list[$pkg_name]['suggests']) as $dep) {
// 遍历该依赖的所有依赖
foreach (array_merge($dep_list[$pkg_name]['depends'] ?? [], $dep_list[$pkg_name]['suggests'] ?? []) as $dep) {
self::visitPlatAllDeps($dep, $dep_list, $visited, $sorted);
}
$sorted[] = $pkg_name;
@ -233,11 +233,11 @@ class DependencyResolver
return;
}
$visited[$pkg_name] = true;
// 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常)
// 遍历该依赖的所有依赖
if (!isset($dep_list[$pkg_name])) {
throw new WrongUsageException("{$pkg_name} not exist !");
}
foreach ($dep_list[$pkg_name]['depends'] as $dep) {
foreach ($dep_list[$pkg_name]['depends'] ?? [] as $dep) {
self::visitPlatDeps($dep, $dep_list, $visited, $sorted);
}
$sorted[] = $pkg_name;