Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d3ba04f
fix grpc shared build (ignores CXXFLAGS, needs CPPFLAGS)
henderkes Sep 18, 2025
2e6329b
add cpp-library for imagemagick too
henderkes Sep 18, 2025
d0a9a3a
fix return of array
henderkes Sep 18, 2025
b5c7185
add comment for new method
henderkes Sep 18, 2025
3c61466
Merge branch 'main' into fix/grpc-shared
henderkes Sep 18, 2025
fa2e041
test shared grpc, imagick
henderkes Sep 18, 2025
40f89d1
is shared_libadd enough?
henderkes Sep 18, 2025
b0538c0
deduplicate those to make it more readable
henderkes Sep 18, 2025
83696e9
remove whitespace
henderkes Sep 18, 2025
81430e6
also use libstdc++.a for grpc?
henderkes Sep 18, 2025
d0b253c
not required
henderkes Sep 18, 2025
e323d7b
revert to private
henderkes Sep 18, 2025
927d7f5
make sure -ldl is not taken as needed, problem on EL8
henderkes Sep 18, 2025
44399cd
remove -Wl,--as-needed for imagemagick build
henderkes Sep 19, 2025
dcbfe1e
e-dant/watcher is a c++ library too
henderkes Sep 19, 2025
8dfe722
Merge branch 'main' into fix/grpc-shared
henderkes Sep 19, 2025
fa87149
shallow submodules as well (grpc download goes from 2.9 gb to 900mb)
henderkes Sep 21, 2025
35a90f2
skip -mcpu or -march=armv8-... flags because zig doesn't support them…
henderkes Sep 21, 2025
e02be69
update grpc from 1.68.x to 1.75.x
henderkes Sep 21, 2025
fc90b4a
allow appending pkg_config_path #910
henderkes Sep 22, 2025
8039ea4
soap requires libxml and session
henderkes Sep 23, 2025
8bda4fd
simdjson requires +evex512
henderkes Sep 23, 2025
59dedbe
simdjson requires +evex512 (for zig-cc)
henderkes Sep 23, 2025
93e6dca
cflags and cxxflags separately
henderkes Sep 23, 2025
21149f6
simdjson needs patch
henderkes Sep 23, 2025
cac57db
php 8.5 has beta 3
henderkes Sep 29, 2025
e862bac
php 8.5 has beta 3
henderkes Sep 29, 2025
8b2b658
Merge branch 'main' into fix/grpc-shared
henderkes Sep 29, 2025
c2813d5
move hasCpp to SPCConfigUtil
henderkes Sep 29, 2025
fe09d8c
add docstring
henderkes Sep 29, 2025
b0b031a
add docstring
henderkes Sep 29, 2025
5b6c923
snappy is a c++ lib
henderkes Sep 29, 2025
f774418
fix configutil
henderkes Sep 29, 2025
2d1a61d
explicitly disable avx512 if zig and march not high enough
henderkes Sep 30, 2025
c5316f9
-v3 doesn't have avx512 yet
henderkes Sep 30, 2025
044275d
typo
henderkes Sep 30, 2025
31a4498
bring back simdjson tests, extension headers do not properly guard fo…
henderkes Sep 30, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions config/ext.json
Original file line number Diff line number Diff line change
Expand Up @@ -759,11 +759,9 @@
},
"type": "builtin",
"arg-type": "custom",
"lib-depends": [
"libxml2"
],
"ext-depends-windows": [
"xml"
"ext-depends": [
"libxml",
"session"
]
},
"sockets": {
Expand Down
4 changes: 4 additions & 0 deletions config/lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
"openssl",
"libcares"
],
"cpp-library": true,
"provide-pre-built": true,
"frameworks": [
"CoreFoundation"
Expand Down Expand Up @@ -230,6 +231,7 @@
},
"imagemagick": {
"source": "imagemagick",
"cpp-library": true,
"pkg-configs": [
"Magick++-7.Q16HDRI",
"MagickCore-7.Q16HDRI",
Expand Down Expand Up @@ -822,6 +824,7 @@
},
"snappy": {
"source": "snappy",
"cpp-library": true,
"static-libs-unix": [
"libsnappy.a"
],
Expand Down Expand Up @@ -867,6 +870,7 @@
},
"watcher": {
"source": "watcher",
"cpp-library": true,
"static-libs-unix": [
"libwatcher-c.a"
],
Expand Down
2 changes: 1 addition & 1 deletion config/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
},
"grpc": {
"type": "git",
"rev": "v1.68.x",
"rev": "v1.75.x",
"url": "https://github.com/grpc/grpc.git",
"provide-pre-built": true,
"license": {
Expand Down
21 changes: 0 additions & 21 deletions src/SPC/builder/BuilderBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,27 +128,6 @@ public function getExts(bool $including_shared = true): array
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.
*
Expand Down
98 changes: 50 additions & 48 deletions src/SPC/builder/Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
namespace SPC\builder;

use SPC\exception\EnvironmentException;
use SPC\exception\FileSystemException;
use SPC\exception\SPCException;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\toolchain\ClangNativeToolchain;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\SPCConfigUtil;
Expand Down Expand Up @@ -226,12 +223,24 @@ public function patchBeforeSharedConfigure(): bool
public function patchBeforeSharedMake(): bool
{
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
[$staticLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
'$1 ' . trim($staticLibs)
);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null;
$lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '';

$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')) {
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
Expand Down Expand Up @@ -405,42 +414,7 @@ public function buildShared(array $visited = []): void
*/
public function buildUnixShared(): void
{
$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 ';
$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) {
}
}
}

$env = $this->getSharedExtensionEnv();
if ($this->patchBeforeSharedPhpize()) {
logger()->info("Extension [{$this->getName()}] patched before shared phpize");
}
Expand All @@ -455,13 +429,17 @@ public function buildUnixShared(): void
logger()->info("Extension [{$this->getName()}] patched before shared configure");
}

$has_avx512 = str_contains($this->builder->arch_c_flags ?? '', '-mavx512') ||
str_contains($this->arch_c_flags ?? '', '-march=x86-64-v4') ||
ToolchainManager::getToolchainClass() !== ZigToolchain::class;

shell()->cd($this->source_dir)
->setEnv($env)
->appendEnv($this->getExtraEnv())
->exec(
'./configure ' . $this->getUnixConfigureArg(true) .
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
'--enable-shared --disable-static'
'--enable-shared --disable-static' . (!$has_avx512 ? ' php_cv_have_avx512=no php_cv_have_avx512vbmi=no' : '')
);

if ($this->patchBeforeSharedMake()) {
Expand Down Expand Up @@ -512,6 +490,30 @@ public function isBuildStatic(): bool
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
{
$depLib = $this->builder->getLib($name);
Expand Down Expand Up @@ -584,12 +586,12 @@ private function getLibraryDependencies(bool $recursive = false): array
$added = 0;
foreach ($ret as $depName => $dep) {
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
if (!in_array($depdepName, array_keys($deps), true)) {
if (!array_key_exists($depdepName, $deps)) {
$deps[$depdepName] = $depdep;
++$added;
}
}
if (!in_array($depName, array_keys($deps), true)) {
if (!array_key_exists($depName, $deps)) {
$deps[$depName] = $dep;
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/SPC/builder/extension/grpc.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,11 @@ public function patchBeforeMake(): bool
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
return true;
}

protected function getSharedExtensionEnv(): array
{
$env = parent::getSharedExtensionEnv();
$env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes';
return $env;
}
}
18 changes: 17 additions & 1 deletion src/SPC/builder/extension/simdjson.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\CustomExt;

#[CustomExt('simdjson')]
Expand All @@ -17,7 +19,7 @@ public function patchBeforeBuildconf(): bool
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
'/php_version=(`.*`)$/m',
'php_version=' . strval($php_ver)
'php_version=' . $php_ver
);
FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
Expand All @@ -31,4 +33,18 @@ public function patchBeforeBuildconf(): bool
);
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;
}
}
7 changes: 7 additions & 0 deletions src/SPC/builder/linux/LinuxBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\GlobalEnvManager;
use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget;
Expand Down Expand Up @@ -103,6 +105,10 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
);
}

