Merge branch 'main' into php-85

# Conflicts:
#	src/SPC/builder/linux/LinuxBuilder.php
#	src/SPC/store/source/PhpSource.php
#	src/globals/test-extensions.php
This commit is contained in:
crazywhalecc
2025-07-31 23:46:34 +08:00
88 changed files with 1129 additions and 678 deletions

View File

@@ -12,7 +12,9 @@ use SPC\store\Config;
use SPC\store\CurlHook;
use SPC\store\Downloader;
use SPC\store\FileSystem;
use SPC\store\pkg\GoXcaddy;
use SPC\util\DependencyUtil;
use SPC\util\GlobalEnvManager;
use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget;
@@ -24,6 +26,9 @@ abstract class UnixBuilderBase extends BuilderBase
/** @var string C++ flags */
public string $arch_cxx_flags;
/** @var string LD flags */
public string $arch_ld_flags;
public function proveLibs(array $sorted_libraries): void
{
// search all supported libs
@@ -122,11 +127,7 @@ abstract class UnixBuilderBase extends BuilderBase
if (SPCTarget::isStatic()) {
$lens .= ' -static';
}
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
if ($ret !== 0) {
throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out));
}
// if someone changed to --enable-embed=shared, we need to add LD_LIBRARY_PATH
// if someone changed to EMBED_TYPE=shared, we need to add LD_LIBRARY_PATH
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
if (PHP_OS_FAMILY === 'Darwin') {
$ext_path = 'DYLD_LIBRARY_PATH=' . BUILD_LIB_PATH . ':$DYLD_LIBRARY_PATH ';
@@ -211,7 +212,6 @@ abstract class UnixBuilderBase extends BuilderBase
logger()->debug('Patching phpize prefix');
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'");
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#');
FileSystem::replaceFileStr(BUILD_LIB_PATH . '/php/build/phpize.m4', 'test "[$]$1" = "no" && $1=yes', '# test "[$]$1" = "no" && $1=yes');
}
// patch php-config
if (file_exists(BUILD_BIN_PATH . '/php-config')) {
@@ -237,18 +237,6 @@ abstract class UnixBuilderBase extends BuilderBase
*/
protected function buildFrankenphp(): void
{
$os = match (PHP_OS_FAMILY) {
'Linux' => 'linux',
'Windows' => 'win',
'Darwin' => 'macos',
'BSD' => 'freebsd',
default => throw new RuntimeException('Unsupported OS: ' . PHP_OS_FAMILY),
};
$arch = arch2gnu(php_uname('m'));
// define executables for go and xcaddy
$xcaddy_exec = PKG_ROOT_PATH . "/go-xcaddy-{$arch}-{$os}/bin/xcaddy";
$nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : '';
$nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : '';
$xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES');
@@ -261,30 +249,30 @@ abstract class UnixBuilderBase extends BuilderBase
$xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules);
}
$lrt = PHP_OS_FAMILY === 'Linux' ? '-lrt' : '';
$releaseInfo = json_decode(Downloader::curlExec('https://api.github.com/repos/php/frankenphp/releases/latest', retries: 3, hooks: [[CurlHook::class, 'setupGithubToken']]), true);
$releaseInfo = json_decode(Downloader::curlExec(
'https://api.github.com/repos/php/frankenphp/releases/latest',
hooks: [[CurlHook::class, 'setupGithubToken']],
), true);
$frankenPhpVersion = $releaseInfo['tag_name'];
$libphpVersion = $this->getPHPVersion();
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
$libphpVersion = preg_replace('/\.\d$/', '', $libphpVersion);
}
$debugFlags = $this->getOption('no-strip') ? "'-w -s' " : '';
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
$extLdFlags = "-extldflags '-pie'";
$muslTags = '';
$staticFlags = '';
if (SPCTarget::isStatic()) {
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000'";
$muslTags = 'static_build,';
$staticFlags = '-static-pie';
}
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list, with_dependencies: true);
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
$env = [
'PATH' => PKG_ROOT_PATH . "/go-xcaddy-{$arch}-{$os}/bin:" . getenv('PATH'),
'GOROOT' => PKG_ROOT_PATH . "/go-xcaddy-{$arch}-{$os}",
'GOBIN' => PKG_ROOT_PATH . "/go-xcaddy-{$arch}-{$os}/bin",
'GOPATH' => PKG_ROOT_PATH . '/go',
'CGO_ENABLED' => '1',
'CGO_CFLAGS' => $config['cflags'],
'CGO_LDFLAGS' => "{$config['ldflags']} {$config['libs']} {$lrt}",
'CGO_LDFLAGS' => "{$staticFlags} {$config['ldflags']} {$config['libs']} {$lrt}",
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags .
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
@@ -292,8 +280,23 @@ abstract class UnixBuilderBase extends BuilderBase
"-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
foreach (GoXcaddy::getEnvironment() as $key => $value) {
if ($key === 'PATH') {
GlobalEnvManager::addPathIfNotExists($value);
} else {
$env[$key] = $value;
}
}
shell()->cd(BUILD_BIN_PATH)
->setEnv($env)
->exec("{$xcaddy_exec} build --output frankenphp {$xcaddyModules}");
->exec("xcaddy build --output frankenphp {$xcaddyModules}");
if (!$this->getOption('no-strip', false) && file_exists(BUILD_BIN_PATH . '/frankenphp')) {
if (PHP_OS_FAMILY === 'Linux') {
shell()->cd(BUILD_BIN_PATH)->exec('strip --strip-unneeded frankenphp');
} else { // macOS doesn't understand strip-unneeded
shell()->cd(BUILD_BIN_PATH)->exec('strip -S frankenphp');
}
}
}
}

