Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions config/ext.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,18 @@
],
"lib-depends-windows": []
},
"gmagick": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"type": "external",
"source": "ext-gmagick",
"arg-type": "custom",
"lib-depends": [
"graphicsmagick"
]
},
"gmp": {
"support": {
"Windows": "wip",
Expand Down
21 changes: 21 additions & 0 deletions config/lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,27 @@
"Security"
]
},
"graphicsmagick": {
"source": "graphicsmagick",
"pkg-configs": [
"GraphicsMagick",
"GraphicsMagickWand"
],
"lib-depends": [
"zlib",
"libpng",
"libjpeg",
"bzip2",
"libxml2"
],
"lib-suggests": [
"libwebp",
"libtiff",
"freetype",
"zstd",
"xz"
]
},
"grpc": {
"source": "grpc",
"pkg-configs": [
Expand Down
31 changes: 22 additions & 9 deletions config/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@
"path": "LICENSE"
}
},
"ext-gmagick": {
"type": "url",
"url": "https://pecl.php.net/get/gmagick",
"path": "php-src/ext/gmagick",
"filename": "gmagick.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-gmssl": {
"type": "ghtar",
"repo": "gmssl/GmSSL-PHP",
Expand Down Expand Up @@ -401,6 +411,14 @@
"path": "LICENSE"
}
},
"graphicsmagick": {
"type": "url",
"url": "https://downloads.sourceforge.net/project/graphicsmagick/graphicsmagick/1.3.46/GraphicsMagick-1.3.46.tar.xz",
"license": {
"type": "file",
"path": "Copyright.txt"
}
},
"grpc": {
"type": "git",
"rev": "v1.75.x",
Expand Down Expand Up @@ -998,15 +1016,10 @@
}
},
"openssl": {
"type": "ghrel",
"repo": "openssl/openssl",
"match": "openssl.+\\.tar\\.gz",
"prefer-stable": true,
"alt": {
"type": "filelist",
"url": "https://www.openssl.org/source/",
"regex": "/href=\"(?<file>openssl-(?<version>[^\"]+)\\.tar\\.gz)\"/"
},
"__comment": "Pinned to 3.5.0 because OpenSSL 4.0.0 (Apr 2026) made ASN1_STRING opaque and breaks PHP 8.4.x openssl ext. Revert to ghrel once static-php-cli supports OpenSSL 4.0 or PHP 8.4 absorbs the API change.",
"type": "url",
"url": "https://github.com/openssl/openssl/releases/download/openssl-3.5.0/openssl-3.5.0.tar.gz",
"filename": "openssl-3.5.0.tar.gz",
"provide-pre-built": true,
"license": {
"type": "file",
Expand Down
34 changes: 34 additions & 0 deletions src/SPC/builder/extension/gmagick.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace SPC\builder\extension;

use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt;

#[CustomExt('gmagick')]
class gmagick extends Extension
{
public function patchBeforeBuildconf(): bool
{
// PHP 8.5 removed zend_exception_get_default(), use zend_ce_exception instead
FileSystem::replaceFileStr($this->source_dir . '/gmagick.c', 'zend_exception_get_default()', 'zend_ce_exception');

// Remove the entire OpenMP check block from config.m4 to avoid linking
// against libgomp in static builds. gmagick's config.m4 uses PHP_CHECK_FUNC
// which does not honour ac_cv cache variables, so we must patch the source.
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/ext/gmagick/config.m4',
'/AC_MSG_CHECKING\(omp_pause_resource_all usability\).*?AC_MSG_RESULT\(no\)\n\t\t\]\)/s',
'dnl OMP check removed for static build'
);
return true;
}

public function getUnixConfigureArg(bool $shared = false): string
{
return '--with-gmagick=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH;
}
}
12 changes: 12 additions & 0 deletions src/SPC/builder/linux/library/graphicsmagick.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace SPC\builder\linux\library;

class graphicsmagick extends LinuxLibraryBase
{
use \SPC\builder\unix\library\graphicsmagick;

public const NAME = 'graphicsmagick';
}
12 changes: 12 additions & 0 deletions src/SPC/builder/macos/library/graphicsmagick.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace SPC\builder\macos\library;

class graphicsmagick extends MacOSLibraryBase
{
use \SPC\builder\unix\library\graphicsmagick;

public const NAME = 'graphicsmagick';
}
54 changes: 54 additions & 0 deletions src/SPC/builder/unix/library/graphicsmagick.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace SPC\builder\unix\library;

use SPC\util\executor\UnixAutoconfExecutor;
use SPC\util\SPCTarget;

trait graphicsmagick
{
protected function build(): void
{
$ac = UnixAutoconfExecutor::create($this)
->optionalLib('zlib', ...ac_with_args('zlib'))
->optionalLib('libpng', ...ac_with_args('png'))
->optionalLib('libjpeg', ...ac_with_args('jpeg'))
->optionalLib('libwebp', ...ac_with_args('webp'))
->optionalLib('libtiff', ...ac_with_args('tiff'))
->optionalLib('freetype', ...ac_with_args('ttf'))
->optionalLib('bzip2', ...ac_with_args('bzlib'))
->addConfigureArgs(
'--disable-openmp',
'--without-x',
'--without-perl',
// HEIF/JXL: GraphicsMagick auto-detects libheif/libjxl from the
// buildroot but the API versions are often incompatible (e.g.
// GM 1.3.46 expects libheif symbols added in 2.4+). Exclude them
// to avoid compile errors. Neither format is needed for typical
// WordPress/web image processing (JPEG/PNG/WebP/GIF suffice).
'--without-heif',
'--without-jxl',
'--enable-shared=no',
'--enable-static=yes',
);

// special: linux-static target needs `-static`
$ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl';

// special: macOS needs -liconv
$libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : '';

$ac->appendEnv([
'LDFLAGS' => $ldflags,
'LIBS' => $libs,
'PKG_CONFIG' => '$PKG_CONFIG --static',
]);

$ac->configure()->make();

$this->patchPkgconfPrefix(['GraphicsMagick.pc', 'GraphicsMagick++.pc', 'GraphicsMagickWand.pc']);
$this->patchLaDependencyPrefix();
}
}
33 changes: 33 additions & 0 deletions src/SPC/store/SourcePatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public static function init(): void
FileSystem::addSourceExtractHook('openssl', [__CLASS__, 'patchOpenssl11Darwin']);
FileSystem::addSourceExtractHook('swoole', [__CLASS__, 'patchSwoole']);
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchPhpLibxml212']);
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchPhpOpcacheEbrResetSafety']);
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchGDWin32']);
// FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchFfiCentos7FixO3strncmp']);
FileSystem::addSourceExtractHook('sqlsrv', [__CLASS__, 'patchSQLSRVWin32']);
Expand Down Expand Up @@ -624,6 +625,38 @@ public static function patchPhpLibxml212(): bool
return false;
}

