Compare commits

..

48 Commits

Author SHA1 Message Date
Marc
38ec03fe30 Merge pull request #871 from crazywhalecc/fix/frankenphp-dynamic-exports
build frankenphp and embed after shared extensions
2025-08-31 15:06:11 +02:00
Marc
55836771c9 Merge pull request #869 from crazywhalecc/pkg-config-pkg
turn pkg-config into a package
2025-08-31 15:04:41 +02:00
crazywhalecc
08a68796bf Call export in dynamic symbol getter 2025-08-31 18:05:09 +08:00
crazywhalecc
3b9efcb2d4 Put it into toolchain manager to skip in unit test 2025-08-31 15:24:29 +08:00
crazywhalecc
022ba3dce4 Merge branch 'main' into pkg-config-pkg
# Conflicts:
#	src/globals/test-extensions.php
2025-08-31 15:20:50 +08:00
crazywhalecc
86973e622d sort config 2025-08-31 15:06:59 +08:00
crazywhalecc
0fa38bad6d Use existing pkg-config builds and pre-built contents for packages 2025-08-31 15:04:34 +08:00
crazywhalecc
465bd3ce85 Use separated functions for exporting symbols 2025-08-31 14:24:28 +08:00
Jerry Ma
0c9130ab6c Update node version in vitepress-deploy.yml 2025-08-31 13:44:37 +08:00
crazywhalecc
6c75ecf0c4 Add docs search 2025-08-31 11:47:41 +08:00
DubbleClick
d533a0591b skip line before preg_replacing 2025-08-30 19:31:22 +07:00
DubbleClick
3f74d58503 fix macos, for real this time 2025-08-30 14:12:13 +07:00
DubbleClick
1ba92ccc99 fix patch version stripping (.\d -> .\d+) 2025-08-30 12:02:15 +07:00
DubbleClick
75db184077 fix macos command to print defined symbols? 2025-08-29 17:50:47 +07:00
DubbleClick
66902d74c4 cs fix 2025-08-29 16:38:48 +07:00
DubbleClick
f6cc6af39c macos? 3 2025-08-29 16:36:43 +07:00
DubbleClick
0da8dcf04a macos? 2 2025-08-29 15:14:54 +07:00
DubbleClick
190be6c7b9 macos? 2025-08-29 14:12:00 +07:00
DubbleClick
2972ab31d7 don't add empty dynamic list x) 2025-08-29 12:15:56 +07:00
DubbleClick
4b4ae9b014 write to a --dynamic-list file
see https://sourceware.org/binutils/docs-2.36/ld/Options.html
2025-08-29 10:53:38 +07:00
DubbleClick
20db00afcc no need to test all static targets, nothing changes for them 2025-08-29 10:26:46 +07:00
DubbleClick
56c90ca4a3 use all symbols from libphp.a, so we don't need to build shared extensions 2025-08-29 10:24:51 +07:00
DubbleClick
fad2314539 found ENABLE_SHARED option in liburing! 2025-08-29 09:25:32 +07:00
DubbleClick
460eb02086 build frankenphp and embed after shared extensions, make sure the linker doesn't drop libphp.a symbols that extensions need 2025-08-29 08:52:55 +07:00
Marc
5a30d509e7 Merge pull request #864 from crazywhalecc/swoolehooks
swoole hooks can be compiled if pgsql/sqlite are not compiled in statically
2025-08-29 03:46:30 +02:00
crazywhalecc
0f0050115c Update cli generator, add frankenphp SAPI, add copy-to-clipboard func 2025-08-28 22:35:51 +08:00
crazywhalecc
bf55db959e Add swoole-hook-odbc notes 2025-08-28 22:35:23 +08:00
DubbleClick
39a9840d49 why is phpstan so stupid about this constant? 2025-08-28 12:14:26 +07:00
DubbleClick
866ca264d9 only disable it for x86_64 2025-08-28 11:35:46 +07:00
DubbleClick
f18725083a disable opcache jit automatically on alpine target (only required for php < 8.5) 2025-08-28 11:32:33 +07:00
crazywhalecc
20fbbb1dbe test 2025-08-28 11:01:58 +08:00
crazywhalecc
1a7bf2d070 test 2025-08-28 10:49:02 +08:00
crazywhalecc
fc7e8ebc53 extension test 2025-08-28 10:29:22 +08:00
crazywhalecc
532360886e Merge branch 'main' into swoolehooks 2025-08-28 10:29:07 +08:00
crazywhalecc
117a54d077 extension test 2025-08-28 10:14:47 +08:00
DubbleClick
f2c131a2cc wno-int-conversion 2025-08-27 17:01:07 +07:00
DubbleClick
6f0310e8f7 cs fix 2025-08-27 16:46:58 +07:00
DubbleClick
c7141003db oops 2025-08-27 16:46:09 +07:00
DubbleClick
d32bdb2825 all env vars 2025-08-27 16:45:47 +07:00
DubbleClick
a66abfa583 test all OS 2025-08-27 16:35:24 +07:00
DubbleClick
2551772de4 use system cc 2025-08-27 16:34:29 +07:00
DubbleClick
694fd2f1e0 turn pkg-config into a package instead of a library 2025-08-27 14:33:39 +07:00
Marc
a5351e1546 Merge pull request #863 from crazywhalecc/brotli-watcher
fix gcc version detection
2025-08-25 05:32:46 +02:00
Marc
bea3bd8392 Merge pull request #861 from crazywhalecc/fix/macos-ar
Add macOS AR and LD
2025-08-22 07:23:49 +02:00
crazywhalecc
99e8900aba Add macOS AR and LD 2025-08-22 13:19:42 +08:00
Marc
1c4a6ca02e Merge pull request #860 from crazywhalecc/brotli-watcher
add brotli and watcher to lib-suggests
2025-08-21 15:31:35 +02:00
Marc
3804e842bb Merge pull request #858 from crazywhalecc/fix/imagick
imagick needs static libstdc++ on gcc-toolset (successor of devtoolse) too
2025-08-20 07:56:08 +02:00
Marc
6b5aaa38ae Merge pull request #857 from crazywhalecc/fix/lstdcpp
move -lstdc++ to the end of the libraries
2025-08-19 10:51:28 +02:00
26 changed files with 1363 additions and 982 deletions

