Compare commits

..

66 Commits

Author SHA1 Message Date
DubbleClick
efb1ff5a93 test fix 2? 2025-06-27 22:56:49 +07:00
DubbleClick
aff9ff20e8 test fix? 2025-06-27 22:55:23 +07:00
DubbleClick
4c8a173213 build_lib_path is better 2025-06-27 22:53:18 +07:00
DubbleClick
b6240f16fb clean files before compiling because it may try to link the wrong one 2025-06-27 22:51:53 +07:00
DubbleClick
f5281535d9 strip libphp.so and frankenphp 2025-06-27 22:48:15 +07:00
DubbleClick
96babd0939 crazy test 2025-06-27 22:06:19 +07:00
DubbleClick
464c2dca85 cs fix 2025-06-27 22:01:56 +07:00
DubbleClick
43dc04b4d0 building shared libphp.so on musl is really pointless and should be an error, since static compilations cannot load it 2025-06-27 22:01:37 +07:00
DubbleClick
e92f043cfa really stupid patch for swoole 2025-06-27 21:38:16 +07:00
DubbleClick
ff95b464ce really stupid patch for swoole 2025-06-27 21:26:06 +07:00
DubbleClick
69e1acd5ae really stupid patch 2025-06-27 20:28:59 +07:00
DubbleClick
e162a0ecd6 libaom uses different PIC check 2025-06-27 19:37:10 +07:00
DubbleClick
383045d1c0 cs fix 2025-06-27 19:27:02 +07:00
DubbleClick
e6bec8eb57 fix lib extra cflags 2025-06-27 19:26:08 +07:00
DubbleClick
d2dea83c63 don't check for musl toolkit when running zig, add -static to ncurses 2025-06-27 18:21:22 +07:00
DubbleClick
797aaf1ea8 remove libdir 2025-06-27 14:51:36 +07:00
DubbleClick
5a7fd8c24e we shouldn't need that, need to figure out the cause 2025-06-27 09:26:57 +07:00
DubbleClick
cc4ec4b598 add back debug 2025-06-27 00:17:24 +07:00
DubbleClick
55d78579c8 pgsql x86_64 fix? 2025-06-27 00:11:28 +07:00
Marc
d94542049c Update test-extensions.php
no debug do I can see where it fails
2025-06-26 22:58:48 +07:00
DubbleClick
6dec25b4f4 space 2025-06-26 22:03:08 +07:00
DubbleClick
8c7049913b can build shared extensions on ubuntu 24.04 now 2025-06-26 17:56:33 +07:00
DubbleClick
7edd8e6e19 test glibc of course 2025-06-26 17:39:42 +07:00
DubbleClick
2b4eb7127d what the frick is going on with my phpstorm 2025-06-26 17:39:05 +07:00
DubbleClick
9a3ce775a8 complete test suite 2025-06-26 17:36:50 +07:00
DubbleClick
2ff78e531e cs fix, where did that come from? 2025-06-26 17:25:46 +07:00
DubbleClick
03a33d87ff fix frankenphp build 2025-06-26 17:23:37 +07:00
DubbleClick
176e5627e5 hahaha, musl 2.17 is a little far away 2025-06-26 16:49:26 +07:00
DubbleClick
5801d05047 test musl (I have not tested this yet!) 2025-06-26 16:47:07 +07:00
DubbleClick
815ba75c76 we can build musl with zig cc too, don't need musl toolchain 2025-06-26 16:43:37 +07:00
DubbleClick
fff16b4019 refactor our 2025-06-26 16:03:57 +07:00
DubbleClick
e408a2cf1d suggestion and aarch64 fix 2025-06-26 15:55:41 +07:00
DubbleClick
b535600297 this is insane 2025-06-26 15:44:21 +07:00
DubbleClick
762c554468 test zig 2025-06-26 14:39:49 +07:00
DubbleClick
a8c7057aba fix windows 2025-06-26 14:30:42 +07:00
DubbleClick
935f3fc37c cs fix 2025-06-26 14:29:00 +07:00
DubbleClick
fae2878c41 refactor env var logic out to packages, abomination of a zig-cc script... 2025-06-26 14:24:00 +07:00
DubbleClick
d30ccb810c Merge remote-tracking branch 'origin/main' into zig 2025-06-26 12:30:50 +07:00
DubbleClick
8d75a85d6d ziggy 2025-06-26 12:30:04 +07:00
DubbleClick
625bfd1bec don't escape 2025-06-26 11:18:34 +07:00
DubbleClick
b142610800 move to systemutil 2025-06-25 14:52:50 +07:00
DubbleClick
9a3a536479 runtime object patch for shared extensions 2025-06-25 14:32:00 +07:00
DubbleClick
55f01149e4 prevent warning 2025-06-25 13:56:12 +07:00
DubbleClick
6f5fc43490 remove extra -lunwind patch since we don't only need it in opcache 2025-06-25 11:26:45 +07:00
DubbleClick
cb62ffdfc2 we manage -fno-sanitize in code, only needed for opcache with jit 2025-06-25 11:24:01 +07:00
DubbleClick
40ac705c46 remove openmp support entirely, system packages distribute it disabled, the ini disables it by default and the authors recommend disabling it. WIth a distinction between libgomp, libomp and the non-existent usable static libraries for them, it's just not worth it. 2025-06-25 11:21:58 +07:00
DubbleClick
5334727528 remove -L/usr/lib64 (need to put it in the zig-cc script, stupid to add it in 15 different places instead) 2025-06-24 23:07:17 +07:00
DubbleClick
253206de22 better 2025-06-24 22:57:12 +07:00
DubbleClick
5a60f4c02b another librdkafka patch 2025-06-24 22:56:48 +07:00
DubbleClick
63fcdd9db4 default param 2025-06-24 21:04:08 +07:00
DubbleClick
832c0230e2 getcctype default 2025-06-24 21:03:32 +07:00
DubbleClick
e1028b0348 swoole has date time conversion error in c++ code, clang needs -lunwind 2025-06-24 20:43:38 +07:00
DubbleClick
2433752273 needless default 2025-06-24 13:17:43 +07:00
DubbleClick
1b0b551fc6 handle case where libphp.so is built instead of libphp-release.so 2025-06-24 12:10:01 +07:00
DubbleClick
74849a8d48 -fno-sanitize=undefined is enabled in zig by default, not in gcc and clang 2025-06-24 09:05:44 +07:00
DubbleClick
ee0de6933f deprecated linker option 2025-06-23 19:21:51 +07:00
DubbleClick
bd863dba34 zig is clang 2025-06-23 15:26:39 +07:00
DubbleClick
f9af24e246 dont fail on -lomp 2025-06-23 13:23:13 +07:00
DubbleClick
864c55feaf oops 2025-06-23 13:12:40 +07:00
DubbleClick
7628847a46 suboptimal solutions, but a bit closer to building 2025-06-23 12:57:00 +07:00
DubbleClick
955b586908 fix lz4 2025-06-22 19:51:55 +07:00
DubbleClick
32a1fd45df don't disable warnings 2025-06-22 17:21:28 +07:00
DubbleClick
15fbde29d4 remove duplicate 2025-06-22 17:02:16 +07:00
DubbleClick
2cce02bfa9 liblz4 replacement 2025-06-22 17:01:08 +07:00
DubbleClick
7e35de8a0e CXX for watcher-c 2025-06-22 16:19:01 +07:00
DubbleClick
9a98fd9cff patch things for zig compatibility 2025-06-22 15:52:01 +07:00
34 changed files with 559 additions and 112 deletions

