Merge branch 'refs/heads/main' into sapi/cgi-win

# Conflicts:
#	src/globals/test-extensions.php
This commit is contained in:
crazywhalecc 2025-10-25 00:11:45 +08:00
commit bb44e88c3b
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
20 changed files with 115 additions and 33 deletions

View File

@ -341,6 +341,7 @@
"ext-depends": [
"xml"
],
"build-with-php": true,
"target": [
"static"
]
@ -461,6 +462,7 @@
"mysqli": {
"type": "builtin",
"arg-type": "with",
"build-with-php": true,
"ext-depends": [
"mysqlnd"
]
@ -468,6 +470,7 @@
"mysqlnd": {
"type": "builtin",
"arg-type-windows": "with",
"build-with-php": true,
"lib-depends": [
"zlib"
]
@ -797,6 +800,7 @@
"type": "builtin",
"arg-type": "with-path",
"arg-type-windows": "with",
"build-with-php": true,
"lib-depends": [
"sqlite"
]
@ -1177,6 +1181,7 @@
"lib-depends": [
"zlib"
],
"build-with-php": true,
"target": [
"static"
]

View File

@ -795,7 +795,7 @@
"libxml2",
"openssl",
"zlib",
"readline"
"libedit"
],
"lib-suggests": [
"icu",

View File

@ -47,7 +47,7 @@
"provide-pre-built": true,
"license": {
"type": "file",
"path": "doc/COPYING"
"path": "doc/COPYING.LGPL"
}
},
"brotli": {
@ -306,16 +306,17 @@
"regex": "/href=\"(?<file>gettext-(?<version>[^\"]+)\\.tar\\.xz)\"/",
"license": {
"type": "file",
"path": "COPYING"
"path": "gettext-runtime/intl/COPYING.LIB"
}
},
"gmp": {
"type": "url",
"url": "https://dl.static-php.dev/static-php-cli/deps/gmp/gmp-6.3.0.tar.xz",
"type": "filelist",
"url": "https://gmplib.org/download/gmp/",
"regex": "/href=\"(?<file>gmp-(?<version>[^\"]+)\\.tar\\.xz)\"/",
"provide-pre-built": true,
"alt": {
"type": "ghtagtar",
"repo": "alisw/GMP"
"type": "url",
"url": "https://dl.static-php.dev/static-php-cli/deps/gmp/gmp-6.3.0.tar.xz"
},
"license": {
"type": "text",
@ -439,7 +440,7 @@
"provide-pre-built": true,
"license": {
"type": "file",
"path": "doc/COPYING"
"path": "doc/COPYING.LGPL"
}
},
"libaom": {

View File

@ -15,7 +15,11 @@ class gettext extends Extension
public function patchBeforeBuildconf(): bool
{
if ($this->builder instanceof MacOSBuilder) {
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/gettext/config.m4', 'AC_CHECK_LIB($GETTEXT_CHECK_IN_LIB', 'AC_CHECK_LIB(intl');
FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/gettext/config.m4',
['AC_CHECK_LIB($GETTEXT_CHECK_IN_LIB', 'AC_CHECK_LIB([$GETTEXT_CHECK_IN_LIB'],
['AC_CHECK_LIB(intl', 'AC_CHECK_LIB([intl'] // new php versions use a bracket
);
}
return true;
}

View File

@ -69,12 +69,15 @@ class swoole extends Extension
$arg .= $this->builder->getExt('swoole-hook-pgsql') ? ' --enable-swoole-pgsql' : ' --disable-swoole-pgsql';
$arg .= $this->builder->getExt('swoole-hook-mysql') ? ' --enable-mysqlnd' : ' --disable-mysqlnd';
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? ' --enable-swoole-sqlite' : ' --disable-swoole-sqlite';
if ($this->builder->getExt('swoole-hook-odbc')) {
$config = (new SPCConfigUtil($this->builder, ['libs_only_deps' => true]))->config([], ['unixodbc']);
$arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"';
}
if ($this->getExtVersion() >= '6.1.0') {
$arg .= ' --enable-swoole-stdext';
}
if (SPCTarget::getTargetOS() === 'Darwin') {
$arg .= ' ac_cv_lib_pthread_pthread_barrier_init=no';
}

View File

@ -7,6 +7,7 @@ namespace SPC\builder\linux;
use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\PatchException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
use SPC\util\GlobalEnvManager;
@ -283,12 +284,17 @@ class LinuxBuilder extends UnixBuilderBase
*/
protected function buildEmbed(): void
{
$sharedExts = array_filter($this->exts, static fn ($ext) => $ext->isBuildShared());
$sharedExts = array_filter($sharedExts, static function ($ext) {
return Config::getExt($ext->getName(), 'build-with-php') === true;
});
$install_modules = $sharedExts ? 'install-modules' : '';
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi install-build install-headers install-programs");
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs");
$ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: '';
$libDir = BUILD_LIB_PATH;

View File

@ -7,6 +7,7 @@ namespace SPC\builder\macos;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
use SPC\util\GlobalEnvManager;
@ -264,10 +265,15 @@ class MacOSBuilder extends UnixBuilderBase
*/
protected function buildEmbed(): void
{
$sharedExts = array_filter($this->exts, static fn ($ext) => $ext->isBuildShared());
$sharedExts = array_filter($sharedExts, static function ($ext) {
return Config::getExt($ext->getName(), 'build-with-php') === true;
});
$install_modules = $sharedExts ? 'install-modules' : '';
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
shell()->cd(SOURCE_PATH . '/php-src')
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi install-build install-headers install-programs");
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs");
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar';

View File

@ -17,7 +17,7 @@ trait attr
->exec('libtoolize --force --copy')
->exec('./autogen.sh || autoreconf -if')
->configure('--disable-nls')
->make();
->make('install-attributes_h install-data install-libattr_h install-libLTLIBRARIES install-pkgincludeHEADERS install-pkgconfDATA', with_install: false);
$this->patchPkgconfPrefix(['libattr.pc'], PKGCONF_PATCH_PREFIX);
}
}

View File

@ -31,7 +31,7 @@ trait gettext
$autoconf->addConfigureArgs('--disable-threads');
}
$autoconf->configure()->make();
$autoconf->configure()->make(dir: $this->getSourceDir() . '/gettext-runtime/intl');
$this->patchLaDependencyPrefix();
}
}

View File

@ -26,7 +26,7 @@ trait libacl
->exec('libtoolize --force --copy')
->exec('./autogen.sh || autoreconf -if')
->configure('--disable-nls', '--disable-tests')
->make();
->make('install-acl_h install-libacl_h install-data install-libLTLIBRARIES install-pkgincludeHEADERS install-sysincludeHEADERS install-pkgconfDATA', with_install: false);
$this->patchPkgconfPrefix(['libacl.pc'], PKGCONF_PATCH_PREFIX);
}
}

