mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-17 20:34:51 +08:00
Refactor all (except command) modules using new exceptions
This commit is contained in:
parent
722bb31815
commit
f68f060be2
@ -4,8 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\exception\SPCException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
@ -30,10 +31,10 @@ class Extension
|
||||
$unix_only = Config::getExt($this->name, 'unix-only', false);
|
||||
$windows_only = Config::getExt($this->name, 'windows-only', false);
|
||||
if (PHP_OS_FAMILY !== 'Windows' && $windows_only) {
|
||||
throw new RuntimeException("{$ext_type} extension {$name} is not supported on Linux and macOS platform");
|
||||
throw new EnvironmentException("{$ext_type} extension {$name} is not supported on Linux and macOS platform");
|
||||
}
|
||||
if (PHP_OS_FAMILY === 'Windows' && $unix_only) {
|
||||
throw new RuntimeException("{$ext_type} extension {$name} is not supported on Windows platform");
|
||||
throw new EnvironmentException("{$ext_type} extension {$name} is not supported on Windows platform");
|
||||
}
|
||||
// set source_dir for builtin
|
||||
if ($ext_type === 'builtin') {
|
||||
@ -41,7 +42,7 @@ class Extension
|
||||
} elseif ($ext_type === 'external') {
|
||||
$source = Config::getExt($this->name, 'source');
|
||||
if ($source === null) {
|
||||
throw new RuntimeException("{$ext_type} extension {$name} source not found");
|
||||
throw new ValidationException("{$ext_type} extension {$name} source not found", validation_module: "Extension [{$name}] loader");
|
||||
}
|
||||
$source_path = Config::getSource($source)['path'] ?? null;
|
||||
$source_path = $source_path === null ? SOURCE_PATH . '/' . $source : SOURCE_PATH . '/' . $source_path;
|
||||
@ -287,13 +288,12 @@ class Extension
|
||||
{
|
||||
// Run compile check if build target is cli
|
||||
// If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php
|
||||
// If check failed, throw RuntimeException
|
||||
$sharedExtensions = $this->getSharedExtensionLoadString();
|
||||
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException(
|
||||
'extension ' . $this->getName() . ' failed runtime check: php-cli returned ' . $ret . "\n" .
|
||||
join("\n", $out)
|
||||
throw new ValidationException(
|
||||
"extension {$this->getName()} failed compile check: php-cli returned {$ret}",
|
||||
validation_module: 'Extension ' . $this->getName() . ' sanity check'
|
||||
);
|
||||
}
|
||||
|
||||
@ -307,8 +307,10 @@ class Extension
|
||||
|
||||
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' -r "' . trim($test) . '"');
|
||||
if ($ret !== 0) {
|
||||
var_dump($out);
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
|
||||
throw new ValidationException(
|
||||
"extension {$this->getName()} failed sanity check. Code: {$ret}, output: " . implode("\n", $out),
|
||||
validation_module: 'Extension ' . $this->getName() . ' function check'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,10 +319,9 @@ class Extension
|
||||
{
|
||||
// Run compile check if build target is cli
|
||||
// If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php
|
||||
// If check failed, throw RuntimeException
|
||||
[$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n --ri "' . $this->getDistName() . '"', false);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
|
||||
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");
|
||||
}
|
||||
|
||||
if (file_exists(FileSystem::convertPath(ROOT_DIR . '/src/globals/ext-tests/' . $this->getName() . '.php'))) {
|
||||
@ -333,7 +334,10 @@ class Extension
|
||||
|
||||
[$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n -r "' . trim($test) . '"');
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
|
||||
throw new ValidationException(
|
||||
"extension {$this->getName()} failed function check",
|
||||
validation_module: "Extension {$this->getName()} function check"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -348,34 +352,39 @@ class Extension
|
||||
*/
|
||||
public function buildShared(): void
|
||||
{
|
||||
if (Config::getExt($this->getName(), 'type') === 'builtin' || Config::getExt($this->getName(), 'build-with-php') === true) {
|
||||
try {
|
||||
if (Config::getExt($this->getName(), 'type') === 'builtin' || Config::getExt($this->getName(), 'build-with-php') === true) {
|
||||
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
|
||||
logger()->info('Shared extension [' . $this->getName() . '] was already built by php-src/configure (' . $this->getName() . '.so)');
|
||||
return;
|
||||
}
|
||||
if (Config::getExt($this->getName(), 'build-with-php') === true) {
|
||||
logger()->warning('Shared extension [' . $this->getName() . '] did not build with php-src/configure (' . $this->getName() . '.so)');
|
||||
logger()->warning('Try deleting your build and source folders and running `spc build`` again.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
|
||||
logger()->info('Shared extension [' . $this->getName() . '] was already built by php-src/configure (' . $this->getName() . '.so)');
|
||||
return;
|
||||
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
|
||||
}
|
||||
if (Config::getExt($this->getName(), 'build-with-php') === true) {
|
||||
logger()->warning('Shared extension [' . $this->getName() . '] did not build with php-src/configure (' . $this->getName() . '.so)');
|
||||
logger()->warning('Try deleting your build and source folders and running `spc build`` again.');
|
||||
return;
|
||||
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
|
||||
foreach ($this->dependencies as $dependency) {
|
||||
if (!$dependency instanceof Extension) {
|
||||
continue;
|
||||
}
|
||||
if (!$dependency->isBuildStatic()) {
|
||||
logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName());
|
||||
$dependency->buildShared();
|
||||
}
|
||||
}
|
||||
match (PHP_OS_FAMILY) {
|
||||
'Darwin', 'Linux' => $this->buildUnixShared(),
|
||||
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
|
||||
};
|
||||
} catch (SPCException $e) {
|
||||
$e->bindExtensionInfo(['extension_name' => $this->getName()]);
|
||||
throw $e;
|
||||
}
|
||||
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
|
||||
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
|
||||
}
|
||||
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
|
||||
foreach ($this->dependencies as $dependency) {
|
||||
if (!$dependency instanceof Extension) {
|
||||
continue;
|
||||
}
|
||||
if (!$dependency->isBuildStatic()) {
|
||||
logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName());
|
||||
$dependency->buildShared();
|
||||
}
|
||||
}
|
||||
match (PHP_OS_FAMILY) {
|
||||
'Darwin', 'Linux' => $this->buildUnixShared(),
|
||||
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -479,7 +488,7 @@ class Extension
|
||||
$depLib = $this->builder->getLib($name);
|
||||
if (!$depLib) {
|
||||
if (!$optional) {
|
||||
throw new RuntimeException("extension {$this->name} requires library {$name}");
|
||||
throw new WrongUsageException("extension {$this->name} requires library {$name}");
|
||||
}
|
||||
logger()->info("enabling {$this->name} without library {$name}");
|
||||
} else {
|
||||
@ -492,7 +501,7 @@ class Extension
|
||||
$depExt = $this->builder->getExt($name);
|
||||
if (!$depExt) {
|
||||
if (!$optional) {
|
||||
throw new RuntimeException("{$this->name} requires extension {$name}");
|
||||
throw new WrongUsageException("{$this->name} requires extension {$name} which is not included");
|
||||
}
|
||||
logger()->info("enabling {$this->name} without extension {$name}");
|
||||
} else {
|
||||
|
||||
@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\Downloader;
|
||||
@ -30,9 +30,9 @@ abstract class LibraryBase
|
||||
public function __construct(?string $source_dir = null)
|
||||
{
|
||||
if (static::NAME === 'unknown') {
|
||||
throw new RuntimeException('no unknown!!!!!');
|
||||
throw new SPCInternalException('Please set the NAME constant in ' . static::class);
|
||||
}
|
||||
$this->source_dir = $source_dir ?? (SOURCE_PATH . '/' . Config::getLib(static::NAME, 'source'));
|
||||
$this->source_dir = $source_dir ?? (SOURCE_PATH . DIRECTORY_SEPARATOR . Config::getLib(static::NAME, 'source'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,7 +154,7 @@ abstract class LibraryBase
|
||||
FileSystem::extractPackage($install_file, $lock['source_type'], DOWNLOAD_PATH . '/' . $install_file, BUILD_ROOT_PATH);
|
||||
$this->install();
|
||||
return LIB_STATUS_OK;
|
||||
} catch (FileSystemException|RuntimeException $e) {
|
||||
} catch (SPCException $e) {
|
||||
logger()->error('Failed to extract pre-built library [' . static::NAME . ']: ' . $e->getMessage());
|
||||
return LIB_STATUS_INSTALL_FAILED;
|
||||
}
|
||||
@ -304,7 +304,7 @@ abstract class LibraryBase
|
||||
}
|
||||
$replace_items = json_decode(file_get_contents($replace_item_file), true);
|
||||
if (!is_array($replace_items)) {
|
||||
throw new RuntimeException('Invalid placeholder file: ' . $replace_item_file);
|
||||
throw new SPCInternalException("Invalid placeholder file: {$replace_item_file}");
|
||||
}
|
||||
$placeholders = get_pack_replace();
|
||||
// replace placeholders in BUILD_ROOT_PATH
|
||||
@ -331,7 +331,7 @@ abstract class LibraryBase
|
||||
return;
|
||||
}
|
||||
if (!$optional) {
|
||||
throw new RuntimeException(static::NAME . " requires library {$name}");
|
||||
throw new WrongUsageException(static::NAME . " requires library {$name} but it is not included");
|
||||
}
|
||||
logger()->debug('enabling ' . static::NAME . " without {$name}");
|
||||
}
|
||||
|
||||
@ -8,8 +8,7 @@ use SPC\builder\Extension;
|
||||
use SPC\builder\linux\LinuxBuilder;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\builder\windows\WindowsBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\PatchException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
@ -98,7 +97,7 @@ class curl extends Extension
|
||||
);
|
||||
|
||||
if ($patched === null) {
|
||||
throw new \RuntimeException('Failed to patch config.m4 due to a regex error');
|
||||
throw new PatchException('shared extension curl patcher', 'Failed to patch config.m4 due to a regex error');
|
||||
}
|
||||
|
||||
FileSystem::writeFile($file, $patched);
|
||||
|
||||
@ -6,6 +6,7 @@ namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\windows\WindowsBuilder;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
@ -18,7 +19,7 @@ class grpc extends Extension
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if ($this->builder instanceof WindowsBuilder) {
|
||||
throw new \RuntimeException('grpc extension does not support windows yet');
|
||||
throw new ValidationException('grpc extension does not support windows yet');
|
||||
}
|
||||
if (file_exists(SOURCE_PATH . '/php-src/ext/grpc')) {
|
||||
return false;
|
||||
@ -27,7 +28,7 @@ class grpc extends Extension
|
||||
if (is_dir($this->source_dir . '/src/php/ext/grpc')) {
|
||||
shell()->exec('ln -s ' . $this->source_dir . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc');
|
||||
} else {
|
||||
throw new \RuntimeException('Cannot find grpc source code');
|
||||
throw new ValidationException('Cannot find grpc source code in ' . $this->source_dir . '/src/php/ext/grpc');
|
||||
}
|
||||
if (SPCTarget::getTargetOS() === 'Darwin') {
|
||||
FileSystem::replaceFileRegex(
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('mbregex')]
|
||||
@ -16,11 +16,6 @@ class mbregex extends Extension
|
||||
return 'mbstring';
|
||||
}
|
||||
|
||||
public function getConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* mbregex is not an extension, we need to overwrite the default check.
|
||||
*/
|
||||
@ -29,7 +24,7 @@ class mbregex extends Extension
|
||||
$sharedext = $this->builder->getExt('mbstring')->isBuildShared() ? '-d "extension_dir=' . BUILD_MODULES_PATH . '" -d "extension=mbstring"' : '';
|
||||
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $sharedext . ' --ri "mbstring" | grep regex', false);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !');
|
||||
throw new ValidationException("Extension {$this->getName()} failed compile check: compiled php-cli mbstring extension does not contain regex !");
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,11 +32,11 @@ class mbregex extends Extension
|
||||
{
|
||||
[$ret, $out] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "mbstring"', false);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli does not contain mbstring !');
|
||||
throw new ValidationException("extension {$this->getName()} failed compile check: compiled php-cli does not contain mbstring !");
|
||||
}
|
||||
$out = implode("\n", $out);
|
||||
if (!str_contains($out, 'regex')) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !');
|
||||
throw new ValidationException("extension {$this->getName()} failed compile check: compiled php-cli mbstring extension does not contain regex !");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
@ -15,7 +16,7 @@ class opentelemetry extends Extension
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
||||
throw new \RuntimeException('The opentelemetry extension requires PHP 8.0 or later');
|
||||
throw new ValidationException('The opentelemetry extension requires PHP 8.0 or later');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('password-argon2')]
|
||||
@ -20,7 +20,7 @@ class password_argon2 extends Extension
|
||||
{
|
||||
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n -r "assert(defined(\'PASSWORD_ARGON2I\'));"');
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
|
||||
throw new ValidationException('extension ' . $this->getName() . ' failed sanity check', validation_module: 'password_argon2 function check');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('protobuf')]
|
||||
@ -13,12 +14,12 @@ class protobuf extends Extension
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
||||
throw new \RuntimeException('The latest protobuf extension requires PHP 8.0 or later');
|
||||
throw new ValidationException('The latest protobuf extension requires PHP 8.0 or later');
|
||||
}
|
||||
$grpc = $this->builder->getExt('grpc');
|
||||
// protobuf conflicts with grpc
|
||||
if ($grpc?->isBuildStatic()) {
|
||||
throw new \RuntimeException('protobuf conflicts with grpc, please remove grpc or protobuf extension');
|
||||
throw new ValidationException('protobuf conflicts with grpc, please remove grpc or protobuf extension');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('swoole-hook-mysql')]
|
||||
@ -32,10 +32,10 @@ class swoole_hook_mysql extends Extension
|
||||
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $this->getSharedExtensionLoadString() . ' --ri "swoole"', false);
|
||||
$out = implode('', $out);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
|
||||
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: 'extension swoole_hook_mysql sanity check');
|
||||
}
|
||||
if (!str_contains($out, 'mysqlnd')) {
|
||||
throw new RuntimeException('swoole mysql hook is not enabled correctly.');
|
||||
throw new ValidationException('swoole mysql hook is not enabled correctly.', validation_module: 'Extension swoole mysql hook avilability check');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
@ -41,10 +41,16 @@ class swoole_hook_pgsql extends Extension
|
||||
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||
$out = implode('', $out);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
|
||||
throw new ValidationException(
|
||||
"extension {$this->getName()} failed sanity check: php-cli returned {$ret}",
|
||||
validation_module: 'Extension swoole-hook-pgsql sanity check'
|
||||
);
|
||||
}
|
||||
if (!str_contains($out, 'coroutine_pgsql')) {
|
||||
throw new RuntimeException('swoole pgsql hook is not enabled correctly.');
|
||||
throw new ValidationException(
|
||||
'swoole pgsql hook is not enabled correctly.',
|
||||
validation_module: 'Extension swoole pgsql hook availability check'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
@ -41,10 +41,10 @@ class swoole_hook_sqlite extends Extension
|
||||
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||
$out = implode('', $out);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
|
||||
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");
|
||||
}
|
||||
if (!str_contains($out, 'coroutine_sqlite')) {
|
||||
throw new RuntimeException('swoole sqlite hook is not enabled correctly.');
|
||||
throw new ValidationException('swoole sqlite hook is not enabled correctly.', validation_module: 'Extension swoole sqlite hook availability check');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('swow')]
|
||||
@ -14,7 +14,7 @@ class swow extends Extension
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
||||
throw new RuntimeException('The latest swow extension requires PHP 8.0 or later');
|
||||
throw new ValidationException('The latest swow extension requires PHP 8.0 or later');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
@ -14,7 +15,7 @@ class uv extends Extension
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
||||
throw new \RuntimeException('The latest uv extension requires PHP 8.0 or later');
|
||||
throw new ValidationException('The latest uv extension requires PHP 8.0 or later');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
@ -24,7 +24,7 @@ class xml extends Extension
|
||||
'xmlreader' => '--enable-xmlreader',
|
||||
'xmlwriter' => '--enable-xmlwriter',
|
||||
'simplexml' => '--enable-simplexml',
|
||||
default => throw new RuntimeException('Not accept non-xml extension'),
|
||||
default => throw new SPCInternalException('Not accept non-xml extension'),
|
||||
};
|
||||
$arg .= ($shared ? '=shared' : '') . ' --with-libxml="' . BUILD_ROOT_PATH . '"';
|
||||
return $arg;
|
||||
@ -44,7 +44,7 @@ class xml extends Extension
|
||||
'xmlreader' => '--enable-xmlreader',
|
||||
'xmlwriter' => '--enable-xmlwriter',
|
||||
'simplexml' => '--with-simplexml',
|
||||
default => throw new RuntimeException('Not accept non-xml extension'),
|
||||
default => throw new SPCInternalException('Not accept non-xml extension'),
|
||||
};
|
||||
$arg .= ' --with-libxml';
|
||||
return $arg;
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\freebsd;
|
||||
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class SystemUtil
|
||||
@ -20,7 +20,10 @@ class SystemUtil
|
||||
{
|
||||
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu');
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('Failed to get cpu count');
|
||||
throw new EnvironmentException(
|
||||
'Failed to get cpu count from FreeBSD sysctl',
|
||||
'Please ensure you are running this command on a FreeBSD system and have the sysctl command available.'
|
||||
);
|
||||
}
|
||||
|
||||
return (int) $output[0];
|
||||
|
||||
@ -358,7 +358,7 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
$out[1] = explode(' ', $out[1]);
|
||||
$offset = $out[1][0];
|
||||
if ($ret !== 0 || !str_starts_with($offset, '0x')) {
|
||||
throw new RuntimeException('Cannot find offset in readelf output');
|
||||
throw new PatchException('phpmicro UPX patcher', 'Cannot find offset in readelf output');
|
||||
}
|
||||
$offset = hexdec($offset);
|
||||
// remove upx extra wastes
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\macos;
|
||||
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class SystemUtil
|
||||
@ -18,12 +18,15 @@ class SystemUtil
|
||||
*/
|
||||
public static function getCpuCount(): int
|
||||
{
|
||||
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu', false);
|
||||
$cpu = exec('sysctl -n hw.ncpu', $output, $ret);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('Failed to get cpu count');
|
||||
throw new EnvironmentException(
|
||||
'Failed to get cpu count from macOS sysctl',
|
||||
'Please ensure you are running this command on a macOS system and have the sysctl command available.'
|
||||
);
|
||||
}
|
||||
|
||||
return (int) $output[0];
|
||||
return (int) $cpu;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -4,9 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\traits;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\PatchException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
@ -38,7 +36,7 @@ trait UnixLibraryTrait
|
||||
foreach ($files as $name) {
|
||||
$realpath = realpath(BUILD_ROOT_PATH . '/lib/pkgconfig/' . $name);
|
||||
if ($realpath === false) {
|
||||
throw new RuntimeException('Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] !');
|
||||
throw new PatchException('pkg-config prefix patcher', 'Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] in ' . BUILD_LIB_PATH . '/pkgconfig/ !');
|
||||
}
|
||||
logger()->debug('Patching ' . $realpath);
|
||||
// replace prefix
|
||||
@ -65,7 +63,7 @@ trait UnixLibraryTrait
|
||||
$realpath = realpath(BUILD_LIB_PATH . '/' . $name);
|
||||
if ($realpath === false) {
|
||||
if ($throwOnMissing) {
|
||||
throw new RuntimeException('Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
|
||||
throw new PatchException('la dependency patcher', 'Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
|
||||
}
|
||||
logger()->warning('Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
|
||||
continue;
|
||||
|
||||
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\traits;
|
||||
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\PkgConfigUtil;
|
||||
|
||||
@ -24,7 +24,7 @@ trait openssl
|
||||
if (PHP_OS_FAMILY !== 'Windows') {
|
||||
try {
|
||||
return PkgConfigUtil::getModuleVersion('openssl');
|
||||
} catch (RuntimeException) {
|
||||
} catch (SPCException) {
|
||||
}
|
||||
}
|
||||
// get openssl version from header openssl/opensslv.h
|
||||
|
||||
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\unix;
|
||||
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\CurlHook;
|
||||
@ -56,7 +56,14 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
}
|
||||
// if some libs are not supported (but in config "lib.json", throw exception)
|
||||
if (!isset($support_lib_list[$library])) {
|
||||
throw new WrongUsageException('library [' . $library . '] is in the lib.json list but not supported to compile, but in the future I will support it!');
|
||||
$os = match (PHP_OS_FAMILY) {
|
||||
'Linux' => 'Linux',
|
||||
'Darwin' => 'macOS',
|
||||
'Windows' => 'Windows',
|
||||
'BSD' => 'FreeBSD',
|
||||
default => PHP_OS_FAMILY,
|
||||
};
|
||||
throw new WrongUsageException("library [{$library}] is in the lib.json list but not supported to build on {$os}.");
|
||||
}
|
||||
$lib = new ($support_lib_list[$library])($this);
|
||||
$this->addLib($lib);
|
||||
@ -80,7 +87,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
[$ret, $output] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -r "echo \"hello\";"');
|
||||
$raw_output = implode('', $output);
|
||||
if ($ret !== 0 || trim($raw_output) !== 'hello') {
|
||||
throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]");
|
||||
throw new ValidationException("cli failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cli sanity check');
|
||||
}
|
||||
|
||||
foreach ($this->getExts() as $ext) {
|
||||
@ -103,7 +110,10 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
foreach ($task['conditions'] as $condition => $closure) {
|
||||
if (!$closure($ret, $out)) {
|
||||
$raw_out = trim(implode('', $out));
|
||||
throw new RuntimeException("micro failed sanity check: {$task_name}, condition [{$condition}], ret[{$ret}], out[{$raw_out}]");
|
||||
throw new ValidationException(
|
||||
"failure info: {$condition}, code: {$ret}, output: {$raw_out}",
|
||||
validation_module: "phpmicro sanity check item [{$task_name}]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,11 +152,17 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
}
|
||||
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out));
|
||||
throw new ValidationException(
|
||||
'embed failed sanity check: build failed. Error message: ' . implode("\n", $out),
|
||||
validation_module: 'static libphp.a sanity check'
|
||||
);
|
||||
}
|
||||
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed');
|
||||
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
||||
throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output));
|
||||
throw new ValidationException(
|
||||
'embed failed sanity check: run failed. Error message: ' . implode("\n", $output),
|
||||
validation_module: 'static libphp.a sanity check'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,14 +171,20 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
logger()->info('running frankenphp sanity check');
|
||||
$frankenphp = BUILD_BIN_PATH . '/frankenphp';
|
||||
if (!file_exists($frankenphp)) {
|
||||
throw new RuntimeException('FrankenPHP binary not found: ' . $frankenphp);
|
||||
throw new ValidationException(
|
||||
"FrankenPHP binary not found: {$frankenphp}",
|
||||
validation_module: 'FrankenPHP sanity check'
|
||||
);
|
||||
}
|
||||
$prefix = PHP_OS_FAMILY === 'Darwin' ? 'DYLD_' : 'LD_';
|
||||
[$ret, $output] = shell()
|
||||
->setEnv(["{$prefix}LIBRARY_PATH" => BUILD_LIB_PATH])
|
||||
->execWithResult("{$frankenphp} version");
|
||||
if ($ret !== 0 || !str_contains(implode('', $output), 'FrankenPHP')) {
|
||||
throw new RuntimeException('FrankenPHP failed sanity check: ret[' . $ret . ']. out[' . implode('', $output) . ']');
|
||||
throw new ValidationException(
|
||||
'FrankenPHP failed sanity check: ret[' . $ret . ']. out[' . implode('', $output) . ']',
|
||||
validation_module: 'FrankenPHP sanity check'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,7 +200,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
|
||||
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
|
||||
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
|
||||
default => throw new RuntimeException('Deployment does not accept type ' . $type),
|
||||
default => throw new SPCInternalException("Deployment does not accept type {$type}"),
|
||||
};
|
||||
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||
FileSystem::createDir(BUILD_BIN_PATH);
|
||||
@ -191,7 +213,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
*/
|
||||
protected function cleanMake(): void
|
||||
{
|
||||
logger()->info('cleaning up');
|
||||
logger()->info('cleaning up php-src build files');
|
||||
shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean');
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\BuildFailureException;
|
||||
|
||||
trait fastlz
|
||||
{
|
||||
protected function build(): void
|
||||
@ -13,10 +15,10 @@ trait fastlz
|
||||
->exec((getenv('AR') ?: 'ar') . ' rcs libfastlz.a fastlz.o');
|
||||
|
||||
if (!copy($this->source_dir . '/fastlz.h', BUILD_INCLUDE_PATH . '/fastlz.h')) {
|
||||
throw new \RuntimeException('Failed to copy fastlz.h');
|
||||
throw new BuildFailureException('Failed to copy fastlz.h, file does not exist');
|
||||
}
|
||||
if (!copy($this->source_dir . '/libfastlz.a', BUILD_LIB_PATH . '/libfastlz.a')) {
|
||||
throw new \RuntimeException('Failed to copy libfastlz.a');
|
||||
throw new BuildFailureException('Failed to copy libfastlz.a, file does not exist');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\builder\linux\library\LinuxLibraryBase;
|
||||
use SPC\exception\BuildFailureException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
@ -60,7 +60,7 @@ trait postgresql
|
||||
$envs .= " LIBS=\"{$libs}{$libcpp}\" ";
|
||||
}
|
||||
if ($error_exec_cnt > 0) {
|
||||
throw new RuntimeException('Failed to get pkg-config information!');
|
||||
throw new BuildFailureException('Failed to get pkg-config information!');
|
||||
}
|
||||
|
||||
FileSystem::resetDir($this->source_dir . '/build');
|
||||
@ -74,7 +74,7 @@ trait postgresql
|
||||
->exec('sed -i.backup "278 s/^/# /" ../src/Makefile.shlib')
|
||||
->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib');
|
||||
} else {
|
||||
throw new RuntimeException('Unsupported version for postgresql: ' . $version . ' !');
|
||||
throw new BuildFailureException('Unsupported version for postgresql: ' . $version . ' !');
|
||||
}
|
||||
|
||||
// configure
|
||||
|
||||
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class SystemUtil
|
||||
|
||||
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\windows;
|
||||
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
@ -267,7 +267,7 @@ class WindowsBuilder extends BuilderBase
|
||||
logger()->info('running cli sanity check');
|
||||
[$ret, $output] = cmd()->execWithResult(BUILD_ROOT_PATH . '\bin\php.exe -n -r "echo \"hello\";"');
|
||||
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
||||
throw new RuntimeException('cli failed sanity check');
|
||||
throw new ValidationException('cli failed sanity check', validation_module: 'php-cli function check');
|
||||
}
|
||||
|
||||
foreach ($this->getExts(false) as $ext) {
|
||||
@ -290,7 +290,10 @@ class WindowsBuilder extends BuilderBase
|
||||
foreach ($task['conditions'] as $condition => $closure) {
|
||||
if (!$closure($ret, $out)) {
|
||||
$raw_out = trim(implode('', $out));
|
||||
throw new RuntimeException("micro failed sanity check: {$task_name}, condition [{$condition}], ret[{$ret}], out[{$raw_out}]");
|
||||
throw new ValidationException(
|
||||
"failure info: {$condition}, code: {$ret}, output: {$raw_out}",
|
||||
validation_module: "phpmicro sanity check item [{$task_name}]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -308,7 +311,7 @@ class WindowsBuilder extends BuilderBase
|
||||
$src = match ($type) {
|
||||
BUILD_TARGET_CLI => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\php.exe",
|
||||
BUILD_TARGET_MICRO => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\micro.sfx",
|
||||
default => throw new RuntimeException('Deployment does not accept type ' . $type),
|
||||
default => throw new SPCInternalException("Deployment does not accept type {$type}"),
|
||||
};
|
||||
|
||||
// with-upx-pack for cli and micro
|
||||
|
||||
@ -5,24 +5,35 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\builder\windows\SystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\BuildFailureException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class libsodium extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'libsodium';
|
||||
|
||||
protected function build()
|
||||
private string $vs_ver_dir;
|
||||
|
||||
public function validate(): void
|
||||
{
|
||||
FileSystem::replaceFileStr($this->source_dir . '\src\libsodium\include\sodium\export.h', '#ifdef SODIUM_STATIC', '#if 1');
|
||||
$vs_ver_dir = match (SystemUtil::findVisualStudio()['version']) {
|
||||
$this->vs_ver_dir = match ($ver = SystemUtil::findVisualStudio()['version']) {
|
||||
'vs17' => '\vs2022',
|
||||
'vs16' => '\vs2019',
|
||||
default => throw new RuntimeException('Current VS version is not supported yet!'),
|
||||
default => throw new EnvironmentException("Current VS version {$ver} is not supported yet!"),
|
||||
};
|
||||
}
|
||||
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
FileSystem::replaceFileStr($this->source_dir . '\src\libsodium\include\sodium\export.h', '#ifdef SODIUM_STATIC', '#if 1');
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
// start build
|
||||
cmd()->cd($this->source_dir . '\builds\msvc\\' . $vs_ver_dir)
|
||||
cmd()->cd($this->source_dir . '\builds\msvc' . $this->vs_ver_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('msbuild'),
|
||||
'libsodium.sln /t:Rebuild /p:Configuration=StaticRelease /p:Platform=x64 /p:PreprocessorDefinitions="SODIUM_STATIC=1"'
|
||||
@ -46,7 +57,7 @@ class libsodium extends WindowsLibraryBase
|
||||
}
|
||||
}
|
||||
if (!$find) {
|
||||
throw new RuntimeException('libsodium.lib not found');
|
||||
throw new BuildFailureException("Build libsodium success, but cannot find libsodium.lib in {$this->source_dir}\\bin .");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,23 +5,33 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\builder\windows\SystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class openssl extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'openssl';
|
||||
|
||||
private ?string $perl;
|
||||
|
||||
public function validate(): void
|
||||
{
|
||||
global $argv;
|
||||
$perl_path_native = PKG_ROOT_PATH . '\strawberry-perl-' . arch2gnu(php_uname('m')) . '-win\perl\bin\perl.exe';
|
||||
$this->perl = file_exists($perl_path_native) ? ($perl_path_native) : SystemUtil::findCommand('perl.exe');
|
||||
if ($this->perl === null) {
|
||||
throw new EnvironmentException(
|
||||
'You need to install perl first!',
|
||||
"Please run \"{$argv[0]} doctor\" to fix the environment.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
$perl_path_native = PKG_ROOT_PATH . '\strawberry-perl-' . arch2gnu(php_uname('m')) . '-win\perl\bin\perl.exe';
|
||||
$perl = file_exists($perl_path_native) ? ($perl_path_native) : SystemUtil::findCommand('perl.exe');
|
||||
if ($perl === null) {
|
||||
throw new RuntimeException('You need to install perl first! (easiest way is using static-php-cli command "doctor")');
|
||||
}
|
||||
cmd()->cd($this->source_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper($perl),
|
||||
$this->builder->makeSimpleWrapper($this->perl),
|
||||
'Configure zlib VC-WIN64A ' .
|
||||
'no-shared ' .
|
||||
'--prefix=' . quote(BUILD_ROOT_PATH) . ' ' .
|
||||
|
||||
@ -9,10 +9,6 @@ use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
use SPC\doctor\OptionalCheck;
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Downloader;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\PackageManager;
|
||||
@ -58,55 +54,47 @@ class LinuxMuslCheck
|
||||
#[AsFixItem('fix-musl-wrapper')]
|
||||
public function fixMusl(): bool
|
||||
{
|
||||
try {
|
||||
$prefix = '';
|
||||
if (get_current_user() !== 'root') {
|
||||
$prefix = 'sudo ';
|
||||
logger()->warning('Current user is not root, using sudo for running command');
|
||||
}
|
||||
// The hardcoded version here is to be consistent with the version compiled by `musl-cross-toolchain`.
|
||||
$musl_version_name = 'musl-1.2.5';
|
||||
$musl_source = [
|
||||
'type' => 'url',
|
||||
'url' => "https://musl.libc.org/releases/{$musl_version_name}.tar.gz",
|
||||
];
|
||||
logger()->info('Downloading ' . $musl_source['url']);
|
||||
Downloader::downloadSource($musl_version_name, $musl_source);
|
||||
FileSystem::extractSource($musl_version_name, SPC_SOURCE_ARCHIVE, DOWNLOAD_PATH . "/{$musl_version_name}.tar.gz");
|
||||
|
||||
// Apply CVE-2025-26519 patch
|
||||
SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0001.patch', SOURCE_PATH . "/{$musl_version_name}");
|
||||
SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0002.patch', SOURCE_PATH . "/{$musl_version_name}");
|
||||
logger()->info('Installing musl wrapper');
|
||||
shell()->cd(SOURCE_PATH . "/{$musl_version_name}")
|
||||
->exec('CC=gcc CXX=g++ AR=ar LD=ld ./configure --disable-gcc-wrapper')
|
||||
->exec('CC=gcc CXX=g++ AR=ar LD=ld make -j')
|
||||
->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
|
||||
// TODO: add path using putenv instead of editing /etc/profile
|
||||
return true;
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
$prefix = '';
|
||||
if (get_current_user() !== 'root') {
|
||||
$prefix = 'sudo ';
|
||||
logger()->warning('Current user is not root, using sudo for running command');
|
||||
}
|
||||
// The hardcoded version here is to be consistent with the version compiled by `musl-cross-toolchain`.
|
||||
$musl_version_name = 'musl-1.2.5';
|
||||
$musl_source = [
|
||||
'type' => 'url',
|
||||
'url' => "https://musl.libc.org/releases/{$musl_version_name}.tar.gz",
|
||||
];
|
||||
logger()->info('Downloading ' . $musl_source['url']);
|
||||
Downloader::downloadSource($musl_version_name, $musl_source);
|
||||
FileSystem::extractSource($musl_version_name, SPC_SOURCE_ARCHIVE, DOWNLOAD_PATH . "/{$musl_version_name}.tar.gz");
|
||||
|
||||
// Apply CVE-2025-26519 patch
|
||||
SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0001.patch', SOURCE_PATH . "/{$musl_version_name}");
|
||||
SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0002.patch', SOURCE_PATH . "/{$musl_version_name}");
|
||||
logger()->info('Installing musl wrapper');
|
||||
shell()->cd(SOURCE_PATH . "/{$musl_version_name}")
|
||||
->exec('CC=gcc CXX=g++ AR=ar LD=ld ./configure --disable-gcc-wrapper')
|
||||
->exec('CC=gcc CXX=g++ AR=ar LD=ld make -j')
|
||||
->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
|
||||
// TODO: add path using putenv instead of editing /etc/profile
|
||||
return true;
|
||||
}
|
||||
|
||||
#[AsFixItem('fix-musl-cross-make')]
|
||||
public function fixMuslCrossMake(): bool
|
||||
{
|
||||
try {
|
||||
$prefix = '';
|
||||
if (get_current_user() !== 'root') {
|
||||
$prefix = 'sudo ';
|
||||
logger()->warning('Current user is not root, using sudo for running command');
|
||||
}
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
logger()->info("Downloading package musl-toolchain-{$arch}-linux");
|
||||
PackageManager::installPackage("musl-toolchain-{$arch}-linux");
|
||||
$pkg_root = PKG_ROOT_PATH . "/musl-toolchain-{$arch}-linux";
|
||||
shell()->exec("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl");
|
||||
FileSystem::removeDir($pkg_root);
|
||||
return true;
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
$prefix = '';
|
||||
if (get_current_user() !== 'root') {
|
||||
$prefix = 'sudo ';
|
||||
logger()->warning('Current user is not root, using sudo for running command');
|
||||
}
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
logger()->info("Downloading package musl-toolchain-{$arch}-linux");
|
||||
PackageManager::installPackage("musl-toolchain-{$arch}-linux");
|
||||
$pkg_root = PKG_ROOT_PATH . "/musl-toolchain-{$arch}-linux";
|
||||
shell()->exec("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl");
|
||||
FileSystem::removeDir($pkg_root);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
|
||||
class LinuxToolCheckList
|
||||
{
|
||||
@ -74,16 +74,7 @@ class LinuxToolCheckList
|
||||
}
|
||||
}
|
||||
if (!empty($missing)) {
|
||||
return match ($distro['dist']) {
|
||||
'ubuntu',
|
||||
'alpine',
|
||||
'redhat',
|
||||
'centos',
|
||||
'Deepin',
|
||||
'arch',
|
||||
'debian' => CheckResult::fail(implode(', ', $missing) . ' not installed on your system', 'install-linux-tools', [$distro, $missing]),
|
||||
default => CheckResult::fail(implode(', ', $missing) . ' not installed on your system'),
|
||||
};
|
||||
return CheckResult::fail(implode(', ', $missing) . ' not installed on your system', 'install-linux-tools', [$distro, $missing]);
|
||||
}
|
||||
return CheckResult::ok();
|
||||
}
|
||||
@ -123,22 +114,23 @@ class LinuxToolCheckList
|
||||
'redhat' => 'dnf install -y',
|
||||
'centos' => 'yum install -y',
|
||||
'arch' => 'pacman -S --noconfirm',
|
||||
default => throw new RuntimeException('Current linux distro does not have an auto-install script for musl packages yet.'),
|
||||
default => throw new EnvironmentException(
|
||||
"Current linux distro [{$distro['dist']}] does not have an auto-install script for packages yet.",
|
||||
'You can submit an issue to request support: https://github.com/crazywhalecc/static-php-cli/issues'
|
||||
),
|
||||
};
|
||||
$prefix = '';
|
||||
if (($user = exec('whoami')) !== 'root') {
|
||||
$prefix = 'sudo ';
|
||||
logger()->warning('Current user (' . $user . ') is not root, using sudo for running command');
|
||||
}
|
||||
try {
|
||||
$is_debian = in_array($distro['dist'], ['debian', 'ubuntu', 'Deepin']);
|
||||
$to_install = $is_debian ? str_replace('xz', 'xz-utils', $missing) : $missing;
|
||||
// debian, alpine libtool -> libtoolize
|
||||
$to_install = str_replace('libtoolize', 'libtool', $to_install);
|
||||
shell(true)->exec($prefix . $install_cmd . ' ' . implode(' ', $to_install));
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
logger()->warning('Current user (' . $user . ') is not root, using sudo for running command (may require password input)');
|
||||
}
|
||||
|
||||
$is_debian = in_array($distro['dist'], ['debian', 'ubuntu', 'Deepin']);
|
||||
$to_install = $is_debian ? str_replace('xz', 'xz-utils', $missing) : $missing;
|
||||
// debian, alpine libtool -> libtoolize
|
||||
$to_install = str_replace('libtoolize', 'libtool', $to_install);
|
||||
shell(true)->exec($prefix . $install_cmd . ' ' . implode(' ', $to_install));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
class MacOSToolCheckList
|
||||
{
|
||||
@ -89,11 +88,7 @@ class MacOSToolCheckList
|
||||
#[AsFixItem('brew')]
|
||||
public function fixBrew(): bool
|
||||
{
|
||||
try {
|
||||
shell(true)->exec('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
}
|
||||
shell(true)->exec('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -104,14 +99,10 @@ class MacOSToolCheckList
|
||||
'glibtoolize' => 'libtool',
|
||||
];
|
||||
foreach ($missing as $cmd) {
|
||||
try {
|
||||
if (isset($replacement[$cmd])) {
|
||||
$cmd = $replacement[$cmd];
|
||||
}
|
||||
shell(true)->exec('brew install --formula ' . escapeshellarg($cmd));
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
if (isset($replacement[$cmd])) {
|
||||
$cmd = $replacement[$cmd];
|
||||
}
|
||||
shell(true)->exec('brew install --formula ' . escapeshellarg($cmd));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ use SPC\builder\windows\SystemUtil;
|
||||
use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\PackageManager;
|
||||
|
||||
@ -80,12 +79,8 @@ class WindowsToolCheckList
|
||||
#[AsFixItem('install-php-sdk')]
|
||||
public function installPhpSdk(): bool
|
||||
{
|
||||
try {
|
||||
FileSystem::removeDir(getenv('PHP_SDK_PATH'));
|
||||
cmd(true)->exec('git.exe clone --depth 1 https://github.com/php/php-sdk-binary-tools.git ' . getenv('PHP_SDK_PATH'));
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
}
|
||||
FileSystem::removeDir(getenv('PHP_SDK_PATH'));
|
||||
cmd(true)->exec('git.exe clone --depth 1 https://github.com/php/php-sdk-binary-tools.git ' . getenv('PHP_SDK_PATH'));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -5,9 +5,8 @@ declare(strict_types=1);
|
||||
namespace SPC\store;
|
||||
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\InterruptException;
|
||||
use SPC\exception\SPCException;
|
||||
use SPC\store\pkg\CustomPackage;
|
||||
use SPC\store\source\CustomSourceBase;
|
||||
use SPC\util\SPCTarget;
|
||||
@ -201,9 +200,9 @@ class Downloader
|
||||
unlink(FileSystem::convertPath(DOWNLOAD_PATH . '/' . $filename));
|
||||
}
|
||||
};
|
||||
self::registerCancelEvent($cancel_func);
|
||||
keyboard_interrupt_register($cancel_func);
|
||||
self::curlDown(url: $url, path: FileSystem::convertPath(DOWNLOAD_PATH . "/{$filename}"), headers: $headers, hooks: $hooks, retries: self::getRetryAttempts());
|
||||
self::unregisterCancelEvent();
|
||||
keyboard_interrupt_unregister();
|
||||
logger()->debug("Locking {$filename}");
|
||||
if ($download_as === SPC_DOWNLOAD_PRE_BUILT) {
|
||||
$name = self::getPreBuiltLockName($name);
|
||||
@ -248,12 +247,12 @@ class Downloader
|
||||
f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule));
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
} catch (SPCException $e) {
|
||||
if (is_dir($download_path)) {
|
||||
FileSystem::removeDir($download_path);
|
||||
}
|
||||
if ($e->getCode() === 2 || $e->getCode() === -1073741510) {
|
||||
throw new WrongUsageException('Keyboard interrupted, download failed !');
|
||||
throw new InterruptException('Keyboard interrupted, download failed !');
|
||||
}
|
||||
if ($retries > 0) {
|
||||
self::downloadGit($name, $url, $branch, $submodules, $move_path, $retries - 1, $lock_as);
|
||||
@ -385,7 +384,7 @@ class Downloader
|
||||
default:
|
||||
throw new DownloaderException('unknown source type: ' . $pkg['type']);
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
} catch (\Throwable $e) {
|
||||
// Because sometimes files downloaded through the command line are not automatically deleted after a failure.
|
||||
// Here we need to manually delete the file if it is detected to exist.
|
||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||
@ -503,7 +502,7 @@ class Downloader
|
||||
default:
|
||||
throw new DownloaderException('unknown source type: ' . $source['type']);
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
} catch (\Throwable $e) {
|
||||
// Because sometimes files downloaded through the command line are not automatically deleted after a failure.
|
||||
// Here we need to manually delete the file if it is detected to exist.
|
||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||
@ -551,7 +550,7 @@ class Downloader
|
||||
}
|
||||
f_exec($cmd, $output, $ret);
|
||||
if ($ret === 2 || $ret === -1073741510) {
|
||||
throw new RuntimeException(sprintf('Failed to fetch "%s"', $url));
|
||||
throw new InterruptException(sprintf('Canceled fetching "%s"', $url));
|
||||
}
|
||||
if ($ret !== 0) {
|
||||
throw new DownloaderException(sprintf('Failed to fetch "%s"', $url));
|
||||
@ -563,7 +562,7 @@ class Downloader
|
||||
}
|
||||
f_exec($cmd, $output, $ret);
|
||||
if ($ret === 2 || $ret === -1073741510) {
|
||||
throw new RuntimeException(sprintf('Failed to fetch "%s"', $url));
|
||||
throw new InterruptException(sprintf('Canceled fetching "%s"', $url));
|
||||
}
|
||||
if ($ret !== 0) {
|
||||
throw new DownloaderException(sprintf('Failed to fetch "%s"', $url));
|
||||
@ -599,9 +598,9 @@ class Downloader
|
||||
$cmd = SPC_CURL_EXEC . " -{$check}fSL {$retry} -o \"{$path}\" {$methodArg} {$headerArg} \"{$url}\"";
|
||||
try {
|
||||
f_passthru($cmd);
|
||||
} catch (RuntimeException $e) {
|
||||
} catch (\Throwable $e) {
|
||||
if ($e->getCode() === 2 || $e->getCode() === -1073741510) {
|
||||
throw new WrongUsageException('Keyboard interrupted, download failed !');
|
||||
throw new InterruptException('Keyboard interrupted, download failed !');
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
@ -639,11 +638,11 @@ class Downloader
|
||||
$url = "https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/{$source_name}/?format=json";
|
||||
$json = json_decode(Downloader::curlExec(url: $url, retries: intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0)), true);
|
||||
if (!is_array($json)) {
|
||||
throw new RuntimeException('failed http fetch');
|
||||
throw new DownloaderException('failed http fetch');
|
||||
}
|
||||
$item = $json[0] ?? null;
|
||||
if ($item === null) {
|
||||
throw new RuntimeException('failed to parse json');
|
||||
throw new DownloaderException('failed to parse json');
|
||||
}
|
||||
$full_url = 'https://dl.static-php.dev' . $item['full_path'];
|
||||
$filename = basename($item['full_path']);
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\store;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCException;
|
||||
|
||||
class FileSystem
|
||||
{
|
||||
@ -147,6 +147,7 @@ class FileSystem
|
||||
*/
|
||||
public static function copyDir(string $from, string $to): void
|
||||
{
|
||||
logger()->debug("Copying directory from {$from} to {$to}");
|
||||
$dst_path = FileSystem::convertPath($to);
|
||||
$src_path = FileSystem::convertPath($from);
|
||||
switch (PHP_OS_FAMILY) {
|
||||
@ -161,6 +162,23 @@ class FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy file from one location to another.
|
||||
* This method will throw an exception if the copy operation fails.
|
||||
*
|
||||
* @param string $from Source file path
|
||||
* @param string $to Destination file path
|
||||
*/
|
||||
public static function copy(string $from, string $to): void
|
||||
{
|
||||
logger()->debug("Copying file from {$from} to {$to}");
|
||||
$dst_path = FileSystem::convertPath($to);
|
||||
$src_path = FileSystem::convertPath($from);
|
||||
if (!copy($src_path, $dst_path)) {
|
||||
throw new FileSystemException('Cannot copy file from ' . $src_path . ' to ' . $dst_path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract package archive to specified directory
|
||||
*
|
||||
@ -187,13 +205,13 @@ class FileSystem
|
||||
try {
|
||||
// extract wrapper command
|
||||
self::extractWithType($source_type, $filename, $extract_path);
|
||||
} catch (RuntimeException $e) {
|
||||
} catch (SPCException $e) {
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
f_passthru('rmdir /s /q ' . $target);
|
||||
} else {
|
||||
f_passthru('rm -rf ' . $target);
|
||||
}
|
||||
throw new FileSystemException('Cannot extract package ' . $name, $e->getCode(), $e);
|
||||
throw new FileSystemException("Cannot extract package {$name}", $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,7 +241,7 @@ class FileSystem
|
||||
try {
|
||||
self::extractWithType($source_type, $filename, $move_path);
|
||||
self::emitSourceExtractHook($name, $target);
|
||||
} catch (RuntimeException $e) {
|
||||
} catch (SPCException $e) {
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
f_passthru('rmdir /s /q ' . $target);
|
||||
} else {
|
||||
@ -505,7 +523,7 @@ class FileSystem
|
||||
public static function restoreBackupFile(string $path): void
|
||||
{
|
||||
if (!file_exists($path . '.bak')) {
|
||||
throw new RuntimeException('Cannot find bak file for ' . $path);
|
||||
throw new FileSystemException("Backup restore failed: Cannot find bak file for {$path}");
|
||||
}
|
||||
copy($path . '.bak', $path);
|
||||
unlink($path . '.bak');
|
||||
|
||||
@ -4,8 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\store;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class LockFile
|
||||
@ -128,10 +127,10 @@ class LockFile
|
||||
SPC_SOURCE_ARCHIVE => sha1_file(DOWNLOAD_PATH . '/' . $lock_options['filename']),
|
||||
SPC_SOURCE_GIT => exec('cd ' . escapeshellarg(DOWNLOAD_PATH . '/' . $lock_options['dirname']) . ' && ' . SPC_GIT_EXEC . ' rev-parse HEAD'),
|
||||
SPC_SOURCE_LOCAL => 'LOCAL HASH IS ALWAYS DIFFERENT',
|
||||
default => filter_var(getenv('SPC_IGNORE_BAD_HASH'), FILTER_VALIDATE_BOOLEAN) ? '' : throw new RuntimeException("Unknown source type: {$lock_options['source_type']}"),
|
||||
default => filter_var(getenv('SPC_IGNORE_BAD_HASH'), FILTER_VALIDATE_BOOLEAN) ? '' : throw new SPCInternalException("Unknown source type: {$lock_options['source_type']}"),
|
||||
};
|
||||
if ($result === false && !filter_var(getenv('SPC_IGNORE_BAD_HASH'), FILTER_VALIDATE_BOOLEAN)) {
|
||||
throw new RuntimeException("Failed to get hash for source: {$lock_options['source_type']}");
|
||||
throw new SPCInternalException("Failed to get hash for source: {$lock_options['source_type']}");
|
||||
}
|
||||
return $result ?: '';
|
||||
}
|
||||
@ -182,7 +181,7 @@ class LockFile
|
||||
$file_content = file_get_contents(self::LOCK_FILE);
|
||||
self::$lock_file_content = json_decode($file_content, true);
|
||||
if (self::$lock_file_content === null) {
|
||||
throw new \RuntimeException('Failed to decode lock file: ' . self::LOCK_FILE);
|
||||
throw new SPCInternalException('Failed to decode lock file: ' . self::LOCK_FILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,7 @@ use SPC\builder\linux\SystemUtil;
|
||||
use SPC\builder\unix\UnixBuilderBase;
|
||||
use SPC\builder\windows\WindowsBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\PatchException;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
class SourcePatcher
|
||||
@ -171,7 +170,7 @@ class SourcePatcher
|
||||
$patches[] = "sapi/micro/patches/{$patchName}_{$tryMajMin}.patch";
|
||||
continue 2;
|
||||
}
|
||||
throw new RuntimeException("failed finding patch {$patchName}");
|
||||
throw new PatchException('phpmicro patches', "Failed finding patch file or versioned file {$patchName} !");
|
||||
}
|
||||
|
||||
foreach ($patches as $patch) {
|
||||
@ -202,7 +201,7 @@ class SourcePatcher
|
||||
|
||||
$patch_str = FileSystem::convertPath($patch_file);
|
||||
if (!file_exists($patch_str)) {
|
||||
throw new RuntimeException("Patch file [{$patch_str}] does not exist");
|
||||
throw new PatchException($patch_name, "Patch file [{$patch_str}] does not exist");
|
||||
}
|
||||
|
||||
// Copy patch from phar
|
||||
@ -524,7 +523,7 @@ class SourcePatcher
|
||||
++$line_num;
|
||||
}
|
||||
if ($found === false) {
|
||||
throw new RuntimeException('Cannot patch windows CLI Makefile!');
|
||||
throw new PatchException('Windows Makefile patching for php.exe target', 'Cannot patch windows CLI Makefile, Makefile does not contain "$(BUILD_DIR)\php.exe:" line');
|
||||
}
|
||||
$lines[$line_num] = '$(BUILD_DIR)\php.exe: generated_files $(DEPS_CLI) $(PHP_GLOBAL_OBJS) $(CLI_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(ASM_OBJS) $(BUILD_DIR)\php.exe.res $(BUILD_DIR)\php.exe.manifest';
|
||||
$lines[$line_num + 1] = "\t" . '"$(LINK)" /nologo $(PHP_GLOBAL_OBJS_RESP) $(CLI_GLOBAL_OBJS_RESP) $(STATIC_EXT_OBJS_RESP) $(STATIC_EXT_LIBS) $(ASM_OBJS) $(LIBS) $(LIBS_CLI) $(BUILD_DIR)\php.exe.res /out:$(BUILD_DIR)\php.exe $(LDFLAGS) $(LDFLAGS_CLI) /ltcg /nodefaultlib:msvcrt /nodefaultlib:msvcrtd /ignore:4286';
|
||||
|
||||
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\store\pkg;
|
||||
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\CurlHook;
|
||||
use SPC\store\Downloader;
|
||||
@ -77,14 +77,14 @@ class Zig extends CustomPackage
|
||||
}
|
||||
|
||||
if (!$latest_version) {
|
||||
throw new RuntimeException('Could not determine latest Zig version');
|
||||
throw new DownloaderException('Could not determine latest Zig version');
|
||||
}
|
||||
|
||||
logger()->info("Installing Zig version {$latest_version}");
|
||||
|
||||
$platform_key = "{$zig_arch}-{$zig_os}";
|
||||
if (!isset($index_json[$latest_version][$platform_key])) {
|
||||
throw new RuntimeException("No download available for {$platform_key} in Zig version {$latest_version}");
|
||||
throw new DownloaderException("No download available for {$platform_key} in Zig version {$latest_version}");
|
||||
}
|
||||
|
||||
$download_info = $index_json[$latest_version][$platform_key];
|
||||
|
||||
@ -7,7 +7,7 @@ namespace SPC\toolchain;
|
||||
use SPC\builder\freebsd\SystemUtil as FreeBSDSystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
@ -35,7 +35,7 @@ class ClangNativeToolchain implements ToolchainInterface
|
||||
'Linux' => LinuxSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'Darwin' => MacOSSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'BSD' => FreeBSDSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
default => throw new RuntimeException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'),
|
||||
default => throw new EnvironmentException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ namespace SPC\toolchain;
|
||||
use SPC\builder\freebsd\SystemUtil as FreeBSDSystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
@ -31,7 +32,7 @@ class GccNativeToolchain implements ToolchainInterface
|
||||
'Linux' => LinuxSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'Darwin' => MacOSSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'BSD' => FreeBSDSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
default => throw new \RuntimeException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'),
|
||||
default => throw new EnvironmentException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
class MuslToolchain implements ToolchainInterface
|
||||
@ -33,7 +33,7 @@ class MuslToolchain implements ToolchainInterface
|
||||
GlobalEnvManager::putenv("SPC_CMD_PREFIX_PHP_CONFIGURE=LD_LIBRARY_PATH=\"{$ld_library_path}\" {$configure}");
|
||||
|
||||
if (!file_exists("/usr/local/musl/{$arch}-linux-musl/lib/libc.a")) {
|
||||
throw new WrongUsageException('You are building with musl-libc target in glibc distro, but musl-toolchain is not installed, please install musl-toolchain first. (You can use `doctor` command to install it)');
|
||||
throw new EnvironmentException('You are building with musl-libc target in glibc distro, but musl-toolchain is not installed, please install musl-toolchain first. (You can use `doctor` command to install it)');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\store\pkg\Zig;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
@ -43,7 +43,7 @@ class ZigToolchain implements ToolchainInterface
|
||||
public function afterInit(): void
|
||||
{
|
||||
if (!is_dir(Zig::getEnvironment()['PATH'])) {
|
||||
throw new WrongUsageException('You are building with zig, but zig is not installed, please install zig first. (You can use `doctor` command to install it)');
|
||||
throw new EnvironmentException('You are building with zig, but zig is not installed, please install zig first. (You can use `doctor` command to install it)');
|
||||
}
|
||||
GlobalEnvManager::addPathIfNotExists(Zig::getEnvironment()['PATH']);
|
||||
f_passthru('ulimit -n 2048'); // zig opens extra file descriptors, so when a lot of extensions are built statically, 1024 is not enough
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\util;
|
||||
|
||||
use SPC\builder\macos\SystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\toolchain\ToolchainManager;
|
||||
|
||||
@ -33,7 +33,7 @@ class GlobalEnvManager
|
||||
}
|
||||
// Check pre-defined env vars exists
|
||||
if (getenv('BUILD_ROOT_PATH') === false) {
|
||||
throw new RuntimeException('You must include src/globals/internal-env.php before using GlobalEnvManager');
|
||||
throw new SPCInternalException('You must include src/globals/internal-env.php before using GlobalEnvManager');
|
||||
}
|
||||
|
||||
// Define env vars for unix
|
||||
|
||||
@ -4,9 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\util;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
@ -100,7 +98,7 @@ class LicenseDumper
|
||||
{
|
||||
$licenses = Config::getSource($source_name)['license'] ?? [];
|
||||
if ($licenses === []) {
|
||||
throw new RuntimeException('source [' . $source_name . '] license meta not exist');
|
||||
throw new SPCInternalException("source [{$source_name}] license meta not exist");
|
||||
}
|
||||
|
||||
if (!array_is_list($licenses)) {
|
||||
@ -111,7 +109,7 @@ class LicenseDumper
|
||||
yield $index => match ($license['type']) {
|
||||
'text' => $license['text'],
|
||||
'file' => $this->loadSourceFile($source_name, $index, $license['path'], Config::getSource($source_name)['path'] ?? null),
|
||||
default => throw new RuntimeException('source [' . $source_name . '] license type is not allowed'),
|
||||
default => throw new SPCInternalException("source [{$source_name}] license type is not allowed"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -122,7 +120,7 @@ class LicenseDumper
|
||||
private function loadSourceFile(string $source_name, int $index, null|array|string $in_path, ?string $custom_base_path = null): string
|
||||
{
|
||||
if (is_null($in_path)) {
|
||||
throw new RuntimeException('source [' . $source_name . '] license file is not set, please check config/source.json');
|
||||
throw new SPCInternalException("source [{$source_name}] license file is not set, please check config/source.json");
|
||||
}
|
||||
|
||||
if (!is_array($in_path)) {
|
||||
@ -139,6 +137,6 @@ class LicenseDumper
|
||||
return file_get_contents(BUILD_ROOT_PATH . '/source-licenses/' . $source_name . '/' . $index . '.txt');
|
||||
}
|
||||
|
||||
throw new RuntimeException('Cannot find any license file in source [' . $source_name . '] directory!');
|
||||
throw new SPCInternalException("Cannot find any license file in source [{$source_name}] directory!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\util;
|
||||
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ExecutionException;
|
||||
|
||||
/**
|
||||
* Utility class for pkg-config operations
|
||||
@ -95,7 +95,7 @@ class PkgConfigUtil
|
||||
{
|
||||
f_exec($cmd, $output, $result_code);
|
||||
if ($result_code !== 0) {
|
||||
throw new RuntimeException("pkg-config command failed with code {$result_code}: {$cmd}");
|
||||
throw new ExecutionException($cmd, "pkg-config command failed with code: {$result_code}");
|
||||
}
|
||||
return implode("\n", $output);
|
||||
}
|
||||
|
||||
@ -6,8 +6,7 @@ namespace SPC\Tests\globals;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LogLevel;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\ExecutionException;
|
||||
use ZM\Logger\ConsoleLogger;
|
||||
|
||||
/**
|
||||
@ -64,7 +63,7 @@ class GlobalFunctionsTest extends TestCase
|
||||
$this->markTestSkipped('Windows not support f_passthru');
|
||||
}
|
||||
$this->assertEquals(null, f_passthru('echo ""'));
|
||||
$this->expectException('SPC\exception\RuntimeException');
|
||||
$this->expectException(ExecutionException::class);
|
||||
f_passthru('false');
|
||||
}
|
||||
|
||||
@ -80,16 +79,16 @@ class GlobalFunctionsTest extends TestCase
|
||||
$this->markTestSkipped('Windows not support shell');
|
||||
}
|
||||
$shell = shell();
|
||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell);
|
||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell->cd('/'));
|
||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell->exec('echo ""'));
|
||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell->setEnv(['SPC_TEST_ENV' => '1']));
|
||||
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell);
|
||||
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell->cd('/'));
|
||||
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell->exec('echo ""'));
|
||||
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell->setEnv(['SPC_TEST_ENV' => '1']));
|
||||
|
||||
[$code, $out] = $shell->execWithResult('echo "_"');
|
||||
$this->assertEquals(0, $code);
|
||||
$this->assertEquals('_', implode('', $out));
|
||||
|
||||
$this->expectException('SPC\exception\RuntimeException');
|
||||
$this->expectException('SPC\exception\ExecutionException');
|
||||
$shell->exec('false');
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\Tests\store;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\exception\InterruptException;
|
||||
use SPC\store\Downloader;
|
||||
use SPC\store\LockFile;
|
||||
|
||||
@ -34,7 +34,7 @@ class DownloaderTest extends TestCase
|
||||
// test keyboard interrupt
|
||||
try {
|
||||
Downloader::downloadGit('setup-static-php', 'https://github.com/static-php/setup-static-php.git', 'SIGINT');
|
||||
} catch (WrongUsageException $e) {
|
||||
} catch (InterruptException $e) {
|
||||
$this->assertStringContainsString('interrupted', $e->getMessage());
|
||||
return;
|
||||
}
|
||||
@ -49,7 +49,7 @@ class DownloaderTest extends TestCase
|
||||
// test keyboard interrupt
|
||||
try {
|
||||
Downloader::downloadFile('fake-file', 'https://fakecmd.com/curlDown', 'SIGINT');
|
||||
} catch (WrongUsageException $e) {
|
||||
} catch (InterruptException $e) {
|
||||
$this->assertStringContainsString('interrupted', $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\Tests\util;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
/**
|
||||
@ -105,7 +105,7 @@ final class GlobalEnvManagerTest extends TestCase
|
||||
// Temporarily unset BUILD_ROOT_PATH
|
||||
putenv('BUILD_ROOT_PATH');
|
||||
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectException(SPCInternalException::class);
|
||||
GlobalEnvManager::init();
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\Tests\util;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\ExecutionException;
|
||||
use SPC\util\PkgConfigUtil;
|
||||
|
||||
/**
|
||||
@ -75,7 +75,7 @@ final class PkgConfigUtilTest extends TestCase
|
||||
*/
|
||||
public function testGetCflagsWithInvalidPackage(string $package): void
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectException(ExecutionException::class);
|
||||
PkgConfigUtil::getCflags($package);
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ final class PkgConfigUtilTest extends TestCase
|
||||
*/
|
||||
public function testGetLibsArrayWithInvalidPackage(string $package): void
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectException(ExecutionException::class);
|
||||
PkgConfigUtil::getLibsArray($package);
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\store;
|
||||
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\InterruptException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
|
||||
function f_exec(string $command, mixed &$output, mixed &$result_code): bool
|
||||
{
|
||||
@ -52,13 +53,13 @@ function f_passthru(string $cmd): bool
|
||||
{
|
||||
if (str_starts_with($cmd, 'git')) {
|
||||
if (str_contains($cmd, '--branch "SIGINT"')) {
|
||||
throw new RuntimeException('Interrupt', 2);
|
||||
throw new InterruptException('interrupted', 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (str_contains($cmd, 'https://fakecmd.com/curlDown')) {
|
||||
if (str_contains($cmd, 'SIGINT')) {
|
||||
throw new RuntimeException('Interrupt', 2);
|
||||
throw new InterruptException('interrupted', 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -71,5 +72,5 @@ function f_passthru(string $cmd): bool
|
||||
return true;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException('Invalid tests');
|
||||
throw new SPCInternalException('Invalid tests');
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user