From 9b809a074f7a9c9692195a73393664f2892bd92a Mon Sep 17 00:00:00 2001 From: Alexander Over Date: Thu, 6 Feb 2025 08:44:39 +0100 Subject: [PATCH] Add command to dump required PHP extensions based on vendor/composer/installed.json, composer.lock, composer.json (in this order) --- README.md | 2 + src/SPC/ConsoleApplication.php | 3 + src/SPC/command/DumpExtensionsCommand.php | 70 +++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/SPC/command/DumpExtensionsCommand.php diff --git a/README.md b/README.md index 38544e84..b4ef97a5 100755 --- a/README.md +++ b/README.md @@ -194,6 +194,8 @@ Basic usage for building php with some extensions: # fetch all libraries ./bin/spc download --all +# dump a list of extensions required by your project +./bin/spc dump-extensions # only fetch necessary sources by needed extensions (recommended) ./bin/spc download --for-extensions="openssl,pcntl,mbstring,pdo_sqlite" # download pre-built libraries first (save time for compiling dependencies) diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php index 2609d317..7d1d8e8b 100644 --- a/src/SPC/ConsoleApplication.php +++ b/src/SPC/ConsoleApplication.php @@ -18,7 +18,9 @@ use SPC\command\dev\PhpVerCommand; use SPC\command\dev\SortConfigCommand; use SPC\command\DoctorCommand; use SPC\command\DownloadCommand; +use SPC\command\DumpExtensionsCommand; use SPC\command\DumpLicenseCommand; +use SPC\command\ExtensionDumperCommand; use SPC\command\ExtractCommand; use SPC\command\InstallPkgCommand; use SPC\command\MicroCombineCommand; @@ -54,6 +56,7 @@ final class ConsoleApplication extends Application new MicroCombineCommand(), new SwitchPhpVersionCommand(), new SPCConfigCommand(), + new DumpExtensionsCommand(), // Dev commands new AllExtCommand(), diff --git a/src/SPC/command/DumpExtensionsCommand.php b/src/SPC/command/DumpExtensionsCommand.php new file mode 100644 index 00000000..215317dc --- /dev/null +++ b/src/SPC/command/DumpExtensionsCommand.php @@ -0,0 +1,70 @@ +files as $file) { + if ($fs->exists($file)) { + $this->output->writeln("Analyzing file: {$file}"); + $data = json_decode(file_get_contents($file), true); + + if (!$data) { + $this->output->writeln("Error parsing {$file}"); + continue; + } + + $extensions = array_merge($extensions, $this->extractExtensions($data)); + } + } + + if (empty($extensions)) { + $this->output->writeln('No extensions found.'); + return static::SUCCESS; + } + + $extensions = array_unique($extensions); + sort($extensions); + + $this->output->writeln("\nRequired PHP extensions:"); + $this->output->writeln(implode(',', array_map(fn ($ext) => substr($ext, 4), $extensions))); + + return static::SUCCESS; + } + + private function extractExtensions(array $data): array + { + return array_merge( + ...array_map( + function ($package) { + return isset($package['require']) ? $this->filterExtensions($package['require']) : []; + }, + $data['packages'] ?? [$data] + ) + ); + } + + private function filterExtensions(array $requirements): array + { + return array_keys(array_filter($requirements, function ($key) { + return str_starts_with($key, 'ext-'); + }, ARRAY_FILTER_USE_KEY)); + } +}