View File

@@ -71,8 +71,8 @@ CXX=${SPC_LINUX_DEFAULT_CXX}
AR=${SPC_LINUX_DEFAULT_AR}
LD=${SPC_LINUX_DEFAULT_LD}
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="-fPIC -Os"
SPC_DEFAULT_CXX_FLAGS="-fPIC -Os"
SPC_DEFAULT_C_FLAGS="-fPIC -Os -Wno-error=date-time"
SPC_DEFAULT_CXX_FLAGS="-fPIC -Os -Wno-error=date-time"
; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated)
SPC_EXTRA_LIBS=
; upx executable path
@@ -98,15 +98,15 @@ SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}"
; LDFLAGS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}"
; LIBS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_LIBS="-ldl -lpthread -lm"
SPC_CMD_VAR_PHP_CONFIGURE_LIBS="-ldl -lrt -lpthread -lm -lresolv -lutil"
; EXTRA_CFLAGS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}"
; EXTRA_LIBS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm"
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lrt -lpthread -lm -lresolv -lutil"
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
; EXTRA_LDFLAGS_PROGRAM for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie"
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -pie"
[macos]
; compiler environments

View File

@@ -54,5 +54,20 @@
},
"go-xcaddy-aarch64-macos": {
"type": "custom"
},
"zig-x86_64-linux": {
"type": "custom"
},
"zig-aarch64-linux": {
"type": "custom"
},
"zig-x86_64-macos": {
"type": "custom"
},
"zig-aarch64-macos": {
"type": "custom"
},
"zig-x86_64-win": {
"type": "custom"
}
}

View File

