use resolved dependency tree instead of asking for with_suggests everywhere

This commit is contained in:
henderkes
2026-05-11 11:35:15 +07:00
parent efdd2a74a5
commit 743934d1fe
6 changed files with 46 additions and 28 deletions

View File

@@ -5,8 +5,10 @@ declare(strict_types=1);
namespace StaticPHP\Util;
use StaticPHP\Config\PackageConfig;
use StaticPHP\DI\ApplicationContext;
use StaticPHP\Exception\WrongUsageException;
use StaticPHP\Package\LibraryPackage;
use StaticPHP\Package\PackageInstaller;
use StaticPHP\Package\PhpExtensionPackage;
use StaticPHP\Runtime\SystemTarget;
@@ -118,6 +120,10 @@ class SPCConfigUtil
* [Helper function]
* Get configuration for a specific extension(s) dependencies.
*
* Uses the installer's resolved package set as the source of truth — only libraries that
* are actually enabled in this build appear in the result. The resolved set already
* reflects the user's `--with-suggests` choice.
*
* @param array|PhpExtensionPackage $extension_packages Extension instance or list
* @return array{
* cflags: string,
@@ -125,30 +131,30 @@ class SPCConfigUtil
* libs: string
* }
*/
public function getExtensionConfig(array|PhpExtensionPackage $extension_packages, bool $include_suggests = false): array
public function getExtensionConfig(array|PhpExtensionPackage $extension_packages): array
{
if (!is_array($extension_packages)) {
$extension_packages = [$extension_packages];
}
return $this->config(
packages: array_map(fn ($y) => $y->getName(), $extension_packages),
include_suggests: $include_suggests,
);
$names = array_map(fn ($y) => $y->getName(), $extension_packages);
return $this->configWithResolvedPackages($this->collectEnabledLinkPackages($names));
}
/**
* [Helper function]
* Get configuration for a specific library(s) dependencies.
*
* @param array|LibraryPackage $lib Library instance or list
* @param bool $include_suggests Whether to include suggested libraries
* Like {@see getExtensionConfig()}, draws from the resolved package set so we never
* link against a library that wasn't built.
*
* @param array|LibraryPackage $lib Library instance or list
* @return array{
* cflags: string,
* ldflags: string,
* libs: string
* }
*/
public function getLibraryConfig(array|LibraryPackage $lib, bool $include_suggests = false): array
public function getLibraryConfig(array|LibraryPackage $lib): array
{
if (!is_array($lib)) {
$lib = [$lib];
@@ -157,35 +163,31 @@ class SPCConfigUtil
$this->no_php = true;
$save_libs_only_deps = $this->libs_only_deps;
$this->libs_only_deps = true;
$ret = $this->config(
packages: array_map(fn ($y) => $y->getName(), $lib),
include_suggests: $include_suggests,
);
$names = array_map(fn ($y) => $y->getName(), $lib);
$ret = $this->configWithResolvedPackages($this->collectEnabledLinkPackages($names));
$this->no_php = $save_no_php;
$this->libs_only_deps = $save_libs_only_deps;
return $ret;
}
/**
* Get build configuration for a package and its sub-dependencies within a resolved set.
* Get build configuration for a package's sub-dependencies within a resolved set.
*
* This is useful when you need to statically link something against a specific
* library and all its transitive dependencies. It properly handles optional
* dependencies by only including those that were actually resolved.
* Walks both depends and suggests edges — the resolved set is the filter, so anything
* reachable but unbuilt is naturally excluded. No `include_suggests` knob is needed.
*
* @param string $package_name The package to get config for
* @param string[] $resolved_packages The full resolved package list
* @param bool $include_suggests Whether to include resolved suggests
* @return array{
* cflags: string,
* ldflags: string,
* libs: string
* }
*/
public function getPackageDepsConfig(string $package_name, array $resolved_packages, bool $include_suggests = false): array
public function getPackageDepsConfig(string $package_name, array $resolved_packages): array
{
// Get sub-dependencies within the resolved set
$sub_deps = DependencyResolver::getSubDependencies($package_name, $resolved_packages, $include_suggests);
$sub_deps = DependencyResolver::getSubDependencies($package_name, $resolved_packages, include_suggests: true);
if (empty($sub_deps)) {
return [
@@ -299,6 +301,24 @@ class SPCConfigUtil
return implode(' ', $list);
}
/**
* 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.
*
* @param string[] $package_names Input package names
* @return string[] Resolved packages to link against
*/
private function collectEnabledLinkPackages(array $package_names): array
{
$resolved = array_keys(ApplicationContext::get(PackageInstaller::class)->getResolvedPackages());
$out = [];
foreach ($package_names as $name) {
$sub = DependencyResolver::getSubDependencies($name, $resolved, include_suggests: true);
$out = [...$out, ...$sub, $name];
}
return array_values(array_unique($out));
}
private function hasCpp(array $packages): bool
{
foreach ($packages as $package) {