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/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(); + } +} 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']]), diff --git a/tests/StaticPHP/Registry/PackageLoaderTest.php b/tests/StaticPHP/Registry/PackageLoaderTest.php index cb78cd181..8d8811338 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; @@ -28,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 @@ -58,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 @@ -533,6 +499,26 @@ 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.'); + } + + 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 { + $this->resetPackageLoaderState(); + $this->resetPackageConfigState(); + } + } + private function removeDirectory(string $dir): void { if (!is_dir($dir)) { @@ -561,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, []); + } }