Compare commits

...

62 Commits

Author SHA1 Message Date
Jerry Ma
c5ae719b9c Update src/SPC/builder/unix/library/postgresql.php
Co-authored-by: Marc <m@pyc.ac>
2025-10-14 00:08:40 +08:00
crazywhalecc
7b6e707e24 Remove unnecessary macOS 15 bug CFLAGS from PostgreSQL build configuration 2025-10-14 00:08:40 +08:00
crazywhalecc
0114700dad Fix PostgreSQL build compatibility for aarch64 on glibc 2.17 and update test configurations 2025-10-14 00:08:40 +08:00
Marc
ec9364db69 use latest zip version for building shared (#917) 2025-10-13 11:28:16 +02:00
Marc
033e29985e Merge branch 'main' into feature/shared-exts 2025-10-13 11:20:54 +02:00
Marc
61cba2342d Drop macos-13 from actions runner (#922) 2025-10-13 11:20:37 +02:00
Marc
a3acad4ef3 Update config/source.json 2025-10-13 10:59:31 +02:00
Marc
1e13eb4abe Merge branch 'main' into ci/macos-15-intel 2025-10-13 10:38:48 +02:00
Jerry Ma
1bac06fe3c Remove more macOS 14 case from shared extensions switch
Yeah. Copied by tab.
2025-10-13 08:27:40 +08:00
Marc
762a768969 Merge branch 'main' into feature/shared-exts 2025-10-12 23:23:25 +02:00
Marc
d0a6e3a860 update pgsql version to 18.0, php 8.5 to RC2 (#916) 2025-10-12 22:59:09 +02:00
henderkes
995187d258 extra information for steps 2025-10-12 22:32:27 +02:00
henderkes
5333a04e1c clarification 2025-10-12 22:27:38 +02:00
henderkes
19be5263b5 add error 2025-10-12 22:26:06 +02:00
crazywhalecc
6e79401ab5 Add missing libs for suggested option defined 2025-10-13 00:21:13 +08:00
crazywhalecc
903036f1c0 Bump version 2025-10-13 00:00:31 +08:00
crazywhalecc
6bd3eea0fe Use SPCConfigUtil for postgresql build, refactor patches 2025-10-12 23:54:59 +08:00
crazywhalecc
f28a3cf5a3 Drop macos-13 from actions runner 2025-10-12 22:33:22 +08:00
Marc
c828c2c6e4 Merge branch 'main' into feature/shared-exts 2025-10-12 11:35:57 +02:00
Marc
ae1193ab16 Merge branch 'main' into pgsql-18 2025-10-12 11:28:49 +02:00
Marc
6d6a29368e fix building of shared extensions (grpc, simdjson, soap) (#905) 2025-10-12 11:24:32 +02:00
crazywhalecc
897cb00351 Use failsafe for SPC_EXTRA_PHP_VARS 2025-10-12 16:42:38 +08:00
henderkes
018dfae15e suggestions 2025-10-11 10:38:51 +02:00
henderkes
e437bf2ffe don't test macos 13 2025-10-06 21:05:05 +02:00
henderkes
a49ae05599 use latest zip version for building shared 2025-10-06 21:00:45 +02:00
henderkes
31a4498056 bring back simdjson tests, extension headers do not properly guard for avx512 symbols 2025-09-30 15:07:22 +02:00
henderkes
044275d909 typo 2025-09-30 14:22:38 +02:00
henderkes
c5316f9231 -v3 doesn't have avx512 yet 2025-09-30 14:21:31 +02:00
henderkes
2d1a61d184 explicitly disable avx512 if zig and march not high enough 2025-09-30 14:00:13 +02:00
henderkes
f7744188f4 fix configutil 2025-09-30 00:34:30 +02:00
henderkes
5b6c923eef snappy is a c++ lib 2025-09-30 00:31:20 +02:00
henderkes
b0b031afb2 add docstring 2025-09-30 00:18:32 +02:00
henderkes
fe09d8c03e add docstring 2025-09-30 00:17:53 +02:00
henderkes
c2813d5736 move hasCpp to SPCConfigUtil 2025-09-30 00:12:59 +02:00
Marc
8b2b658ced Merge branch 'main' into fix/grpc-shared 2025-09-29 23:27:58 +02:00
henderkes
e862bacc8a php 8.5 has beta 3 2025-09-29 21:15:56 +02:00
henderkes
cac57dbf79 php 8.5 has beta 3 2025-09-29 21:15:18 +02:00
henderkes
21149f6807 simdjson needs patch 2025-09-23 12:42:29 +02:00
henderkes
93e6dcab1d cflags and cxxflags separately 2025-09-23 12:01:09 +02:00
henderkes
59dedbea2c simdjson requires +evex512 (for zig-cc) 2025-09-23 12:00:15 +02:00
henderkes
8bda4fd31e simdjson requires +evex512 2025-09-23 11:59:30 +02:00
henderkes
8039ea49f9 soap requires libxml and session 2025-09-23 11:56:12 +02:00
henderkes
fc90b4ae23 allow appending pkg_config_path #910 2025-09-22 13:10:48 +02:00
henderkes
e02be69e40 update grpc from 1.68.x to 1.75.x 2025-09-21 21:01:07 +02:00
henderkes
35a90f2769 skip -mcpu or -march=armv8-... flags because zig doesn't support them (stupid grpc build thirdparty hardcode) 2025-09-21 20:32:47 +02:00
henderkes
fa87149631 shallow submodules as well (grpc download goes from 2.9 gb to 900mb) 2025-09-21 19:59:24 +02:00
Marc
8dfe722e14 Merge branch 'main' into fix/grpc-shared 2025-09-19 15:31:25 +02:00
henderkes
dcbfe1e0ab e-dant/watcher is a c++ library too 2025-09-19 15:29:49 +02:00
henderkes
44399cd185 remove -Wl,--as-needed for imagemagick build 2025-09-19 09:21:17 +02:00
henderkes
927d7f55ba make sure -ldl is not taken as needed, problem on EL8 2025-09-18 22:47:01 +02:00
henderkes
e323d7b155 revert to private 2025-09-18 21:41:35 +02:00
henderkes
d0b253c346 not required 2025-09-18 21:36:38 +02:00
henderkes
81430e6853 also use libstdc++.a for grpc? 2025-09-18 21:29:46 +02:00
henderkes
83696e92b7 remove whitespace 2025-09-18 20:12:41 +02:00
henderkes
b0538c09bf deduplicate those to make it more readable 2025-09-18 20:09:17 +02:00
henderkes
40f89d1dca is shared_libadd enough? 2025-09-18 19:44:48 +02:00
henderkes
fa2e041cc9 test shared grpc, imagick 2025-09-18 19:01:10 +02:00
Marc
3c614663a3 Merge branch 'main' into fix/grpc-shared 2025-09-18 18:22:42 +02:00
henderkes
b5c7185374 add comment for new method 2025-09-18 18:20:26 +02:00
henderkes
d0a9a3a594 fix return of array 2025-09-18 18:17:48 +02:00
henderkes
2e6329bb86 add cpp-library for imagemagick too 2025-09-18 18:16:42 +02:00
henderkes
d3ba04fc5b fix grpc shared build (ignores CXXFLAGS, needs CPPFLAGS) 2025-09-18 18:16:41 +02:00
27 changed files with 279 additions and 220 deletions

View File

@@ -136,12 +136,12 @@ jobs:
macos-x86_64) macos-x86_64)
DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download" DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download"
BUILD_CMD="./bin/spc build" BUILD_CMD="./bin/spc build"
RUNS_ON="macos-13" RUNS_ON="macos-15-intel"
;; ;;
macos-aarch64) macos-aarch64)
DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download" DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download"
BUILD_CMD="./bin/spc build" BUILD_CMD="./bin/spc build"
RUNS_ON="macos-14" RUNS_ON="macos-15"
;; ;;
esac esac
DOWN_CMD="$DOWN_CMD --with-php=${{ inputs.php-version }} --for-extensions=${{ inputs.extensions }} --ignore-cache-sources=php-src" DOWN_CMD="$DOWN_CMD --with-php=${{ inputs.php-version }} --for-extensions=${{ inputs.extensions }} --ignore-cache-sources=php-src"

