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:
type: ghrel
repo: openssl/openssl
match: openssl.+\.tar\.gz
match: openssl-3.+\.tar\.gz
prefer-stable: true
source-mirror:
type: filelist
url: 'https://www.openssl.org/source/'
regex: '/href="(?<file>openssl-(?<version>[^"]+)\.tar\.gz)"/'
regex: '/href="(?<file>openssl-(?<version>3\.[^"]+)\.tar\.gz)"/'
binary: hosted
metadata:
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}
| Option | Description |
|-------------------------|-----------------------------------------------------------------------|
| `--build-shared=<list>` | Compile specific extensions as shared libraries (requires embed SAPI) |
| Option | Description |
|-----------------------------|------------------------------------------------------------------------------------------------------|
| `--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}

View File

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

View File

@@ -22,8 +22,14 @@ class decimal extends PhpExtensionPackage
{
FileSystem::replaceFileStr(
$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\Runtime\Executor\UnixAutoconfExecutor;
use StaticPHP\Runtime\SystemTarget;
use StaticPHP\Toolchain\Interface\ToolchainInterface;
use StaticPHP\Toolchain\ZigToolchain;
use StaticPHP\Util\SPCConfigUtil;
#[Library('krb5')]
@@ -17,7 +19,7 @@ class krb5
{
#[BuildFor('Linux')]
#[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')) {
shell()->cd($lib->getSourceRoot())->exec('autoreconf -if');
@@ -45,12 +47,15 @@ class krb5
$extraEnv['LDFLAGS'] = '-framework Kerberos';
$args[] = 'ac_cv_func_secure_getenv=no';
}
UnixAutoconfExecutor::create($lib)
$executor = UnixAutoconfExecutor::create($lib)
->appendEnv($extraEnv)
->optionalPackage('ldap', '--with-ldap', '--without-ldap')
->optionalPackage('libedit', '--with-libedit', '--without-libedit')
->configure(...$args)
->make();
->configure(...$args);
if ($toolchain instanceof ZigToolchain) {
$executor->exec('find . -name Makefile -exec sed -i "s/-Werror=incompatible-pointer-types//g" {} +');
}
$executor->make();
$lib->patchPkgconfPrefix([
'krb5-gssapi.pc',
'krb5.pc',

View File

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

View File

@@ -55,6 +55,10 @@ trait unix
foreach (glob("{$package->getSourceDir()}/ext/*/*.m4") as $m4file) {
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]
@@ -443,7 +447,7 @@ trait unix
#[BuildFor('Darwin')]
#[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)
if ($package->getName() === 'frankenphp') {
@@ -457,9 +461,21 @@ trait unix
return;
}
$package->runStage([$this, 'buildconfForUnix']);
$package->runStage([$this, 'configureForUnix']);
$package->runStage([$this, 'makeForUnix']);
// maintainer can skip build though ...
$skip_build = false;
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']);
}

View File

@@ -61,9 +61,19 @@ class LinuxToolCheck
'alpine' => self::TOOLS_ALPINE,
'redhat' => self::TOOLS_RHEL,
'centos' => array_merge(self::TOOLS_RHEL, ['perl-IPC-Cmd', 'perl-Time-Piece']),
'arch' => self::TOOLS_ARCH,
default => self::TOOLS_DEBIAN,
'arch', 'manjaro' => self::TOOLS_ARCH,
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 = [];
foreach ($required as $package) {
if (LinuxUtil::findCommand(self::PROVIDED_COMMAND[$package] ?? $package) === null) {
@@ -116,10 +126,12 @@ class LinuxToolCheck
if ($install_cmd === null) {
// try 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';
} elseif (in_array('rhel', $family) || in_array('fedora', $family)) {
$install_cmd = 'dnf install -y';
} elseif (in_array('arch', $family)) {
$install_cmd = 'pacman -S --noconfirm';
} else {
throw new EnvironmentException(
"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'])) {
return CheckResult::fail('Current OS is not supported: ' . PHP_OS_FAMILY);
}
$distro = PHP_OS_FAMILY === 'Linux' ? (' ' . LinuxUtil::getOSRelease()['dist']) : '';
$known_distro = PHP_OS_FAMILY !== 'Linux' || in_array(LinuxUtil::getOSRelease()['dist'], LinuxUtil::getSupportedDistros());
$release = PHP_OS_FAMILY === 'Linux' ? LinuxUtil::getOSRelease() : null;
$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)'));
}
}

View File

@@ -10,6 +10,9 @@ use StaticPHP\DI\ApplicationContext;
use StaticPHP\Exception\ValidationException;
use StaticPHP\Exception\WrongUsageException;
use StaticPHP\Runtime\SystemTarget;
use StaticPHP\Toolchain\ToolchainManager;
use StaticPHP\Toolchain\ZigToolchain;
use StaticPHP\Util\GlobalEnvManager;
use StaticPHP\Util\SPCConfigUtil;
/**
@@ -266,6 +269,11 @@ class PhpExtensionPackage extends Package
*/
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);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$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");
}
$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['ver'] = trim($ret['ver'], '"\'');
$ret['family'] = trim($ret['family'], '"\'');
if (strcasecmp($ret['dist'], 'centos') === 0) {
$ret['dist'] = 'redhat';
@@ -91,7 +92,7 @@ class LinuxUtil extends UnixUtil
{
return [
// debian-like
'debian', 'ubuntu', 'Deepin', 'neon',
'debian', 'ubuntu', 'Deepin',
// rhel-like
'redhat',
// centos

View File

@@ -4,12 +4,11 @@ declare(strict_types=1);
namespace StaticPHP\Util\System;
use StaticPHP\DI\ApplicationContext;
use StaticPHP\Exception\ExecutionException;
use StaticPHP\Exception\SPCInternalException;
use StaticPHP\Exception\WrongUsageException;
use StaticPHP\Runtime\SystemTarget;
use StaticPHP\Toolchain\Interface\ToolchainInterface;
use StaticPHP\Toolchain\ToolchainManager;
use StaticPHP\Toolchain\ZigToolchain;
abstract class UnixUtil
@@ -73,12 +72,8 @@ abstract class UnixUtil
if (!is_file($symbol_file)) {
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
$toolchain = ApplicationContext::get(ToolchainInterface::class);
if ($toolchain instanceof ZigToolchain) {
return '-Wl,--export-dynamic'; // needs release 0.16, can be removed then
}
if (SystemTarget::getTargetOS() !== 'Linux') {
// macOS/zig
if (SystemTarget::getTargetOS() === 'Darwin' || ToolchainManager::getToolchainClass() === ZigToolchain::class) {
return "-Wl,-exported_symbols_list,{$symbol_file}";
}
return "-Wl,--dynamic-list={$symbol_file}";

View File

@@ -23,12 +23,16 @@ const DANGER_CMD = [
// spc internal extensions
const SPC_INTERNAL_EXTENSIONS = [
'core',
'date',
'hash',
'json',
'lexbor',
'pcre',
'random',
'reflection',
'spl',
'standard',
'uri',
];
// 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])
])