V3 refactor/forward ports (#1123)

This commit is contained in:
Jerry Ma
2026-04-30 07:58:08 +08:00
committed by GitHub
14 changed files with 178 additions and 30 deletions

View File

@@ -4,12 +4,12 @@ openssl:
source: source:
type: ghrel type: ghrel
repo: openssl/openssl repo: openssl/openssl
match: openssl.+\.tar\.gz match: openssl-3.+\.tar\.gz
prefer-stable: true prefer-stable: true
source-mirror: source-mirror:
type: filelist type: filelist
url: 'https://www.openssl.org/source/' url: 'https://www.openssl.org/source/'
regex: '/href="(?<file>openssl-(?<version>[^"]+)\.tar\.gz)"/' regex: '/href="(?<file>openssl-(?<version>3\.[^"]+)\.tar\.gz)"/'
binary: hosted binary: hosted
metadata: metadata:
license-files: [LICENSE.txt] license-files: [LICENSE.txt]

View File

@@ -125,9 +125,10 @@ These flags apply only to the combined `build:php` target. To build a specific S
### embed Options {#embed-options} ### embed Options {#embed-options}
| Option | Description | | Option | Description |
|-------------------------|-----------------------------------------------------------------------| |-----------------------------|------------------------------------------------------------------------------------------------------|
| `--build-shared=<list>` | Compile specific extensions as shared libraries (requires embed SAPI) | | `--build-shared=<list>` | Compile specific extensions as shared libraries (requires embed SAPI) |
| `--maintainer-skip-build` | (maintainer only) Skip the PHP embed build if `libphp.a` / `libphp.so` already exists in buildroot |
### Download Pass-through Options {#download-options} ### Download Pass-through Options {#download-options}

View File

@@ -128,6 +128,7 @@ spc build:php <extensions> [options]
| 选项 | 说明 | | 选项 | 说明 |
|---|---| |---|---|
| `--build-shared=<list>` | 将指定扩展编译为共享库(需要 embed SAPI| | `--build-shared=<list>` | 将指定扩展编译为共享库(需要 embed SAPI|
| `--maintainer-skip-build` | (仅维护者)若 buildroot 中已存在 `libphp.a` / `libphp.so`,则跳过 PHP embed 的编译构建 |
### 下载透传选项 {#download-options} ### 下载透传选项 {#download-options}

View File

@@ -22,8 +22,14 @@ class decimal extends PhpExtensionPackage
{ {
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
$this->getSourceDir() . '/php_decimal.c', $this->getSourceDir() . '/php_decimal.c',
'zend_module_entry decimal_module_entry', [
'zend_module_entry php_decimal_module_entry' 'zend_module_entry decimal_module_entry',
'ZEND_GET_MODULE(decimal)',
],
[
'zend_module_entry php_decimal_module_entry',
'ZEND_GET_MODULE(php_decimal)',
]
); );
} }

View File

@@ -10,6 +10,8 @@ use StaticPHP\Package\LibraryPackage;
use StaticPHP\Package\PackageInstaller; use StaticPHP\Package\PackageInstaller;
use StaticPHP\Runtime\Executor\UnixAutoconfExecutor; use StaticPHP\Runtime\Executor\UnixAutoconfExecutor;
use StaticPHP\Runtime\SystemTarget; use StaticPHP\Runtime\SystemTarget;
use StaticPHP\Toolchain\Interface\ToolchainInterface;
use StaticPHP\Toolchain\ZigToolchain;
use StaticPHP\Util\SPCConfigUtil; use StaticPHP\Util\SPCConfigUtil;
#[Library('krb5')] #[Library('krb5')]
@@ -17,7 +19,7 @@ class krb5
{ {
#[BuildFor('Linux')] #[BuildFor('Linux')]
#[BuildFor('Darwin')] #[BuildFor('Darwin')]
public function build(LibraryPackage $lib, PackageInstaller $installer): void public function build(LibraryPackage $lib, PackageInstaller $installer, ToolchainInterface $toolchain): void
{ {
if (!file_exists($lib->getSourceRoot() . '/configure')) { if (!file_exists($lib->getSourceRoot() . '/configure')) {
shell()->cd($lib->getSourceRoot())->exec('autoreconf -if'); shell()->cd($lib->getSourceRoot())->exec('autoreconf -if');
@@ -45,12 +47,15 @@ class krb5
$extraEnv['LDFLAGS'] = '-framework Kerberos'; $extraEnv['LDFLAGS'] = '-framework Kerberos';
$args[] = 'ac_cv_func_secure_getenv=no'; $args[] = 'ac_cv_func_secure_getenv=no';
} }
UnixAutoconfExecutor::create($lib) $executor = UnixAutoconfExecutor::create($lib)
->appendEnv($extraEnv) ->appendEnv($extraEnv)
->optionalPackage('ldap', '--with-ldap', '--without-ldap') ->optionalPackage('ldap', '--with-ldap', '--without-ldap')
->optionalPackage('libedit', '--with-libedit', '--without-libedit') ->optionalPackage('libedit', '--with-libedit', '--without-libedit')
->configure(...$args) ->configure(...$args);
->make(); if ($toolchain instanceof ZigToolchain) {
$executor->exec('find . -name Makefile -exec sed -i "s/-Werror=incompatible-pointer-types//g" {} +');
}
$executor->make();
$lib->patchPkgconfPrefix([ $lib->patchPkgconfPrefix([
'krb5-gssapi.pc', 'krb5-gssapi.pc',
'krb5.pc', 'krb5.pc',

View File

@@ -17,7 +17,11 @@ class libde265 extends LibraryPackage
public function buildUnix(): void public function buildUnix(): void
{ {
UnixCMakeExecutor::create($this) UnixCMakeExecutor::create($this)
->addConfigureArgs('-DENABLE_SDL=OFF') ->addConfigureArgs(
'-DENABLE_SDL=OFF',
'-DENABLE_DECODER=OFF',
'-DHAVE_NEON=OFF',
)
->build(); ->build();
$this->patchPkgconfPrefix(['libde265.pc']); $this->patchPkgconfPrefix(['libde265.pc']);
} }

View File

@@ -55,6 +55,10 @@ trait unix
foreach (glob("{$package->getSourceDir()}/ext/*/*.m4") as $m4file) { foreach (glob("{$package->getSourceDir()}/ext/*/*.m4") as $m4file) {
FileSystem::replaceFileStr($m4file, 'PKG_CHECK_MODULES(', 'PKG_CHECK_MODULES_STATIC('); FileSystem::replaceFileStr($m4file, 'PKG_CHECK_MODULES(', 'PKG_CHECK_MODULES_STATIC(');
} }
if (self::getPHPVersionID() >= 80300 && self::getPHPVersionID() < 80400) {
SourcePatcher::patchFile('spc_fix_avx512_cache_before_80400.patch', $this->getSourceDir());
}
} }
#[Stage] #[Stage]
@@ -443,7 +447,7 @@ trait unix
#[BuildFor('Darwin')] #[BuildFor('Darwin')]
#[BuildFor('Linux')] #[BuildFor('Linux')]
public function build(TargetPackage $package): void public function build(TargetPackage $package, PackageInstaller $installer): void
{ {
// frankenphp is not a php sapi, it's a standalone Go binary that depends on libphp.a (embed) // frankenphp is not a php sapi, it's a standalone Go binary that depends on libphp.a (embed)
if ($package->getName() === 'frankenphp') { if ($package->getName() === 'frankenphp') {
@@ -457,9 +461,21 @@ trait unix
return; return;
} }
$package->runStage([$this, 'buildconfForUnix']); // maintainer can skip build though ...
$package->runStage([$this, 'configureForUnix']); $skip_build = false;
$package->runStage([$this, 'makeForUnix']); if ($installer->isPackageResolved('php-embed')
&& $installer->getTargetPackage('php-embed')->getBuildOption('maintainer-skip-build')
) {
$suffix = SystemTarget::getTargetOS() === 'Darwin' ? 'dylib' : 'so';
$skip_build = file_exists(BUILD_LIB_PATH . '/libphp.a')
|| file_exists(BUILD_LIB_PATH . "/libphp.{$suffix}");
}
if (!$skip_build) {
$package->runStage([$this, 'buildconfForUnix']);
$package->runStage([$this, 'configureForUnix']);
$package->runStage([$this, 'makeForUnix']);
}
$package->runStage([$this, 'unixBuildSharedExt']); $package->runStage([$this, 'unixBuildSharedExt']);
} }

View File

@@ -61,9 +61,19 @@ class LinuxToolCheck
'alpine' => self::TOOLS_ALPINE, 'alpine' => self::TOOLS_ALPINE,
'redhat' => self::TOOLS_RHEL, 'redhat' => self::TOOLS_RHEL,
'centos' => array_merge(self::TOOLS_RHEL, ['perl-IPC-Cmd', 'perl-Time-Piece']), 'centos' => array_merge(self::TOOLS_RHEL, ['perl-IPC-Cmd', 'perl-Time-Piece']),
'arch' => self::TOOLS_ARCH, 'arch', 'manjaro' => self::TOOLS_ARCH,
default => self::TOOLS_DEBIAN, default => null,
}; };
if ($required === null) {
// fallback to family-based detection
$family = explode(' ', strtolower($distro['family']));
$required = match (true) {
in_array('alpine', $family) => self::TOOLS_ALPINE,
in_array('rhel', $family) || in_array('fedora', $family) => self::TOOLS_RHEL,
in_array('arch', $family) => self::TOOLS_ARCH,
default => self::TOOLS_DEBIAN,
};
}
$missing = []; $missing = [];
foreach ($required as $package) { foreach ($required as $package) {
if (LinuxUtil::findCommand(self::PROVIDED_COMMAND[$package] ?? $package) === null) { if (LinuxUtil::findCommand(self::PROVIDED_COMMAND[$package] ?? $package) === null) {
@@ -116,10 +126,12 @@ class LinuxToolCheck
if ($install_cmd === null) { if ($install_cmd === null) {
// try family // try family
$family = explode(' ', strtolower($distro['family'])); $family = explode(' ', strtolower($distro['family']));
if (in_array('debian', $family)) { if (in_array('debian', $family) || in_array('ubuntu', $family)) {
$install_cmd = 'apt-get install -y'; $install_cmd = 'apt-get install -y';
} elseif (in_array('rhel', $family) || in_array('fedora', $family)) { } elseif (in_array('rhel', $family) || in_array('fedora', $family)) {
$install_cmd = 'dnf install -y'; $install_cmd = 'dnf install -y';
} elseif (in_array('arch', $family)) {
$install_cmd = 'pacman -S --noconfirm';
} else { } else {
throw new EnvironmentException( throw new EnvironmentException(
"Current linux distro [{$distro['dist']}] does not have an auto-install script for packages yet.", "Current linux distro [{$distro['dist']}] does not have an auto-install script for packages yet.",

View File

@@ -16,8 +16,11 @@ class OSCheck
if (!in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'Windows'])) { if (!in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'Windows'])) {
return CheckResult::fail('Current OS is not supported: ' . PHP_OS_FAMILY); return CheckResult::fail('Current OS is not supported: ' . PHP_OS_FAMILY);
} }
$distro = PHP_OS_FAMILY === 'Linux' ? (' ' . LinuxUtil::getOSRelease()['dist']) : ''; $release = PHP_OS_FAMILY === 'Linux' ? LinuxUtil::getOSRelease() : null;
$known_distro = PHP_OS_FAMILY !== 'Linux' || in_array(LinuxUtil::getOSRelease()['dist'], LinuxUtil::getSupportedDistros()); $distro = $release !== null ? (' ' . $release['dist']) : '';
$known_distro = $release === null
|| in_array($release['dist'], LinuxUtil::getSupportedDistros())
|| count(array_intersect(explode(' ', $release['family']), LinuxUtil::getSupportedDistros())) > 0;
return CheckResult::ok(PHP_OS_FAMILY . ' ' . php_uname('m') . $distro . ', supported' . ($known_distro ? '' : ' (but not tested on this distro)')); return CheckResult::ok(PHP_OS_FAMILY . ' ' . php_uname('m') . $distro . ', supported' . ($known_distro ? '' : ' (but not tested on this distro)'));
} }
} }

View File

@@ -10,6 +10,9 @@ use StaticPHP\DI\ApplicationContext;
use StaticPHP\Exception\ValidationException; use StaticPHP\Exception\ValidationException;
use StaticPHP\Exception\WrongUsageException; use StaticPHP\Exception\WrongUsageException;
use StaticPHP\Runtime\SystemTarget; use StaticPHP\Runtime\SystemTarget;
use StaticPHP\Toolchain\ToolchainManager;
use StaticPHP\Toolchain\ZigToolchain;
use StaticPHP\Util\GlobalEnvManager;
use StaticPHP\Util\SPCConfigUtil; use StaticPHP\Util\SPCConfigUtil;
/** /**
@@ -266,6 +269,11 @@ class PhpExtensionPackage extends Package
*/ */
public function getSharedExtensionEnv(): array public function getSharedExtensionEnv(): array
{ {
$compiler_extra = getenv('SPC_COMPILER_EXTRA') ?: '';
if (!str_contains($compiler_extra, '-lcompiler_rt') && ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$compiler_extra = trim($compiler_extra . ' -lcompiler_rt');
GlobalEnvManager::putenv("SPC_COMPILER_EXTRA={$compiler_extra}");
}
$config = (new SPCConfigUtil())->getExtensionConfig($this); $config = (new SPCConfigUtil())->getExtensionConfig($this);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group '; $preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
@@ -337,6 +345,7 @@ class PhpExtensionPackage extends Package
throw new ValidationException("Extension {$this->getExtensionName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getExtensionName()} build"); throw new ValidationException("Extension {$this->getExtensionName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getExtensionName()} build");
} }
$builder->deployBinary($soFile, $soFile, false); $builder->deployBinary($soFile, $soFile, false);
$this->setOutput('Shared extension path', $soFile);
} }
/** /**

View File

@@ -50,6 +50,7 @@ class LinuxUtil extends UnixUtil
$ret['dist'] = trim($ret['dist'], '"\''); $ret['dist'] = trim($ret['dist'], '"\'');
$ret['ver'] = trim($ret['ver'], '"\''); $ret['ver'] = trim($ret['ver'], '"\'');
$ret['family'] = trim($ret['family'], '"\'');
if (strcasecmp($ret['dist'], 'centos') === 0) { if (strcasecmp($ret['dist'], 'centos') === 0) {
$ret['dist'] = 'redhat'; $ret['dist'] = 'redhat';
@@ -91,7 +92,7 @@ class LinuxUtil extends UnixUtil
{ {
return [ return [
// debian-like // debian-like
'debian', 'ubuntu', 'Deepin', 'neon', 'debian', 'ubuntu', 'Deepin',
// rhel-like // rhel-like
'redhat', 'redhat',
// centos // centos

View File

@@ -4,12 +4,11 @@ declare(strict_types=1);
namespace StaticPHP\Util\System; namespace StaticPHP\Util\System;
use StaticPHP\DI\ApplicationContext;
use StaticPHP\Exception\ExecutionException; use StaticPHP\Exception\ExecutionException;
use StaticPHP\Exception\SPCInternalException; use StaticPHP\Exception\SPCInternalException;
use StaticPHP\Exception\WrongUsageException; use StaticPHP\Exception\WrongUsageException;
use StaticPHP\Runtime\SystemTarget; use StaticPHP\Runtime\SystemTarget;
use StaticPHP\Toolchain\Interface\ToolchainInterface; use StaticPHP\Toolchain\ToolchainManager;
use StaticPHP\Toolchain\ZigToolchain; use StaticPHP\Toolchain\ZigToolchain;
abstract class UnixUtil abstract class UnixUtil
@@ -73,12 +72,8 @@ abstract class UnixUtil
if (!is_file($symbol_file)) { if (!is_file($symbol_file)) {
throw new SPCInternalException("The symbol file {$symbol_file} does not exist, please check if nm command is available."); throw new SPCInternalException("The symbol file {$symbol_file} does not exist, please check if nm command is available.");
} }
// https://github.com/ziglang/zig/issues/24662 // macOS/zig
$toolchain = ApplicationContext::get(ToolchainInterface::class); if (SystemTarget::getTargetOS() === 'Darwin' || ToolchainManager::getToolchainClass() === ZigToolchain::class) {
if ($toolchain instanceof ZigToolchain) {
return '-Wl,--export-dynamic'; // needs release 0.16, can be removed then
}
if (SystemTarget::getTargetOS() !== 'Linux') {
return "-Wl,-exported_symbols_list,{$symbol_file}"; return "-Wl,-exported_symbols_list,{$symbol_file}";
} }
return "-Wl,--dynamic-list={$symbol_file}"; return "-Wl,--dynamic-list={$symbol_file}";

View File

@@ -23,12 +23,16 @@ const DANGER_CMD = [
// spc internal extensions // spc internal extensions
const SPC_INTERNAL_EXTENSIONS = [ const SPC_INTERNAL_EXTENSIONS = [
'core', 'core',
'date',
'hash', 'hash',
'json', 'json',
'lexbor',
'pcre', 'pcre',
'random',
'reflection', 'reflection',
'spl', 'spl',
'standard', 'standard',
'uri',
]; ];
// spc extension alias // spc extension alias

View File

@@ -0,0 +1,91 @@
--- a/build/php.m4
+++ b/build/php.m4
@@ -2812,27 +2812,26 @@
dnl PHP_CHECK_AVX512_SUPPORTS
dnl
AC_DEFUN([PHP_CHECK_AVX512_SUPPORTS], [
- AC_MSG_CHECKING([for avx512 supports in compiler])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw $CFLAGS"
-
- AC_LINK_IFELSE([AC_LANG_SOURCE([[
- #include <immintrin.h>
- int main(void) {
- __m512i mask = _mm512_set1_epi32(0x1);
- char out[32];
- _mm512_storeu_si512(out, _mm512_shuffle_epi8(mask, mask));
- return 0;
- }]])], [
+ AC_CACHE_CHECK([whether compiler supports AVX-512], [php_cv_have_avx512], [
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw $CFLAGS"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[
+ #include <immintrin.h>
+ int main(void) {
+ __m512i mask = _mm512_set1_epi32(0x1);
+ char out[32];
+ _mm512_storeu_si512(out, _mm512_shuffle_epi8(mask, mask));
+ return 0;
+ }]])],
+ [php_cv_have_avx512=yes],
+ [php_cv_have_avx512=no])
+ CFLAGS="$save_CFLAGS"
+ ])
+ if test "$php_cv_have_avx512" = "yes"; then
have_avx512_supports=1
- AC_MSG_RESULT([yes])
- ], [
+ else
have_avx512_supports=0
- AC_MSG_RESULT([no])
- ])
-
- CFLAGS="$save_CFLAGS"
-
+ fi
AC_DEFINE_UNQUOTED([PHP_HAVE_AVX512_SUPPORTS],
[$have_avx512_supports], [Whether the compiler supports AVX512])
])
@@ -2841,24 +2840,26 @@
dnl PHP_CHECK_AVX512_VBMI_SUPPORTS
dnl
AC_DEFUN([PHP_CHECK_AVX512_VBMI_SUPPORTS], [
- AC_MSG_CHECKING([for avx512 vbmi supports in compiler])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi $CFLAGS"
- AC_LINK_IFELSE([AC_LANG_SOURCE([[
- #include <immintrin.h>
- int main(void) {
- __m512i mask = _mm512_set1_epi32(0x1);
- char out[32];
- _mm512_storeu_si512(out, _mm512_permutexvar_epi8(mask, mask));
- return 0;
- }]])], [
+ AC_CACHE_CHECK([whether compiler supports AVX-512 VBMI], [php_cv_have_avx512vbmi], [
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi $CFLAGS"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[
+ #include <immintrin.h>
+ int main(void) {
+ __m512i mask = _mm512_set1_epi32(0x1);
+ char out[32];
+ _mm512_storeu_si512(out, _mm512_permutexvar_epi8(mask, mask));
+ return 0;
+ }]])],
+ [php_cv_have_avx512vbmi=yes],
+ [php_cv_have_avx512vbmi=no])
+ CFLAGS="$save_CFLAGS"
+ ])
+ if test "$php_cv_have_avx512vbmi" = "yes"; then
have_avx512_vbmi_supports=1
- AC_MSG_RESULT([yes])
- ], [
+ else
have_avx512_vbmi_supports=0
- AC_MSG_RESULT([no])
- ])
- CFLAGS="$save_CFLAGS"
+ fi
AC_DEFINE_UNQUOTED([PHP_HAVE_AVX512_VBMI_SUPPORTS],
[$have_avx512_vbmi_supports], [Whether the compiler supports AVX512 VBMI])
])