View File

@@ -12,5 +12,5 @@ trim_trailing_whitespace = true
trim_trailing_whitespace = false
indent_size = 2
[*.{yml,yaml, vue}]
[*.{yml,yaml,vue,ts}]
indent_size = 2

View File

@@ -65,7 +65,7 @@ jobs:
- sqlsrv
- ssh2
- swoole
- swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite
- swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite,swoole-hook-odbc
- swow
- sysvmsg,sysvsem,sysvshm
- tidy
@@ -82,7 +82,7 @@ jobs:
- zlib
- zstd
php-version:
- "8.5"
- "8.4"
operating-system:
- "ubuntu-latest"
#- "macos-13"

View File

@@ -21,7 +21,6 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 18
cache: yarn
- run: yarn install --frozen-lockfile

View File

@@ -124,6 +124,8 @@ SPC_TARGET=native-macos
; compiler environments
CC=clang
CXX=clang++
AR=ar
LD=ld
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"

View File

@@ -1,9 +1,6 @@
{
"lib-base": {
"type": "root",
"lib-depends-unix": [
"pkg-config"
]
"type": "root"
},
"php": {
"type": "root",

View File

@@ -1,4 +1,16 @@
{
"go-xcaddy-aarch64-linux": {
"type": "custom"
},
"go-xcaddy-aarch64-macos": {
"type": "custom"
},
"go-xcaddy-x86_64-linux": {
"type": "custom"
},
"go-xcaddy-x86_64-macos": {
"type": "custom"
},
"musl-toolchain-aarch64-linux": {
"type": "url",
"url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/aarch64-musl-toolchain.tgz"
@@ -15,6 +27,38 @@
"nasm-2.16.01/ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe"
}
},
"pkg-config-aarch64-linux": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-aarch64-linux-musl-1.2.5.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"pkg-config-aarch64-macos": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-aarch64-darwin.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"pkg-config-x86_64-linux": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-x86_64-linux-musl-1.2.5.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"pkg-config-x86_64-macos": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-x86_64-darwin.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"strawberry-perl-x86_64-win": {
"type": "url",
"url": "https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip"
@@ -43,30 +87,18 @@
"upx-*-win64/upx.exe": "{pkg_root_path}/bin/upx.exe"
}
},
"go-xcaddy-x86_64-linux": {
"zig-aarch64-linux": {
"type": "custom"
},
"go-xcaddy-aarch64-linux": {
"type": "custom"
},
"go-xcaddy-x86_64-macos": {
"type": "custom"
},
"go-xcaddy-aarch64-macos": {
"zig-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"
}

File diff suppressed because it is too large Load Diff

View File

@@ -51,6 +51,14 @@ export default {
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2023-present crazywhalecc'
}
},
search: {
provider: 'algolia',
options: {
appId: 'IHJHUB1SF1',
apiKey: '8266d31cc2ffbd0e059f1c6e5bdaf8fc',
indexName: 'static-php docs',
},
},
}
}