@@ -48,17 +48,17 @@ This extension contains an implementation of the coroutine environment for `pdo_
## swow
1. Only PHP 8.0 ~ 8.4 is supported.
1. Only PHP 8.0+ is supported.
## imagick
1. The imagick extension currently only has openmp support on musl libc. This means that multithreading is disabled on glibc or other operating systems. The extension is still fully functional.
1. OpenMP support is disabled, this is recommended by the maintainers and also the case system packages.
## imap
1. Kerberos is not supported
2. ext-imap is not thread safe due to the underlying c-client. It's not possible to use it in --enable-zts builds.
3. Because the extension may be dropped from php, we recommend you look for an alternative implementation, such as [Webklex/php-imap](https://github.com/Webklex/php-imap)
2. ext-imap is not thread safe due to the underlying c-client. It's not possible to use it in `--enable-zts` builds.
3. The extension was dropped from php 8.4, we recommend you look for an alternative implementation, such as [Webklex/php-imap](https://github.com/Webklex/php-imap)
## gd

View File

@@ -45,17 +45,17 @@ swoole-hook-sqlite 与 `pdo_sqlite` 扩展冲突。如需使用 Swoole 和 `pdo_
## swow
1. swow 仅支持 PHP 8.0 ~ 8.4 版本。
1. swow 仅支持 PHP 8.0+ 版本。
## imagick
imagick 扩展目前仅在 musl libc 上支持 OpenMPlibgomp。使用 glibc 方式构建的 imagick 扩展无法支持多线程特性
1. OpenMP 支持已被禁用,这是维护者推荐的做法,系统软件包也是如此配置
## imap
1. 该扩展目前不支持 Kerberos。
2. 由于底层的 c-client、ext-imap 不是线程安全的。 无法在 `--enable-zts` 构建中使用它。
3. 由于该扩展可能会从未来的 PHP 中删除,因此我们建议您寻找替代实现,例如 [Webklex/php-imap](https://github.com/Webklex/php-imap)。
3. 该扩展已在 PHP 8.4 中被移除,因此我们建议您寻找替代实现,例如 [Webklex/php-imap](https://github.com/Webklex/php-imap)。
## gd

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\builder;
use SPC\builder\linux\SystemUtil;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
@@ -215,7 +216,16 @@ class Extension
*/
public function patchBeforeSharedMake(): bool
{
return false;
$extra = SystemUtil::getExtraRuntimeObjects();
if (!$extra) {
return false;
}
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
"/^(shared_objects_{$this->getName()}\\s*=.*)$/m",
"$1 {$extra}",
);
return true;
}
/**
@@ -387,8 +397,8 @@ class Extension
// macOS ld64 doesn't understand these, while Linux and BSD do
// use them to make sure that all symbols are picked up, even if a library has already been visited before
$preStatic = PHP_OS_FAMILY !== 'Darwin' ? '-Wl,-Bstatic -Wl,--start-group ' : '';
$postStatic = PHP_OS_FAMILY !== 'Darwin' ? ' -Wl,--end-group -Wl,-Bdynamic ' : ' ';
$preStatic = PHP_OS_FAMILY !== 'Darwin' ? '-Wl,--start-group ' : '';
$postStatic = PHP_OS_FAMILY !== 'Darwin' ? ' -Wl,--end-group ' : ' ';
$env = [
'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
@@ -404,6 +414,7 @@ class Extension
// prepare configure args
shell()->cd($this->source_dir)
->setEnv($env)
->appendEnv($this->getExtraEnv())
->exec(BUILD_BIN_PATH . '/phpize');
if ($this->patchBeforeSharedConfigure()) {
@@ -412,6 +423,7 @@ class Extension
shell()->cd($this->source_dir)
->setEnv($env)
->appendEnv($this->getExtraEnv())
->exec(
'./configure ' . $this->getUnixConfigureArg(true) .
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
@@ -431,6 +443,7 @@ class Extension
shell()->cd($this->source_dir)
->setEnv($env)
->appendEnv($this->getExtraEnv())
->exec('make clean')
->exec('make -j' . $this->builder->concurrency)
->exec('make install');
@@ -535,6 +548,11 @@ class Extension
return [trim($staticLibString), trim($sharedLibString)];
}
protected function getExtraEnv(): array
{
return [];
}
private function getLibraryDependencies(bool $recursive = false): array
{
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);

View File

@@ -10,31 +10,16 @@ use SPC\util\CustomExt;
#[CustomExt('imagick')]
class imagick extends Extension
{
public function patchBeforeMake(): bool
{
if (PHP_OS_FAMILY !== 'Linux') {
return false;
}
if (getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) {
return false;
}
// imagick with calls omp_pause_all, which requires openmp, on non-musl we build imagick without openmp
$extra_libs = trim(getenv('SPC_EXTRA_LIBS') . ' -lgomp');
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
return true;
}
public function getUnixConfigureArg(bool $shared = false): string
{
$disable_omp = !(getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) ? '' : ' ac_cv_func_omp_pause_resource_all=no';
return '--with-imagick=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $disable_omp;
return '--with-imagick=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . ' ac_cv_func_omp_pause_resource_all=no';
}
protected function getStaticAndSharedLibs(): array
{
// on centos 7, it will use the symbol _ZTINSt6thread6_StateE, which is not defined in system libstdc++.so.6
[$static, $shared] = parent::getStaticAndSharedLibs();
if (getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) {
if (str_contains(getenv('CC'), 'devtoolset-10')) {
$static .= ' -lstdc++';
$shared = str_replace('-lstdc++', '', $shared);
}

View File

@@ -57,4 +57,11 @@ class pgsql extends Extension
}
return '--with-pgsql=' . BUILD_ROOT_PATH;
}
protected function getExtraEnv(): array
{
return [
'CFLAGS' => '-Wno-int-conversion',
];
}
}

View File

@@ -7,6 +7,7 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
use SPC\util\CustomExt;
#[CustomExt('swoole')]
@@ -14,13 +15,18 @@ class swoole extends Extension
{
public function patchBeforeMake(): bool
{
$patched = false;
if (PHP_OS_FAMILY === 'Linux') {
SourcePatcher::patchFile('swoole_fix_date_time.patch', $this->source_dir);
$patched = true;
}
if ($this->builder instanceof MacOSBuilder) {
// Fix swoole with event extension <util.h> conflict bug
$util_path = shell()->execWithResult('xcrun --show-sdk-path', false)[1][0] . '/usr/include/util.h';
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/swoole/thirdparty/php/standard/proc_open.cc', 'include <util.h>', 'include "' . $util_path . '"');
return true;
$patched = true;
}
return false;
return $patched;
}
public function getExtVersion(): ?string

View File

@@ -20,6 +20,7 @@ class uv extends Extension
public function patchBeforeSharedMake(): bool
{
parent::patchBeforeSharedMake();
if (PHP_OS_FAMILY !== 'Linux' || arch2gnu(php_uname('m')) !== 'aarch64') {
return false;
}

View File

@@ -30,7 +30,7 @@ class LinuxBuilder extends UnixBuilderBase
GlobalEnvManager::init();
if (getenv('SPC_LIBC') === 'musl' && !SystemUtil::isMuslDist()) {
if (getenv('SPC_LIBC') === 'musl' && !SystemUtil::isMuslDist() && !str_contains((string) getenv('CC'), 'zig')) {
$this->setOptionIfNotExist('library_path', "LIBRARY_PATH=\"/usr/local/musl/{$arch}-linux-musl/lib\"");
$this->setOptionIfNotExist('ld_library_path', "LD_LIBRARY_PATH=\"/usr/local/musl/{$arch}-linux-musl/lib\"");
$configure = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
@@ -80,6 +80,7 @@ class LinuxBuilder extends UnixBuilderBase
}
// add libstdc++, some extensions or libraries need it
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : '');
$extra_libs .= (SystemUtil::getCCType() === 'clang' ? ' -lunwind' : '');
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
$cflags = $this->arch_c_flags;
f_putenv('CFLAGS=' . $cflags);
@@ -103,6 +104,10 @@ class LinuxBuilder extends UnixBuilderBase
$zts = '';
}
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
$cc = trim(getenv('CC'));
if (!$disable_jit && $this->getExt('opcache') && str_contains($cc, 'zig')) {
f_putenv("CC={$cc} -fno-sanitize=undefined");
}
$config_file_path = $this->getOption('with-config-file-path', false) ?
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
@@ -134,6 +139,9 @@ class LinuxBuilder extends UnixBuilderBase
}
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
if ($embed_type !== 'static' && getenv('SPC_LIBC') === 'musl') {
throw new WrongUsageException('Musl libc does not support dynamic linking of PHP embed!');
}
shell()->cd(SOURCE_PATH . '/php-src')
->exec(
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
@@ -175,6 +183,9 @@ class LinuxBuilder extends UnixBuilderBase
}
$this->buildEmbed();
}
if (!$disable_jit && $this->getExt('opcache') && str_contains($cc, 'zig')) {
f_putenv("CC={$cc}");
}
if ($enableFrankenphp) {
logger()->info('building frankenphp');
$this->buildFrankenphp();
@@ -289,34 +300,48 @@ class LinuxBuilder extends UnixBuilderBase
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
$ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS');
$realLibName = 'libphp.so';
if (preg_match('/-release\s+(\S+)/', $ldflags, $matches)) {
$release = $matches[1];
$realLibName = 'libphp-' . $release . '.so';
$realLib = BUILD_LIB_PATH . '/' . $realLibName;
rename(BUILD_LIB_PATH . '/libphp.so', $realLib);
$cwd = getcwd();
chdir(BUILD_LIB_PATH);
symlink($realLibName, 'libphp.so');
chdir(BUILD_MODULES_PATH);
foreach ($this->getExts() as $ext) {
if (!$ext->isBuildShared()) {
continue;
$libphpPath = BUILD_LIB_PATH . '/libphp.so';
$libphpRelease = BUILD_LIB_PATH . '/' . $realLibName;
if (!file_exists($libphpRelease) && file_exists($libphpPath)) {
rename($libphpPath, $libphpRelease);
}
if (file_exists($libphpRelease)) {
chdir(BUILD_LIB_PATH);
if (file_exists($libphpPath)) {
unlink($libphpPath);
}
$name = $ext->getName();
$versioned = "{$name}-{$release}.so";
$unversioned = "{$name}.so";
if (is_file(BUILD_MODULES_PATH . "/{$versioned}")) {
rename(BUILD_MODULES_PATH . "/{$versioned}", BUILD_MODULES_PATH . "/{$unversioned}");
shell()->cd(BUILD_MODULES_PATH)
->exec(sprintf(
'patchelf --set-soname %s %s',
escapeshellarg($unversioned),
escapeshellarg($unversioned)
));
symlink($realLibName, 'libphp.so');
}
if (is_dir(BUILD_MODULES_PATH)) {
chdir(BUILD_MODULES_PATH);
foreach ($this->getExts() as $ext) {
if (!$ext->isBuildShared()) {
continue;
}
$name = $ext->getName();
$versioned = "{$name}-{$release}.so";
$unversioned = "{$name}.so";
if (is_file(BUILD_MODULES_PATH . "/{$versioned}")) {
rename(BUILD_MODULES_PATH . "/{$versioned}", BUILD_MODULES_PATH . "/{$unversioned}");
shell()->cd(BUILD_MODULES_PATH)
->exec(sprintf(
'patchelf --set-soname %s %s',
escapeshellarg($unversioned),
escapeshellarg($unversioned)
));
}
}
}
chdir($cwd);
}
if (!$this->getOption('no-strip', false) && file_exists(BUILD_LIB_PATH . '/' . $realLibName)) {
shell()->cd(BUILD_LIB_PATH)->exec("strip --strip-all {$realLibName}");
}
$this->patchPhpScripts();
}

View File

@@ -13,6 +13,8 @@ class SystemUtil
public static ?string $libc_version = null;
private static ?string $extra_runtime_objects = null;
/** @noinspection PhpMissingBreakStatementInspection */
public static function getOSRelease(): array
{
@@ -78,9 +80,11 @@ class SystemUtil
/**
* @throws RuntimeException
*/
public static function getCCType(string $cc): string
public static function getCCType(?string $cc = null): string
{
$cc ??= getenv('CC');
return match (true) {
str_contains($cc, 'zig') => 'clang',
str_ends_with($cc, 'c++'), str_ends_with($cc, 'cc'), str_ends_with($cc, 'g++'), str_ends_with($cc, 'gcc') => 'gcc',
$cc === 'clang++', $cc === 'clang', str_starts_with($cc, 'musl-clang') => 'clang',
default => throw new RuntimeException("unknown cc type: {$cc}"),
@@ -224,4 +228,38 @@ class SystemUtil
}
return null;
}
public static function getExtraRuntimeObjects(): string
{
$cc = getenv('CC');
if (!$cc || !str_contains($cc, 'zig')) {
return '';
}
if (self::$extra_runtime_objects !== null) {
return self::$extra_runtime_objects;
}
$paths = ['/usr/lib/gcc', '/usr/local/lib/gcc'];
$objects = ['crtbeginS.o', 'crtendS.o'];
$found = [];
foreach ($objects as $obj) {
$located = null;
foreach ($paths as $base) {
$output = shell_exec("find {$base} -name {$obj} -print -quit 2>/dev/null");
$line = trim((string) $output);
if ($line !== '') {
$located = $line;
break;
}
}
if ($located) {
$found[] = $located;
}
}
self::$extra_runtime_objects = implode(' ', $found);
return implode(' ', $found);
}
}

View File

@@ -62,7 +62,8 @@ class openssl extends LinuxLibraryBase
$ex_lib = trim($ex_lib);
$clang_postfix = SystemUtil::getCCType(getenv('CC')) === 'clang' ? '-clang' : '';
/* @phpstan-ignore-next-line */
$clang_postfix = SystemUtil::getCCType() === 'clang' && (GNU_ARCH === 'x86_64' || PHP_OS_FAMILY === 'Darwin') ? '-clang' : '';
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(

View File

@@ -119,9 +119,9 @@ trait UnixLibraryTrait
{
$env = getenv($this->getSnakeCaseName() . '_CFLAGS') ?: '';
if (!str_contains($env, $this->builder->arch_c_flags)) {
$env .= $this->builder->arch_c_flags;
$env .= ' ' . $this->builder->arch_c_flags;
}
return $env;
return trim($env);
}
public function getLibExtraLdFlags(): string
@@ -138,8 +138,8 @@ trait UnixLibraryTrait
{
$env = getenv($this->getSnakeCaseName() . '_CXXFLAGS') ?: '';
if (!str_contains($env, $this->builder->arch_cxx_flags)) {
$env .= $this->builder->arch_cxx_flags;
$env .= ' ' . $this->builder->arch_cxx_flags;
}
return $env;
return trim($env);
}
}

View File

@@ -15,7 +15,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;
abstract class UnixBuilderBase extends BuilderBase
@@ -203,18 +205,20 @@ abstract class UnixBuilderBase extends BuilderBase
if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'musl') {
$lens .= ' -static';
}
// if someone changed to EMBED_TYPE=shared, we need to add LD_LIBRARY_PATH
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
$ext_path = 'LD_LIBRARY_PATH=' . BUILD_LIB_PATH . ':$LD_LIBRARY_PATH ';
FileSystem::removeFileIfExists(BUILD_LIB_PATH . '/libphp.a');
} else {
$ext_path = '';
foreach (glob(BUILD_LIB_PATH . '/libphp*.so') as $file) {
unlink($file);
}
}
[$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 (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
$ext_path = 'LD_LIBRARY_PATH=' . BUILD_ROOT_PATH . '/lib:$LD_LIBRARY_PATH ';
FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '/lib/libphp.a');
} else {
$ext_path = '';
FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '/lib/libphp.so');
}
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed');
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output));
@@ -301,18 +305,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');
@@ -325,7 +317,10 @@ 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') {
@@ -334,21 +329,19 @@ abstract class UnixBuilderBase extends BuilderBase
$debugFlags = $this->getOption('no-strip') ? "'-w -s' " : '';
$extLdFlags = "-extldflags '-pie'";
$muslTags = '';
$staticFlags = '';
if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'musl') {
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000'";
$muslTags = 'static_build,';
$staticFlags = '-static -static-pie';
}
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list, with_dependencies: true);
$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 ' .
@@ -356,8 +349,19 @@ 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')) {
shell()->cd(BUILD_BIN_PATH)->exec('strip --strip-all 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

@@ -32,8 +32,7 @@ trait imagemagick
->optionalLib('freetype', ...ac_with_args('freetype'))
->optionalLib('bzip2', ...ac_with_args('bzlib'))
->addConfigureArgs(
// TODO: glibc rh 10 toolset's libgomp.a was built without -fPIC so we can't use openmp without depending on libgomp.so
getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10') ? '--disable-openmp' : '--enable-openmp',
'--disable-openmp',
'--without-jxl',
'--without-x',
);

View File

@@ -26,8 +26,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

@@ -16,10 +16,20 @@ trait libaom
*/
protected function build(): void
{
$cc = getenv('CC');
$cxx = getenv('CXX');
if (str_contains($cc, 'zig') && getenv('SPC_LIBC') === 'musl') {
putenv('CC=' . $cc . ' -D_POSIX_SOURCE');
putenv('CXX=' . $cxx . ' -D_POSIX_SOURCE');
}
UnixCMakeExecutor::create($this)
->setBuildDir("{$this->source_dir}/builddir")
->addConfigureArgs('-DAOM_TARGET_CPU=generic')
->build();
if (str_contains($cc, 'zig') && getenv('SPC_LIBC') === 'musl') {
putenv('CC=' . $cc);
putenv('CXX=' . $cxx);
}
$this->patchPkgconfPrefix(['aom.pc']);
}
}

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,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait librdkafka
@@ -16,7 +17,18 @@ trait librdkafka
*/
protected function build(): void
{
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__"
);
UnixAutoconfExecutor::create($this)
->appendEnv(['CFLAGS' => '-Wno-int-conversion -Wno-unused-but-set-variable -Wno-unused-variable'])
->optionalLib(
'zstd',
function ($lib) {

View File

@@ -14,6 +14,9 @@ trait ncurses
$filelist = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true);
UnixAutoconfExecutor::create($this)
->appendEnv([
'LDFLAGS' => getenv('SPC_LIBC') === 'musl' ? '-static' : '',
])
->configure(
'--enable-overwrite',
'--with-curses-h',

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' => !($this instanceof LinuxLibraryBase) || getenv('SPC_LIBC') === 'glibc' ? '' : '--static',
])
->configure(

View File

@@ -18,7 +18,7 @@ trait watcher
{
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 -fPIC')
->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');

View File

@@ -29,6 +29,9 @@ class LinuxMuslCheck
if (getenv('SPC_LIBC') === 'glibc') {
return CheckResult::ok('Building with glibc, skipped');
}
if (str_contains(getenv('CC'), 'zig')) {
return CheckResult::ok('Building with zig, skipped');
}
$musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m'));
if (file_exists($musl_wrapper_lib) && file_exists('/usr/local/musl/lib/libc.a')) {
@@ -46,6 +49,9 @@ class LinuxMuslCheck
if (getenv('SPC_LIBC') === 'glibc') {
return CheckResult::ok('Building with glibc, skipped');
}
if (str_contains(getenv('CC'), 'zig')) {
return CheckResult::ok('Building with zig, skipped');
}
$arch = arch2gnu(php_uname('m'));
$cross_compile_lib = "/usr/local/musl/{$arch}-linux-musl/lib/libc.a";

View File

@@ -365,8 +365,8 @@ class Downloader
$cls = new $class();
if (in_array($name, $cls->getSupportName())) {
(new $class())->fetch($name, $force, $pkg);
break;
}
break;
}
}
break;

View File

@@ -10,8 +10,7 @@ abstract class CustomPackage
abstract public function fetch(string $name, bool $force = false, ?array $config = null): void;
public function extract(string $name): void
{
throw new \RuntimeException("Extract method not implemented for package: {$name}");
}
abstract public function extract(string $name): void;
abstract public static function getEnvironment(): array;
}