View File

@@ -85,9 +85,9 @@ jobs:
- "8.4" - "8.4"
operating-system: operating-system:
- "ubuntu-latest" - "ubuntu-latest"
#- "macos-13" #- "macos-15-intel"
#- "debian-arm64-self-hosted" #- "debian-arm64-self-hosted"
- "macos-14" - "macos-15"
steps: steps:
- name: "Checkout" - name: "Checkout"
@@ -99,11 +99,11 @@ jobs:
OS="" OS=""
if [ "${{ matrix.operating-system }}" = "ubuntu-latest" ]; then if [ "${{ matrix.operating-system }}" = "ubuntu-latest" ]; then
OS="linux-x86_64" OS="linux-x86_64"
elif [ "${{ matrix.operating-system }}" = "macos-13" ]; then elif [ "${{ matrix.operating-system }}" = "macos-15-intel" ]; then
OS="macos-x86_64" OS="macos-x86_64"
elif [ "${{ matrix.operating-system }}" = "debian-arm64-self-hosted" ]; then elif [ "${{ matrix.operating-system }}" = "debian-arm64-self-hosted" ]; then
OS="linux-aarch64" OS="linux-aarch64"
elif [ "${{ matrix.operating-system }}" = "macos-14" ]; then elif [ "${{ matrix.operating-system }}" = "macos-15" ]; then
OS="macos-aarch64" OS="macos-aarch64"
fi fi
echo "OS=$OS" >> $GITHUB_ENV echo "OS=$OS" >> $GITHUB_ENV

View File

@@ -27,7 +27,7 @@ jobs:
os: "ubuntu-latest" os: "ubuntu-latest"
filename: "spc-linux-x86_64.tar.gz" filename: "spc-linux-x86_64.tar.gz"
- name: "macos-x86_64" - name: "macos-x86_64"
os: "macos-13" os: "macos-15-intel"
filename: "spc-macos-x86_64.tar.gz" filename: "spc-macos-x86_64.tar.gz"
- name: "linux-aarch64" - name: "linux-aarch64"
os: "ubuntu-latest" os: "ubuntu-latest"
@@ -147,11 +147,11 @@ jobs:
- name: "linux-x86_64" - name: "linux-x86_64"
os: "ubuntu-latest" os: "ubuntu-latest"
- name: "macos-x86_64" - name: "macos-x86_64"
os: "macos-13" os: "macos-15-intel"
- name: "linux-aarch64" - name: "linux-aarch64"
os: "ubuntu-24.04-arm" os: "ubuntu-24.04-arm"
- name: "macos-aarch64" - name: "macos-aarch64"
os: "macos-latest" os: "macos-15"
- name: "windows-x64" - name: "windows-x64"
os: "windows-latest" os: "windows-latest"
steps: steps:

View File