View File

@@ -46,6 +46,14 @@ If you use `swoole,swoole-hook-sqlite`, you will enable the coroutine mode of Sw
swoole-hook-sqlite conflicts with the `pdo_sqlite` extension. If you want to use Swoole and `pdo_sqlite`, please delete the pdo_sqlite extension and enable `swoole` and `swoole-hook-sqlite`.
This extension contains an implementation of the coroutine environment for `pdo_sqlite`.
## swoole-hook-odbc
swoole-hook-odbc is not an extension, it's a Hook feature of Swoole.
If you use `swoole,swoole-hook-odbc`, you will enable the coroutine mode of Swoole's `odbc` extension.
swoole-hook-odbc conflicts with the `pdo_odbc` extension. If you want to use Swoole and `pdo_odbc`, please delete the `pdo_odbc` extension and enable `swoole` and `swoole-hook-odbc`.
This extension contains an implementation of the coroutine environment for `pdo_odbc`.
## swow
1. Only PHP 8.0+ is supported.

View File

@@ -43,6 +43,14 @@ swoole-hook-sqlite 不是一个扩展,而是 Swoole 的 Hook 特性。
swoole-hook-sqlite 与 `pdo_sqlite` 扩展冲突。如需使用 Swoole 和 `pdo_sqlite`,请删除 pdo_sqlite 扩展,启用 `swoole``swoole-hook-sqlite` 即可。
该扩展包含了 `pdo_sqlite` 的协程环境的实现。
## swoole-hook-odbc
swoole-hook-odbc 不是一个扩展,而是 Swoole 的 Hook 特性。
如果你在编译时添加了 `swoole,swoole-hook-odbc`,你将启用 Swoole 的 `odbc` 扩展的协程模式。
swoole-hook-odbc 与 `pdo_odbc` 扩展冲突。如需使用 Swoole 和 `pdo_odbc`,请删除 `pdo_odbc` 扩展,启用 `swoole``swoole-hook-odbc` 即可。
该扩展包含了 `pdo_odbc` 的协程环境的实现。
## swow
1. swow 仅支持 PHP 8.0+ 版本。

View File

@@ -12,9 +12,9 @@ class mongodb extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
$arg = ' --enable-mongodb ';
$arg = ' --enable-mongodb' . ($shared ? '=shared' : '') . ' ';
$arg .= ' --with-mongodb-system-libs=no --with-mongodb-client-side-encryption=no ';
$arg .= ' --with-mongodb-sasl=no ';
$arg .= ' --with-mongodb-sasl=no ';
if ($this->builder->getLib('openssl')) {
$arg .= '--with-mongodb-ssl=openssl';
}
@@ -22,6 +22,6 @@ class mongodb extends Extension
$arg .= $this->builder->getLib('zstd') ? ' --with-mongodb-zstd=yes ' : ' --with-mongodb-zstd=no ';
// $arg .= $this->builder->getLib('snappy') ? ' --with-mongodb-snappy=yes ' : ' --with-mongodb-snappy=no ';
$arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled ';
return $arg;
return clean_spaces($arg);
}
}