View File

@ -4,10 +4,21 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait libedit
{
public function patchBeforeBuild(): bool
{
FileSystem::replaceFileRegex(
$this->source_dir . '/src/sys.h',
'|//#define\s+strl|',
'#define strl'
);
return true;
}
protected function build(): void
{
UnixAutoconfExecutor::create($this)

View File

@ -10,7 +10,13 @@ trait libiconv
{
protected function build(): void
{
UnixAutoconfExecutor::create($this)->configure('--enable-extra-encodings')->make();
UnixAutoconfExecutor::create($this)
->configure(
'--enable-extra-encodings',
'--enable-year2038',
)
->make('install-lib', with_install: false)
->make('install-lib', with_install: false, dir: $this->getSourceDir() . '/libcharset');
$this->patchLaDependencyPrefix();
}
}

View File

@ -22,6 +22,7 @@ trait libzip
'-DBUILD_EXAMPLES=OFF',
'-DBUILD_REGRESS=OFF',
'-DBUILD_TOOLS=OFF',
'-DBUILD_OSSFUZZ=OFF',
)
->build();
$this->patchPkgconfPrefix(['libzip.pc'], PKGCONF_PATCH_PREFIX);

View File

@ -82,14 +82,14 @@ class LinuxToolCheckList
return CheckResult::ok();
}
#[AsCheckItem('if cmake version >= 3.18', limit_os: 'Linux')]
#[AsCheckItem('if cmake version >= 3.22', limit_os: 'Linux')]
public function checkCMakeVersion(): ?CheckResult
{
$ver = get_cmake_version();
if ($ver === null) {
return CheckResult::fail('Failed to get cmake version');
}
if (version_compare($ver, '3.18.0') < 0) {
if (version_compare($ver, '3.22.0') < 0) {
return CheckResult::fail('cmake version is too low (' . $ver . '), please update it manually!');
}
return CheckResult::ok($ver);

View File

@ -645,6 +645,36 @@ class FileSystem
};
}
/**
* Move file or directory, handling cross-device scenarios
* Uses rename() if possible, falls back to copy+delete for cross-device moves
*
* @param string $source Source path
* @param string $dest Destination path
*/
private static function moveFileOrDir(string $source, string $dest): void
{
$source = self::convertPath($source);
$dest = self::convertPath($dest);
// Try rename first (fast, atomic)
if (@rename($source, $dest)) {
return;
}
if (is_dir($source)) {
self::copyDir($source, $dest);
self::removeDir($source);
} else {
if (!copy($source, $dest)) {
throw new FileSystemException("Failed to copy file from {$source} to {$dest}");
}
if (!unlink($source)) {
throw new FileSystemException("Failed to remove source file: {$source}");
}
}
}
/**
* Unzip file with stripping top-level directory
*/
@ -675,10 +705,10 @@ class FileSystem
if (is_dir($extract_path)) {
self::removeDir($extract_path);
}
// if only one dir, move its contents to extract_path using rename
// if only one dir, move its contents to extract_path
$subdir = self::convertPath("{$temp_dir}/{$contents[0]}");
if (count($contents) === 1 && is_dir($subdir)) {
rename($subdir, $extract_path);
self::moveFileOrDir($subdir, $extract_path);
} else {
// else, if it contains only one dir, strip dir and copy other files
$dircount = 0;
@ -701,17 +731,20 @@ class FileSystem
throw new FileSystemException("Cannot scan unzip temp sub-dir: {$dir[0]}");
}
foreach ($sub_contents as $sub_item) {
rename(self::convertPath("{$temp_dir}/{$dir[0]}/{$sub_item}"), self::convertPath("{$extract_path}/{$sub_item}"));
self::moveFileOrDir(self::convertPath("{$temp_dir}/{$dir[0]}/{$sub_item}"), self::convertPath("{$extract_path}/{$sub_item}"));
}
} else {
foreach ($dir as $item) {
rename(self::convertPath("{$temp_dir}/{$item}"), self::convertPath("{$extract_path}/{$item}"));
self::moveFileOrDir(self::convertPath("{$temp_dir}/{$item}"), self::convertPath("{$extract_path}/{$item}"));
}
}
// move top-level files to extract_path
foreach ($top_files as $top_file) {
rename(self::convertPath("{$temp_dir}/{$top_file}"), self::convertPath("{$extract_path}/{$top_file}"));
self::moveFileOrDir(self::convertPath("{$temp_dir}/{$top_file}"), self::convertPath("{$extract_path}/{$top_file}"));
}
}
// Clean up temp directory
self::removeDir($temp_dir);
}
}

