Skip to content

Commit b0f630f

Browse files
committed
Add package outputs, colorize motd
1 parent ac01867 commit b0f630f

File tree

8 files changed

+98
-26
lines changed

8 files changed

+98
-26
lines changed

src/Package/Target/php.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#[Target('php-cgi')]
4646
#[Target('php-embed')]
4747
#[Target('frankenphp')]
48-
class php
48+
class php extends TargetPackage
4949
{
5050
public static function getPHPVersionID(): int
5151
{
@@ -350,6 +350,9 @@ public function makeCliForUnix(TargetPackage $package, PackageInstaller $install
350350
shell()->cd($package->getSourceDir())
351351
->setEnv($this->makeVars($installer))
352352
->exec("make -j{$concurrency} cli");
353+
354+
$builder->deployBinary("{$package->getSourceDir()}/sapi/cli/php", BUILD_BIN_PATH . '/php');
355+
$package->setOutput('Binary path for cli SAPI', BUILD_BIN_PATH . '/php');
353356
}
354357

355358
#[Stage]
@@ -360,6 +363,9 @@ public function makeCgiForUnix(TargetPackage $package, PackageInstaller $install
360363
shell()->cd($package->getSourceDir())
361364
->setEnv($this->makeVars($installer))
362365
->exec("make -j{$concurrency} cgi");
366+
367+
$builder->deployBinary("{$package->getSourceDir()}/sapi/cgi/php-cgi", BUILD_BIN_PATH . '/php-cgi');
368+
$package->setOutput('Binary path for cgi SAPI', BUILD_BIN_PATH . '/php-cgi');
363369
}
364370

365371
#[Stage]
@@ -370,6 +376,9 @@ public function makeFpmForUnix(TargetPackage $package, PackageInstaller $install
370376
shell()->cd($package->getSourceDir())
371377
->setEnv($this->makeVars($installer))
372378
->exec("make -j{$concurrency} fpm");
379+
380+
$builder->deployBinary("{$package->getSourceDir()}/sapi/fpm/php-fpm", BUILD_BIN_PATH . '/php-fpm');
381+
$package->setOutput('Binary path for fpm SAPI', BUILD_BIN_PATH . '/php-fpm');
373382
}
374383

375384
#[Stage]
@@ -392,6 +401,7 @@ public function makeMicroForUnix(TargetPackage $package, PackageInstaller $insta
392401
->exec("make -j{$builder->concurrency} micro");
393402

394403
$builder->deployBinary($package->getSourceDir() . '/sapi/micro/micro.sfx', BUILD_BIN_PATH . '/micro.sfx');
404+
$package->setOutput('Binary path for micro SAPI', BUILD_BIN_PATH . '/micro.sfx');
395405
} finally {
396406
if ($phar_patched) {
397407
SourcePatcher::unpatchMicroPhar();
@@ -432,12 +442,17 @@ public function makeEmbedForUnix(TargetPackage $package, PackageInstaller $insta
432442
}
433443
// deploy
434444
$builder->deployBinary($libphp_so, $libphp_so, false);
445+
$package->setOutput('Library path for embed SAPI', $libphp_so);
435446
}
436447

437448
// process shared extensions that built-with-php
438449
$increment_files = $diff->getChangedFiles();
439450
foreach ($increment_files as $increment_file) {
440451
$builder->deployBinary($increment_file, $increment_file, false);
452+
$files[] = basename($increment_file);
453+
}
454+
if (!empty($files)) {
455+
$package->setOutput('Built shared extensions', implode(', ', $files));
441456
}
442457

443458
// ------------- SPC_CMD_VAR_PHP_EMBED_TYPE=static -------------
@@ -524,6 +539,7 @@ public function patchEmbedScripts(): void
524539
logger()->debug('Patching phpize prefix');
525540
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'");
526541
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#');
542+
$this->setOutput('phpize script path for embed SAPI', BUILD_BIN_PATH . '/phpize');
527543
}
528544
// patch php-config
529545
if (file_exists(BUILD_BIN_PATH . '/php-config')) {
@@ -535,6 +551,7 @@ public function patchEmbedScripts(): void
535551
// move lstdc++ to the end of libs
536552
$php_config_str = preg_replace('/(libs=")(.*?)\s*(-lstdc\+\+)\s*(.*?)"/', '$1$2 $4 $3"', $php_config_str);
537553
FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str);
554+
$this->setOutput('php-config script path for embed SAPI', BUILD_BIN_PATH . '/php-config');
538555
}
539556
}
540557