$has_avx512 = str_contains($this->arch_c_flags, '-mavx512') ||
str_contains($this->arch_c_flags, '-march=x86-64-v4') ||
ToolchainManager::getToolchainClass() !== ZigToolchain::class;

$this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec(
$php_configure_env . ' ' .
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
Expand All @@ -116,6 +122,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
$json_74 .
$zts .
$maxExecutionTimers .
(!$has_avx512 ? 'php_cv_have_avx512=no php_cv_have_avx512vbmi=no ' : '') .
$this->makeStaticExtensionArgs() . ' '
));

Expand Down
5 changes: 2 additions & 3 deletions src/SPC/builder/unix/UnixBuilderBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,19 +291,18 @@ protected function buildFrankenphp(): void
}
}
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
$extLdFlags = "-extldflags '-pie{$dynamic_exports}'";
$extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
$muslTags = '';
$staticFlags = '';
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,';
$staticFlags = '-static-pie';
}

$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');
$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.
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&
Expand Down
9 changes: 8 additions & 1 deletion src/SPC/builder/unix/library/imagemagick.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ trait imagemagick
{
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);
}

Comment on lines +15 to +19
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to change only for this scope rather than modifying builder property? I don't think modifying builder's value is the best idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of a way, unfortunately, other than patching imagemagick's ./configure, but that would be much worse than temporarily changing the ldflags.

$ac = UnixAutoconfExecutor::create($this)
->optionalLib('libzip', ...ac_with_args('zip'))
->optionalLib('libjpeg', ...ac_with_args('jpeg'))
Expand All @@ -32,7 +37,7 @@ protected function build(): void
);

// special: linux-static target needs `-static`
$ldflags = SPCTarget::isStatic() ? ('-static -ldl') : '-ldl';
$ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl';

// special: macOS needs -iconv
$libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : '';
Expand All @@ -45,6 +50,8 @@ protected function build(): void

$ac->configure()->make();

$this->builder->arch_ld_flags = $original_ldflags;

$filelist = [
'ImageMagick.pc',
'ImageMagick-7.Q16HDRI.pc',
Expand Down
4 changes: 2 additions & 2 deletions src/SPC/command/DownloadCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public function handle(): int
}

// retry
$retry = intval($this->getOption('retry'));
$retry = (int) $this->getOption('retry');
f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry);

// Use shallow-clone can reduce git resource download
Expand Down Expand Up @@ -265,7 +265,7 @@ private function downloadFromZip(string $path): int
f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH);
}
// 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('You can use "bin/spc doctor" command to check and install required tools');
return static::FAILURE;
Expand Down
Loading