View File

@ -44,7 +44,7 @@ class SourcePatcher
}
foreach ($builder->getLibs() as $lib) {
if ($lib->patchBeforeBuildconf() === true) {
logger()->info("Library [{$lib->getName()}]patched before buildconf");
logger()->info("Library [{$lib->getName()}] patched before buildconf");
}
}
// patch windows php 8.1 bug

View File

@ -16,7 +16,7 @@ class PhpSource extends CustomSourceBase
{
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4';
if ($major === '8.5') {
Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://github.com/php/php-src/archive/refs/tags/php-8.5.0RC2.tar.gz'], $force);
Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~daniels/php-8.5.0RC3.tar.xz'], $force);
} elseif ($major === 'git') {
Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force);
} else {

View File

@ -50,18 +50,22 @@ class UnixAutoconfExecutor extends Executor
* @param bool $with_clean Whether to clean before building
* @param array $after_env_vars Environment variables postfix
*/
public function make(string $target = '', false|string $with_install = 'install', bool $with_clean = true, array $after_env_vars = []): static
public function make(string $target = '', false|string $with_install = 'install', bool $with_clean = true, array $after_env_vars = [], ?string $dir = null): static
{
return $this->seekLogFileOnException(function () use ($target, $with_install, $with_clean, $after_env_vars) {
return $this->seekLogFileOnException(function () use ($target, $with_install, $with_clean, $after_env_vars, $dir) {
$shell = $this->shell;
if ($dir) {
$shell = $shell->cd($dir);
}
if ($with_clean) {
$this->shell->exec('make clean');
$shell->exec('make clean');
}
$after_env_vars_str = $after_env_vars !== [] ? shell()->setEnv($after_env_vars)->getEnvString() : '';
$this->shell->exec("make -j{$this->library->getBuilder()->concurrency} {$target} {$after_env_vars_str}");
$shell->exec("make -j{$this->library->getBuilder()->concurrency} {$target} {$after_env_vars_str}");
if ($with_install !== false) {
$this->shell->exec("make {$with_install}");
$shell->exec("make {$with_install}");
}
return $this->shell;
return $shell;
});
}

View File

@ -205,7 +205,7 @@ SET(CMAKE_INSTALL_PREFIX "{$root}")
SET(CMAKE_INSTALL_LIBDIR "lib")
set(PKG_CONFIG_EXECUTABLE "{$pkgConfigExecutable}")
list(APPEND PKG_CONFIG_EXECUTABLE "--static")
set(PKG_CONFIG_ARGN "--static" CACHE STRING "Extra arguments for pkg-config" FORCE)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -8,6 +8,7 @@ use SPC\builder\freebsd\library\BSDLibraryBase;
use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\SPCInternalException;
use SPC\util\SPCTarget;
use ZM\Logger\ConsoleColor;
/**
@ -28,6 +29,7 @@ class UnixShell extends Shell
public function exec(string $cmd): static
{
$cmd = clean_spaces($cmd);
/* @phpstan-ignore-next-line */
logger()->info(ConsoleColor::yellow('[EXEC] ') . ConsoleColor::green($cmd));
$original_command = $cmd;
@ -48,7 +50,7 @@ class UnixShell extends Shell
'CFLAGS' => $library->getLibExtraCFlags(),
'CXXFLAGS' => $library->getLibExtraCXXFlags(),
'LDFLAGS' => $library->getLibExtraLdFlags(),
'LIBS' => $library->getLibExtraLibs(),
'LIBS' => $library->getLibExtraLibs() . SPCTarget::getRuntimeLibs(),
]);
return $this;
}