View File

@@ -8,6 +8,7 @@ use SPC\builder\Extension;
use SPC\exception\WrongUsageException;
use SPC\store\SourcePatcher;
use SPC\util\CustomExt;
use SPC\util\SPCTarget;
#[CustomExt('opcache')]
class opcache extends Extension
@@ -46,7 +47,18 @@ class opcache extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
return '--enable-opcache';
$phpVersionID = $this->builder->getPHPVersionID();
$opcache_jit = ' --enable-opcache-jit';
if ((SPCTarget::getTargetOS() === 'Linux' &&
SPCTarget::getLibc() === 'musl' &&
$this->builder->getOption('enable-zts') &&
arch2gnu(php_uname('m')) === 'x86_64' &&
$phpVersionID < 80500) ||
$this->builder->getOption('disable-opcache-jit')
) {
$opcache_jit = ' --disable-opcache-jit';
}
return '--enable-opcache' . ($shared ? '=shared' : '') . $opcache_jit;
}
public function getDistName(): string

View File

@@ -25,10 +25,6 @@ class BSDBuilder extends UnixBuilderBase
f_putenv('CXX=' . $this->getOption('cxx', 'clang++'));
// set PATH
f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
// set PKG_CONFIG
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
// set PKG_CONFIG_PATH
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig/');
// set arch (default: current)
$this->setOptionIfNotExist('arch', php_uname('m'));
@@ -122,6 +118,11 @@ class BSDBuilder extends UnixBuilderBase
}
$this->buildEmbed();
}
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...');
$this->buildSharedExts();
}
if ($enableFrankenphp) {
logger()->info('building frankenphp');
$this->buildFrankenphp();

View File

@@ -64,10 +64,7 @@ class LinuxBuilder extends UnixBuilderBase
// if opcache_jit is enabled for 8.5 or opcache enabled,
// we need to disable undefined behavior sanitizer.
f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined');
} elseif ($opcache_jit) {
$opcache_jit = false;
}
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit ' : '--disable-opcache-jit ';
if ($this->getOption('enable-zts', false)) {
$maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : '';
@@ -115,7 +112,6 @@ class LinuxBuilder extends UnixBuilderBase
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
$config_file_path .
$config_file_scan_dir .
$opcache_jit_arg .
$json_74 .
$zts .
$maxExecutionTimers .
@@ -146,6 +142,12 @@ class LinuxBuilder extends UnixBuilderBase
}
$this->buildEmbed();
}
// build dynamic extensions if needed, must happen before building FrankenPHP to make sure we export all necessary, undefined symbols
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...');
$this->buildSharedExts();
}
if ($enableFrankenphp) {
logger()->info('building frankenphp');
$this->buildFrankenphp();
@@ -316,6 +318,8 @@ class LinuxBuilder extends UnixBuilderBase
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar';
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');
// export dynamic symbols
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
}
if (!$this->getOption('no-strip', false) && file_exists(BUILD_LIB_PATH . '/' . $realLibName)) {

View File

@@ -51,8 +51,7 @@ class liburing extends LinuxLibraryBase
$use_libc ? '--use-libc' : '',
)
->configure()
->make('library', with_clean: false)
->exec("rm -rf {$this->getLibDir()}/liburing*.so*");
->make('library', 'install ENABLE_SHARED=0', with_clean: false);
$this->patchPkgconfPrefix();
}

View File

