mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-17 20:34:51 +08:00
Add package outputs, colorize motd
This commit is contained in:
parent
ac01867e9c
commit
b0f630f95f
@ -45,7 +45,7 @@ use ZM\Logger\ConsoleColor;
|
||||
#[Target('php-cgi')]
|
||||
#[Target('php-embed')]
|
||||
#[Target('frankenphp')]
|
||||
class php
|
||||
class php extends TargetPackage
|
||||
{
|
||||
public static function getPHPVersionID(): int
|
||||
{
|
||||
@ -350,6 +350,9 @@ class php
|
||||
shell()->cd($package->getSourceDir())
|
||||
->setEnv($this->makeVars($installer))
|
||||
->exec("make -j{$concurrency} cli");
|
||||
|
||||
$builder->deployBinary("{$package->getSourceDir()}/sapi/cli/php", BUILD_BIN_PATH . '/php');
|
||||
$package->setOutput('Binary path for cli SAPI', BUILD_BIN_PATH . '/php');
|
||||
}
|
||||
|
||||
#[Stage]
|
||||
@ -360,6 +363,9 @@ class php
|
||||
shell()->cd($package->getSourceDir())
|
||||
->setEnv($this->makeVars($installer))
|
||||
->exec("make -j{$concurrency} cgi");
|
||||
|
||||
$builder->deployBinary("{$package->getSourceDir()}/sapi/cgi/php-cgi", BUILD_BIN_PATH . '/php-cgi');
|
||||
$package->setOutput('Binary path for cgi SAPI', BUILD_BIN_PATH . '/php-cgi');
|
||||
}
|
||||
|
||||
#[Stage]
|
||||
@ -370,6 +376,9 @@ class php
|
||||
shell()->cd($package->getSourceDir())
|
||||
->setEnv($this->makeVars($installer))
|
||||
->exec("make -j{$concurrency} fpm");
|
||||
|
||||
$builder->deployBinary("{$package->getSourceDir()}/sapi/fpm/php-fpm", BUILD_BIN_PATH . '/php-fpm');
|
||||
$package->setOutput('Binary path for fpm SAPI', BUILD_BIN_PATH . '/php-fpm');
|
||||
}
|
||||
|
||||
#[Stage]
|
||||
@ -392,6 +401,7 @@ class php
|
||||
->exec("make -j{$builder->concurrency} micro");
|
||||
|
||||
$builder->deployBinary($package->getSourceDir() . '/sapi/micro/micro.sfx', BUILD_BIN_PATH . '/micro.sfx');
|
||||
$package->setOutput('Binary path for micro SAPI', BUILD_BIN_PATH . '/micro.sfx');
|
||||
} finally {
|
||||
if ($phar_patched) {
|
||||
SourcePatcher::unpatchMicroPhar();
|
||||
@ -432,12 +442,17 @@ class php
|
||||
}
|
||||
// deploy
|
||||
$builder->deployBinary($libphp_so, $libphp_so, false);
|
||||
$package->setOutput('Library path for embed SAPI', $libphp_so);
|
||||
}
|
||||
|
||||
// process shared extensions that built-with-php
|
||||
$increment_files = $diff->getChangedFiles();
|
||||
foreach ($increment_files as $increment_file) {
|
||||
$builder->deployBinary($increment_file, $increment_file, false);
|
||||
$files[] = basename($increment_file);
|
||||
}
|
||||
if (!empty($files)) {
|
||||
$package->setOutput('Built shared extensions', implode(', ', $files));
|
||||
}
|
||||
|
||||
// ------------- SPC_CMD_VAR_PHP_EMBED_TYPE=static -------------
|
||||
@ -524,6 +539,7 @@ class php
|
||||
logger()->debug('Patching phpize prefix');
|
||||
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'");
|
||||
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#');
|
||||
$this->setOutput('phpize script path for embed SAPI', BUILD_BIN_PATH . '/phpize');
|
||||
}
|
||||
// patch php-config
|
||||
if (file_exists(BUILD_BIN_PATH . '/php-config')) {
|
||||
@ -535,6 +551,7 @@ class php
|
||||
// move lstdc++ to the end of libs
|
||||
$php_config_str = preg_replace('/(libs=")(.*?)\s*(-lstdc\+\+)\s*(.*?)"/', '$1$2 $4 $3"', $php_config_str);
|
||||
FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str);
|
||||
$this->setOutput('php-config script path for embed SAPI', BUILD_BIN_PATH . '/php-config');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace StaticPHP\Attribute\Package;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
readonly class PatchBeforeBuild
|
||||
{
|
||||
public function __construct() {}
|
||||
}
|
||||
@ -10,6 +10,7 @@ use StaticPHP\Exception\SPCException;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use ZM\Logger\ConsoleColor;
|
||||
|
||||
abstract class BaseCommand extends Command
|
||||
{
|
||||
@ -21,7 +22,7 @@ abstract class BaseCommand extends Command
|
||||
/ ___|| |_ __ _| |_(_) ___| _ \| | | | _ \
|
||||
\___ \| __/ _` | __| |/ __| |_) | |_| | |_) |
|
||||
___) | || (_| | |_| | (__| __/| _ | __/
|
||||
|____/ \__\__,_|\__|_|\___|_| |_| |_|_| v{version}
|
||||
|____/ \__\__,_|\__|_|\___|_| |_| |_|_| {version}
|
||||
|
||||
';
|
||||
|
||||
@ -69,7 +70,7 @@ abstract class BaseCommand extends Command
|
||||
});
|
||||
$version = $this->getVersionWithCommit();
|
||||
if (!$this->no_motd) {
|
||||
echo str_replace('{version}', $version, self::$motd);
|
||||
echo str_replace('{version}', '' . ConsoleColor::none("v{$version}"), '' . ConsoleColor::magenta(self::$motd));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -51,6 +51,8 @@ class BuildTargetCommand extends BaseCommand
|
||||
$this->output->writeln("<info>✔ BUILD SUCCESSFUL ({$usedtime} s)</info>");
|
||||
$this->output->writeln("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
$installer->printBuildPackageOutputs();
|
||||
|
||||
return static::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,10 @@ class CallbackInvoker
|
||||
* 4. Default value
|
||||
* 5. Null (if nullable)
|
||||
*
|
||||
* Note: For object values in context, the invoker automatically registers
|
||||
* the object under all its parent classes and interfaces, allowing type hints
|
||||
* to match any type in the inheritance hierarchy.
|
||||
*
|
||||
* @param callable $callback The callback to invoke
|
||||
* @param array $context Context parameters (type => value or name => value)
|
||||
*
|
||||
@ -35,6 +39,9 @@ class CallbackInvoker
|
||||
*/
|
||||
public function invoke(callable $callback, array $context = []): mixed
|
||||
{
|
||||
// Expand context to include all parent classes and interfaces for objects
|
||||
$context = $this->expandContextHierarchy($context);
|
||||
|
||||
$reflection = new \ReflectionFunction(\Closure::fromCallable($callback));
|
||||
$args = [];
|
||||
|
||||
@ -95,4 +102,43 @@ class CallbackInvoker
|
||||
'void', 'null', 'false', 'true', 'never',
|
||||
], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand context to include all parent classes and interfaces for object values.
|
||||
* This allows type hints to match any type in the object's inheritance hierarchy.
|
||||
*
|
||||
* @param array $context Original context array
|
||||
* @return array Expanded context with all class hierarchy mappings
|
||||
*/
|
||||
private function expandContextHierarchy(array $context): array
|
||||
{
|
||||
$expanded = [];
|
||||
|
||||
foreach ($context as $key => $value) {
|
||||
// Keep the original key-value pair
|
||||
$expanded[$key] = $value;
|
||||
|
||||
// If value is an object, add mappings for all parent classes and interfaces
|
||||
if (is_object($value)) {
|
||||
$reflection = new \ReflectionClass($value);
|
||||
|
||||
// Add concrete class
|
||||
$expanded[$reflection->getName()] = $value;
|
||||
|
||||
// Add all parent classes
|
||||
while ($parent = $reflection->getParentClass()) {
|
||||
$expanded[$parent->getName()] = $value;
|
||||
$reflection = $parent;
|
||||
}
|
||||
|
||||
// Add all interfaces
|
||||
$interfaces = (new \ReflectionClass($value))->getInterfaceNames();
|
||||
foreach ($interfaces as $interface) {
|
||||
$expanded[$interface] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $expanded;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,9 @@ abstract class Package
|
||||
/** @var array<string, callable> $build_functions Build functions for different OS binding */
|
||||
protected array $build_functions = [];
|
||||
|
||||
/** @var array<string, string> */
|
||||
protected array $outputs = [];
|
||||
|
||||
/**
|
||||
* @param string $name Name of the package
|
||||
* @param string $type Type of the package
|
||||
@ -69,6 +72,17 @@ abstract class Package
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function setOutput(string $key, string $value): static
|
||||
{
|
||||
$this->outputs[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOutputs(): array
|
||||
{
|
||||
return $this->outputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a build function for a specific platform.
|
||||
*
|
||||
|
||||
@ -104,6 +104,16 @@ class PackageInstaller
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function printBuildPackageOutputs(): void
|
||||
{
|
||||
foreach ($this->build_packages as $package) {
|
||||
if (($outputs = $package->getOutputs()) !== []) {
|
||||
InteractiveTerm::notice('Package ' . ConsoleColor::green($package->getName()) . ' outputs');
|
||||
$this->printArrayInfo(info: $outputs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the package installation process.
|
||||
*/
|
||||
|
||||
@ -12,7 +12,6 @@ use StaticPHP\Attribute\Package\Extension;
|
||||
use StaticPHP\Attribute\Package\Info;
|
||||
use StaticPHP\Attribute\Package\InitPackage;
|
||||
use StaticPHP\Attribute\Package\Library;
|
||||
use StaticPHP\Attribute\Package\PatchBeforeBuild;
|
||||
use StaticPHP\Attribute\Package\ResolveBuild;
|
||||
use StaticPHP\Attribute\Package\Stage;
|
||||
use StaticPHP\Attribute\Package\Target;
|
||||
@ -166,16 +165,14 @@ class PackageLoader
|
||||
if ($refClass->getParentClass() !== false) {
|
||||
if (is_a($class_name, Package::class, true)) {
|
||||
self::$packages[$attribute_instance->name] = new $class_name($attribute_instance->name, $package_type);
|
||||
$instance_class = self::$packages[$attribute_instance->name];
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($instance_class)) {
|
||||
$instance_class = $refClass->newInstance();
|
||||
}
|
||||
|
||||
$pkg = self::$packages[$attribute_instance->name];
|
||||
|
||||
// Use the package instance if it's a Package subclass, otherwise create a new instance
|
||||
$instance_class = is_a($class_name, Package::class, true) ? $pkg : $refClass->newInstance();
|
||||
|
||||
// validate package type matches
|
||||
$pkg_type_attr = match ($attribute->getName()) {
|
||||
Target::class => ['target', 'virtual-target'],
|
||||
@ -204,18 +201,13 @@ class PackageLoader
|
||||
// #[Stage('stage_name')]
|
||||
Stage::class => self::addStage($method, $pkg, $instance_class, $method_instance),
|
||||
// #[InitPackage] (run now with package context)
|
||||
InitPackage::class => ApplicationContext::invoke([$instance_class, $method->getName()], [
|
||||
Package::class => $pkg,
|
||||
$pkg::class => $pkg,
|
||||
]),
|
||||
InitPackage::class => ApplicationContext::invoke([$instance_class, $method->getName()], ['package' => $pkg]),
|
||||
// #[InitBuild]
|
||||
ResolveBuild::class => $pkg instanceof TargetPackage ? $pkg->setResolveBuildCallback([$instance_class, $method->getName()]) : null,
|
||||
// #[Info]
|
||||
Info::class => $pkg->setInfoCallback([$instance_class, $method->getName()]),
|
||||
// #[Validate]
|
||||
Validate::class => $pkg->setValidateCallback([$instance_class, $method->getName()]),
|
||||
// #[PatchBeforeBuild]
|
||||
PatchBeforeBuild::class => $pkg->setPatchBeforeBuildCallback([$instance_class, $method->getName()]),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
@ -224,6 +216,7 @@ class PackageLoader
|
||||
self::$packages[$pkg->getName()] = $pkg;
|
||||
}
|
||||
|
||||
// For classes without package attributes, create a simple instance for non-package stage callbacks
|
||||
if (!isset($instance_class)) {
|
||||
$instance_class = $refClass->newInstance();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user