diff --git a/src/Package/Target/php/frankenphp.php b/src/Package/Target/php/frankenphp.php index 424efad4..50c4af45 100644 --- a/src/Package/Target/php/frankenphp.php +++ b/src/Package/Target/php/frankenphp.php @@ -73,9 +73,7 @@ trait frankenphp $staticFlags = ''; } - $resolved = $installer->getAvailableResolvedPackageNames(); - $resolved = array_values(array_filter($resolved, fn ($pkg_name) => $pkg_name !== $package->getName())); - $config = new SPCConfigUtil()->config($resolved); + $config = new SPCConfigUtil()->config(['frankenphp']); $cflags = "{$package->getLibExtraCFlags()} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . " -DFRANKENPHP_VERSION={$frankenphp_version}"; $libs = $config['libs']; diff --git a/src/Package/Target/php/unix.php b/src/Package/Target/php/unix.php index 805813ea..d6324209 100644 --- a/src/Package/Target/php/unix.php +++ b/src/Package/Target/php/unix.php @@ -543,8 +543,8 @@ trait unix $package->runStage([$this, 'configureForUnix']); $package->runStage([$this, 'makeForUnix']); } - - $package->runStage([$this, 'unixBuildSharedExt']); + // shared extensions build in php's postInstall (php.php) so they run AFTER + // frankenphp's main-loop build — frankenphp links libphp only, not the .so exts. } /** @@ -656,7 +656,7 @@ trait unix copy(ROOT_DIR . '/src/globals/common-tests/embed.c', $sample_file_path . '/embed.c'); copy(ROOT_DIR . '/src/globals/common-tests/embed.php', $sample_file_path . '/embed.php'); - $config = new SPCConfigUtil()->config($installer->getAvailableResolvedPackageNames()); + $config = new SPCConfigUtil()->config(['php']); $lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}"; if ($toolchain->isStatic()) { $lens .= ' -static'; @@ -743,7 +743,7 @@ trait unix */ private function makeVars(PackageInstaller $installer): array { - $config = new SPCConfigUtil(['libs_only_deps' => true])->config($installer->getAvailableResolvedPackageNames()); + $config = new SPCConfigUtil(['libs_only_deps' => true])->config(['php']); $static = ApplicationContext::get(ToolchainInterface::class)->isStatic() ? '-all-static' : ''; $pie = SystemTarget::getTargetOS() === 'Linux' ? '-pie' : ''; $lib = BUILD_LIB_PATH; diff --git a/src/StaticPHP/Command/SPCConfigCommand.php b/src/StaticPHP/Command/SPCConfigCommand.php index 2b1ac6bd..742662ff 100644 --- a/src/StaticPHP/Command/SPCConfigCommand.php +++ b/src/StaticPHP/Command/SPCConfigCommand.php @@ -44,7 +44,7 @@ class SPCConfigCommand extends BaseCommand 'absolute_libs' => (bool) $this->getOption('absolute-libs'), ]); $packages = array_merge(array_map(fn ($x) => "ext-{$x}", $extensions), $libraries); - $config = $util->config($packages, $include_suggests); + $config = $util->config($packages); $this->output->writeln(match (true) { $this->getOption('includes') => $config['cflags'], diff --git a/src/StaticPHP/Util/SPCConfigUtil.php b/src/StaticPHP/Util/SPCConfigUtil.php index ef69f023..163a21fb 100644 --- a/src/StaticPHP/Util/SPCConfigUtil.php +++ b/src/StaticPHP/Util/SPCConfigUtil.php @@ -10,6 +10,7 @@ use StaticPHP\Exception\WrongUsageException; use StaticPHP\Package\LibraryPackage; use StaticPHP\Package\PackageInstaller; use StaticPHP\Package\PhpExtensionPackage; +use StaticPHP\Package\TargetPackage; use StaticPHP\Runtime\SystemTarget; class SPCConfigUtil @@ -34,15 +35,39 @@ class SPCConfigUtil $this->absolute_libs = $options['absolute_libs'] ?? false; } - public function config(array $packages = [], bool $include_suggests = false): array + public function config(array $packages = []): array { - // if have php, make php as all extension's dependency - $dep_override = $this->no_php - ? [] - : ['php' => array_filter($packages, fn ($y) => str_starts_with($y, 'ext-'))]; - return $this->configWithResolvedPackages( - DependencyResolver::resolve($packages, $dep_override, $include_suggests) - ); + // Walk depends+suggests within the resolved set; reaching `php` fans out to its + // effective link closure (resolved static exts + virtual-target SAPIs). + $installer = ApplicationContext::get(PackageInstaller::class); + $resolved_set = array_flip(array_keys($installer->getResolvedPackages())); + + $php_extras = []; + if (!$this->no_php) { + foreach ($installer->getResolvedPackages(PhpExtensionPackage::class) as $ext) { + if ($ext->isBuildStatic()) { + $php_extras[] = $ext->getName(); + } + } + foreach ($installer->getResolvedPackages(TargetPackage::class) as $target) { + if ($target->isVirtualTarget()) { + $php_extras[] = $target->getName(); + } + } + } + + $sorted = []; + $visited = []; + foreach ($packages as $pkg) { + self::visitConfigDeps( + is_string($pkg) ? $pkg : $pkg->getName(), + $resolved_set, + $php_extras, + $visited, + $sorted, + ); + } + return $this->configWithResolvedPackages($sorted); } /** @@ -251,6 +276,32 @@ class SPCConfigUtil return implode(' ', $list); } + private static function visitConfigDeps( + string $name, + array $resolved_set, + array $php_extras, + array &$visited, + array &$sorted, + ): void { + if (isset($visited[$name]) || !isset($resolved_set[$name])) { + return; + } + $visited[$name] = true; + + $deps = array_merge( + PackageConfig::get($name, 'depends', []), + PackageConfig::get($name, 'suggests', []), + ); + if ($name === 'php') { + $deps = array_merge($deps, $php_extras); + } + + foreach ($deps as $dep) { + self::visitConfigDeps($dep, $resolved_set, $php_extras, $visited, $sorted); + } + $sorted[] = $name; + } + /** * For each input package name, gather its transitive deps within the installer's resolved * set (walking depends + suggests edges), plus the package itself, deduped and in build order.