/**
* Apply opcache EBR reset-safety fix (upstream PR php/php-src#21778)
* to PHP 8.4.x until it lands in a tagged release. Fixes zend_mm_heap
* corruption crashes caused by opcache_reset()/opcache_invalidate()
* racing with concurrent readers under ZTS (FrankenPHP) and FPM.
*
* Fixes GH-8739, GH-14471, GH-18517.
*/
public static function patchPhpOpcacheEbrResetSafety(): bool
{
$file = SOURCE_PATH . '/php-src/main/php_version.h';
if (!file_exists($file)) {
return false;
}
if (preg_match('/PHP_VERSION_ID (\d+)/', file_get_contents($file), $match) === 0) {
return false;
}
$ver_id = intval($match[1]);
// Apply only to PHP 8.4.x releases prior to the version that ships the fix.
// Upper bound will be tightened once PR #21778 is merged and tagged.
if ($ver_id < 80400 || $ver_id >= 80500) {
return false;
}
// Skip if already applied (e.g. rerunning on an already-patched tree)
$probe = SOURCE_PATH . '/php-src/ext/opcache/ZendAccelerator.c';
if (file_exists($probe) && str_contains(file_get_contents($probe), 'accel_try_complete_deferred_reset')) {
return false;
}
self::patchFile('php84_opcache_ebr_reset_safety.patch', SOURCE_PATH . '/php-src');
return true;
}

public static function patchGDWin32(): bool
{
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
Expand Down
7 changes: 7 additions & 0 deletions src/globals/ext-tests/gmagick.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

declare(strict_types=1);

assert(class_exists('Gmagick'));
assert(in_array('JPEG', (new Gmagick())->queryformats()));
assert(in_array('PNG', (new Gmagick())->queryformats()));
Loading