From 3cd8f9cbd5d8ba0291232e6bfe1e6d7cd99fa785 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:20:22 +0000 Subject: [PATCH 1/6] Initial plan From 32cbd8f23517d513dce9a3bd74edf2529fd4ac4a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:22:18 +0000 Subject: [PATCH 2/6] Add lcms2 support to imagemagick build Co-authored-by: henderkes <7896469+henderkes@users.noreply.github.com> --- config/pkg/lib/imagemagick.yml | 2 ++ config/pkg/lib/lcms2.yml | 16 ++++++++++++++ src/Package/Library/imagemagick.php | 1 + .../Dev/GenExtTestMatrixCommandTest.php | 21 +++++++++++++++++-- 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 config/pkg/lib/lcms2.yml diff --git a/config/pkg/lib/imagemagick.yml b/config/pkg/lib/imagemagick.yml index 10acadfaa..e0f68ce8a 100644 --- a/config/pkg/lib/imagemagick.yml +++ b/config/pkg/lib/imagemagick.yml @@ -23,6 +23,8 @@ imagemagick: - xz - libzip - libxml2 + suggests@unix: + - lcms2 headers@windows: - imagemagick/MagickWand/MagickWand.h lang: cpp diff --git a/config/pkg/lib/lcms2.yml b/config/pkg/lib/lcms2.yml new file mode 100644 index 000000000..b40782f98 --- /dev/null +++ b/config/pkg/lib/lcms2.yml @@ -0,0 +1,16 @@ +lcms2: + type: library + artifact: + source: + type: ghtagtar + repo: mm2/Little-CMS + match: lcms2\.\d+(\.\d+)?$ + metadata: + license-files: [COPYING] + license: MIT + headers@unix: + - lcms2.h + pkg-configs: + - lcms2 + static-libs@unix: + - liblcms2.a diff --git a/src/Package/Library/imagemagick.php b/src/Package/Library/imagemagick.php index 7e6604993..649894349 100644 --- a/src/Package/Library/imagemagick.php +++ b/src/Package/Library/imagemagick.php @@ -106,6 +106,7 @@ public function buildUnix(LibraryPackage $lib, ToolchainInterface $toolchain): v ->optionalPackage('zlib', ...ac_with_args('zlib')) ->optionalPackage('xz', ...ac_with_args('lzma')) ->optionalPackage('zstd', ...ac_with_args('zstd')) + ->optionalPackage('lcms2', ...ac_with_args('lcms')) ->optionalPackage('freetype', ...ac_with_args('freetype')) ->optionalPackage('bzip2', ...ac_with_args('bzlib')) ->optionalPackage('libjxl', ...ac_with_args('jxl')) diff --git a/tests/StaticPHP/Command/Dev/GenExtTestMatrixCommandTest.php b/tests/StaticPHP/Command/Dev/GenExtTestMatrixCommandTest.php index 4db6da59d..c638923fd 100644 --- a/tests/StaticPHP/Command/Dev/GenExtTestMatrixCommandTest.php +++ b/tests/StaticPHP/Command/Dev/GenExtTestMatrixCommandTest.php @@ -190,6 +190,20 @@ public function testForLibsFilterIncludesTransitiveLibraryDeps(): void } } + /** + * --for-libs must include extensions that depend on the library through suggested libraries. + */ + public function testForLibsFilterIncludesTransitiveSuggestedLibraryDeps(): void + { + $matrix = $this->runMatrix(['--os' => 'Linux', '--for-libs' => 'lcms2']); + + $this->assertNotEmpty($matrix, '--for-libs=lcms2 must yield at least one entry'); + foreach ($matrix as $entry) { + $parts = explode(',', $entry['extension']); + $this->assertContains('imagick', $parts, "Entry {$entry['extension']} should not appear in --for-libs=lcms2 results"); + } + } + /** * Multiple filters should include entries matching any changed package. */ @@ -313,11 +327,14 @@ private static function buildFixture(): array 'ext-xml' => $ext(['arg-type' => 'standard'], ['depends' => ['libxml2']]), 'ext-dom' => $ext(['arg-type' => 'standard'], ['depends' => ['ext-xml']]), - // Transitive library chain: imagick -> imagemagick -> libheif -> libde265 + // Transitive library chains: + // imagick -> imagemagick -> libheif -> libde265 + // imagick -> imagemagick -> (suggests) lcms2 'ext-imagick' => $ext(['arg-type' => 'standard'], ['depends' => ['imagemagick']]), - 'imagemagick' => $lib(['depends' => ['libheif']]), + 'imagemagick' => $lib(['depends' => ['libheif'], 'suggests' => ['lcms2']]), 'libheif' => $lib(['depends' => ['libde265']]), 'libde265' => $lib(), + 'lcms2' => $lib(), // OS-restricted to Linux only 'ext-linux-only' => $ext(['os' => ['Linux']]), From ca7bb7277a8096b06e0f5b53b1fc20b9df021592 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:59:12 +0000 Subject: [PATCH 3/6] Add lcms2 Unix build stage package class Co-authored-by: henderkes <7896469+henderkes@users.noreply.github.com> --- src/Package/Library/lcms2.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/Package/Library/lcms2.php diff --git a/src/Package/Library/lcms2.php b/src/Package/Library/lcms2.php new file mode 100644 index 000000000..11f111045 --- /dev/null +++ b/src/Package/Library/lcms2.php @@ -0,0 +1,26 @@ +configure() + ->make(); + + $lib->patchPkgconfPrefix(['lcms2.pc']); + $lib->patchLaDependencyPrefix(); + } +} From bd11dc23212e552f1e4ae1fe941e1bc028cfc91e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:00:03 +0000 Subject: [PATCH 4/6] Add lcms2 build-stage regression test Co-authored-by: henderkes <7896469+henderkes@users.noreply.github.com> --- tests/StaticPHP/Registry/PackageLoaderTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/StaticPHP/Registry/PackageLoaderTest.php b/tests/StaticPHP/Registry/PackageLoaderTest.php index cb78cd181..c1f4fe82e 100644 --- a/tests/StaticPHP/Registry/PackageLoaderTest.php +++ b/tests/StaticPHP/Registry/PackageLoaderTest.php @@ -4,6 +4,7 @@ namespace Tests\StaticPHP\Registry; +use Package\Library\lcms2; use PHPUnit\Framework\TestCase; use StaticPHP\Attribute\Package\Extension; use StaticPHP\Attribute\Package\Library; @@ -533,6 +534,21 @@ class TestPackage1 { $this->assertTrue(PackageLoader::hasPackage('test-lib')); } + public function testLcms2PackageRegistersBuildStageOnUnix(): void + { + if (PHP_OS_FAMILY === 'Windows') { + $this->markTestSkipped('lcms2 build stage is only registered for Unix in this test.'); + } + + PackageConfig::loadFromFile(__DIR__ . '/../../../config/pkg/lib/lcms2.yml', 'test'); + PackageLoader::initPackageInstances(); + PackageLoader::loadFromClass(lcms2::class); + + $package = PackageLoader::getLibraryPackage('lcms2'); + $this->assertTrue($package->hasBuildFunctionForCurrentOS()); + $this->assertTrue($package->hasStage('build')); + } + private function removeDirectory(string $dir): void { if (!is_dir($dir)) { From 8e974bac8312dea94bdbcde6a2e7ffdc581ac099 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:00:34 +0000 Subject: [PATCH 5/6] Isolate lcms2 package-loader regression test state Co-authored-by: henderkes <7896469+henderkes@users.noreply.github.com> --- .../StaticPHP/Registry/PackageLoaderTest.php | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/StaticPHP/Registry/PackageLoaderTest.php b/tests/StaticPHP/Registry/PackageLoaderTest.php index c1f4fe82e..72cdecce9 100644 --- a/tests/StaticPHP/Registry/PackageLoaderTest.php +++ b/tests/StaticPHP/Registry/PackageLoaderTest.php @@ -540,13 +540,23 @@ public function testLcms2PackageRegistersBuildStageOnUnix(): void $this->markTestSkipped('lcms2 build stage is only registered for Unix in this test.'); } - PackageConfig::loadFromFile(__DIR__ . '/../../../config/pkg/lib/lcms2.yml', 'test'); - PackageLoader::initPackageInstances(); - PackageLoader::loadFromClass(lcms2::class); + try { + PackageConfig::loadFromFile(__DIR__ . '/../../../config/pkg/lib/lcms2.yml', 'test'); + PackageLoader::initPackageInstances(); + PackageLoader::loadFromClass(lcms2::class); + + $package = PackageLoader::getLibraryPackage('lcms2'); + $this->assertTrue($package->hasBuildFunctionForCurrentOS()); + $this->assertTrue($package->hasStage('build')); + } finally { + $loaderReflection = new \ReflectionClass(PackageLoader::class); + foreach (['packages' => null, 'before_stages' => [], 'after_stages' => [], 'loaded_classes' => []] as $propName => $value) { + $loaderReflection->getProperty($propName)->setValue(null, $value); + } - $package = PackageLoader::getLibraryPackage('lcms2'); - $this->assertTrue($package->hasBuildFunctionForCurrentOS()); - $this->assertTrue($package->hasStage('build')); + $configReflection = new \ReflectionClass(PackageConfig::class); + $configReflection->getProperty('package_configs')->setValue(null, []); + } } private function removeDirectory(string $dir): void From f80fc3ade412f702f7cfe80d40555efad7eb5f04 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:01:06 +0000 Subject: [PATCH 6/6] Refactor registry test state-reset helpers Co-authored-by: henderkes <7896469+henderkes@users.noreply.github.com> --- .../StaticPHP/Registry/PackageLoaderTest.php | 66 ++++++------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/tests/StaticPHP/Registry/PackageLoaderTest.php b/tests/StaticPHP/Registry/PackageLoaderTest.php index 72cdecce9..8d8811338 100644 --- a/tests/StaticPHP/Registry/PackageLoaderTest.php +++ b/tests/StaticPHP/Registry/PackageLoaderTest.php @@ -29,26 +29,8 @@ protected function setUp(): void parent::setUp(); $this->tempDir = sys_get_temp_dir() . '/package_loader_test_' . uniqid(); mkdir($this->tempDir, 0755, true); - - // Reset PackageLoader state - $reflection = new \ReflectionClass(PackageLoader::class); - - $property = $reflection->getProperty('packages'); - $property->setValue(null, null); - - $property = $reflection->getProperty('before_stages'); - $property->setValue(null, []); - - $property = $reflection->getProperty('after_stages'); - $property->setValue(null, []); - - $property = $reflection->getProperty('loaded_classes'); - $property->setValue(null, []); - - // Reset PackageConfig state - $configReflection = new \ReflectionClass(PackageConfig::class); - $configProperty = $configReflection->getProperty('package_configs'); - $configProperty->setValue(null, []); + $this->resetPackageLoaderState(); + $this->resetPackageConfigState(); } protected function tearDown(): void @@ -59,25 +41,8 @@ protected function tearDown(): void $this->removeDirectory($this->tempDir); } - // Reset PackageLoader state - $reflection = new \ReflectionClass(PackageLoader::class); - - $property = $reflection->getProperty('packages'); - $property->setValue(null, null); - - $property = $reflection->getProperty('before_stages'); - $property->setValue(null, []); - - $property = $reflection->getProperty('after_stages'); - $property->setValue(null, []); - - $property = $reflection->getProperty('loaded_classes'); - $property->setValue(null, []); - - // Reset PackageConfig state - $configReflection = new \ReflectionClass(PackageConfig::class); - $configProperty = $configReflection->getProperty('package_configs'); - $configProperty->setValue(null, []); + $this->resetPackageLoaderState(); + $this->resetPackageConfigState(); } public function testInitPackageInstancesOnlyRunsOnce(): void @@ -549,13 +514,8 @@ public function testLcms2PackageRegistersBuildStageOnUnix(): void $this->assertTrue($package->hasBuildFunctionForCurrentOS()); $this->assertTrue($package->hasStage('build')); } finally { - $loaderReflection = new \ReflectionClass(PackageLoader::class); - foreach (['packages' => null, 'before_stages' => [], 'after_stages' => [], 'loaded_classes' => []] as $propName => $value) { - $loaderReflection->getProperty($propName)->setValue(null, $value); - } - - $configReflection = new \ReflectionClass(PackageConfig::class); - $configReflection->getProperty('package_configs')->setValue(null, []); + $this->resetPackageLoaderState(); + $this->resetPackageConfigState(); } } @@ -587,4 +547,18 @@ private function createTestPackageConfig(string $name, string $type): void ]; $property->setValue(null, $configs); } + + private function resetPackageLoaderState(): void + { + $reflection = new \ReflectionClass(PackageLoader::class); + foreach (['packages' => null, 'before_stages' => [], 'after_stages' => [], 'loaded_classes' => []] as $propName => $value) { + $reflection->getProperty($propName)->setValue(null, $value); + } + } + + private function resetPackageConfigState(): void + { + $configReflection = new \ReflectionClass(PackageConfig::class); + $configReflection->getProperty('package_configs')->setValue(null, []); + } }