@@ -90,13 +90,6 @@ class MacOSBuilder extends UnixBuilderBase
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
$opcache_jit = !$this->getOption('disable-opcache-jit', false);
// disable opcache jit for PHP < 8.5.0 when opcache is not enabled
if ($opcache_jit && $phpVersionID < 80500 && !$this->getExt('opcache')) {
$opcache_jit = false;
}
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit ' : '--disable-opcache-jit ';
$config_file_path = $this->getOption('with-config-file-path', false) ?
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
@@ -131,7 +124,6 @@ class MacOSBuilder extends UnixBuilderBase
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
$opcache_jit_arg .
$config_file_path .
$config_file_scan_dir .
$json_74 .
@@ -164,6 +156,11 @@ class MacOSBuilder extends UnixBuilderBase
}
$this->buildEmbed();
}
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...');
$this->buildSharedExts();
}
if ($enableFrankenphp) {
logger()->info('building frankenphp');
$this->buildFrankenphp();
@@ -255,6 +252,8 @@ class MacOSBuilder extends UnixBuilderBase
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar';
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');
// export dynamic symbols
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
}
$this->patchPhpScripts();
}

View File

@@ -4,15 +4,92 @@ declare(strict_types=1);
namespace SPC\builder\traits;
/**
* Unix 系统的工具函数 Trait适用于 Linux、macOS
*/
use SPC\exception\ExecutionException;
use SPC\exception\SPCInternalException;
use SPC\exception\WrongUsageException;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\SPCTarget;
trait UnixSystemUtilTrait
{
/**
* @param string $name 命令名称
* @param array $paths 寻找的目标路径(如果不传入,则使用环境变量 PATH
* @return null|string 找到了返回命令路径,找不到返回 null
* Export static library dynamic symbols to a .dynsym file.
* It will export to "/path/to/libxxx.a.dynsym".
*
* @param string $lib_file Static library file path (e.g. /path/to/libxxx.a)
*/
public static function exportDynamicSymbols(string $lib_file): void
{
// check
if (!is_file($lib_file)) {
throw new WrongUsageException("The lib archive file {$lib_file} does not exist, please build it first.");
}
// shell out
$cmd = 'nm -g --defined-only -P ' . escapeshellarg($lib_file);
$result = shell()->execWithResult($cmd);
if ($result[0] !== 0) {
throw new ExecutionException($cmd, 'Failed to get defined symbols from ' . $lib_file);
}
// parse shell output and filter
$defined = [];
foreach ($result[1] as $line) {
$line = trim($line);
if ($line === '' || str_ends_with($line, '.o:') || str_ends_with($line, '.o]:')) {
continue;
}
$name = strtok($line, " \t");
if (!$name) {
continue;
}
$name = preg_replace('/@.*$/', '', $name);
if ($name !== '' && $name !== false) {
$defined[] = $name;
}
}
$defined = array_unique($defined);
sort($defined);
// export
if (SPCTarget::getTargetOS() === 'Linux') {
file_put_contents("{$lib_file}.dynsym", "{\n" . implode("\n", array_map(fn ($x) => " {$x};", $defined)) . "};\n");
} else {
file_put_contents("{$lib_file}.dynsym", implode("\n", $defined) . "\n");
}
}
/**
* Get linker flag to export dynamic symbols from a static library.
*
* @param string $lib_file Static library file path (e.g. /path/to/libxxx.a)
* @return null|string Linker flag to export dynamic symbols, null if no .dynsym file found
*/
public static function getDynamicExportedSymbols(string $lib_file): ?string
{
$symbol_file = "{$lib_file}.dynsym";
if (!is_file($symbol_file)) {
self::exportDynamicSymbols($lib_file);
}
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
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
return '-Wl,--export-dynamic';
}
// macOS
if (SPCTarget::getTargetOS() !== 'Linux') {
return "-Wl,-exported_symbols_list,{$symbol_file}";
}
return "-Wl,--dynamic-list={$symbol_file}";
}
/**
* Find a command in given paths or system PATH.
* If $name is an absolute path, check if it exists.
*
* @param string $name Command name or absolute path
* @param array $paths Paths to search, if empty, use system PATH
* @return null|string Absolute path of the command if found, null otherwise
*/
public static function findCommand(string $name, array $paths = []): ?string
{
@@ -31,6 +108,8 @@ trait UnixSystemUtilTrait
}
/**
* Make environment variable string for shell command.
*
* @param array $vars Variables, like: ["CFLAGS" => "-Ixxx"]
* @return string like: CFLAGS="-Ixxx"
*/

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\unix;
use SPC\builder\BuilderBase;
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
use SPC\exception\SPCInternalException;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
@@ -137,6 +138,7 @@ abstract class UnixBuilderBase extends BuilderBase
if (SPCTarget::isStatic()) {
$lens .= ' -static';
}
$dynamic_exports = '';
// 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') {
@@ -151,8 +153,13 @@ abstract class UnixBuilderBase extends BuilderBase
foreach (glob(BUILD_LIB_PATH . "/libphp*.{$suffix}") as $file) {
unlink($file);
}
// calling linux system util in other unix OS is okay
if ($dynamic_exports = LinuxSystemUtil::getDynamicExportedSymbols(BUILD_LIB_PATH . '/libphp.a')) {
$dynamic_exports = ' ' . $dynamic_exports;
}
}
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
$cc = getenv('CC');
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult("{$cc} -o embed embed.c {$lens} {$dynamic_exports}");
if ($ret !== 0) {
throw new ValidationException(
'embed failed sanity check: build failed. Error message: ' . implode("\n", $out),
@@ -267,15 +274,20 @@ abstract class UnixBuilderBase extends BuilderBase
), true);
$frankenPhpVersion = $releaseInfo['tag_name'];
$libphpVersion = $this->getPHPVersion();
$dynamic_exports = '';
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
$libphpVersion = preg_replace('/\.\d$/', '', $libphpVersion);
$libphpVersion = preg_replace('/\.\d+$/', '', $libphpVersion);
} else {
if ($dynamicSymbolsArgument = LinuxSystemUtil::getDynamicExportedSymbols(BUILD_LIB_PATH . '/libphp.a')) {
$dynamic_exports = ' ' . $dynamicSymbolsArgument;
}
}
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
$extLdFlags = "-extldflags '-pie'";
$extLdFlags = "-extldflags '-pie{$dynamic_exports}'";
$muslTags = '';
$staticFlags = '';
if (SPCTarget::isStatic()) {
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000'";
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports}'";
$muslTags = 'static_build,';
$staticFlags = '-static-pie';
}