View File

@@ -73,4 +73,25 @@ class GoXcaddy extends CustomPackage
])
->exec("{$go_exec} install github.com/caddyserver/xcaddy/cmd/xcaddy@latest");
}
public static function getEnvironment(): array
{
$arch = arch2gnu(php_uname('m'));
$os = match (PHP_OS_FAMILY) {
'Windows' => 'win',
'Darwin' => 'macos',
'BSD' => 'freebsd',
default => 'linux',
};
$packageName = "go-xcaddy-{$arch}-{$os}";
$pkgroot = PKG_ROOT_PATH;
return [
'PATH' => "{$pkgroot}/{$packageName}/bin",
'GOROOT' => "{$pkgroot}/{$packageName}",
'GOBIN' => "{$pkgroot}/{$packageName}/bin",
'GOPATH' => "{$pkgroot}/go",
];
}
}

143
src/SPC/store/pkg/Zig.php Normal file
View File

@@ -0,0 +1,143 @@
<?php
declare(strict_types=1);
namespace SPC\store\pkg;
use SPC\store\CurlHook;
use SPC\store\Downloader;
use SPC\store\FileSystem;
use SPC\store\LockFile;
class Zig extends CustomPackage
{
public function getSupportName(): array
{
return [
'zig-x86_64-linux',
'zig-aarch64-linux',
'zig-x86_64-macos',
'zig-aarch64-macos',
'zig-x86_64-win',
];
}
public function fetch(string $name, bool $force = false, ?array $config = null): void
{
$pkgroot = PKG_ROOT_PATH;
$zig_exec = match (PHP_OS_FAMILY) {
'Windows' => "{$pkgroot}/{$name}/bin/zig.exe",
default => "{$pkgroot}/{$name}/bin/zig",
};
if (file_exists($zig_exec) && !$force) {
return;
}
$parts = explode('-', $name);
$arch = $parts[1];
$os = $parts[2];
$zig_arch = match ($arch) {
'x86_64', 'aarch64' => $arch,
default => throw new \InvalidArgumentException('Unsupported architecture: ' . $arch),
};
$zig_os = match ($os) {
'linux' => 'linux',
'macos' => 'macos',
'win' => 'windows',
default => throw new \InvalidArgumentException('Unsupported OS: ' . $os),
};
$index_json = json_decode(Downloader::curlExec('https://ziglang.org/download/index.json', hooks: [[CurlHook::class, 'setupGithubToken']]), true);
$latest_version = null;
foreach ($index_json as $version => $data) {
$latest_version = $version;
break;
}
if (!$latest_version) {
throw new \RuntimeException('Could not determine latest Zig version');
}
logger()->info("Installing Zig version {$latest_version}");
$platform_key = "{$zig_arch}-{$zig_os}";
if (!isset($index_json[$latest_version][$platform_key])) {
throw new \RuntimeException("No download available for {$platform_key} in Zig version {$latest_version}");
}
$download_info = $index_json[$latest_version][$platform_key];
$url = $download_info['tarball'];
$filename = basename($url);
$config = [
'type' => 'url',
'url' => $url,
'filename' => $filename,
];
Downloader::downloadPackage($name, $config, $force);
}
public function extract(string $name): void
{
$pkgroot = PKG_ROOT_PATH;
$zig_bin_dir = "{$pkgroot}/{$name}";
$zig_exec = match (PHP_OS_FAMILY) {
'Windows' => "{$zig_bin_dir}/zig.exe",
default => "{$zig_bin_dir}/zig",
};
if (file_exists($zig_exec)) {
if (!file_exists("{$zig_bin_dir}/zig-cc")) {
$this->createZigCcScript($zig_bin_dir);
return;
}
return;
}
$lock = json_decode(FileSystem::readFile(LockFile::LOCK_FILE), true);
$source_type = $lock[$name]['source_type'];
$filename = DOWNLOAD_PATH . '/' . ($lock[$name]['filename'] ?? $lock[$name]['dirname']);
$extract = "{$pkgroot}/{$name}";
FileSystem::extractPackage($name, $source_type, $filename, $extract);
$this->createZigCcScript($zig_bin_dir);
}
public static function getEnvironment(): array
{
$arch = arch2gnu(php_uname('m'));
$os = match (PHP_OS_FAMILY) {
'Linux' => 'linux',
'Windows' => 'win',
'Darwin' => 'macos',
'BSD' => 'freebsd',
default => 'linux',
};
$packageName = "zig-{$arch}-{$os}";
$path = PKG_ROOT_PATH . "/{$packageName}";
return [
'PATH' => $path,
];
}
private function createZigCcScript(string $bin_dir): void
{
$script_path = __DIR__ . '/../scripts/zig-cc.sh';
$script_content = file_get_contents($script_path);
file_put_contents("{$bin_dir}/zig-cc", $script_content);
chmod("{$bin_dir}/zig-cc", 0755);
$script_content = str_replace('zig cc', 'zig c++', $script_content);
file_put_contents("{$bin_dir}/zig-c++", $script_content);
chmod("{$bin_dir}/zig-c++", 0755);
}
}

