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;
|
namespace SPC\builder;
|
||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCException;
|
||||||
|
use SPC\exception\ValidationException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
@ -30,10 +31,10 @@ class Extension
|
|||||||
$unix_only = Config::getExt($this->name, 'unix-only', false);
|
$unix_only = Config::getExt($this->name, 'unix-only', false);
|
||||||
$windows_only = Config::getExt($this->name, 'windows-only', false);
|
$windows_only = Config::getExt($this->name, 'windows-only', false);
|
||||||
if (PHP_OS_FAMILY !== 'Windows' && $windows_only) {
|
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) {
|
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
|
// set source_dir for builtin
|
||||||
if ($ext_type === 'builtin') {
|
if ($ext_type === 'builtin') {
|
||||||
@ -41,7 +42,7 @@ class Extension
|
|||||||
} elseif ($ext_type === 'external') {
|
} elseif ($ext_type === 'external') {
|
||||||
$source = Config::getExt($this->name, 'source');
|
$source = Config::getExt($this->name, 'source');
|
||||||
if ($source === null) {
|
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 = Config::getSource($source)['path'] ?? null;
|
||||||
$source_path = $source_path === null ? SOURCE_PATH . '/' . $source : SOURCE_PATH . '/' . $source_path;
|
$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
|
// 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 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();
|
$sharedExtensions = $this->getSharedExtensionLoadString();
|
||||||
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||||
if ($ret !== 0) {
|
if ($ret !== 0) {
|
||||||
throw new RuntimeException(
|
throw new ValidationException(
|
||||||
'extension ' . $this->getName() . ' failed runtime check: php-cli returned ' . $ret . "\n" .
|
"extension {$this->getName()} failed compile check: php-cli returned {$ret}",
|
||||||
join("\n", $out)
|
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) . '"');
|
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' -r "' . trim($test) . '"');
|
||||||
if ($ret !== 0) {
|
if ($ret !== 0) {
|
||||||
var_dump($out);
|
throw new ValidationException(
|
||||||
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
|
"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
|
// 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 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);
|
[$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n --ri "' . $this->getDistName() . '"', false);
|
||||||
if ($ret !== 0) {
|
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'))) {
|
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) . '"');
|
[$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n -r "' . trim($test) . '"');
|
||||||
if ($ret !== 0) {
|
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
|
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')) {
|
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)');
|
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (Config::getExt($this->getName(), 'build-with-php') === true) {
|
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
|
||||||
logger()->warning('Shared extension [' . $this->getName() . '] did not build with php-src/configure (' . $this->getName() . '.so)');
|
foreach ($this->dependencies as $dependency) {
|
||||||
logger()->warning('Try deleting your build and source folders and running `spc build`` again.');
|
if (!$dependency instanceof Extension) {
|
||||||
return;
|
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);
|
$depLib = $this->builder->getLib($name);
|
||||||
if (!$depLib) {
|
if (!$depLib) {
|
||||||
if (!$optional) {
|
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}");
|
logger()->info("enabling {$this->name} without library {$name}");
|
||||||
} else {
|
} else {
|
||||||
@ -492,7 +501,7 @@ class Extension
|
|||||||
$depExt = $this->builder->getExt($name);
|
$depExt = $this->builder->getExt($name);
|
||||||
if (!$depExt) {
|
if (!$depExt) {
|
||||||
if (!$optional) {
|
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}");
|
logger()->info("enabling {$this->name} without extension {$name}");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -4,8 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\builder;
|
namespace SPC\builder;
|
||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\SPCException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\Downloader;
|
use SPC\store\Downloader;
|
||||||
@ -30,9 +30,9 @@ abstract class LibraryBase
|
|||||||
public function __construct(?string $source_dir = null)
|
public function __construct(?string $source_dir = null)
|
||||||
{
|
{
|
||||||
if (static::NAME === 'unknown') {
|
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);
|
FileSystem::extractPackage($install_file, $lock['source_type'], DOWNLOAD_PATH . '/' . $install_file, BUILD_ROOT_PATH);
|
||||||
$this->install();
|
$this->install();
|
||||||
return LIB_STATUS_OK;
|
return LIB_STATUS_OK;
|
||||||
} catch (FileSystemException|RuntimeException $e) {
|
} catch (SPCException $e) {
|
||||||
logger()->error('Failed to extract pre-built library [' . static::NAME . ']: ' . $e->getMessage());
|
logger()->error('Failed to extract pre-built library [' . static::NAME . ']: ' . $e->getMessage());
|
||||||
return LIB_STATUS_INSTALL_FAILED;
|
return LIB_STATUS_INSTALL_FAILED;
|
||||||
}
|
}
|
||||||
@ -304,7 +304,7 @@ abstract class LibraryBase
|
|||||||
}
|
}
|
||||||
$replace_items = json_decode(file_get_contents($replace_item_file), true);
|
$replace_items = json_decode(file_get_contents($replace_item_file), true);
|
||||||
if (!is_array($replace_items)) {
|
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();
|
$placeholders = get_pack_replace();
|
||||||
// replace placeholders in BUILD_ROOT_PATH
|
// replace placeholders in BUILD_ROOT_PATH
|
||||||
@ -331,7 +331,7 @@ abstract class LibraryBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!$optional) {
|
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}");
|
logger()->debug('enabling ' . static::NAME . " without {$name}");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,7 @@ use SPC\builder\Extension;
|
|||||||
use SPC\builder\linux\LinuxBuilder;
|
use SPC\builder\linux\LinuxBuilder;
|
||||||
use SPC\builder\macos\MacOSBuilder;
|
use SPC\builder\macos\MacOSBuilder;
|
||||||
use SPC\builder\windows\WindowsBuilder;
|
use SPC\builder\windows\WindowsBuilder;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\PatchException;
|
||||||
use SPC\exception\WrongUsageException;
|
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ class curl extends Extension
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ($patched === null) {
|
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);
|
FileSystem::writeFile($file, $patched);
|
||||||
|
|||||||
@ -6,6 +6,7 @@ namespace SPC\builder\extension;
|
|||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\builder\windows\WindowsBuilder;
|
use SPC\builder\windows\WindowsBuilder;
|
||||||
|
use SPC\exception\ValidationException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
use SPC\util\GlobalEnvManager;
|
use SPC\util\GlobalEnvManager;
|
||||||
@ -18,7 +19,7 @@ class grpc extends Extension
|
|||||||
public function patchBeforeBuildconf(): bool
|
public function patchBeforeBuildconf(): bool
|
||||||
{
|
{
|
||||||
if ($this->builder instanceof WindowsBuilder) {
|
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')) {
|
if (file_exists(SOURCE_PATH . '/php-src/ext/grpc')) {
|
||||||
return false;
|
return false;
|
||||||
@ -27,7 +28,7 @@ class grpc extends Extension
|
|||||||
if (is_dir($this->source_dir . '/src/php/ext/grpc')) {
|
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');
|
shell()->exec('ln -s ' . $this->source_dir . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc');
|
||||||
} else {
|
} 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') {
|
if (SPCTarget::getTargetOS() === 'Darwin') {
|
||||||
FileSystem::replaceFileRegex(
|
FileSystem::replaceFileRegex(
|
||||||
|
|||||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace SPC\builder\extension;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
#[CustomExt('mbregex')]
|
#[CustomExt('mbregex')]
|
||||||
@ -16,11 +16,6 @@ class mbregex extends Extension
|
|||||||
return 'mbstring';
|
return 'mbstring';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConfigureArg(bool $shared = false): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mbregex is not an extension, we need to overwrite the default check.
|
* 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"' : '';
|
$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);
|
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $sharedext . ' --ri "mbstring" | grep regex', false);
|
||||||
if ($ret !== 0) {
|
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);
|
[$ret, $out] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "mbstring"', false);
|
||||||
if ($ret !== 0) {
|
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);
|
$out = implode("\n", $out);
|
||||||
if (!str_contains($out, 'regex')) {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
|
use SPC\exception\ValidationException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
use SPC\util\GlobalEnvManager;
|
use SPC\util\GlobalEnvManager;
|
||||||
@ -15,7 +16,7 @@ class opentelemetry extends Extension
|
|||||||
public function validate(): void
|
public function validate(): void
|
||||||
{
|
{
|
||||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
#[CustomExt('password-argon2')]
|
#[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\'));"');
|
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n -r "assert(defined(\'PASSWORD_ARGON2I\'));"');
|
||||||
if ($ret !== 0) {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
|
use SPC\exception\ValidationException;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
#[CustomExt('protobuf')]
|
#[CustomExt('protobuf')]
|
||||||
@ -13,12 +14,12 @@ class protobuf extends Extension
|
|||||||
public function validate(): void
|
public function validate(): void
|
||||||
{
|
{
|
||||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
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');
|
$grpc = $this->builder->getExt('grpc');
|
||||||
// protobuf conflicts with grpc
|
// protobuf conflicts with grpc
|
||||||
if ($grpc?->isBuildStatic()) {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
#[CustomExt('swoole-hook-mysql')]
|
#[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);
|
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $this->getSharedExtensionLoadString() . ' --ri "swoole"', false);
|
||||||
$out = implode('', $out);
|
$out = implode('', $out);
|
||||||
if ($ret !== 0) {
|
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')) {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\CustomExt;
|
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() . '"');
|
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||||
$out = implode('', $out);
|
$out = implode('', $out);
|
||||||
if ($ret !== 0) {
|
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')) {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\CustomExt;
|
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() . '"');
|
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||||
$out = implode('', $out);
|
$out = implode('', $out);
|
||||||
if ($ret !== 0) {
|
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')) {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
#[CustomExt('swow')]
|
#[CustomExt('swow')]
|
||||||
@ -14,7 +14,7 @@ class swow extends Extension
|
|||||||
public function validate(): void
|
public function validate(): void
|
||||||
{
|
{
|
||||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
|
use SPC\exception\ValidationException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ class uv extends Extension
|
|||||||
public function validate(): void
|
public function validate(): void
|
||||||
{
|
{
|
||||||
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
|
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;
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ class xml extends Extension
|
|||||||
'xmlreader' => '--enable-xmlreader',
|
'xmlreader' => '--enable-xmlreader',
|
||||||
'xmlwriter' => '--enable-xmlwriter',
|
'xmlwriter' => '--enable-xmlwriter',
|
||||||
'simplexml' => '--enable-simplexml',
|
'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 . '"';
|
$arg .= ($shared ? '=shared' : '') . ' --with-libxml="' . BUILD_ROOT_PATH . '"';
|
||||||
return $arg;
|
return $arg;
|
||||||
@ -44,7 +44,7 @@ class xml extends Extension
|
|||||||
'xmlreader' => '--enable-xmlreader',
|
'xmlreader' => '--enable-xmlreader',
|
||||||
'xmlwriter' => '--enable-xmlwriter',
|
'xmlwriter' => '--enable-xmlwriter',
|
||||||
'simplexml' => '--with-simplexml',
|
'simplexml' => '--with-simplexml',
|
||||||
default => throw new RuntimeException('Not accept non-xml extension'),
|
default => throw new SPCInternalException('Not accept non-xml extension'),
|
||||||
};
|
};
|
||||||
$arg .= ' --with-libxml';
|
$arg .= ' --with-libxml';
|
||||||
return $arg;
|
return $arg;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace SPC\builder\freebsd;
|
namespace SPC\builder\freebsd;
|
||||||
|
|
||||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
|
|
||||||
class SystemUtil
|
class SystemUtil
|
||||||
@ -20,7 +20,10 @@ class SystemUtil
|
|||||||
{
|
{
|
||||||
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu');
|
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu');
|
||||||
if ($ret !== 0) {
|
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];
|
return (int) $output[0];
|
||||||
|
|||||||
@ -358,7 +358,7 @@ class LinuxBuilder extends UnixBuilderBase
|
|||||||
$out[1] = explode(' ', $out[1]);
|
$out[1] = explode(' ', $out[1]);
|
||||||
$offset = $out[1][0];
|
$offset = $out[1][0];
|
||||||
if ($ret !== 0 || !str_starts_with($offset, '0x')) {
|
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);
|
$offset = hexdec($offset);
|
||||||
// remove upx extra wastes
|
// remove upx extra wastes
|
||||||
|
|||||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace SPC\builder\macos;
|
namespace SPC\builder\macos;
|
||||||
|
|
||||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
|
|
||||||
class SystemUtil
|
class SystemUtil
|
||||||
@ -18,12 +18,15 @@ class SystemUtil
|
|||||||
*/
|
*/
|
||||||
public static function getCpuCount(): int
|
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) {
|
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;
|
namespace SPC\builder\traits;
|
||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\PatchException;
|
||||||
use SPC\exception\RuntimeException;
|
|
||||||
use SPC\exception\WrongUsageException;
|
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\SPCConfigUtil;
|
use SPC\util\SPCConfigUtil;
|
||||||
@ -38,7 +36,7 @@ trait UnixLibraryTrait
|
|||||||
foreach ($files as $name) {
|
foreach ($files as $name) {
|
||||||
$realpath = realpath(BUILD_ROOT_PATH . '/lib/pkgconfig/' . $name);
|
$realpath = realpath(BUILD_ROOT_PATH . '/lib/pkgconfig/' . $name);
|
||||||
if ($realpath === false) {
|
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);
|
logger()->debug('Patching ' . $realpath);
|
||||||
// replace prefix
|
// replace prefix
|
||||||
@ -65,7 +63,7 @@ trait UnixLibraryTrait
|
|||||||
$realpath = realpath(BUILD_LIB_PATH . '/' . $name);
|
$realpath = realpath(BUILD_LIB_PATH . '/' . $name);
|
||||||
if ($realpath === false) {
|
if ($realpath === false) {
|
||||||
if ($throwOnMissing) {
|
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 . '] !');
|
logger()->warning('Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\builder\traits;
|
namespace SPC\builder\traits;
|
||||||
|
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\PkgConfigUtil;
|
use SPC\util\PkgConfigUtil;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ trait openssl
|
|||||||
if (PHP_OS_FAMILY !== 'Windows') {
|
if (PHP_OS_FAMILY !== 'Windows') {
|
||||||
try {
|
try {
|
||||||
return PkgConfigUtil::getModuleVersion('openssl');
|
return PkgConfigUtil::getModuleVersion('openssl');
|
||||||
} catch (RuntimeException) {
|
} catch (SPCException) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// get openssl version from header openssl/opensslv.h
|
// get openssl version from header openssl/opensslv.h
|
||||||
|
|||||||
@ -5,8 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace SPC\builder\unix;
|
namespace SPC\builder\unix;
|
||||||
|
|
||||||
use SPC\builder\BuilderBase;
|
use SPC\builder\BuilderBase;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\CurlHook;
|
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 some libs are not supported (but in config "lib.json", throw exception)
|
||||||
if (!isset($support_lib_list[$library])) {
|
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);
|
$lib = new ($support_lib_list[$library])($this);
|
||||||
$this->addLib($lib);
|
$this->addLib($lib);
|
||||||
@ -80,7 +87,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
|||||||
[$ret, $output] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -r "echo \"hello\";"');
|
[$ret, $output] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -r "echo \"hello\";"');
|
||||||
$raw_output = implode('', $output);
|
$raw_output = implode('', $output);
|
||||||
if ($ret !== 0 || trim($raw_output) !== 'hello') {
|
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) {
|
foreach ($this->getExts() as $ext) {
|
||||||
@ -103,7 +110,10 @@ abstract class UnixBuilderBase extends BuilderBase
|
|||||||
foreach ($task['conditions'] as $condition => $closure) {
|
foreach ($task['conditions'] as $condition => $closure) {
|
||||||
if (!$closure($ret, $out)) {
|
if (!$closure($ret, $out)) {
|
||||||
$raw_out = trim(implode('', $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);
|
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
|
||||||
if ($ret !== 0) {
|
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');
|
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed');
|
||||||
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
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');
|
logger()->info('running frankenphp sanity check');
|
||||||
$frankenphp = BUILD_BIN_PATH . '/frankenphp';
|
$frankenphp = BUILD_BIN_PATH . '/frankenphp';
|
||||||
if (!file_exists($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_';
|
$prefix = PHP_OS_FAMILY === 'Darwin' ? 'DYLD_' : 'LD_';
|
||||||
[$ret, $output] = shell()
|
[$ret, $output] = shell()
|
||||||
->setEnv(["{$prefix}LIBRARY_PATH" => BUILD_LIB_PATH])
|
->setEnv(["{$prefix}LIBRARY_PATH" => BUILD_LIB_PATH])
|
||||||
->execWithResult("{$frankenphp} version");
|
->execWithResult("{$frankenphp} version");
|
||||||
if ($ret !== 0 || !str_contains(implode('', $output), 'FrankenPHP')) {
|
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_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
|
||||||
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
|
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
|
||||||
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
|
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');
|
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||||
FileSystem::createDir(BUILD_BIN_PATH);
|
FileSystem::createDir(BUILD_BIN_PATH);
|
||||||
@ -191,7 +213,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
|||||||
*/
|
*/
|
||||||
protected function cleanMake(): void
|
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');
|
shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\builder\unix\library;
|
namespace SPC\builder\unix\library;
|
||||||
|
|
||||||
|
use SPC\exception\BuildFailureException;
|
||||||
|
|
||||||
trait fastlz
|
trait fastlz
|
||||||
{
|
{
|
||||||
protected function build(): void
|
protected function build(): void
|
||||||
@ -13,10 +15,10 @@ trait fastlz
|
|||||||
->exec((getenv('AR') ?: 'ar') . ' rcs libfastlz.a fastlz.o');
|
->exec((getenv('AR') ?: 'ar') . ' rcs libfastlz.a fastlz.o');
|
||||||
|
|
||||||
if (!copy($this->source_dir . '/fastlz.h', BUILD_INCLUDE_PATH . '/fastlz.h')) {
|
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')) {
|
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;
|
namespace SPC\builder\unix\library;
|
||||||
|
|
||||||
use SPC\builder\linux\library\LinuxLibraryBase;
|
use SPC\builder\linux\library\LinuxLibraryBase;
|
||||||
|
use SPC\exception\BuildFailureException;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\SPCTarget;
|
use SPC\util\SPCTarget;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ trait postgresql
|
|||||||
$envs .= " LIBS=\"{$libs}{$libcpp}\" ";
|
$envs .= " LIBS=\"{$libs}{$libcpp}\" ";
|
||||||
}
|
}
|
||||||
if ($error_exec_cnt > 0) {
|
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');
|
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 "278 s/^/# /" ../src/Makefile.shlib')
|
||||||
->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib');
|
->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib');
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException('Unsupported version for postgresql: ' . $version . ' !');
|
throw new BuildFailureException('Unsupported version for postgresql: ' . $version . ' !');
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure
|
// configure
|
||||||
|
|||||||
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\builder\windows;
|
namespace SPC\builder\windows;
|
||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
class SystemUtil
|
class SystemUtil
|
||||||
|
|||||||
@ -5,8 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace SPC\builder\windows;
|
namespace SPC\builder\windows;
|
||||||
|
|
||||||
use SPC\builder\BuilderBase;
|
use SPC\builder\BuilderBase;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
@ -267,7 +267,7 @@ class WindowsBuilder extends BuilderBase
|
|||||||
logger()->info('running cli sanity check');
|
logger()->info('running cli sanity check');
|
||||||
[$ret, $output] = cmd()->execWithResult(BUILD_ROOT_PATH . '\bin\php.exe -n -r "echo \"hello\";"');
|
[$ret, $output] = cmd()->execWithResult(BUILD_ROOT_PATH . '\bin\php.exe -n -r "echo \"hello\";"');
|
||||||
if ($ret !== 0 || trim(implode('', $output)) !== '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) {
|
foreach ($this->getExts(false) as $ext) {
|
||||||
@ -290,7 +290,10 @@ class WindowsBuilder extends BuilderBase
|
|||||||
foreach ($task['conditions'] as $condition => $closure) {
|
foreach ($task['conditions'] as $condition => $closure) {
|
||||||
if (!$closure($ret, $out)) {
|
if (!$closure($ret, $out)) {
|
||||||
$raw_out = trim(implode('', $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) {
|
$src = match ($type) {
|
||||||
BUILD_TARGET_CLI => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\php.exe",
|
BUILD_TARGET_CLI => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\php.exe",
|
||||||
BUILD_TARGET_MICRO => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\micro.sfx",
|
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
|
// with-upx-pack for cli and micro
|
||||||
|
|||||||
@ -5,24 +5,35 @@ declare(strict_types=1);
|
|||||||
namespace SPC\builder\windows\library;
|
namespace SPC\builder\windows\library;
|
||||||
|
|
||||||
use SPC\builder\windows\SystemUtil;
|
use SPC\builder\windows\SystemUtil;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\BuildFailureException;
|
||||||
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
class libsodium extends WindowsLibraryBase
|
class libsodium extends WindowsLibraryBase
|
||||||
{
|
{
|
||||||
public const NAME = 'libsodium';
|
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');
|
$this->vs_ver_dir = match ($ver = SystemUtil::findVisualStudio()['version']) {
|
||||||
$vs_ver_dir = match (SystemUtil::findVisualStudio()['version']) {
|
|
||||||
'vs17' => '\vs2022',
|
'vs17' => '\vs2022',
|
||||||
'vs16' => '\vs2019',
|
'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
|
// start build
|
||||||
cmd()->cd($this->source_dir . '\builds\msvc\\' . $vs_ver_dir)
|
cmd()->cd($this->source_dir . '\builds\msvc' . $this->vs_ver_dir)
|
||||||
->execWithWrapper(
|
->execWithWrapper(
|
||||||
$this->builder->makeSimpleWrapper('msbuild'),
|
$this->builder->makeSimpleWrapper('msbuild'),
|
||||||
'libsodium.sln /t:Rebuild /p:Configuration=StaticRelease /p:Platform=x64 /p:PreprocessorDefinitions="SODIUM_STATIC=1"'
|
'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) {
|
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;
|
namespace SPC\builder\windows\library;
|
||||||
|
|
||||||
use SPC\builder\windows\SystemUtil;
|
use SPC\builder\windows\SystemUtil;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
class openssl extends WindowsLibraryBase
|
class openssl extends WindowsLibraryBase
|
||||||
{
|
{
|
||||||
public const NAME = 'openssl';
|
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
|
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)
|
cmd()->cd($this->source_dir)
|
||||||
->execWithWrapper(
|
->execWithWrapper(
|
||||||
$this->builder->makeSimpleWrapper($perl),
|
$this->builder->makeSimpleWrapper($this->perl),
|
||||||
'Configure zlib VC-WIN64A ' .
|
'Configure zlib VC-WIN64A ' .
|
||||||
'no-shared ' .
|
'no-shared ' .
|
||||||
'--prefix=' . quote(BUILD_ROOT_PATH) . ' ' .
|
'--prefix=' . quote(BUILD_ROOT_PATH) . ' ' .
|
||||||
|
|||||||
@ -9,10 +9,6 @@ use SPC\doctor\AsCheckItem;
|
|||||||
use SPC\doctor\AsFixItem;
|
use SPC\doctor\AsFixItem;
|
||||||
use SPC\doctor\CheckResult;
|
use SPC\doctor\CheckResult;
|
||||||
use SPC\doctor\OptionalCheck;
|
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\Downloader;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\store\PackageManager;
|
use SPC\store\PackageManager;
|
||||||
@ -58,55 +54,47 @@ class LinuxMuslCheck
|
|||||||
#[AsFixItem('fix-musl-wrapper')]
|
#[AsFixItem('fix-musl-wrapper')]
|
||||||
public function fixMusl(): bool
|
public function fixMusl(): bool
|
||||||
{
|
{
|
||||||
try {
|
$prefix = '';
|
||||||
$prefix = '';
|
if (get_current_user() !== 'root') {
|
||||||
if (get_current_user() !== 'root') {
|
$prefix = 'sudo ';
|
||||||
$prefix = 'sudo ';
|
logger()->warning('Current user is not root, using sudo for running command');
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
// 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')]
|
#[AsFixItem('fix-musl-cross-make')]
|
||||||
public function fixMuslCrossMake(): bool
|
public function fixMuslCrossMake(): bool
|
||||||
{
|
{
|
||||||
try {
|
$prefix = '';
|
||||||
$prefix = '';
|
if (get_current_user() !== 'root') {
|
||||||
if (get_current_user() !== 'root') {
|
$prefix = 'sudo ';
|
||||||
$prefix = 'sudo ';
|
logger()->warning('Current user is not root, using sudo for running command');
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
$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\AsCheckItem;
|
||||||
use SPC\doctor\AsFixItem;
|
use SPC\doctor\AsFixItem;
|
||||||
use SPC\doctor\CheckResult;
|
use SPC\doctor\CheckResult;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\EnvironmentException;
|
||||||
|
|
||||||
class LinuxToolCheckList
|
class LinuxToolCheckList
|
||||||
{
|
{
|
||||||
@ -74,16 +74,7 @@ class LinuxToolCheckList
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!empty($missing)) {
|
if (!empty($missing)) {
|
||||||
return match ($distro['dist']) {
|
return CheckResult::fail(implode(', ', $missing) . ' not installed on your system', 'install-linux-tools', [$distro, $missing]);
|
||||||
'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::ok();
|
return CheckResult::ok();
|
||||||
}
|
}
|
||||||
@ -123,22 +114,23 @@ class LinuxToolCheckList
|
|||||||
'redhat' => 'dnf install -y',
|
'redhat' => 'dnf install -y',
|
||||||
'centos' => 'yum install -y',
|
'centos' => 'yum install -y',
|
||||||
'arch' => 'pacman -S --noconfirm',
|
'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 = '';
|
$prefix = '';
|
||||||
if (($user = exec('whoami')) !== 'root') {
|
if (($user = exec('whoami')) !== 'root') {
|
||||||
$prefix = 'sudo ';
|
$prefix = 'sudo ';
|
||||||
logger()->warning('Current user (' . $user . ') is not root, using sudo for running command');
|
logger()->warning('Current user (' . $user . ') is not root, using sudo for running command (may require password input)');
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use SPC\builder\traits\UnixSystemUtilTrait;
|
|||||||
use SPC\doctor\AsCheckItem;
|
use SPC\doctor\AsCheckItem;
|
||||||
use SPC\doctor\AsFixItem;
|
use SPC\doctor\AsFixItem;
|
||||||
use SPC\doctor\CheckResult;
|
use SPC\doctor\CheckResult;
|
||||||
use SPC\exception\RuntimeException;
|
|
||||||
|
|
||||||
class MacOSToolCheckList
|
class MacOSToolCheckList
|
||||||
{
|
{
|
||||||
@ -89,11 +88,7 @@ class MacOSToolCheckList
|
|||||||
#[AsFixItem('brew')]
|
#[AsFixItem('brew')]
|
||||||
public function fixBrew(): bool
|
public function fixBrew(): bool
|
||||||
{
|
{
|
||||||
try {
|
shell(true)->exec('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
|
||||||
shell(true)->exec('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
|
|
||||||
} catch (RuntimeException) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,14 +99,10 @@ class MacOSToolCheckList
|
|||||||
'glibtoolize' => 'libtool',
|
'glibtoolize' => 'libtool',
|
||||||
];
|
];
|
||||||
foreach ($missing as $cmd) {
|
foreach ($missing as $cmd) {
|
||||||
try {
|
if (isset($replacement[$cmd])) {
|
||||||
if (isset($replacement[$cmd])) {
|
$cmd = $replacement[$cmd];
|
||||||
$cmd = $replacement[$cmd];
|
|
||||||
}
|
|
||||||
shell(true)->exec('brew install --formula ' . escapeshellarg($cmd));
|
|
||||||
} catch (RuntimeException) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
shell(true)->exec('brew install --formula ' . escapeshellarg($cmd));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use SPC\builder\windows\SystemUtil;
|
|||||||
use SPC\doctor\AsCheckItem;
|
use SPC\doctor\AsCheckItem;
|
||||||
use SPC\doctor\AsFixItem;
|
use SPC\doctor\AsFixItem;
|
||||||
use SPC\doctor\CheckResult;
|
use SPC\doctor\CheckResult;
|
||||||
use SPC\exception\RuntimeException;
|
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\store\PackageManager;
|
use SPC\store\PackageManager;
|
||||||
|
|
||||||
@ -80,12 +79,8 @@ class WindowsToolCheckList
|
|||||||
#[AsFixItem('install-php-sdk')]
|
#[AsFixItem('install-php-sdk')]
|
||||||
public function installPhpSdk(): bool
|
public function installPhpSdk(): bool
|
||||||
{
|
{
|
||||||
try {
|
FileSystem::removeDir(getenv('PHP_SDK_PATH'));
|
||||||
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'));
|
||||||
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;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace SPC\store;
|
namespace SPC\store;
|
||||||
|
|
||||||
use SPC\exception\DownloaderException;
|
use SPC\exception\DownloaderException;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\InterruptException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCException;
|
||||||
use SPC\exception\WrongUsageException;
|
|
||||||
use SPC\store\pkg\CustomPackage;
|
use SPC\store\pkg\CustomPackage;
|
||||||
use SPC\store\source\CustomSourceBase;
|
use SPC\store\source\CustomSourceBase;
|
||||||
use SPC\util\SPCTarget;
|
use SPC\util\SPCTarget;
|
||||||
@ -201,9 +200,9 @@ class Downloader
|
|||||||
unlink(FileSystem::convertPath(DOWNLOAD_PATH . '/' . $filename));
|
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::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}");
|
logger()->debug("Locking {$filename}");
|
||||||
if ($download_as === SPC_DOWNLOAD_PRE_BUILT) {
|
if ($download_as === SPC_DOWNLOAD_PRE_BUILT) {
|
||||||
$name = self::getPreBuiltLockName($name);
|
$name = self::getPreBuiltLockName($name);
|
||||||
@ -248,12 +247,12 @@ class Downloader
|
|||||||
f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule));
|
f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RuntimeException $e) {
|
} catch (SPCException $e) {
|
||||||
if (is_dir($download_path)) {
|
if (is_dir($download_path)) {
|
||||||
FileSystem::removeDir($download_path);
|
FileSystem::removeDir($download_path);
|
||||||
}
|
}
|
||||||
if ($e->getCode() === 2 || $e->getCode() === -1073741510) {
|
if ($e->getCode() === 2 || $e->getCode() === -1073741510) {
|
||||||
throw new WrongUsageException('Keyboard interrupted, download failed !');
|
throw new InterruptException('Keyboard interrupted, download failed !');
|
||||||
}
|
}
|
||||||
if ($retries > 0) {
|
if ($retries > 0) {
|
||||||
self::downloadGit($name, $url, $branch, $submodules, $move_path, $retries - 1, $lock_as);
|
self::downloadGit($name, $url, $branch, $submodules, $move_path, $retries - 1, $lock_as);
|
||||||
@ -385,7 +384,7 @@ class Downloader
|
|||||||
default:
|
default:
|
||||||
throw new DownloaderException('unknown source type: ' . $pkg['type']);
|
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.
|
// 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.
|
// Here we need to manually delete the file if it is detected to exist.
|
||||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||||
@ -503,7 +502,7 @@ class Downloader
|
|||||||
default:
|
default:
|
||||||
throw new DownloaderException('unknown source type: ' . $source['type']);
|
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.
|
// 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.
|
// Here we need to manually delete the file if it is detected to exist.
|
||||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||||
@ -551,7 +550,7 @@ class Downloader
|
|||||||
}
|
}
|
||||||
f_exec($cmd, $output, $ret);
|
f_exec($cmd, $output, $ret);
|
||||||
if ($ret === 2 || $ret === -1073741510) {
|
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) {
|
if ($ret !== 0) {
|
||||||
throw new DownloaderException(sprintf('Failed to fetch "%s"', $url));
|
throw new DownloaderException(sprintf('Failed to fetch "%s"', $url));
|
||||||
@ -563,7 +562,7 @@ class Downloader
|
|||||||
}
|
}
|
||||||
f_exec($cmd, $output, $ret);
|
f_exec($cmd, $output, $ret);
|
||||||
if ($ret === 2 || $ret === -1073741510) {
|
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) {
|
if ($ret !== 0) {
|
||||||
throw new DownloaderException(sprintf('Failed to fetch "%s"', $url));
|
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}\"";
|
$cmd = SPC_CURL_EXEC . " -{$check}fSL {$retry} -o \"{$path}\" {$methodArg} {$headerArg} \"{$url}\"";
|
||||||
try {
|
try {
|
||||||
f_passthru($cmd);
|
f_passthru($cmd);
|
||||||
} catch (RuntimeException $e) {
|
} catch (\Throwable $e) {
|
||||||
if ($e->getCode() === 2 || $e->getCode() === -1073741510) {
|
if ($e->getCode() === 2 || $e->getCode() === -1073741510) {
|
||||||
throw new WrongUsageException('Keyboard interrupted, download failed !');
|
throw new InterruptException('Keyboard interrupted, download failed !');
|
||||||
}
|
}
|
||||||
throw $e;
|
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";
|
$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);
|
$json = json_decode(Downloader::curlExec(url: $url, retries: intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0)), true);
|
||||||
if (!is_array($json)) {
|
if (!is_array($json)) {
|
||||||
throw new RuntimeException('failed http fetch');
|
throw new DownloaderException('failed http fetch');
|
||||||
}
|
}
|
||||||
$item = $json[0] ?? null;
|
$item = $json[0] ?? null;
|
||||||
if ($item === 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'];
|
$full_url = 'https://dl.static-php.dev' . $item['full_path'];
|
||||||
$filename = basename($item['full_path']);
|
$filename = basename($item['full_path']);
|
||||||
|
|||||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace SPC\store;
|
namespace SPC\store;
|
||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCException;
|
||||||
|
|
||||||
class FileSystem
|
class FileSystem
|
||||||
{
|
{
|
||||||
@ -147,6 +147,7 @@ class FileSystem
|
|||||||
*/
|
*/
|
||||||
public static function copyDir(string $from, string $to): void
|
public static function copyDir(string $from, string $to): void
|
||||||
{
|
{
|
||||||
|
logger()->debug("Copying directory from {$from} to {$to}");
|
||||||
$dst_path = FileSystem::convertPath($to);
|
$dst_path = FileSystem::convertPath($to);
|
||||||
$src_path = FileSystem::convertPath($from);
|
$src_path = FileSystem::convertPath($from);
|
||||||
switch (PHP_OS_FAMILY) {
|
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
|
* Extract package archive to specified directory
|
||||||
*
|
*
|
||||||
@ -187,13 +205,13 @@ class FileSystem
|
|||||||
try {
|
try {
|
||||||
// extract wrapper command
|
// extract wrapper command
|
||||||
self::extractWithType($source_type, $filename, $extract_path);
|
self::extractWithType($source_type, $filename, $extract_path);
|
||||||
} catch (RuntimeException $e) {
|
} catch (SPCException $e) {
|
||||||
if (PHP_OS_FAMILY === 'Windows') {
|
if (PHP_OS_FAMILY === 'Windows') {
|
||||||
f_passthru('rmdir /s /q ' . $target);
|
f_passthru('rmdir /s /q ' . $target);
|
||||||
} else {
|
} else {
|
||||||
f_passthru('rm -rf ' . $target);
|
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 {
|
try {
|
||||||
self::extractWithType($source_type, $filename, $move_path);
|
self::extractWithType($source_type, $filename, $move_path);
|
||||||
self::emitSourceExtractHook($name, $target);
|
self::emitSourceExtractHook($name, $target);
|
||||||
} catch (RuntimeException $e) {
|
} catch (SPCException $e) {
|
||||||
if (PHP_OS_FAMILY === 'Windows') {
|
if (PHP_OS_FAMILY === 'Windows') {
|
||||||
f_passthru('rmdir /s /q ' . $target);
|
f_passthru('rmdir /s /q ' . $target);
|
||||||
} else {
|
} else {
|
||||||
@ -505,7 +523,7 @@ class FileSystem
|
|||||||
public static function restoreBackupFile(string $path): void
|
public static function restoreBackupFile(string $path): void
|
||||||
{
|
{
|
||||||
if (!file_exists($path . '.bak')) {
|
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);
|
copy($path . '.bak', $path);
|
||||||
unlink($path . '.bak');
|
unlink($path . '.bak');
|
||||||
|
|||||||
@ -4,8 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\store;
|
namespace SPC\store;
|
||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\exception\RuntimeException;
|
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
|
|
||||||
class LockFile
|
class LockFile
|
||||||
@ -128,10 +127,10 @@ class LockFile
|
|||||||
SPC_SOURCE_ARCHIVE => sha1_file(DOWNLOAD_PATH . '/' . $lock_options['filename']),
|
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_GIT => exec('cd ' . escapeshellarg(DOWNLOAD_PATH . '/' . $lock_options['dirname']) . ' && ' . SPC_GIT_EXEC . ' rev-parse HEAD'),
|
||||||
SPC_SOURCE_LOCAL => 'LOCAL HASH IS ALWAYS DIFFERENT',
|
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)) {
|
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 ?: '';
|
return $result ?: '';
|
||||||
}
|
}
|
||||||
@ -182,7 +181,7 @@ class LockFile
|
|||||||
$file_content = file_get_contents(self::LOCK_FILE);
|
$file_content = file_get_contents(self::LOCK_FILE);
|
||||||
self::$lock_file_content = json_decode($file_content, true);
|
self::$lock_file_content = json_decode($file_content, true);
|
||||||
if (self::$lock_file_content === null) {
|
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\unix\UnixBuilderBase;
|
||||||
use SPC\builder\windows\WindowsBuilder;
|
use SPC\builder\windows\WindowsBuilder;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\PatchException;
|
||||||
use SPC\exception\WrongUsageException;
|
|
||||||
use SPC\util\SPCTarget;
|
use SPC\util\SPCTarget;
|
||||||
|
|
||||||
class SourcePatcher
|
class SourcePatcher
|
||||||
@ -171,7 +170,7 @@ class SourcePatcher
|
|||||||
$patches[] = "sapi/micro/patches/{$patchName}_{$tryMajMin}.patch";
|
$patches[] = "sapi/micro/patches/{$patchName}_{$tryMajMin}.patch";
|
||||||
continue 2;
|
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) {
|
foreach ($patches as $patch) {
|
||||||
@ -202,7 +201,7 @@ class SourcePatcher
|
|||||||
|
|
||||||
$patch_str = FileSystem::convertPath($patch_file);
|
$patch_str = FileSystem::convertPath($patch_file);
|
||||||
if (!file_exists($patch_str)) {
|
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
|
// Copy patch from phar
|
||||||
@ -524,7 +523,7 @@ class SourcePatcher
|
|||||||
++$line_num;
|
++$line_num;
|
||||||
}
|
}
|
||||||
if ($found === false) {
|
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] = '$(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';
|
$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;
|
namespace SPC\store\pkg;
|
||||||
|
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\DownloaderException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\CurlHook;
|
use SPC\store\CurlHook;
|
||||||
use SPC\store\Downloader;
|
use SPC\store\Downloader;
|
||||||
@ -77,14 +77,14 @@ class Zig extends CustomPackage
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$latest_version) {
|
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}");
|
logger()->info("Installing Zig version {$latest_version}");
|
||||||
|
|
||||||
$platform_key = "{$zig_arch}-{$zig_os}";
|
$platform_key = "{$zig_arch}-{$zig_os}";
|
||||||
if (!isset($index_json[$latest_version][$platform_key])) {
|
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];
|
$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\freebsd\SystemUtil as FreeBSDSystemUtil;
|
||||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\GlobalEnvManager;
|
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."),
|
'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."),
|
'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."),
|
'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\freebsd\SystemUtil as FreeBSDSystemUtil;
|
||||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||||
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\GlobalEnvManager;
|
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."),
|
'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."),
|
'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."),
|
'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;
|
namespace SPC\toolchain;
|
||||||
|
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\util\GlobalEnvManager;
|
use SPC\util\GlobalEnvManager;
|
||||||
|
|
||||||
class MuslToolchain implements ToolchainInterface
|
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}");
|
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")) {
|
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;
|
namespace SPC\toolchain;
|
||||||
|
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\store\pkg\Zig;
|
use SPC\store\pkg\Zig;
|
||||||
use SPC\util\GlobalEnvManager;
|
use SPC\util\GlobalEnvManager;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class ZigToolchain implements ToolchainInterface
|
|||||||
public function afterInit(): void
|
public function afterInit(): void
|
||||||
{
|
{
|
||||||
if (!is_dir(Zig::getEnvironment()['PATH'])) {
|
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']);
|
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
|
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;
|
namespace SPC\util;
|
||||||
|
|
||||||
use SPC\builder\macos\SystemUtil;
|
use SPC\builder\macos\SystemUtil;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\toolchain\ToolchainManager;
|
use SPC\toolchain\ToolchainManager;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ class GlobalEnvManager
|
|||||||
}
|
}
|
||||||
// Check pre-defined env vars exists
|
// Check pre-defined env vars exists
|
||||||
if (getenv('BUILD_ROOT_PATH') === false) {
|
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
|
// Define env vars for unix
|
||||||
|
|||||||
@ -4,9 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\util;
|
namespace SPC\util;
|
||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\exception\RuntimeException;
|
|
||||||
use SPC\exception\WrongUsageException;
|
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
@ -100,7 +98,7 @@ class LicenseDumper
|
|||||||
{
|
{
|
||||||
$licenses = Config::getSource($source_name)['license'] ?? [];
|
$licenses = Config::getSource($source_name)['license'] ?? [];
|
||||||
if ($licenses === []) {
|
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)) {
|
if (!array_is_list($licenses)) {
|
||||||
@ -111,7 +109,7 @@ class LicenseDumper
|
|||||||
yield $index => match ($license['type']) {
|
yield $index => match ($license['type']) {
|
||||||
'text' => $license['text'],
|
'text' => $license['text'],
|
||||||
'file' => $this->loadSourceFile($source_name, $index, $license['path'], Config::getSource($source_name)['path'] ?? null),
|
'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
|
private function loadSourceFile(string $source_name, int $index, null|array|string $in_path, ?string $custom_base_path = null): string
|
||||||
{
|
{
|
||||||
if (is_null($in_path)) {
|
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)) {
|
if (!is_array($in_path)) {
|
||||||
@ -139,6 +137,6 @@ class LicenseDumper
|
|||||||
return file_get_contents(BUILD_ROOT_PATH . '/source-licenses/' . $source_name . '/' . $index . '.txt');
|
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;
|
namespace SPC\util;
|
||||||
|
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for pkg-config operations
|
* Utility class for pkg-config operations
|
||||||
@ -95,7 +95,7 @@ class PkgConfigUtil
|
|||||||
{
|
{
|
||||||
f_exec($cmd, $output, $result_code);
|
f_exec($cmd, $output, $result_code);
|
||||||
if ($result_code !== 0) {
|
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);
|
return implode("\n", $output);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,7 @@ namespace SPC\Tests\globals;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Log\LogLevel;
|
use Psr\Log\LogLevel;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ExecutionException;
|
||||||
use SPC\exception\WrongUsageException;
|
|
||||||
use ZM\Logger\ConsoleLogger;
|
use ZM\Logger\ConsoleLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +63,7 @@ class GlobalFunctionsTest extends TestCase
|
|||||||
$this->markTestSkipped('Windows not support f_passthru');
|
$this->markTestSkipped('Windows not support f_passthru');
|
||||||
}
|
}
|
||||||
$this->assertEquals(null, f_passthru('echo ""'));
|
$this->assertEquals(null, f_passthru('echo ""'));
|
||||||
$this->expectException('SPC\exception\RuntimeException');
|
$this->expectException(ExecutionException::class);
|
||||||
f_passthru('false');
|
f_passthru('false');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,16 +79,16 @@ class GlobalFunctionsTest extends TestCase
|
|||||||
$this->markTestSkipped('Windows not support shell');
|
$this->markTestSkipped('Windows not support shell');
|
||||||
}
|
}
|
||||||
$shell = shell();
|
$shell = shell();
|
||||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell);
|
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell);
|
||||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell->cd('/'));
|
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell->cd('/'));
|
||||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell->exec('echo ""'));
|
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell->exec('echo ""'));
|
||||||
$this->assertInstanceOf('SPC\util\UnixShell', $shell->setEnv(['SPC_TEST_ENV' => '1']));
|
$this->assertInstanceOf('SPC\util\shell\UnixShell', $shell->setEnv(['SPC_TEST_ENV' => '1']));
|
||||||
|
|
||||||
[$code, $out] = $shell->execWithResult('echo "_"');
|
[$code, $out] = $shell->execWithResult('echo "_"');
|
||||||
$this->assertEquals(0, $code);
|
$this->assertEquals(0, $code);
|
||||||
$this->assertEquals('_', implode('', $out));
|
$this->assertEquals('_', implode('', $out));
|
||||||
|
|
||||||
$this->expectException('SPC\exception\RuntimeException');
|
$this->expectException('SPC\exception\ExecutionException');
|
||||||
$shell->exec('false');
|
$shell->exec('false');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace SPC\Tests\store;
|
namespace SPC\Tests\store;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\InterruptException;
|
||||||
use SPC\store\Downloader;
|
use SPC\store\Downloader;
|
||||||
use SPC\store\LockFile;
|
use SPC\store\LockFile;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class DownloaderTest extends TestCase
|
|||||||
// test keyboard interrupt
|
// test keyboard interrupt
|
||||||
try {
|
try {
|
||||||
Downloader::downloadGit('setup-static-php', 'https://github.com/static-php/setup-static-php.git', 'SIGINT');
|
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());
|
$this->assertStringContainsString('interrupted', $e->getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ class DownloaderTest extends TestCase
|
|||||||
// test keyboard interrupt
|
// test keyboard interrupt
|
||||||
try {
|
try {
|
||||||
Downloader::downloadFile('fake-file', 'https://fakecmd.com/curlDown', 'SIGINT');
|
Downloader::downloadFile('fake-file', 'https://fakecmd.com/curlDown', 'SIGINT');
|
||||||
} catch (WrongUsageException $e) {
|
} catch (InterruptException $e) {
|
||||||
$this->assertStringContainsString('interrupted', $e->getMessage());
|
$this->assertStringContainsString('interrupted', $e->getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace SPC\Tests\util;
|
namespace SPC\Tests\util;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\SPCInternalException;
|
||||||
use SPC\util\GlobalEnvManager;
|
use SPC\util\GlobalEnvManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,7 +105,7 @@ final class GlobalEnvManagerTest extends TestCase
|
|||||||
// Temporarily unset BUILD_ROOT_PATH
|
// Temporarily unset BUILD_ROOT_PATH
|
||||||
putenv('BUILD_ROOT_PATH');
|
putenv('BUILD_ROOT_PATH');
|
||||||
|
|
||||||
$this->expectException(RuntimeException::class);
|
$this->expectException(SPCInternalException::class);
|
||||||
GlobalEnvManager::init();
|
GlobalEnvManager::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace SPC\Tests\util;
|
namespace SPC\Tests\util;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\ExecutionException;
|
||||||
use SPC\util\PkgConfigUtil;
|
use SPC\util\PkgConfigUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,7 +75,7 @@ final class PkgConfigUtilTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetCflagsWithInvalidPackage(string $package): void
|
public function testGetCflagsWithInvalidPackage(string $package): void
|
||||||
{
|
{
|
||||||
$this->expectException(RuntimeException::class);
|
$this->expectException(ExecutionException::class);
|
||||||
PkgConfigUtil::getCflags($package);
|
PkgConfigUtil::getCflags($package);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ final class PkgConfigUtilTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetLibsArrayWithInvalidPackage(string $package): void
|
public function testGetLibsArrayWithInvalidPackage(string $package): void
|
||||||
{
|
{
|
||||||
$this->expectException(RuntimeException::class);
|
$this->expectException(ExecutionException::class);
|
||||||
PkgConfigUtil::getLibsArray($package);
|
PkgConfigUtil::getLibsArray($package);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\store;
|
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
|
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_starts_with($cmd, 'git')) {
|
||||||
if (str_contains($cmd, '--branch "SIGINT"')) {
|
if (str_contains($cmd, '--branch "SIGINT"')) {
|
||||||
throw new RuntimeException('Interrupt', 2);
|
throw new InterruptException('interrupted', 2);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (str_contains($cmd, 'https://fakecmd.com/curlDown')) {
|
if (str_contains($cmd, 'https://fakecmd.com/curlDown')) {
|
||||||
if (str_contains($cmd, 'SIGINT')) {
|
if (str_contains($cmd, 'SIGINT')) {
|
||||||
throw new RuntimeException('Interrupt', 2);
|
throw new InterruptException('interrupted', 2);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -71,5 +72,5 @@ function f_passthru(string $cmd): bool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException('Invalid tests');
|
throw new SPCInternalException('Invalid tests');
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user