View File

@@ -15,6 +15,9 @@ trait attr
protected function build(): void
{
UnixAutoconfExecutor::create($this)
->appendEnv([
'CFLAGS' => '-Wno-int-conversion -Wno-implicit-function-declaration',
])
->exec('libtoolize --force --copy')
->exec('./autogen.sh || autoreconf -if')
->configure('--disable-nls')

View File

@@ -31,7 +31,7 @@ trait gettext
$autoconf->addConfigureArgs('--disable-threads');
}
$autoconf->configure()->make(with_clean: true);
$autoconf->configure()->make();
$this->patchLaDependencyPrefix();
}
}

View File

@@ -33,6 +33,7 @@ trait imagemagick
->optionalLib('freetype', ...ac_with_args('freetype'))
->optionalLib('bzip2', ...ac_with_args('bzlib'))
->optionalLib('libjxl', ...ac_with_args('jxl'))
->optionalLib('jbig', ...ac_with_args('jbig'))
->addConfigureArgs(
'--disable-openmp',
'--without-x',

View File

@@ -27,8 +27,10 @@ trait ldap
'--disable-slapd',
'--without-systemd',
'--without-cyrus-sasl',
'ac_cv_func_pthread_kill_other_threads_np=no'
)
->appendEnv([
'CFLAGS' => '-Wno-date-time',
'LDFLAGS' => "-L{$this->getLibDir()}",
'CPPFLAGS' => "-I{$this->getIncludeDir()}",
])

View File

@@ -4,22 +4,24 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\executor\UnixCMakeExecutor;
trait libaom
{
/**
* @throws RuntimeException
* @throws FileSystemException
*/
protected function build(): void
{
$extra = getenv('SPC_COMPILER_EXTRA');
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$new = trim($extra . ' -D_GNU_SOURCE');
f_putenv("SPC_COMPILER_EXTRA={$new}");
}
UnixCMakeExecutor::create($this)
->setBuildDir("{$this->source_dir}/builddir")
->addConfigureArgs('-DAOM_TARGET_CPU=generic')
->build();
f_putenv("SPC_COMPILER_EXTRA={$extra}");
$this->patchPkgconfPrefix(['aom.pc']);
}
}

View File