View File

@@ -0,0 +1,98 @@
#!/usr/bin/env bash
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
BUILDROOT_ABS="$(realpath "$SCRIPT_DIR/../../buildroot/include" 2>/dev/null || echo "")"
PARSED_ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
-isystem)
shift
ARG="$1"
[[ -n "$ARG" ]] && shift || break
ARG_ABS="$(realpath "$ARG" 2>/dev/null || echo "")"
if [[ -n "$ARG_ABS" && "$ARG_ABS" == "$BUILDROOT_ABS" ]]; then
PARSED_ARGS+=("-I$ARG")
else
PARSED_ARGS+=("-isystem" "$ARG")
fi
;;
-isystem*)
ARG="${1#-isystem}"
shift
ARG_ABS="$(realpath "$ARG" 2>/dev/null || echo "")"
if [[ -n "$ARG_ABS" && "$ARG_ABS" == "$BUILDROOT_ABS" ]]; then
PARSED_ARGS+=("-I$ARG")
else
PARSED_ARGS+=("-isystem$ARG")
fi
;;
*)
PARSED_ARGS+=("$1")
shift
;;
esac
done
SPC_TARGET_WAS_SET=1
if [ -z "${SPC_TARGET+x}" ]; then
SPC_TARGET_WAS_SET=0
fi
UNAME_M="$(uname -m)"
UNAME_S="$(uname -s)"
case "$UNAME_M" in
x86_64) ARCH="x86_64" ;;
aarch64|arm64) ARCH="aarch64" ;;
*) echo "Unsupported architecture: $UNAME_M" >&2; exit 1 ;;
esac
case "$UNAME_S" in
Linux) OS="linux" ;;
Darwin) OS="macos" ;;
*) echo "Unsupported OS: $UNAME_S" >&2; exit 1 ;;
esac
SPC_TARGET="${SPC_TARGET:-$ARCH-$OS}"
if [ "$SPC_LIBC" = "glibc" ]; then
SPC_LIBC="gnu"
fi
if [ "$SPC_TARGET_WAS_SET" -eq 0 ] && [ -z "$SPC_LIBC" ] && [ -z "$SPC_LIBC_VERSION" ]; then
exec zig cc "${PARSED_ARGS[@]}"
elif [ -z "$SPC_LIBC" ] && [ -z "$SPC_LIBC_VERSION" ]; then
exec zig cc -target ${SPC_TARGET} "${PARSED_ARGS[@]}"
else
TARGET="${SPC_TARGET}-${SPC_LIBC}"
[ -n "$SPC_LIBC_VERSION" ] && TARGET="${TARGET}.${SPC_LIBC_VERSION}"
output=$(zig cc -target "$TARGET" -lstdc++ "${PARSED_ARGS[@]}" 2>&1)
status=$?
filtered_output=$(echo "$output" | grep -v "version '.*' in target triple")
if [ $status -eq 0 ]; then
echo "$filtered_output"
exit 0
fi
if echo "$output" | grep -q "version '.*' in target triple"; then
TARGET_FALLBACK="${SPC_TARGET}-${SPC_LIBC}"
output=$(zig cc -target "$TARGET_FALLBACK" -lstdc++ "${PARSED_ARGS[@]}" 2>&1)
status=$?
filtered_output=$(echo "$output" | grep -v "version '.*' in target triple")
if [ $status -eq 0 ]; then
echo "$filtered_output"
exit 0
else
exec zig cc -target "$TARGET_FALLBACK" "${PARSED_ARGS[@]}"
fi
else
echo "$filtered_output"
exec zig cc -target "$TARGET" "${PARSED_ARGS[@]}"
fi
fi