View File

@@ -211,12 +211,6 @@ class BuildPHPCommand extends BuildCommand
// start to build
$builder->buildPHP($rule);
// build dynamic extensions if needed
if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...');
$builder->buildSharedExts();
}
$builder->testPHP($rule);
// compile stopwatch :P

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace SPC\doctor\item;
use SPC\doctor\AsCheckItem;
use SPC\doctor\AsFixItem;
use SPC\doctor\CheckResult;
use SPC\doctor\OptionalCheck;
use SPC\store\PackageManager;
use SPC\util\PkgConfigUtil;
#[OptionalCheck([self::class, 'optionalCheck'])]
class PkgConfigCheck
{
public static function optionalCheck(): bool
{
return PHP_OS_FAMILY !== 'Windows';
}
/** @noinspection PhpUnused */
#[AsCheckItem('if pkg-config is installed or built', level: 800)]
public function checkPkgConfig(): CheckResult
{
if (!($pkgconf = PkgConfigUtil::findPkgConfig())) {
return CheckResult::fail('pkg-config is not installed', 'install-pkgconfig');
}
return CheckResult::ok($pkgconf);
}
#[AsFixItem('install-pkgconfig')]
public function installPkgConfig(): bool
{
PackageManager::installPackage('pkg-config');
return true;
}
}

View File