@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\executor\UnixCMakeExecutor;
use SPC\util\SPCTarget;
@@ -11,18 +13,31 @@ trait libjxl
{
protected function build(): void
{
UnixCMakeExecutor::create($this)
->addConfigureArgs('-DJPEGXL_ENABLE_TOOLS=OFF')
->addConfigureArgs('-DJPEGXL_ENABLE_EXAMPLES=OFF')
->addConfigureArgs('-DJPEGXL_ENABLE_MANPAGES=OFF')
->addConfigureArgs('-DJPEGXL_ENABLE_BENCHMARK=OFF')
->addConfigureArgs('-DJPEGXL_ENABLE_PLUGINS=OFF')
->addConfigureArgs('-DJPEGXL_ENABLE_SJPOEG=ON')
->addConfigureArgs('-DJPEGXL_ENABLE_JNI=OFF')
->addConfigureArgs('-DJPEGXL_ENABLE_TRANSCODE_JPEG=ON')
->addConfigureArgs('-DJPEGXL_STATIC=' . (SPCTarget::isStatic() ? 'ON' : 'OFF'))
->addConfigureArgs('-DJPEGXL_FORCE_SYSTEM_BROTLI=ON')
->addConfigureArgs('-DBUILD_TESTING=OFF')
->build();
$cmake = UnixCMakeExecutor::create($this)
->addConfigureArgs(
'-DJPEGXL_ENABLE_TOOLS=OFF',
'-DJPEGXL_ENABLE_EXAMPLES=OFF',
'-DJPEGXL_ENABLE_MANPAGES=OFF',
'-DJPEGXL_ENABLE_BENCHMARK=OFF',
'-DJPEGXL_ENABLE_PLUGINS=OFF',
'-DJPEGXL_ENABLE_SJPEG=ON',
'-DJPEGXL_ENABLE_JNI=OFF',
'-DJPEGXL_ENABLE_TRANSCODE_JPEG=ON',
'-DJPEGXL_STATIC=' . (SPCTarget::isStatic() ? 'ON' : 'OFF'),
'-DJPEGXL_FORCE_SYSTEM_BROTLI=ON',
'-DBUILD_TESTING=OFF'
);
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$cmake->addConfigureArgs(
'-DCXX_MAVX512F_SUPPORTED:BOOL=FALSE',
'-DCXX_MAVX512DQ_SUPPORTED:BOOL=FALSE',
'-DCXX_MAVX512CD_SUPPORTED:BOOL=FALSE',
'-DCXX_MAVX512BW_SUPPORTED:BOOL=FALSE',
'-DCXX_MAVX512VL_SUPPORTED:BOOL=FALSE'
);
}
$cmake->build();
}
}

View File

@@ -19,7 +19,11 @@ trait liblz4
{
shell()->cd($this->source_dir)->initializeEnv($this)
->exec("make PREFIX='' clean")
->exec("make -j{$this->builder->concurrency} PREFIX=''")
->exec("make lib -j{$this->builder->concurrency} PREFIX=''");
FileSystem::replaceFileStr($this->source_dir . '/Makefile', '$(MAKE) -C $(PRGDIR) $@', '');
shell()->cd($this->source_dir)
->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['liblz4.pc']);

View File

