Generate PHPDocs for future vendor mode

This commit is contained in:
crazywhalecc
2025-07-28 14:57:08 +08:00
parent bbd83cbd1b
commit 1c8d67017b
10 changed files with 344 additions and 80 deletions

View File

@@ -4,7 +4,18 @@ declare(strict_types=1);
namespace SPC\builder; namespace SPC\builder;
/**
* Interface for library implementations
*
* This interface defines the basic contract that all library classes must implement.
* It provides a common way to identify and work with different library types.
*/
interface LibraryInterface interface LibraryInterface
{ {
/**
* Get the name of the library
*
* @return string The library name
*/
public function getName(): string; public function getName(): string;
} }

View File

@@ -7,9 +7,6 @@ namespace SPC\store;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
/**
* 一个读取 config 配置的操作类
*/
class Config class Config
{ {
public static ?array $pkg = null; public static ?array $pkg = null;
@@ -23,6 +20,10 @@ class Config
public static ?array $pre_built = null; public static ?array $pre_built = null;
/** /**
* Get pre-built configuration by name
*
* @param string $name The name of the pre-built configuration
* @return mixed The pre-built configuration or null if not found
* @throws WrongUsageException * @throws WrongUsageException
* @throws FileSystemException * @throws FileSystemException
*/ */
@@ -50,8 +51,10 @@ class Config
} }
/** /**
* 从配置文件读取一个资源(source)的元信息 * Get source configuration by name
* *
* @param string $name The name of the source
* @return null|array The source configuration or null if not found
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function getSource(string $name): ?array public static function getSource(string $name): ?array
@@ -63,8 +66,10 @@ class Config
} }
/** /**
* Read pkg from pkg.json * Get package configuration by name
* *
* @param string $name The name of the package
* @return null|array The package configuration or null if not found
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function getPkg(string $name): ?array public static function getPkg(string $name): ?array
@@ -76,11 +81,13 @@ class Config
} }
/** /**
* 根据不同的操作系统分别选择不同的 lib 库依赖项 * Get library configuration by name and optional key
* 如果 key 为 null那么直接返回整个 meta。 * Supports platform-specific configurations for different operating systems
* 如果 key 不为 null则可以使用的 key 有 static-libs、headers、lib-depends、lib-suggests。
* 对于 macOS 平台,支持 frameworks。
* *
* @param string $name The name of the library
* @param null|string $key The configuration key (static-libs, headers, lib-depends, lib-suggests, frameworks, bin)
* @param mixed $default Default value if key not found
* @return mixed The library configuration or default value
* @throws FileSystemException * @throws FileSystemException
* @throws WrongUsageException * @throws WrongUsageException
*/ */
@@ -115,6 +122,9 @@ class Config
} }
/** /**
* Get all library configurations
*
* @return array All library configurations
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function getLibs(): array public static function getLibs(): array
@@ -126,6 +136,10 @@ class Config
} }
/** /**
* Get extension target configuration by name
*
* @param string $name The name of the extension
* @return null|array The extension target configuration or default ['static', 'shared']
* @throws WrongUsageException * @throws WrongUsageException
* @throws FileSystemException * @throws FileSystemException
*/ */
@@ -141,6 +155,13 @@ class Config
} }
/** /**
* Get extension configuration by name and optional key
* Supports platform-specific configurations for different operating systems
*
* @param string $name The name of the extension
* @param null|string $key The configuration key (lib-depends, lib-suggests, ext-depends, ext-suggests, arg-type)
* @param mixed $default Default value if key not found
* @return mixed The extension configuration or default value
* @throws FileSystemException * @throws FileSystemException
* @throws WrongUsageException * @throws WrongUsageException
*/ */
@@ -175,6 +196,9 @@ class Config
} }
/** /**
* Get all extension configurations
*
* @return array All extension configurations
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function getExts(): array public static function getExts(): array
@@ -186,6 +210,9 @@ class Config
} }
/** /**
* Get all source configurations
*
* @return array All source configurations
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function getSources(): array public static function getSources(): array

View File

@@ -18,12 +18,13 @@ use SPC\util\SPCTarget;
class Downloader class Downloader
{ {
/** /**
* Get latest version from BitBucket tag (type = bitbuckettag) * Get latest version from BitBucket tag
* *
* @param string $name source name * @param string $name Source name
* @param array $source source meta info: [repo] * @param array $source Source meta info: [repo]
* @return array<int, string> [url, filename] * @return array<int, string> [url, filename]
* @throws DownloaderException * @throws DownloaderException
* @throws RuntimeException
*/ */
public static function getLatestBitbucketTag(string $name, array $source): array public static function getLatestBitbucketTag(string $name, array $source): array
{ {
@@ -53,13 +54,12 @@ class Downloader
} }
/** /**
* Get latest version from GitHub tarball (type = ghtar / ghtagtar) * Get latest version from GitHub tarball
*
* @param string $name source name
* @param array $source source meta info: [repo]
* @param string $type type of tarball, default is 'releases'
* @return array<int, string> [url, filename]
* *
* @param string $name Source name
* @param array $source Source meta info: [repo]
* @param string $type Type of tarball, default is 'releases'
* @return array<int, string> [url, filename]
* @throws DownloaderException * @throws DownloaderException
*/ */
public static function getLatestGithubTarball(string $name, array $source, string $type = 'releases'): array public static function getLatestGithubTarball(string $name, array $source, string $type = 'releases'): array
@@ -107,8 +107,8 @@ class Downloader
/** /**
* Get latest version from GitHub release (uploaded archive) * Get latest version from GitHub release (uploaded archive)
* *
* @param string $name source name * @param string $name Source name
* @param array $source source meta info: [repo, match] * @param array $source Source meta info: [repo, match]
* @param bool $match_result Whether to return matched result by `match` param (default: true) * @param bool $match_result Whether to return matched result by `match` param (default: true)
* @return array<int, string> When $match_result = true, and we matched, [url, filename]. Otherwise, [{asset object}. ...] * @return array<int, string> When $match_result = true, and we matched, [url, filename]. Otherwise, [{asset object}. ...]
* @throws DownloaderException * @throws DownloaderException
@@ -150,8 +150,8 @@ class Downloader
/** /**
* Get latest version from file list (regex based crawler) * Get latest version from file list (regex based crawler)
* *
* @param string $name source name * @param string $name Source name
* @param array $source source meta info: [url, regex] * @param array $source Source meta info: [filelist]
* @return array<int, string> [url, filename] * @return array<int, string> [url, filename]
* @throws DownloaderException * @throws DownloaderException
*/ */
@@ -187,11 +187,17 @@ class Downloader
} }
/** /**
* Just download file using system curl command, and lock it * Download file from URL
* *
* @throws FileSystemException * @param string $name Download name
* @param string $url Download URL
* @param string $filename Target filename
* @param null|string $move_path Optional move path after download
* @param int $download_as Download type constant
* @param array $headers Optional HTTP headers
* @param array $hooks Optional curl hooks
* @throws DownloaderException
* @throws RuntimeException * @throws RuntimeException
* @throws WrongUsageException
*/ */
public static function downloadFile(string $name, string $url, string $filename, ?string $move_path = null, int $download_as = SPC_DOWNLOAD_SOURCE, array $headers = [], array $hooks = []): void public static function downloadFile(string $name, string $url, string $filename, ?string $move_path = null, int $download_as = SPC_DOWNLOAD_SOURCE, array $headers = [], array $hooks = []): void
{ {
@@ -213,11 +219,17 @@ class Downloader
} }
/** /**
* Download git source, and lock it. * Download Git repository
* *
* @throws FileSystemException * @param string $name Repository name
* @param string $url Git repository URL
* @param string $branch Branch to checkout
* @param null|array $submodules Optional submodules to initialize
* @param null|string $move_path Optional move path after download
* @param int $retries Number of retry attempts
* @param int $lock_as Lock type constant
* @throws DownloaderException
* @throws RuntimeException * @throws RuntimeException
* @throws WrongUsageException
*/ */
public static function downloadGit(string $name, string $url, string $branch, ?array $submodules = null, ?string $move_path = null, int $retries = 0, int $lock_as = SPC_DOWNLOAD_SOURCE): void public static function downloadGit(string $name, string $url, string $branch, ?array $submodules = null, ?string $move_path = null, int $retries = 0, int $lock_as = SPC_DOWNLOAD_SOURCE): void
{ {
@@ -304,7 +316,6 @@ class Downloader
if ($pkg === null) { if ($pkg === null) {
$pkg = Config::getPkg($name); $pkg = Config::getPkg($name);
} }
if ($pkg === null) { if ($pkg === null) {
logger()->warning('Package {name} unknown. Skipping.', ['name' => $name]); logger()->warning('Package {name} unknown. Skipping.', ['name' => $name]);
return; return;
@@ -398,7 +409,7 @@ class Downloader
} }
/** /**
* Download source by name and meta. * Download source
* *
* @param string $name source name * @param string $name source name
* @param null|array{ * @param null|array{
@@ -428,7 +439,6 @@ class Downloader
if ($source === null) { if ($source === null) {
$source = Config::getSource($name); $source = Config::getSource($name);
} }
if ($source === null) { if ($source === null) {
logger()->warning('Source {name} unknown. Skipping.', ['name' => $name]); logger()->warning('Source {name} unknown. Skipping.', ['name' => $name]);
return; return;
@@ -522,7 +532,14 @@ class Downloader
/** /**
* Use curl command to get http response * Use curl command to get http response
* *
* @param string $url Target URL
* @param string $method HTTP method (GET, POST, etc.)
* @param array $headers HTTP headers
* @param array $hooks Curl hooks
* @param int $retries Number of retry attempts
* @return string Response body
* @throws DownloaderException * @throws DownloaderException
* @throws RuntimeException
*/ */
public static function curlExec(string $url, string $method = 'GET', array $headers = [], array $hooks = [], int $retries = 0): string public static function curlExec(string $url, string $method = 'GET', array $headers = [], array $hooks = [], int $retries = 0): string
{ {
@@ -574,6 +591,13 @@ class Downloader
/** /**
* Use curl to download sources from url * Use curl to download sources from url
* *
* @param string $url Download URL
* @param string $path Target file path
* @param string $method HTTP method
* @param array $headers HTTP headers
* @param array $hooks Curl hooks
* @param int $retries Number of retry attempts
* @throws DownloaderException
* @throws RuntimeException * @throws RuntimeException
* @throws WrongUsageException * @throws WrongUsageException
*/ */
@@ -603,6 +627,12 @@ class Downloader
} }
} }
/**
* Get pre-built lock name from source
*
* @param string $source Source name
* @return string Lock name
*/
public static function getPreBuiltLockName(string $source): string public static function getPreBuiltLockName(string $source): string
{ {
$os_family = PHP_OS_FAMILY; $os_family = PHP_OS_FAMILY;
@@ -613,6 +643,12 @@ class Downloader
return "{$source}-{$os_family}-{$gnu_arch}-{$libc}-{$libc_version}"; return "{$source}-{$os_family}-{$gnu_arch}-{$libc}-{$libc_version}";
} }
/**
* Get default alternative source
*
* @param string $source_name Source name
* @return array Alternative source configuration
*/
public static function getDefaultAlternativeSource(string $source_name): array public static function getDefaultAlternativeSource(string $source_name): array
{ {
return [ return [

View File

@@ -12,6 +12,11 @@ class FileSystem
private static array $_extract_hook = []; private static array $_extract_hook = [];
/** /**
* Load configuration array from JSON file
*
* @param string $config The configuration name (ext, lib, source, pkg, pre-built)
* @param null|string $config_dir Optional custom config directory
* @return array The loaded configuration array
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function loadConfigArray(string $config, ?string $config_dir = null): array public static function loadConfigArray(string $config, ?string $config_dir = null): array
@@ -37,9 +42,10 @@ class FileSystem
} }
/** /**
* 读取文件,读不出来直接抛出异常 * Read file contents and throw exception on failure
* *
* @param string $filename 文件路径 * @param string $filename The file path to read
* @return string The file contents
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function readFile(string $filename): string public static function readFile(string $filename): string
@@ -53,6 +59,12 @@ class FileSystem
} }
/** /**
* Replace string content in file
*
* @param string $filename The file path
* @param mixed $search The search string
* @param mixed $replace The replacement string
* @return false|int Number of replacements or false on failure
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function replaceFileStr(string $filename, mixed $search = null, mixed $replace = null): false|int public static function replaceFileStr(string $filename, mixed $search = null, mixed $replace = null): false|int
@@ -61,6 +73,12 @@ class FileSystem
} }
/** /**
* Replace content in file using regex
*
* @param string $filename The file path
* @param mixed $search The regex pattern
* @param mixed $replace The replacement string
* @return false|int Number of replacements or false on failure
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function replaceFileRegex(string $filename, mixed $search = null, mixed $replace = null): false|int public static function replaceFileRegex(string $filename, mixed $search = null, mixed $replace = null): false|int
@@ -69,6 +87,11 @@ class FileSystem
} }
/** /**
* Replace content in file using custom callback
*
* @param string $filename The file path
* @param mixed $callback The callback function
* @return false|int Number of replacements or false on failure
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function replaceFileUser(string $filename, mixed $callback = null): false|int public static function replaceFileUser(string $filename, mixed $callback = null): false|int
@@ -77,9 +100,10 @@ class FileSystem
} }
/** /**
* 获取文件后缀 * Get file extension from filename
* *
* @param string $fn 文件名 * @param string $fn The filename
* @return string The file extension (without dot)
*/ */
public static function extname(string $fn): string public static function extname(string $fn): string
{ {
@@ -91,10 +115,11 @@ class FileSystem
} }
/** /**
* 寻找命令的真实路径,效果类似 which * Find command path in system PATH (similar to which command)
* *
* @param string $name 命令名称 * @param string $name The command name
* @param array $paths 路径列表,如果为空则默认从 PATH 系统变量搜索 * @param array $paths Optional array of paths to search
* @return null|string The full path to the command or null if not found
*/ */
public static function findCommandPath(string $name, array $paths = []): ?string public static function findCommandPath(string $name, array $paths = []): ?string
{ {
@@ -120,6 +145,10 @@ class FileSystem
} }
/** /**
* Copy directory recursively
*
* @param string $from Source directory path
* @param string $to Destination directory path
* @throws RuntimeException * @throws RuntimeException
*/ */
public static function copyDir(string $from, string $to): void public static function copyDir(string $from, string $to): void
@@ -139,6 +168,12 @@ class FileSystem
} }
/** /**
* Extract package archive to specified directory
*
* @param string $name Package name
* @param string $source_type Archive type (tar.gz, zip, etc.)
* @param string $filename Archive filename
* @param null|string $extract_path Optional extraction path
* @throws RuntimeException * @throws RuntimeException
* @throws FileSystemException * @throws FileSystemException
*/ */
@@ -171,10 +206,12 @@ class FileSystem
} }
/** /**
* 解压缩下载的资源包到 source 目录 * Extract source archive to source directory
* *
* @param string $name 资源名 * @param string $name Source name
* @param string $filename 文件名 * @param string $source_type Archive type (tar.gz, zip, etc.)
* @param string $filename Archive filename
* @param null|string $move_path Optional move path
* @throws FileSystemException * @throws FileSystemException
* @throws RuntimeException * @throws RuntimeException
*/ */
@@ -207,9 +244,10 @@ class FileSystem
} }
/** /**
* 根据系统环境的不同,自动转换路径的分隔符 * Convert path to system-specific format
* *
* @param string $path 路径 * @param string $path The path to convert
* @return string The converted path
*/ */
public static function convertPath(string $path): string public static function convertPath(string $path): string
{ {
@@ -219,6 +257,12 @@ class FileSystem
return str_replace('/', DIRECTORY_SEPARATOR, $path); return str_replace('/', DIRECTORY_SEPARATOR, $path);
} }
/**
* Convert Windows path to MinGW format
*
* @param string $path The Windows path
* @return string The MinGW format path
*/
public static function convertWinPathToMinGW(string $path): string public static function convertWinPathToMinGW(string $path): string
{ {
if (preg_match('/^[A-Za-z]:/', $path)) { if (preg_match('/^[A-Za-z]:/', $path)) {
@@ -228,28 +272,21 @@ class FileSystem
} }
/** /**
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表 * Scan directory files recursively
* *
* @param string $dir 目录 * @param string $dir Directory to scan
* @param bool $recursive 是否递归扫描子目录 * @param bool $recursive Whether to scan recursively
* @param bool|string $relative 是否返回相对目录如果为true则返回相对目录如果为false则返回绝对目录 * @param bool|string $relative Whether to return relative paths
* @param bool $include_dir 非递归模式下,是否包含目录 * @param bool $include_dir Whether to include directories in result
* @since 2.5 * @return array|false Array of files or false on failure
*/ */
public static function scanDirFiles(string $dir, bool $recursive = true, bool|string $relative = false, bool $include_dir = false): array|false public static function scanDirFiles(string $dir, bool $recursive = true, bool|string $relative = false, bool $include_dir = false): array|false
{ {
$dir = self::convertPath($dir); $dir = self::convertPath($dir);
// 不是目录不扫,直接 false 处理
if (!file_exists($dir)) {
logger()->debug('Scan dir failed, no such file or directory.');
return false;
}
if (!is_dir($dir)) { if (!is_dir($dir)) {
logger()->warning('Scan dir failed, not directory.');
return false; return false;
} }
logger()->debug('scanning directory ' . $dir); logger()->debug('scanning directory ' . $dir);
// 套上 zm_dir
$scan_list = scandir($dir); $scan_list = scandir($dir);
if ($scan_list === false) { if ($scan_list === false) {
logger()->warning('Scan dir failed, cannot scan directory: ' . $dir); logger()->warning('Scan dir failed, cannot scan directory: ' . $dir);
@@ -283,18 +320,17 @@ class FileSystem
} }
/** /**
* 获取该路径下的所有类名,根据 psr-4 方式 * Get PSR-4 classes from directory
* *
* @param string $dir 目录 * @param string $dir Directory to scan
* @param string $base_namespace 基类命名空间 * @param string $base_namespace Base namespace
* @param null|mixed $rule 规则回调 * @param mixed $rule Optional filtering rule
* @param bool|string $return_path_value 是否返回路径对应的数组,默认只返回类名列表 * @param bool|string $return_path_value Whether to return path as value
* @throws FileSystemException * @return array Array of class names or class=>path pairs
*/ */
public static function getClassesPsr4(string $dir, string $base_namespace, mixed $rule = null, bool|string $return_path_value = false): array public static function getClassesPsr4(string $dir, string $base_namespace, mixed $rule = null, bool|string $return_path_value = false): array
{ {
$classes = []; $classes = [];
// 扫描目录使用递归模式相对路径模式因为下面此路径要用作转换成namespace
$files = FileSystem::scanDirFiles($dir, true, true); $files = FileSystem::scanDirFiles($dir, true, true);
if ($files === false) { if ($files === false) {
throw new FileSystemException('Cannot scan dir files during get classes psr-4 from dir: ' . $dir); throw new FileSystemException('Cannot scan dir files during get classes psr-4 from dir: ' . $dir);
@@ -325,15 +361,15 @@ class FileSystem
} }
/** /**
* 删除目录及目录下的所有文件(危险操作) * Remove directory recursively
* *
* @throws FileSystemException * @param string $dir Directory to remove
* @return bool Success status
*/ */
public static function removeDir(string $dir): bool public static function removeDir(string $dir): bool
{ {
$dir = FileSystem::convertPath($dir); $dir = FileSystem::convertPath($dir);
logger()->debug('Removing path recursively: "' . $dir . '"'); logger()->debug('Removing path recursively: "' . $dir . '"');
// 不是目录不扫,直接 false 处理
if (!file_exists($dir)) { if (!file_exists($dir)) {
logger()->debug('Scan dir failed, no such file or directory.'); logger()->debug('Scan dir failed, no such file or directory.');
return false; return false;
@@ -374,6 +410,9 @@ class FileSystem
} }
/** /**
* Create directory recursively
*
* @param string $path Directory path to create
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function createDir(string $path): void public static function createDir(string $path): void
@@ -384,7 +423,12 @@ class FileSystem
} }
/** /**
* @param mixed ...$args Arguments passed to file_put_contents * Write content to file
*
* @param string $path File path
* @param mixed $content Content to write
* @param mixed ...$args Additional arguments passed to file_put_contents
* @return bool|int|string Result of file writing operation
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function writeFile(string $path, mixed $content, ...$args): bool|int|string public static function writeFile(string $path, mixed $content, ...$args): bool|int|string
@@ -397,27 +441,36 @@ class FileSystem
} }
/** /**
* Reset (remove recursively and create again) dir * Reset directory by removing and recreating it
* *
* @param string $dir_name Directory name
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function resetDir(string $dir_name): void public static function resetDir(string $dir_name): void
{ {
$dir_name = self::convertPath($dir_name);
if (is_dir($dir_name)) { if (is_dir($dir_name)) {
self::removeDir($dir_name); self::removeDir($dir_name);
} }
self::createDir($dir_name); self::createDir($dir_name);
} }
/**
* Add source extraction hook
*
* @param string $name Source name
* @param callable $callback Callback function
*/
public static function addSourceExtractHook(string $name, callable $callback): void public static function addSourceExtractHook(string $name, callable $callback): void
{ {
self::$_extract_hook[$name][] = $callback; self::$_extract_hook[$name][] = $callback;
} }
/** /**
* Check whether the path is a relative path (judging according to whether the first character is "/") * Check if path is relative
* *
* @param string $path Path * @param string $path Path to check
* @return bool True if path is relative
*/ */
public static function isRelativePath(string $path): bool public static function isRelativePath(string $path): bool
{ {
@@ -427,6 +480,12 @@ class FileSystem
return strlen($path) > 0 && $path[0] !== '/'; return strlen($path) > 0 && $path[0] !== '/';
} }
/**
* Replace path variables with actual values
*
* @param string $path Path with variables
* @return string Path with replaced variables
*/
public static function replacePathVariable(string $path): string public static function replacePathVariable(string $path): string
{ {
$replacement = [ $replacement = [
@@ -439,12 +498,23 @@ class FileSystem
return str_replace(array_keys($replacement), array_values($replacement), $path); return str_replace(array_keys($replacement), array_values($replacement), $path);
} }
/**
* Create backup of file
*
* @param string $path File path
* @return string Backup file path
*/
public static function backupFile(string $path): string public static function backupFile(string $path): string
{ {
copy($path, $path . '.bak'); copy($path, $path . '.bak');
return $path . '.bak'; return $path . '.bak';
} }
/**
* Restore file from backup
*
* @param string $path Original file path
*/
public static function restoreBackupFile(string $path): void public static function restoreBackupFile(string $path): void
{ {
if (!file_exists($path . '.bak')) { if (!file_exists($path . '.bak')) {
@@ -454,14 +524,26 @@ class FileSystem
unlink($path . '.bak'); unlink($path . '.bak');
} }
/**
* Remove file if it exists
*
* @param string $string File path
*/
public static function removeFileIfExists(string $string): void public static function removeFileIfExists(string $string): void
{ {
$string = self::convertPath($string);
if (file_exists($string)) { if (file_exists($string)) {
unlink($string); unlink($string);
} }
} }
/** /**
* Replace line in file that contains specific string
*
* @param string $file File path
* @param string $find String to find in line
* @param string $line New line content
* @return false|int Number of replacements or false on failure
* @throws FileSystemException * @throws FileSystemException
*/ */
public static function replaceFileLineContainsString(string $file, string $find, string $line): false|int public static function replaceFileLineContainsString(string $file, string $find, string $line): false|int

View File

@@ -4,12 +4,36 @@ declare(strict_types=1);
namespace SPC\store\pkg; namespace SPC\store\pkg;
/**
* Abstract base class for custom package implementations
*
* This class provides a framework for implementing custom package download
* and extraction logic. Extend this class to create custom package handlers.
*/
abstract class CustomPackage abstract class CustomPackage
{ {
/**
* Get the list of package names supported by this implementation
*
* @return array Array of supported package names
*/
abstract public function getSupportName(): array; abstract public function getSupportName(): array;
/**
* Fetch the package from its source
*
* @param string $name Package name
* @param bool $force Force download even if already exists
* @param null|array $config Optional configuration array
*/
abstract public function fetch(string $name, bool $force = false, ?array $config = null): void; abstract public function fetch(string $name, bool $force = false, ?array $config = null): void;
/**
* Extract the downloaded package
*
* @param string $name Package name
* @throws \RuntimeException If extraction is not implemented
*/
public function extract(string $name): void public function extract(string $name): void
{ {
throw new \RuntimeException("Extract method not implemented for package: {$name}"); throw new \RuntimeException("Extract method not implemented for package: {$name}");

View File

@@ -4,9 +4,25 @@ declare(strict_types=1);
namespace SPC\store\source; namespace SPC\store\source;
/**
* Abstract base class for custom source implementations
*
* This class provides a framework for implementing custom source download
* logic. Extend this class to create custom source handlers.
*/
abstract class CustomSourceBase abstract class CustomSourceBase
{ {
/**
* The name of this source implementation
*/
public const NAME = 'unknown'; public const NAME = 'unknown';
/**
* Fetch the source from its repository
*
* @param bool $force Force download even if already exists
* @param null|array $config Optional configuration array
* @param int $lock_as Lock type constant
*/
abstract public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_DOWNLOAD_SOURCE): void; abstract public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_DOWNLOAD_SOURCE): void;
} }

View File

@@ -4,15 +4,27 @@ declare(strict_types=1);
namespace SPC\toolchain; namespace SPC\toolchain;
/**
* Interface for toolchain implementations
*
* This interface defines the contract for toolchain classes that handle
* environment initialization and setup for different build targets.
*/
interface ToolchainInterface interface ToolchainInterface
{ {
/** /**
* Initialize the environment for the given target. * Initialize the environment for the given target.
*
* This method should set up any necessary environment variables,
* paths, or configurations required for the build process.
*/ */
public function initEnv(): void; public function initEnv(): void;
/** /**
* Perform actions after the environment has been initialized for the given target. * Perform actions after the environment has been initialized for the given target.
*
* This method is called after initEnv() and can be used for any
* post-initialization setup or validation.
*/ */
public function afterInit(): void; public function afterInit(): void;
} }

View File

@@ -8,16 +8,30 @@ use SPC\builder\Extension;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\store\FileSystem; use SPC\store\FileSystem;
/**
* Custom extension attribute and manager
*
* This class provides functionality to register and manage custom PHP extensions
* that can be used during the build process.
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)] #[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)]
class CustomExt class CustomExt
{ {
private static array $custom_ext_class = []; private static array $custom_ext_class = [];
/**
* Constructor for custom extension attribute
*
* @param string $ext_name The extension name
*/
public function __construct(protected string $ext_name) {} public function __construct(protected string $ext_name) {}
/** /**
* Load all custom extension classes * Load all custom extension classes
* *
* This method scans the extension directory and registers all classes
* that have the CustomExt attribute.
*
* @throws \ReflectionException * @throws \ReflectionException
* @throws FileSystemException * @throws FileSystemException
*/ */
@@ -32,6 +46,12 @@ class CustomExt
} }
} }
/**
* Get the class name for a custom extension
*
* @param string $ext_name The extension name
* @return string The class name for the extension
*/
public static function getExtClass(string $ext_name): string public static function getExtClass(string $ext_name): string
{ {
return self::$custom_ext_class[$ext_name] ?? Extension::class; return self::$custom_ext_class[$ext_name] ?? Extension::class;

View File

@@ -9,13 +9,25 @@ use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
/** /**
* Dependency processing tool class, including processing extensions, library dependency list order, etc. * Dependency processing tool class
*
* This class handles processing extensions, library dependency list ordering, etc.
* It provides utilities for managing dependencies between extensions and libraries.
*/ */
class DependencyUtil class DependencyUtil
{ {
/** /**
* Convert platform extensions to library dependencies and suggestions. * Convert platform extensions to library dependencies and suggestions
* *
* This method processes all extensions and libraries to create a comprehensive
* dependency map that can be used for build ordering.
*
* Returns an associative array where the key is the extension or library name (string),
* and the value is an array with two keys:
* - 'depends': array of dependency names (string)
* - 'suggests': array of suggested dependency names (string)
*
* @return array<string, array{depends: array<int, string>, suggests: array<int, string>}>
* @throws WrongUsageException * @throws WrongUsageException
* @throws FileSystemException * @throws FileSystemException
*/ */
@@ -53,6 +65,10 @@ class DependencyUtil
} }
/** /**
* Get library dependencies in correct order
*
* @param array $libs Array of library names
* @return array Ordered array of library names
* @throws WrongUsageException * @throws WrongUsageException
* @throws FileSystemException * @throws FileSystemException
*/ */
@@ -88,7 +104,13 @@ class DependencyUtil
} }
/** /**
* @throws FileSystemException|WrongUsageException * Get extension dependencies in correct order
*
* @param array $exts Array of extension names
* @param array $additional_libs Array of additional libraries
* @return array Ordered array of extension names
* @throws WrongUsageException
* @throws FileSystemException
*/ */
public static function getExtsAndLibs(array $exts, array $additional_libs = [], bool $include_suggested_exts = false, bool $include_suggested_libs = false): array public static function getExtsAndLibs(array $exts, array $additional_libs = [], bool $include_suggested_exts = false, bool $include_suggested_libs = false): array
{ {
@@ -155,9 +177,6 @@ class DependencyUtil
return [$exts_final, $libs_final, $not_included_final]; return [$exts_final, $libs_final, $not_included_final];
} }
/**
* @throws WrongUsageException
*/
private static function doVisitPlat(array $deps, array $dep_list): array private static function doVisitPlat(array $deps, array $dep_list): array
{ {
// default: get extension exts and libs sorted by dep_list // default: get extension exts and libs sorted by dep_list

View File

@@ -6,15 +6,23 @@ namespace SPC\util;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
/**
* Utility class for pkg-config operations
*
* This class provides methods to interact with pkg-config to get
* compilation flags and library information for building extensions.
*/
class PkgConfigUtil class PkgConfigUtil
{ {
/** /**
* Returns --cflags-only-other output. * Get CFLAGS from pkg-config
*
* Returns --cflags-only-other output from pkg-config.
* The reason we return the string is we cannot use array_unique() on cflags, * The reason we return the string is we cannot use array_unique() on cflags,
* some cflags may contains spaces. * some cflags may contains spaces.
* *
* @param string $pkg_config_str .pc file str, accepts multiple files * @param string $pkg_config_str .pc file string, accepts multiple files
* @return string cflags string, e.g. "-Wno-implicit-int-float-conversion ..." * @return string CFLAGS string, e.g. "-Wno-implicit-int-float-conversion ..."
* @throws RuntimeException * @throws RuntimeException
*/ */
public static function getCflags(string $pkg_config_str): string public static function getCflags(string $pkg_config_str): string
@@ -25,10 +33,12 @@ class PkgConfigUtil
} }
/** /**
* Get library flags from pkg-config
*
* Returns --libs-only-l and --libs-only-other output. * Returns --libs-only-l and --libs-only-other output.
* The reason we return the array is to avoid duplicate lib defines. * The reason we return the array is to avoid duplicate lib defines.
* *
* @param string $pkg_config_str .pc file str, accepts multiple files * @param string $pkg_config_str .pc file string, accepts multiple files
* @return array Unique libs array, e.g. [-lz, -lxml, ...] * @return array Unique libs array, e.g. [-lz, -lxml, ...]
* @throws RuntimeException * @throws RuntimeException
*/ */
@@ -64,6 +74,13 @@ class PkgConfigUtil
return array_reverse(array_unique(array_reverse($libs))); return array_reverse(array_unique(array_reverse($libs)));
} }
/**
* Execute pkg-config command and return result
*
* @param string $cmd The pkg-config command to execute
* @return string The command output
* @throws RuntimeException If command fails
*/
private static function execWithResult(string $cmd): string private static function execWithResult(string $cmd): string
{ {
f_exec($cmd, $output, $result_code); f_exec($cmd, $output, $result_code);