src/StaticPHP/Attribute/Package/PatchBeforeBuild.php

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/StaticPHP/Command/BaseCommand.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Symfony\Component\Console\Command\Command;
1111
use Symfony\Component\Console\Input\InputInterface;
1212
use Symfony\Component\Console\Output\OutputInterface;
13+
use ZM\Logger\ConsoleColor;
1314

1415
abstract class BaseCommand extends Command
1516
{
@@ -21,7 +22,7 @@ abstract class BaseCommand extends Command
2122
/ ___|| |_ __ _| |_(_) ___| _ \| | | | _ \
2223
\___ \| __/ _` | __| |/ __| |_) | |_| | |_) |
2324
___) | || (_| | |_| | (__| __/| _ | __/
24-
|____/ \__\__,_|\__|_|\___|_| |_| |_|_| v{version}
25+
|____/ \__\__,_|\__|_|\___|_| |_| |_|_| {version}
2526
2627
';
2728

@@ -69,7 +70,7 @@ public function initialize(InputInterface $input, OutputInterface $output): void
6970
});
7071
$version = $this->getVersionWithCommit();
7172
if (!$this->no_motd) {
72-
echo str_replace('{version}', $version, self::$motd);
73+
echo str_replace('{version}', '' . ConsoleColor::none("v{$version}"), '' . ConsoleColor::magenta(self::$motd));
7374
}
7475
}
7576

src/StaticPHP/Command/BuildTargetCommand.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public function handle(): int
5151
$this->output->writeln("<info>✔ BUILD SUCCESSFUL ({$usedtime} s)</info>");
5252
$this->output->writeln("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
5353

54+
$installer->printBuildPackageOutputs();
55+
5456
return static::SUCCESS;
5557
}
5658
}

src/StaticPHP/DI/CallbackInvoker.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public function __construct(
2626
* 4. Default value
2727
* 5. Null (if nullable)
2828
*
29+
* Note: For object values in context, the invoker automatically registers
30+
* the object under all its parent classes and interfaces, allowing type hints
31+
* to match any type in the inheritance hierarchy.
32+
*
2933
* @param callable $callback The callback to invoke
3034
* @param array $context Context parameters (type => value or name => value)
3135
*
@@ -35,6 +39,9 @@ public function __construct(
3539
*/
3640
public function invoke(callable $callback, array $context = []): mixed
3741
{
42+
// Expand context to include all parent classes and interfaces for objects
43+
$context = $this->expandContextHierarchy($context);
44+
3845
$reflection = new \ReflectionFunction(\Closure::fromCallable($callback));
3946
$args = [];
4047

@@ -95,4 +102,43 @@ private function isBuiltinType(string $typeName): bool
95102
'void', 'null', 'false', 'true', 'never',
96103
], true);
97104
}
105+
106+
/**
107+
* Expand context to include all parent classes and interfaces for object values.
108+
* This allows type hints to match any type in the object's inheritance hierarchy.
109+
*
110+
* @param array $context Original context array
111+
* @return array Expanded context with all class hierarchy mappings
112+
*/
113+
private function expandContextHierarchy(array $context): array
114+
{
115+
$expanded = [];
116+
117+
foreach ($context as $key => $value) {
118+
// Keep the original key-value pair
119+
$expanded[$key] = $value;
120+
121+
// If value is an object, add mappings for all parent classes and interfaces
122+
if (is_object($value)) {
123+
$reflection = new \ReflectionClass($value);
124+
125+
// Add concrete class
126+
$expanded[$reflection->getName()] = $value;
127+
128+
// Add all parent classes
129+
while ($parent = $reflection->getParentClass()) {
130+
$expanded[$parent->getName()] = $value;
131+
$reflection = $parent;
132+
}
133+
134+
// Add all interfaces
135+
$interfaces = (new \ReflectionClass($value))->getInterfaceNames();
136+
foreach ($interfaces as $interface) {
137+
$expanded[$interface] = $value;
138+
}
139+
}
140+
}
141+
142+
return $expanded;
143+
}
98144
}

src/StaticPHP/Package/Package.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ abstract class Package
2323
/** @var array<string, callable> $build_functions Build functions for different OS binding */
2424
protected array $build_functions = [];
2525

26+
/** @var array<string, string> */
27+
protected array $outputs = [];
28+
2629
/**
2730
* @param string $name Name of the package
2831
* @param string $type Type of the package
@@ -69,6 +72,17 @@ public function runStage(mixed $name, array $context = []): mixed
6972
return $ret;
7073
}
7174

75+
public function setOutput(string $key, string $value): static
76+
{
77+
$this->outputs[$key] = $value;
78+
return $this;
79+
}
80+
81+
public function getOutputs(): array
82+
{
83+
return $this->outputs;
84+
}
85+
7286
/**
7387
* Add a build function for a specific platform.
7488
*

src/StaticPHP/Package/PackageInstaller.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ public function setDownload(bool $download = true): static
104104
return $this;
105105
}
106106

107+
public function printBuildPackageOutputs(): void
108+
{
109+
foreach ($this->build_packages as $package) {
110+
if (($outputs = $package->getOutputs()) !== []) {
111+
InteractiveTerm::notice('Package ' . ConsoleColor::green($package->getName()) . ' outputs');
112+
$this->printArrayInfo(info: $outputs);
113+
}
114+
}
115+
}
116+
107117
/**
108118
* Run the package installation process.
109119
*/

src/StaticPHP/Registry/PackageLoader.php

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use StaticPHP\Attribute\Package\Info;
1313
use StaticPHP\Attribute\Package\InitPackage;
1414
use StaticPHP\Attribute\Package\Library;
15-
use StaticPHP\Attribute\Package\PatchBeforeBuild;
1615
use StaticPHP\Attribute\Package\ResolveBuild;
1716
use StaticPHP\Attribute\Package\Stage;
1817
use StaticPHP\Attribute\Package\Target;
@@ -166,16 +165,14 @@ public static function loadFromClass(mixed $class): void
166165
if ($refClass->getParentClass() !== false) {
167166
if (is_a($class_name, Package::class, true)) {
168167
self::$packages[$attribute_instance->name] = new $class_name($attribute_instance->name, $package_type);
169-
$instance_class = self::$packages[$attribute_instance->name];
170168
}
171169
}
172170

173-
if (!isset($instance_class)) {
174-
$instance_class = $refClass->newInstance();
175-
}
176-
177171
$pkg = self::$packages[$attribute_instance->name];
178172

173+
// Use the package instance if it's a Package subclass, otherwise create a new instance
174+
$instance_class = is_a($class_name, Package::class, true) ? $pkg : $refClass->newInstance();
175+
179176
// validate package type matches
180177
$pkg_type_attr = match ($attribute->getName()) {
181178
Target::class => ['target', 'virtual-target'],
@@ -204,18 +201,13 @@ public static function loadFromClass(mixed $class): void
204201
// #[Stage('stage_name')]
205202
Stage::class => self::addStage($method, $pkg, $instance_class, $method_instance),
206203
// #[InitPackage] (run now with package context)
207-
InitPackage::class => ApplicationContext::invoke([$instance_class, $method->getName()], [
208-
Package::class => $pkg,
209-
$pkg::class => $pkg,
210-
]),
204+
InitPackage::class => ApplicationContext::invoke([$instance_class, $method->getName()], ['package' => $pkg]),
211205
// #[InitBuild]
212206
ResolveBuild::class => $pkg instanceof TargetPackage ? $pkg->setResolveBuildCallback([$instance_class, $method->getName()]) : null,
213207
// #[Info]
214208
Info::class => $pkg->setInfoCallback([$instance_class, $method->getName()]),
215209
// #[Validate]
216210
Validate::class => $pkg->setValidateCallback([$instance_class, $method->getName()]),
217-
// #[PatchBeforeBuild]
218-
PatchBeforeBuild::class => $pkg->setPatchBeforeBuildCallback([$instance_class, $method->getName()]),
219211
default => null,
220212
};
221213
}
@@ -224,6 +216,7 @@ public static function loadFromClass(mixed $class): void
224216
self::$packages[$pkg->getName()] = $pkg;
225217
}
226218

219+
// For classes without package attributes, create a simple instance for non-package stage callbacks
227220
if (!isset($instance_class)) {
228221
$instance_class = $refClass->newInstance();
229222
}

0 commit comments

Comments
 (0)