@@ -6,10 +6,26 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait librdkafka
{
public function patchBeforeBuild(): bool
{
FileSystem::replaceFileStr(
$this->source_dir . '/lds-gen.py',
"funcs.append('rd_ut_coverage_check')",
''
);
FileSystem::replaceFileStr(
$this->source_dir . '/src/rd.h',
'#error "IOV_MAX not defined"',
"#define IOV_MAX 1024\n#define __GNU__"
);
return true;
}
/**
* @throws FileSystemException
* @throws RuntimeException
@@ -17,6 +33,7 @@ trait librdkafka
protected function build(): void
{
UnixAutoconfExecutor::create($this)
->appendEnv(['CFLAGS' => '-Wno-int-conversion -Wno-unused-but-set-variable -Wno-unused-variable'])
->optionalLib(
'zstd',
function ($lib) {

View File

@@ -35,18 +35,19 @@ trait libxslt
'--without-debugger',
"--with-libxml-prefix={$this->getBuildRootPath()}",
);
if (getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH') && getenv('SPC_LINUX_DEFAULT_LIBRARY_PATH')) {
if (getenv('SPC_LD_LIBRARY_PATH') && getenv('SPC_LIBRARY_PATH')) {
$ac->appendEnv([
'LD_LIBRARY_PATH' => getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH'),
'LIBRARY_PATH' => getenv('SPC_LINUX_DEFAULT_LIBRARY_PATH'),
'LD_LIBRARY_PATH' => getenv('SPC_LD_LIBRARY_PATH'),
'LIBRARY_PATH' => getenv('SPC_LIBRARY_PATH'),
]);
}
$ac->configure()->make();
$this->patchPkgconfPrefix(['libexslt.pc', 'libxslt.pc']);
$this->patchLaDependencyPrefix();
$AR = getenv('AR') ?: 'ar';
shell()->cd(BUILD_LIB_PATH)
->exec("ar -t libxslt.a | grep '\\.a$' | xargs -n1 ar d libxslt.a")
->exec("ar -t libexslt.a | grep '\\.a$' | xargs -n1 ar d libexslt.a");
->exec("{$AR} -t libxslt.a | grep '\\.a$' | xargs -n1 {$AR} d libxslt.a")
->exec("{$AR} -t libexslt.a | grep '\\.a$' | xargs -n1 {$AR} d libexslt.a");
}
}

View File

@@ -14,6 +14,7 @@ trait mimalloc
$cmake = UnixCMakeExecutor::create($this)
->addConfigureArgs(
'-DMI_BUILD_SHARED=OFF',
'-DMI_BUILD_OBJECT=OFF',
'-DMI_INSTALL_TOPLEVEL=ON',
);
if (SPCTarget::getLibc() === 'musl') {

View File

@@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
use SPC\util\SPCTarget;
trait ncurses
{
@@ -14,6 +15,9 @@ trait ncurses
$filelist = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true);
UnixAutoconfExecutor::create($this)
->appendEnv([
'LDFLAGS' => SPCTarget::isStatic() ? '-static' : '',
])
->configure(
'--enable-overwrite',
'--with-curses-h',

View File

@@ -48,6 +48,7 @@ trait ngtcp2
// on macOS, the static library may contain other static libraries?
// ld: archive member 'libssl.a' not a mach-o file in libngtcp2_crypto_ossl.a
shell()->cd(BUILD_LIB_PATH)->exec("ar -t libngtcp2_crypto_ossl.a | grep '\\.a$' | xargs -n1 ar d libngtcp2_crypto_ossl.a");
$AR = getenv('AR') ?: 'ar';
shell()->cd(BUILD_LIB_PATH)->exec("{$AR} -t libngtcp2_crypto_ossl.a | grep '\\.a$' | xargs -n1 {$AR} d libngtcp2_crypto_ossl.a");
}
}

View File

@@ -13,7 +13,7 @@ trait pkgconfig
{
UnixAutoconfExecutor::create($this)
->appendEnv([
'CFLAGS' => PHP_OS_FAMILY !== 'Linux' ? '-Wimplicit-function-declaration -Wno-int-conversion' : '',
'CFLAGS' => '-Wimplicit-function-declaration -Wno-int-conversion',
'LDFLAGS' => SPCTarget::isStatic() ? '--static' : '',
])
->configure(

View File

@@ -16,9 +16,13 @@ trait watcher
*/
protected function build(): void
{
$cflags = $this->getLibExtraCXXFlags();
if (stripos($cflags, '-fpic') === false) {
$cflags .= ' -fPIC';
}
$ldflags = $this->getLibExtraLdFlags() ? ' ' . $this->getLibExtraLdFlags() : '';
shell()->cd($this->source_dir . '/watcher-c')
->initializeEnv($this)
->exec(getenv('CC') . ' -c -o libwatcher-c.o ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -Wall -Wextra -fPIC')
->exec(getenv('CXX') . " -c -o libwatcher-c.o ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -Wall -Wextra {$cflags}{$ldflags}")
->exec(getenv('AR') . ' rcs libwatcher-c.a libwatcher-c.o');
copy($this->source_dir . '/watcher-c/libwatcher-c.a', BUILD_LIB_PATH . '/libwatcher-c.a');