View File

@@ -7,6 +7,7 @@ namespace SPC\util;
use SPC\builder\linux\SystemUtil;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\pkg\Zig;
/**
* Environment variable manager
@@ -43,7 +44,13 @@ class GlobalEnvManager
// Define env vars for linux
if (PHP_OS_FAMILY === 'Linux') {
$arch = getenv('GNU_ARCH');
if (SystemUtil::isMuslDist() || getenv('SPC_LIBC') === 'glibc') {
if (str_contains((string) getenv('CC'), 'zig')) {
self::putenv('SPC_LINUX_DEFAULT_CC=zig-cc');
self::putenv('SPC_LINUX_DEFAULT_CXX=zig-c++');
self::putenv('SPC_LINUX_DEFAULT_AR=ar');
self::putenv('SPC_LINUX_DEFAULT_LD=ld.lld');
} elseif (SystemUtil::isMuslDist() || getenv('SPC_LIBC') === 'glibc') {
self::putenv('SPC_LINUX_DEFAULT_CC=gcc');
self::putenv('SPC_LINUX_DEFAULT_CXX=g++');
self::putenv('SPC_LINUX_DEFAULT_AR=ar');
@@ -100,6 +107,14 @@ class GlobalEnvManager
self::putenv("{$k}={$v}");
}
}
if (str_contains((string) getenv('CC'), 'zig') || str_contains((string) getenv('CXX'), 'zig')) {
$zigEnv = Zig::getEnvironment();
foreach ($zigEnv as $key => $value) {
if ($key === 'PATH') {
self::addPathIfNotExists($value);
}
}
}
}
public static function putenv(string $val): void
@@ -108,7 +123,7 @@ class GlobalEnvManager
self::$env_cache[] = $val;
}
private static function addPathIfNotExists(string $path): void
public static function addPathIfNotExists(string $path): void
{
if (is_unix() && !str_contains(getenv('PATH'), $path)) {
self::putenv("PATH={$path}:" . getenv('PATH'));

View File

@@ -6,6 +6,7 @@ namespace SPC\util;
use SPC\builder\BuilderBase;
use SPC\builder\BuilderProvider;
use SPC\builder\linux\SystemUtil;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
@@ -70,6 +71,9 @@ class SPCConfigUtil
if ($this->builder->hasCpp()) {
$libs .= $this->builder instanceof MacOSBuilder ? ' -lc++' : ' -lstdc++';
}
if (SystemUtil::getCCType() === 'clang') {
$libs .= ' -lunwind';
}
// mimalloc must come first
if (str_contains($libs, BUILD_LIB_PATH . '/mimalloc.o')) {
$libs = BUILD_LIB_PATH . '/mimalloc.o ' . str_replace(BUILD_LIB_PATH . '/mimalloc.o', '', $libs);
@@ -145,10 +149,6 @@ class SPCConfigUtil
}
}
}
// patch: imagick (imagemagick wrapper) for linux needs libgomp
if (in_array('imagemagick', $libraries) && PHP_OS_FAMILY === 'Linux' && !(getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10'))) {
$short_name[] = '-lgomp';
}
return implode(' ', $short_name);
}

View File

@@ -0,0 +1,11 @@
--- a/config.m4
+++ b/config.m4
@@ -1307,7 +1307,7 @@
PHP_REQUIRE_CXX()
- CXXFLAGS="$CXXFLAGS -Wall -Wno-unused-function -Wno-deprecated -Wno-deprecated-declarations"
+ CXXFLAGS="$CXXFLAGS -Wall -Wno-date-time -Wno-unused-function -Wno-deprecated -Wno-deprecated-declarations"
if test "$SW_OS" = "CYGWIN" || test "$SW_OS" = "MINGW"; then
CXXFLAGS="$CXXFLAGS -std=gnu++14"

View File

@@ -13,9 +13,9 @@ declare(strict_types=1);
// test php version (8.1 ~ 8.4 available, multiple for matrix)
$test_php_version = [
'8.1',
'8.2',
'8.3',
// '8.1',
// '8.2',
// '8.3',
'8.4',
];
@@ -26,12 +26,24 @@ $test_os = [
// 'macos-15',
// 'ubuntu-latest',
// 'ubuntu-22.04',
// 'ubuntu-24.04',
// 'ubuntu-22.04-arm',
// 'ubuntu-24.04-arm',
'windows-latest',
'ubuntu-24.04',
'ubuntu-24.04-arm',
// 'windows-latest',
];
$zig = true;
// temporary!
if ($zig) {
putenv('SPC_LIBC=musl');
// putenv('SPC_LIBC_VERSION=2.17');
putenv('CC=zig-cc');
putenv('CXX=zig-c++');
putenv('AR=ar');
putenv('LD=ld.lld');
exec('ulimit -n 2048');
}
// whether enable thread safe
$zts = true;
@@ -48,13 +60,13 @@ $prefer_pre_built = true;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'curl',
'Linux', 'Darwin' => 'apcu,ast,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,iconv,libxml,mbregex,mbstring,opcache,openssl,pcntl,phar,posix,readline,session,simplexml,sockets,sodium,tokenizer,xml,xmlreader,xmlwriter,zip,zlib,amqp,brotli,bz2,dio,ds,ev,event,ffi,ftp,gd,gettext,gmp,gmssl,igbinary,imagick,inotify,intl,ldap,lz4,memcache,memcached,mongodb,msgpack,mysqli,mysqlnd,odbc,opentelemetry,parallel,pdo,pdo_mysql,pdo_odbc,pdo_pgsql,pdo_sqlite,pdo_sqlsrv,pgsql,protobuf,rar,redis,rdkafka,shmop,spx,sqlite3,sqlsrv,ssh2,swoole,sysvmsg,sysvsem,sysvshm,tidy,uuid,uv,xhprof,xlswriter,xsl,xz,yac,yaml,zstd',
'Windows' => 'intl',
};
// If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`).
$shared_extensions = match (PHP_OS_FAMILY) {
'Linux' => 'uv',
'Linux' => 'amqp,brotli,bz2,dio,ds,ev,event,ffi,ftp,gd,gettext,gmp,gmssl,igbinary,imagick,inotify,intl,ldap,lz4,memcache,memcached,mongodb,msgpack,mysqli,mysqlnd,odbc,opentelemetry,parallel,pdo,pdo_mysql,pdo_odbc,pdo_pgsql,pdo_sqlite,pdo_sqlsrv,pgsql,protobuf,rar,redis,rdkafka,shmop,spx,sqlite3,sqlsrv,ssh2,swoole,sysvmsg,sysvsem,sysvshm,tidy,uuid,uv,xdebug,xhprof,xlswriter,xsl,xz,yac,yaml,zstd',
'Darwin' => '',
'Windows' => '',
};
@@ -156,6 +168,12 @@ if ($shared_extensions) {
case 'ubuntu-22.04-arm':
$shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' ';
break;
case 'ubuntu-24.04':
case 'ubuntu-24.04-arm':
if (getenv('SPC_LIBC') === 'glibc') {
$shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' ';
}
break;
case 'macos-13':
case 'macos-14':
case 'macos-15':
@@ -208,6 +226,9 @@ switch ($argv[1] ?? null) {
passthru($prefix . $down_cmd, $retcode);
break;
case 'build_cmd':
if ($zig) {
passthru("{$prefix}install-pkg zig --debug", $retcode);
}
passthru($prefix . $build_cmd . ' --build-cli --build-micro', $retcode);
break;
case 'build_embed_cmd':