@@ -7,6 +7,7 @@ namespace SPC\toolchain;
use SPC\builder\linux\SystemUtil;
use SPC\exception\WrongUsageException;
use SPC\util\GlobalEnvManager;
use SPC\util\PkgConfigUtil;
use SPC\util\SPCTarget;
class ToolchainManager
@@ -56,6 +57,15 @@ class ToolchainManager
if (SPCTarget::getLibc() === 'glibc' && SystemUtil::isMuslDist()) {
throw new WrongUsageException('You are linking against glibc dynamically, which is only supported on glibc distros.');
}
// init pkg-config for unix
if (is_unix()) {
if (($found = PkgConfigUtil::findPkgConfig()) === null) {
throw new WrongUsageException('Cannot find pkg-config executable. Please run `doctor` to fix this.');
}
GlobalEnvManager::putenv("PKG_CONFIG={$found}");
}
$toolchain = getenv('SPC_TOOLCHAIN');
/* @var ToolchainInterface $toolchain */
$instance = new $toolchain();

View File

@@ -39,8 +39,8 @@ class GlobalEnvManager
// Define env vars for unix
if (is_unix()) {
self::addPathIfNotExists(BUILD_BIN_PATH);
self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config');
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
self::addPathIfNotExists(PKG_ROOT_PATH . '/bin');
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
}
$ini = self::readIniFile();

View File

@@ -14,6 +14,28 @@ use SPC\exception\ExecutionException;
*/
class PkgConfigUtil
{
/**
* Find the pkg-config executable which is compatible with static builds.
*
* @return null|string Path to pkg-config executable, or null if not found
*/
public static function findPkgConfig(): ?string
{
// Find pkg-config executable
$find_list = [
PKG_ROOT_PATH . '/bin/pkg-config',
BUILD_BIN_PATH . '/pkg-config',
];
$found = null;
foreach ($find_list as $file) {
if (file_exists($file) && is_executable($file)) {
$found = $file;
break;
}
}
return $found;
}
/**
* Returns the version of a module.
* This method uses `pkg-config --modversion` to get the version of the specified module.

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\store\FileSystem;
use SPC\util\PkgConfigUtil;
use SPC\util\shell\UnixShell;
/**
@@ -184,6 +185,7 @@ class UnixCMakeExecutor extends Executor
$cxx = getenv('CCX');
logger()->debug("making cmake tool chain file for {$os} {$target_arch} with CFLAGS='{$cflags}'");
$root = BUILD_ROOT_PATH;
$pkgConfigExecutable = PkgConfigUtil::findPkgConfig();
$ccLine = '';
if ($cc) {
$ccLine = 'SET(CMAKE_C_COMPILER ' . $cc . ')';
@@ -202,7 +204,7 @@ SET(CMAKE_PREFIX_PATH "{$root}")
SET(CMAKE_INSTALL_PREFIX "{$root}")
SET(CMAKE_INSTALL_LIBDIR "lib")
set(PKG_CONFIG_EXECUTABLE "{$root}/bin/pkg-config")
set(PKG_CONFIG_EXECUTABLE "{$pkgConfigExecutable}")
list(APPEND PKG_CONFIG_EXECUTABLE "--static")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)

View File

@@ -23,14 +23,14 @@ $test_php_version = [
// test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available)
$test_os = [
// 'macos-13', // bin/spc for x86_64
'macos-13', // bin/spc for x86_64
// 'macos-14', // bin/spc for arm64
'macos-15', // bin/spc for arm64
'ubuntu-latest', // bin/spc-alpine-docker for x86_64
'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
'ubuntu-24.04', // bin/spc for x86_64
// 'ubuntu-24.04', // bin/spc for x86_64
'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
'ubuntu-24.04-arm', // bin/spc for arm64
// 'ubuntu-24.04-arm', // bin/spc for arm64
// 'windows-latest', // .\bin\spc.ps1
];
@@ -50,13 +50,13 @@ $prefer_pre_built = false;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'swoole,swoole-hook-mysql,swoole-hook-pgsql,swoole-hook-sqlite,swoole-hook-odbc',
'Linux', 'Darwin' => 'bcmath',
'Windows' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pdo,pdo_mysql,pdo_sqlite,phar,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip',
};
// If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`).
$shared_extensions = match (PHP_OS_FAMILY) {
'Linux' => '',
'Linux' => 'zip',
'Darwin' => '',
'Windows' => '',
};

1134
yarn.lock

File diff suppressed because it is too large Load Diff