@@ -34,6 +34,7 @@
; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`) ; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`) ; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`) ; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
; SPC_EXTRA_PHP_VARS: the extra vars for building php, used in `configure` and `make` command.
[global] [global]
; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs. ; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs.

View File

@@ -759,11 +759,9 @@
}, },
"type": "builtin", "type": "builtin",
"arg-type": "custom", "arg-type": "custom",
"lib-depends": [ "ext-depends": [
"libxml2" "libxml",
], "session"
"ext-depends-windows": [
"xml"
] ]
}, },
"sockets": { "sockets": {
@@ -1154,8 +1152,9 @@
"support": { "support": {
"BSD": "wip" "BSD": "wip"
}, },
"type": "builtin", "type": "external",
"arg-type": "with-path", "source": "ext-zip",
"arg-type": "custom",
"arg-type-windows": "enable", "arg-type-windows": "enable",
"lib-depends-unix": [ "lib-depends-unix": [
"libzip" "libzip"

View File

@@ -202,6 +202,7 @@
"openssl", "openssl",
"libcares" "libcares"
], ],
"cpp-library": true,
"provide-pre-built": true, "provide-pre-built": true,
"frameworks": [ "frameworks": [
"CoreFoundation" "CoreFoundation"
@@ -230,6 +231,7 @@
}, },
"imagemagick": { "imagemagick": {
"source": "imagemagick", "source": "imagemagick",
"cpp-library": true,
"pkg-configs": [ "pkg-configs": [
"Magick++-7.Q16HDRI", "Magick++-7.Q16HDRI",
"MagickCore-7.Q16HDRI", "MagickCore-7.Q16HDRI",
@@ -822,6 +824,7 @@
}, },
"snappy": { "snappy": {
"source": "snappy", "source": "snappy",
"cpp-library": true,
"static-libs-unix": [ "static-libs-unix": [
"libsnappy.a" "libsnappy.a"
], ],
@@ -867,6 +870,7 @@
}, },
"watcher": { "watcher": {
"source": "watcher", "source": "watcher",
"cpp-library": true,
"static-libs-unix": [ "static-libs-unix": [
"libwatcher-c.a" "libwatcher-c.a"
], ],

View File

@@ -263,6 +263,15 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-zip": {
"type": "url",
"url": "https://pecl.php.net/get/zip",
"filename": "ext-zip.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-zstd": { "ext-zstd": {
"type": "git", "type": "git",
"path": "php-src/ext/zstd", "path": "php-src/ext/zstd",
@@ -324,7 +333,7 @@
}, },
"grpc": { "grpc": {
"type": "git", "type": "git",
"rev": "v1.68.x", "rev": "v1.75.x",
"url": "https://github.com/grpc/grpc.git", "url": "https://github.com/grpc/grpc.git",
"provide-pre-built": true, "provide-pre-built": true,
"license": { "license": {

View File

@@ -34,7 +34,7 @@ use Symfony\Component\Console\Application;
*/ */
final class ConsoleApplication extends Application final class ConsoleApplication extends Application
{ {
public const string VERSION = '2.7.4'; public const string VERSION = '2.7.5';
public function __construct() public function __construct()
{ {

View File

@@ -128,27 +128,6 @@ abstract class BuilderBase
return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic()); return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic());
} }
/**
* Check if there is a cpp extensions or libraries.
*/
public function hasCpp(): bool
{
// judge cpp-extension
$exts = array_keys($this->getExts(false));
foreach ($exts as $ext) {
if (Config::getExt($ext, 'cpp-extension', false) === true) {
return true;
}
}
$libs = array_keys($this->getLibs());
foreach ($libs as $lib) {
if (Config::getLib($lib, 'cpp-library', false) === true) {
return true;
}
}
return false;
}
/** /**
* Set libs only mode. * Set libs only mode.
* *

View File

@@ -5,16 +5,11 @@ declare(strict_types=1);
namespace SPC\builder; namespace SPC\builder;
use SPC\exception\EnvironmentException; use SPC\exception\EnvironmentException;
use SPC\exception\FileSystemException;
use SPC\exception\SPCException; use SPC\exception\SPCException;
use SPC\exception\ValidationException; use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\toolchain\ClangNativeToolchain;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\SPCConfigUtil; use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget; use SPC\util\SPCTarget;
@@ -226,12 +221,24 @@ class Extension
public function patchBeforeSharedMake(): bool public function patchBeforeSharedMake(): bool
{ {
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs())); $config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
[$staticLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
FileSystem::replaceFileRegex( $lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null;
$this->source_dir . '/Makefile', $lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '';
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
'$1 ' . trim($staticLibs) $makefileContent = file_get_contents($this->source_dir . '/Makefile');
); if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) {
$prefix = $matches[1];
$currentLibs = trim($matches[2]);
$newLibs = trim("{$currentLibs} {$staticLibs} {$lstdcpp}");
$deduplicatedLibs = deduplicate_flags($newLibs);
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
$prefix . $deduplicatedLibs
);
}
if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) { if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) {
FileSystem::replaceFileRegex( FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile', $this->source_dir . '/Makefile',
@@ -405,42 +412,7 @@ class Extension
*/ */
public function buildUnixShared(): void public function buildUnixShared(): void
{ {
$config = (new SPCConfigUtil($this->builder))->config( $env = $this->getSharedExtensionEnv();
[$this->getName()],
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
$this->builder->getOption('with-suggested-exts'),
$this->builder->getOption('with-suggested-libs'),
);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
$env = [
'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'],
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
if (str_contains($env['LIBS'], '-lstdc++') && SPCTarget::getTargetOS() === 'Linux') {
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$env['SPC_COMPILER_EXTRA'] = '-lstdc++';
} elseif (ToolchainManager::getToolchainClass() === GccNativeToolchain::class || ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) {
try {
$content = FileSystem::readFile($this->source_dir . '/config.m4');
if ($content && !str_contains($content, 'PHP_ADD_LIBRARY(stdc++')) {
$pattern = '/(PHP_NEW_EXTENSION\(' . $this->name . ',.*\))/m';
$replacement = "$1\nPHP_ADD_LIBRARY(stdc++, 1, " . strtoupper($this->name) . '_SHARED_LIBADD)';
FileSystem::replaceFileRegex(
$this->source_dir . '/config.m4',
$pattern,
$replacement
);
}
} catch (FileSystemException) {
}
}
}
if ($this->patchBeforeSharedPhpize()) { if ($this->patchBeforeSharedPhpize()) {
logger()->info("Extension [{$this->getName()}] patched before shared phpize"); logger()->info("Extension [{$this->getName()}] patched before shared phpize");
} }
@@ -455,13 +427,15 @@ class Extension
logger()->info("Extension [{$this->getName()}] patched before shared configure"); logger()->info("Extension [{$this->getName()}] patched before shared configure");
} }
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->setEnv($env) ->setEnv($env)
->appendEnv($this->getExtraEnv()) ->appendEnv($this->getExtraEnv())
->exec( ->exec(
'./configure ' . $this->getUnixConfigureArg(true) . './configure ' . $this->getUnixConfigureArg(true) .
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
'--enable-shared --disable-static' "--enable-shared --disable-static {$phpvars}"
); );
if ($this->patchBeforeSharedMake()) { if ($this->patchBeforeSharedMake()) {
@@ -512,6 +486,30 @@ class Extension
return $this->build_static; return $this->build_static;
} }
/**
* Returns the environment variables a shared extension needs to be built.
* CFLAGS, CXXFLAGS, LDFLAGS and so on.
*/
protected function getSharedExtensionEnv(): array
{
$config = (new SPCConfigUtil($this->builder))->config(
[$this->getName()],
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
$this->builder->getOption('with-suggested-exts'),
$this->builder->getOption('with-suggested-libs'),
);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
return [
'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'],
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
}
protected function addLibraryDependency(string $name, bool $optional = false): void protected function addLibraryDependency(string $name, bool $optional = false): void
{ {
$depLib = $this->builder->getLib($name); $depLib = $this->builder->getLib($name);
@@ -584,12 +582,12 @@ class Extension
$added = 0; $added = 0;
foreach ($ret as $depName => $dep) { foreach ($ret as $depName => $dep) {
foreach ($dep->getDependencies(true) as $depdepName => $depdep) { foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
if (!in_array($depdepName, array_keys($deps), true)) { if (!array_key_exists($depdepName, $deps)) {
$deps[$depdepName] = $depdep; $deps[$depdepName] = $depdep;
++$added; ++$added;
} }
} }
if (!in_array($depName, array_keys($deps), true)) { if (!array_key_exists($depName, $deps)) {
$deps[$depName] = $dep; $deps[$depName] = $dep;
} }
} }

View File

@@ -56,4 +56,11 @@ class grpc extends Extension
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes'); GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
return true; return true;
} }
protected function getSharedExtensionEnv(): array
{
$env = parent::getSharedExtensionEnv();
$env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes';
return $env;
}
} }

View File

@@ -6,6 +6,8 @@ namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\CustomExt; use SPC\util\CustomExt;
#[CustomExt('simdjson')] #[CustomExt('simdjson')]
@@ -17,7 +19,7 @@ class simdjson extends Extension
FileSystem::replaceFileRegex( FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/ext/simdjson/config.m4', SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
'/php_version=(`.*`)$/m', '/php_version=(`.*`)$/m',
'php_version=' . strval($php_ver) 'php_version=' . $php_ver
); );
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/simdjson/config.m4', SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
@@ -31,4 +33,18 @@ class simdjson extends Extension
); );
return true; return true;
} }
public function getSharedExtensionEnv(): array
{
$env = parent::getSharedExtensionEnv();
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$extra = getenv('SPC_COMPILER_EXTRA');
if (!str_contains((string) $extra, '-lstdc++')) {
f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++'));
}
$env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
$env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
}
return $env;
}
} }

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('zip')]
class zip extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
return !$shared ? '--with-zip=' . BUILD_ROOT_PATH : '--enable-zip=shared';
}
}

View File

@@ -95,6 +95,8 @@ class LinuxBuilder extends UnixBuilderBase
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions! // 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
]); ]);
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
if ($embed_type !== 'static' && SPCTarget::isStatic()) { if ($embed_type !== 'static' && SPCTarget::isStatic()) {
throw new WrongUsageException( throw new WrongUsageException(
@@ -116,6 +118,7 @@ class LinuxBuilder extends UnixBuilderBase
$json_74 . $json_74 .
$zts . $zts .
$maxExecutionTimers . $maxExecutionTimers .
"{$phpvars} " .
$this->makeStaticExtensionArgs() . ' ' $this->makeStaticExtensionArgs() . ' '
)); ));
@@ -153,7 +156,14 @@ class LinuxBuilder extends UnixBuilderBase
} }
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared')))); $shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) { if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...'); if (SPCTarget::isStatic()) {
throw new WrongUsageException(
"You're building against musl libc statically (the default on Linux), but you're trying to build shared extensions.\n" .
'Static musl libc does not implement `dlopen`, so your php binary is not able to load shared extensions.' . "\n" .
'Either use SPC_LIBC=glibc to link against glibc on a glibc OS, or use SPC_TARGET="native-native-musl -dynamic" to link against musl libc dynamically using `zig cc`.'
);
}
logger()->info('Building shared extensions...');
$this->buildSharedExts(); $this->buildSharedExts();
} }
} }

View File

@@ -291,11 +291,11 @@ abstract class UnixBuilderBase extends BuilderBase
} }
} }
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : ''; $debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
$extLdFlags = "-extldflags '-pie{$dynamic_exports}'"; $extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
$muslTags = ''; $muslTags = '';
$staticFlags = ''; $staticFlags = '';
if (SPCTarget::isStatic()) { if (SPCTarget::isStatic()) {
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports}'"; $extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports} {$this->arch_ld_flags}'";
$muslTags = 'static_build,'; $muslTags = 'static_build,';
$staticFlags = '-static-pie'; $staticFlags = '-static-pie';
} }
@@ -303,7 +303,6 @@ abstract class UnixBuilderBase extends BuilderBase
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list); $config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'); $cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
$libs = $config['libs']; $libs = $config['libs'];
$libs .= PHP_OS_FAMILY === 'Linux' ? ' -lrt' : '';
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix. // Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') || if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) && str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&

View File

@@ -12,6 +12,11 @@ trait imagemagick
{ {
protected function build(): void protected function build(): void
{ {
$original_ldflags = $this->builder->arch_ld_flags;
if (str_contains($this->builder->arch_ld_flags, '-Wl,--as-needed')) {
$this->builder->arch_ld_flags = str_replace('-Wl,--as-needed', '', $original_ldflags);
}
$ac = UnixAutoconfExecutor::create($this) $ac = UnixAutoconfExecutor::create($this)
->optionalLib('libzip', ...ac_with_args('zip')) ->optionalLib('libzip', ...ac_with_args('zip'))
->optionalLib('libjpeg', ...ac_with_args('jpeg')) ->optionalLib('libjpeg', ...ac_with_args('jpeg'))
@@ -32,7 +37,7 @@ trait imagemagick
); );
// special: linux-static target needs `-static` // special: linux-static target needs `-static`
$ldflags = SPCTarget::isStatic() ? ('-static -ldl') : '-ldl'; $ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl';
// special: macOS needs -iconv // special: macOS needs -iconv
$libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : ''; $libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : '';
@@ -45,6 +50,8 @@ trait imagemagick
$ac->configure()->make(); $ac->configure()->make();
$this->builder->arch_ld_flags = $original_ldflags;
$filelist = [ $filelist = [
'ImageMagick.pc', 'ImageMagick.pc',
'ImageMagick-7.Q16HDRI.pc', 'ImageMagick-7.Q16HDRI.pc',

View File

@@ -4,111 +4,77 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\builder\linux\library\LinuxLibraryBase; use SPC\exception\FileSystemException;
use SPC\exception\BuildFailureException;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\util\PkgConfigUtil; use SPC\util\PkgConfigUtil;
use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget; use SPC\util\SPCTarget;
trait postgresql trait postgresql
{ {
public function patchBeforeBuild(): bool public function patchBeforeBuild(): bool
{ {
// fix aarch64 build on glibc 2.17 (e.g. CentOS 7)
if (SPCTarget::getLibcVersion() === '2.17' && GNU_ARCH === 'aarch64') { if (SPCTarget::getLibcVersion() === '2.17' && GNU_ARCH === 'aarch64') {
FileSystem::replaceFileStr( try {
$this->source_dir . '/src/port/pg_popcount_aarch64.c', FileSystem::replaceFileStr("{$this->source_dir}/src/port/pg_popcount_aarch64.c", 'HWCAP_SVE', '0');
'HWCAP_SVE', FileSystem::replaceFileStr(
'0', "{$this->source_dir}/src/port/pg_crc32c_armv8_choose.c",
); '#if defined(__linux__) && !defined(__aarch64__) && !defined(HWCAP2_CRC32)',
FileSystem::replaceFileStr( '#if defined(__linux__) && !defined(HWCAP_CRC32)'
$this->source_dir . '/src/port/pg_crc32c_armv8_choose.c', );
'#if defined(__linux__) && !defined(__aarch64__) && !defined(HWCAP2_CRC32)', } catch (FileSystemException) {
'#if defined(__linux__) && !defined(HWCAP_CRC32)', // allow file not-existence to make it compatible with old and new version
); }
return true;
} }
return false; // skip the test on platforms where libpq infrastructure may be provided by statically-linked libraries
FileSystem::replaceFileStr("{$this->source_dir}/src/interfaces/libpq/Makefile", 'invokes exit\'; exit 1;', 'invokes exit\';');
// disable shared libs build
FileSystem::replaceFileStr(
"{$this->source_dir}/src/Makefile.shlib",
[
'$(LINK.shared) -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK)',
'$(INSTALL_SHLIB) $< \'$(DESTDIR)$(pkglibdir)/$(shlib)\'',
'$(INSTALL_SHLIB) $< \'$(DESTDIR)$(libdir)/$(shlib)\'',
'$(INSTALL_SHLIB) $< \'$(DESTDIR)$(bindir)/$(shlib)\'',
],
''
);
return true;
} }
protected function build(): void protected function build(): void
{ {
$builddir = BUILD_ROOT_PATH; $libs = array_map(fn ($x) => $x->getName(), $this->getDependencies());
$envs = ''; $spc = new SPCConfigUtil($this->getBuilder(), ['no_php' => true, 'libs_only_deps' => true]);
$packages = 'zlib openssl readline libxml-2.0'; $config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs'));
$optional_packages = [
'zstd' => 'libzstd', $env_vars = [
'ldap' => 'ldap', 'CFLAGS' => $config['cflags'],
'libxslt' => 'libxslt', 'CPPFLAGS' => '-DPIC',
'icu' => 'icu-i18n', 'LDFLAGS' => $config['ldflags'],
'LIBS' => $config['libs'],
]; ];
$error_exec_cnt = 0;
foreach ($optional_packages as $lib => $pkg) { if ($ldLibraryPath = getenv('SPC_LD_LIBRARY_PATH')) {
if ($this->builder->getLib($lib)) { $env_vars['LD_LIBRARY_PATH'] = $ldLibraryPath;
$packages .= ' ' . $pkg;
$output = shell()->execWithResult("pkg-config --static {$pkg}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
logger()->info(var_export($output[1], true));
}
}
$output = shell()->execWithResult("pkg-config --cflags-only-I --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
$macos_15_bug_cflags = PHP_OS_FAMILY === 'Darwin' ? ' -Wno-unguarded-availability-new' : '';
$cflags = '';
if (!empty($output[1][0])) {
$cflags = $output[1][0];
$envs .= ' CPPFLAGS="-DPIC"';
$cflags = "{$cflags} -fno-ident{$macos_15_bug_cflags}";
}
$output = shell()->execWithResult("pkg-config --libs-only-L --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
if (!empty($output[1][0])) {
$ldflags = $output[1][0];
$envs .= " LDFLAGS=\"{$ldflags}\" ";
}
$output = shell()->execWithResult("pkg-config --libs-only-l --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
if (!empty($output[1][0])) {
$libs = $output[1][0];
$libcpp = '';
if ($this->builder->getLib('icu')) {
$libcpp = $this instanceof LinuxLibraryBase ? ' -lstdc++' : ' -lc++';
}
$envs .= " LIBS=\"{$libs}{$libcpp}\" ";
}
if ($error_exec_cnt > 0) {
throw new BuildFailureException('Failed to get pkg-config information!');
} }
FileSystem::resetDir($this->source_dir . '/build'); FileSystem::resetDir($this->source_dir . '/build');
# 有静态链接配置 参考文件: src/interfaces/libpq/Makefile
shell()->cd($this->source_dir . '/build')
->exec('sed -i.backup "s/invokes exit\'; exit 1;/invokes exit\';/" ../src/interfaces/libpq/Makefile')
->exec('sed -i.backup "278 s/^/# /" ../src/Makefile.shlib')
->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib');
// php source relies on the non-private encoding functions in libpgcommon.a // php source relies on the non-private encoding functions in libpgcommon.a
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
$this->source_dir . '/src/common/Makefile', "{$this->source_dir}/src/common/Makefile",
'$(OBJS_FRONTEND): CPPFLAGS += -DUSE_PRIVATE_ENCODING_FUNCS', '$(OBJS_FRONTEND): CPPFLAGS += -DUSE_PRIVATE_ENCODING_FUNCS',
'$(OBJS_FRONTEND): CPPFLAGS += -UUSE_PRIVATE_ENCODING_FUNCS -DFRONTEND', '$(OBJS_FRONTEND): CPPFLAGS += -UUSE_PRIVATE_ENCODING_FUNCS -DFRONTEND',
); );
$env = [
'CFLAGS' => $cflags,
];
if ($ldLibraryPath = getenv('SPC_LD_LIBRARY_PATH')) {
$env['LD_LIBRARY_PATH'] = $ldLibraryPath;
}
// configure // configure
$shell = shell()->cd($this->source_dir . '/build')->initializeEnv($this) $shell = shell()->cd("{$this->source_dir}/build")->initializeEnv($this)
->appendEnv($env) ->appendEnv($env_vars)
->exec( ->exec(
"{$envs} ../configure " . '../configure ' .
"--prefix={$builddir} " . "--prefix={$this->getBuildRootPath()} " .
'--enable-coverage=no ' . '--enable-coverage=no ' .
'--with-ssl=openssl ' . '--with-ssl=openssl ' .
'--with-readline ' . '--with-readline ' .
@@ -125,6 +91,7 @@ trait postgresql
'--without-tcl ' '--without-tcl '
); );
// patch ldap lib
if ($this->builder->getLib('ldap')) { if ($this->builder->getLib('ldap')) {
$libs = PkgConfigUtil::getLibsArray('ldap'); $libs = PkgConfigUtil::getLibsArray('ldap');
$libs = clean_spaces(implode(' ', $libs)); $libs = clean_spaces(implode(' ', $libs));
@@ -133,18 +100,18 @@ trait postgresql
} }
$shell $shell
->exec($envs . ' make -C src/bin/pg_config install') ->exec('make -C src/bin/pg_config install')
->exec($envs . ' make -C src/include install') ->exec('make -C src/include install')
->exec($envs . ' make -C src/common install') ->exec('make -C src/common install')
->exec($envs . ' make -C src/port install') ->exec('make -C src/port install')
->exec($envs . ' make -C src/interfaces/libpq install'); ->exec('make -C src/interfaces/libpq install');
// remove dynamic libs // remove dynamic libs
shell()->cd($this->source_dir . '/build') shell()->cd($this->source_dir . '/build')
->exec("rm -rf {$builddir}/lib/*.so.*") ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so.*")
->exec("rm -rf {$builddir}/lib/*.so") ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so")
->exec("rm -rf {$builddir}/lib/*.dylib"); ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib");
FileSystem::replaceFileStr(BUILD_LIB_PATH . '/pkgconfig/libpq.pc', '-lldap', '-lldap -llber'); FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber');
} }
} }

View File

@@ -106,7 +106,7 @@ class DownloadCommand extends BaseCommand
} }
// retry // retry
$retry = intval($this->getOption('retry')); $retry = (int) $this->getOption('retry');
f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry); f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry);
// Use shallow-clone can reduce git resource download // Use shallow-clone can reduce git resource download
@@ -265,7 +265,7 @@ class DownloadCommand extends BaseCommand
f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH); f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH);
} }
// unzip command check // unzip command check
if (PHP_OS_FAMILY !== 'Windows' && !$this->findCommand('unzip')) { if (PHP_OS_FAMILY !== 'Windows' && !self::findCommand('unzip')) {
$this->output->writeln('Missing unzip command, you need to install it first !'); $this->output->writeln('Missing unzip command, you need to install it first !');
$this->output->writeln('You can use "bin/spc doctor" command to check and install required tools'); $this->output->writeln('You can use "bin/spc doctor" command to check and install required tools');
return static::FAILURE; return static::FAILURE;

View File

@@ -65,19 +65,19 @@ class Downloader
url: "https://api.github.com/repos/{$source['repo']}/{$type}", url: "https://api.github.com/repos/{$source['repo']}/{$type}",
hooks: [[CurlHook::class, 'setupGithubToken']], hooks: [[CurlHook::class, 'setupGithubToken']],
retries: self::getRetryAttempts() retries: self::getRetryAttempts()
), true); ), true, 512, JSON_THROW_ON_ERROR);
$url = null; $url = null;
for ($i = 0; $i < count($data); ++$i) { foreach ($data as $rel) {
if (($data[$i]['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) { if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) {
continue; continue;
} }
if (!($source['match'] ?? null)) { if (!($source['match'] ?? null)) {
$url = $data[$i]['tarball_url'] ?? null; $url = $rel['tarball_url'] ?? null;
break; break;
} }
if (preg_match('|' . $source['match'] . '|', $data[$i]['tarball_url'])) { if (preg_match('|' . $source['match'] . '|', $rel['tarball_url'])) {
$url = $data[$i]['tarball_url']; $url = $rel['tarball_url'];
break; break;
} }
} }
@@ -232,7 +232,8 @@ class Downloader
$quiet = !defined('DEBUG_MODE') ? '-q --quiet' : ''; $quiet = !defined('DEBUG_MODE') ? '-q --quiet' : '';
$git = SPC_GIT_EXEC; $git = SPC_GIT_EXEC;
$shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : ''; $shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : '';
$recursive = ($submodules === null) ? '--recursive' : ''; $recursive = ($submodules === null && defined('GIT_SHALLOW_CLONE')) ? '--recursive --shallow-submodules' : null;
$recursive ??= $submodules === null ? '--recursive' : '';
try { try {
self::registerCancelEvent(function () use ($download_path) { self::registerCancelEvent(function () use ($download_path) {
@@ -243,8 +244,9 @@ class Downloader
}); });
f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\""); f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\"");
if ($submodules !== null) { if ($submodules !== null) {
$depth_flag = defined('GIT_SHALLOW_CLONE') ? '--depth 1' : '';
foreach ($submodules as $submodule) { foreach ($submodules as $submodule) {
f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule)); f_passthru("cd \"{$download_path}\" && {$git} submodule update --init {$depth_flag} " . escapeshellarg($submodule));
} }
} }
} catch (SPCException $e) { } catch (SPCException $e) {
@@ -399,7 +401,7 @@ class Downloader
* Download source * Download source
* *
* @param string $name source name * @param string $name source name
* @param null|array{ * @param null|array{
* type: string, * type: string,
* repo: ?string, * repo: ?string,
* url: ?string, * url: ?string,
@@ -414,7 +416,7 @@ class Downloader
* path: ?string, * path: ?string,
* text: ?string * text: ?string
* } * }
* } $source source meta info: [type, path, rev, url, filename, regex, license] * } $source source meta info: [type, path, rev, url, filename, regex, license]
* @param bool $force Whether to force download (default: false) * @param bool $force Whether to force download (default: false)
* @param int $download_as Lock source type (default: SPC_LOCK_SOURCE) * @param int $download_as Lock source type (default: SPC_LOCK_SOURCE)
*/ */

View File

@@ -19,9 +19,15 @@ while [[ $# -gt 0 ]]; do
ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)" ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)"
[[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG") [[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG")
;; ;;
-march=*|-mcpu=*) # replace -march=x86-64 with -march=x86_64 -march=*|-mcpu=*)
OPT_NAME="${1%%=*}" OPT_NAME="${1%%=*}"
OPT_VALUE="${1#*=}" OPT_VALUE="${1#*=}"
# Skip armv8- flags entirely as Zig doesn't support them
if [[ "$OPT_VALUE" == armv8-* ]]; then
shift
continue
fi
# replace -march=x86-64 with -march=x86_64
OPT_VALUE="${OPT_VALUE//-/_}" OPT_VALUE="${OPT_VALUE//-/_}"
PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}") PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}")
shift shift

View File

@@ -20,7 +20,7 @@ class PhpSource extends CustomSourceBase
} elseif ($major === 'git') { } elseif ($major === 'git') {
Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force); Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force);
} else { } else {
Downloader::downloadSource('php-src', self::getLatestPHPInfo($major), $force); Downloader::downloadSource('php-src', $this->getLatestPHPInfo($major), $force);
} }
} }
@@ -33,7 +33,7 @@ class PhpSource extends CustomSourceBase
// 查找最新的小版本号 // 查找最新的小版本号
$info = json_decode(Downloader::curlExec( $info = json_decode(Downloader::curlExec(
url: "https://www.php.net/releases/index.php?json&version={$major_version}", url: "https://www.php.net/releases/index.php?json&version={$major_version}",
retries: intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0) retries: (int) getenv('SPC_DOWNLOAD_RETRIES') ?: 0
), true); ), true);
if (!isset($info['version'])) { if (!isset($info['version'])) {
throw new DownloaderException("Version {$major_version} not found."); throw new DownloaderException("Version {$major_version} not found.");

View File

@@ -64,6 +64,11 @@ class ZigToolchain implements ToolchainInterface
$extra_libs = trim($extra_libs . ' -lunwind'); $extra_libs = trim($extra_libs . ' -lunwind');
GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}"); GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}");
} }
$cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: '';
$has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4');
if (!$has_avx512) {
GlobalEnvManager::putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no');
}
} }
public function getCompilerInfo(): ?string public function getCompilerInfo(): ?string

View File

@@ -40,7 +40,12 @@ class GlobalEnvManager
if (is_unix()) { if (is_unix()) {
self::addPathIfNotExists(BUILD_BIN_PATH); self::addPathIfNotExists(BUILD_BIN_PATH);
self::addPathIfNotExists(PKG_ROOT_PATH . '/bin'); self::addPathIfNotExists(PKG_ROOT_PATH . '/bin');
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); $pkgConfigPath = getenv('PKG_CONFIG_PATH');
if ($pkgConfigPath !== false) {
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . "/pkgconfig:{$pkgConfigPath}");
} else {
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
}
} }
$ini = self::readIniFile(); $ini = self::readIniFile();

View File

@@ -6,6 +6,7 @@ namespace SPC\util;
use SPC\builder\BuilderBase; use SPC\builder\BuilderBase;
use SPC\builder\BuilderProvider; use SPC\builder\BuilderProvider;
use SPC\builder\Extension;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArgvInput;
@@ -87,7 +88,7 @@ class SPCConfigUtil
if (SPCTarget::getTargetOS() === 'Darwin') { if (SPCTarget::getTargetOS() === 'Darwin') {
$libs .= " {$this->getFrameworksString($extensions)}"; $libs .= " {$this->getFrameworksString($extensions)}";
} }
if ($this->builder->hasCpp()) { if ($this->hasCpp($extensions, $libraries)) {
$libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++'; $libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++';
$libs = str_replace($libcpp, '', $libs) . " {$libcpp}"; $libs = str_replace($libcpp, '', $libs) . " {$libcpp}";
} }
@@ -123,6 +124,27 @@ class SPCConfigUtil
]; ];
} }
private function hasCpp(array $extensions, array $libraries): bool
{
// judge cpp-extension
$builderExtNames = array_keys($this->builder->getExts(false));
$exts = array_unique([...$builderExtNames, ...$extensions]);
foreach ($exts as $ext) {
if (Config::getExt($ext, 'cpp-extension', false) === true) {
return true;
}
}
$builderLibNames = array_keys($this->builder->getLibs());
$libs = array_unique([...$builderLibNames, ...$libraries]);
foreach ($libs as $lib) {
if (Config::getLib($lib, 'cpp-library', false) === true) {
return true;
}
}
return false;
}
private function getIncludesString(array $libraries): string private function getIncludesString(array $libraries): string
{ {
$base = BUILD_INCLUDE_PATH; $base = BUILD_INCLUDE_PATH;

View File

@@ -245,6 +245,23 @@ function clean_spaces(string $string): string
return trim(preg_replace('/\s+/', ' ', $string)); return trim(preg_replace('/\s+/', ' ', $string));
} }
/**
* Deduplicate flags in a string. Only the last occurence of each flag will be kept.
* E.g. `-lintl -lstdc++ -lphp -lstdc++` becomes `-lintl -lphp -lstdc++`
*
* @param string $flags the string containing flags to deduplicate
* @return string the deduplicated string with no duplicate flags
*/
function deduplicate_flags(string $flags): string
{
$tokens = preg_split('/\s+/', trim($flags));
// Reverse, unique, reverse back - keeps last occurrence of duplicates
$deduplicated = array_reverse(array_unique(array_reverse($tokens)));
return implode(' ', $deduplicated);
}
/** /**
* Register a callback function to handle keyboard interrupts (Ctrl+C). * Register a callback function to handle keyboard interrupts (Ctrl+C).
* *

View File

@@ -21,21 +21,20 @@ $test_php_version = [
// 'git', // 'git',
]; ];
// test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available) // test os (macos-15-intel, macos-15, ubuntu-latest, windows-latest are available)
$test_os = [ $test_os = [
// 'macos-13', // bin/spc for x86_64 'macos-15-intel', // bin/spc for x86_64
// 'macos-14', // bin/spc for arm64
'macos-15', // bin/spc for arm64 'macos-15', // bin/spc for arm64
'ubuntu-latest', // bin/spc-alpine-docker for x86_64 // 'ubuntu-latest', // bin/spc-alpine-docker for x86_64
'ubuntu-22.04', // bin/spc-gnu-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-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 // 'windows-latest', // .\bin\spc.ps1
]; ];
// whether enable thread safe // whether enable thread safe
$zts = true; $zts = false;
$no_strip = false; $no_strip = false;
@@ -50,7 +49,7 @@ $prefer_pre_built = false;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) { $extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'pgsql', 'Linux', 'Darwin' => 'pdo_pgsql',
'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', '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',
}; };
@@ -156,17 +155,13 @@ if ($shared_extensions) {
switch ($argv[2] ?? null) { switch ($argv[2] ?? null) {
case 'ubuntu-22.04': case 'ubuntu-22.04':
case 'ubuntu-22.04-arm': case 'ubuntu-22.04-arm':
case 'macos-15':
case 'macos-15-intel':
$shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' '; $shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' ';
break; break;
case 'ubuntu-24.04': case 'ubuntu-24.04':
case 'ubuntu-24.04-arm': case 'ubuntu-24.04-arm':
break; break;
case 'macos-13':
case 'macos-14':
case 'macos-15':
$shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' ';
$no_strip = true;
break;
default: default:
$shared_cmd = ''; $shared_cmd = '';
break; break;

View File

@@ -62,12 +62,6 @@ class BuilderTest extends TestCase
$this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex')); $this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex'));
} }
public function testHasCpp()
{
// mbregex doesn't have cpp
$this->assertFalse($this->builder->hasCpp());
}
public function testMakeExtensionArgs() public function testMakeExtensionArgs()
{ {
$this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs()); $this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs());