Skip to content

Commit 6d6a293

Browse files
authored
fix building of shared extensions (grpc, simdjson, soap) (#905)
2 parents e6408b4 + 897cb00 commit 6d6a293

File tree

21 files changed

+173
-110
lines changed

21 files changed

+173
-110
lines changed

config/env.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
3535
; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
3636
; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
37+
; SPC_EXTRA_PHP_VARS: the extra vars for building php, used in `configure` and `make` command.
3738

3839
[global]
3940
; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs.

config/ext.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -759,11 +759,9 @@
759759
},
760760
"type": "builtin",
761761
"arg-type": "custom",
762-
"lib-depends": [
763-
"libxml2"
764-
],
765-
"ext-depends-windows": [
766-
"xml"
762+
"ext-depends": [
763+
"libxml",
764+
"session"
767765
]
768766
},
769767
"sockets": {

config/lib.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@
202202
"openssl",
203203
"libcares"
204204
],
205+
"cpp-library": true,
205206
"provide-pre-built": true,
206207
"frameworks": [
207208
"CoreFoundation"
@@ -230,6 +231,7 @@
230231
},
231232
"imagemagick": {
232233
"source": "imagemagick",
234+
"cpp-library": true,
233235
"pkg-configs": [
234236
"Magick++-7.Q16HDRI",
235237
"MagickCore-7.Q16HDRI",
@@ -822,6 +824,7 @@
822824
},
823825
"snappy": {
824826
"source": "snappy",
827+
"cpp-library": true,
825828
"static-libs-unix": [
826829
"libsnappy.a"
827830
],
@@ -867,6 +870,7 @@
867870
},
868871
"watcher": {
869872
"source": "watcher",
873+
"cpp-library": true,
870874
"static-libs-unix": [
871875
"libwatcher-c.a"
872876
],

config/source.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@
324324
},
325325
"grpc": {
326326
"type": "git",
327-
"rev": "v1.68.x",
327+
"rev": "v1.75.x",
328328
"url": "https://github.com/grpc/grpc.git",
329329
"provide-pre-built": true,
330330
"license": {

src/SPC/builder/BuilderBase.php

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -128,27 +128,6 @@ public function getExts(bool $including_shared = true): array
128128
return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic());
129129
}
130130

131-
/**
132-
* Check if there is a cpp extensions or libraries.
133-
*/
134-
public function hasCpp(): bool
135-
{
136-
// judge cpp-extension
137-
$exts = array_keys($this->getExts(false));
138-
foreach ($exts as $ext) {
139-
if (Config::getExt($ext, 'cpp-extension', false) === true) {
140-
return true;
141-
}
142-
}
143-
$libs = array_keys($this->getLibs());
144-
foreach ($libs as $lib) {
145-
if (Config::getLib($lib, 'cpp-library', false) === true) {
146-
return true;
147-
}
148-
}
149-
return false;
150-
}
151-
152131
/**
153132
* Set libs only mode.
154133
*

src/SPC/builder/Extension.php

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@
55
namespace SPC\builder;
66

77
use SPC\exception\EnvironmentException;
8-
use SPC\exception\FileSystemException;
98
use SPC\exception\SPCException;
109
use SPC\exception\ValidationException;
1110
use SPC\exception\WrongUsageException;
1211
use SPC\store\Config;
1312
use SPC\store\FileSystem;
14-
use SPC\toolchain\ClangNativeToolchain;
15-
use SPC\toolchain\GccNativeToolchain;
16-
use SPC\toolchain\ToolchainManager;
17-
use SPC\toolchain\ZigToolchain;
1813
use SPC\util\SPCConfigUtil;
1914
use SPC\util\SPCTarget;
2015

@@ -226,12 +221,24 @@ public function patchBeforeSharedConfigure(): bool
226221
public function patchBeforeSharedMake(): bool
227222
{
228223
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
229-
[$staticLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
230-
FileSystem::replaceFileRegex(
231-
$this->source_dir . '/Makefile',
232-
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
233-
'$1 ' . trim($staticLibs)
234-
);
224+
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
225+
$lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null;
226+
$lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '';
227+
228+
$makefileContent = file_get_contents($this->source_dir . '/Makefile');
229+
if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) {
230+
$prefix = $matches[1];
231+
$currentLibs = trim($matches[2]);
232+
$newLibs = trim("{$currentLibs} {$staticLibs} {$lstdcpp}");
233+
$deduplicatedLibs = deduplicate_flags($newLibs);
234+
235+
FileSystem::replaceFileRegex(
236+
$this->source_dir . '/Makefile',
237+
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
238+
$prefix . $deduplicatedLibs
239+
);
240+
}
241+
235242
if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) {
236243
FileSystem::replaceFileRegex(
237244
$this->source_dir . '/Makefile',
@@ -405,42 +412,7 @@ public function buildShared(array $visited = []): void
405412
*/
406413
public function buildUnixShared(): void
407414
{
408-
$config = (new SPCConfigUtil($this->builder))->config(
409-
[$this->getName()],
410-
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
411-
$this->builder->getOption('with-suggested-exts'),
412-
$this->builder->getOption('with-suggested-libs'),
413-
);
414-
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
415-
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
416-
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
417-
$env = [
418-
'CFLAGS' => $config['cflags'],
419-
'CXXFLAGS' => $config['cflags'],
420-
'LDFLAGS' => $config['ldflags'],
421-
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
422-
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
423-
];
424-
if (str_contains($env['LIBS'], '-lstdc++') && SPCTarget::getTargetOS() === 'Linux') {
425-
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
426-
$env['SPC_COMPILER_EXTRA'] = '-lstdc++';
427-
} elseif (ToolchainManager::getToolchainClass() === GccNativeToolchain::class || ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) {
428-
try {
429-
$content = FileSystem::readFile($this->source_dir . '/config.m4');
430-
if ($content && !str_contains($content, 'PHP_ADD_LIBRARY(stdc++')) {
431-
$pattern = '/(PHP_NEW_EXTENSION\(' . $this->name . ',.*\))/m';
432-
$replacement = "$1\nPHP_ADD_LIBRARY(stdc++, 1, " . strtoupper($this->name) . '_SHARED_LIBADD)';
433-
FileSystem::replaceFileRegex(
434-
$this->source_dir . '/config.m4',
435-
$pattern,
436-
$replacement
437-
);
438-
}
439-
} catch (FileSystemException) {
440-
}
441-
}
442-
}
443-
415+
$env = $this->getSharedExtensionEnv();
444416
if ($this->patchBeforeSharedPhpize()) {
445417
logger()->info("Extension [{$this->getName()}] patched before shared phpize");
446418
}
@@ -455,13 +427,15 @@ public function buildUnixShared(): void
455427
logger()->info("Extension [{$this->getName()}] patched before shared configure");
456428
}
457429

430+
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
431+
458432
shell()->cd($this->source_dir)
459433
->setEnv($env)
460434
->appendEnv($this->getExtraEnv())
461435
->exec(
462436
'./configure ' . $this->getUnixConfigureArg(true) .
463437
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
464-
'--enable-shared --disable-static'
438+
"--enable-shared --disable-static {$phpvars}"
465439
);
466440

467441
if ($this->patchBeforeSharedMake()) {
@@ -512,6 +486,30 @@ public function isBuildStatic(): bool
512486
return $this->build_static;
513487
}
514488

489+
/**
490+
* Returns the environment variables a shared extension needs to be built.
491+
* CFLAGS, CXXFLAGS, LDFLAGS and so on.
492+
*/
493+
protected function getSharedExtensionEnv(): array
494+
{
495+
$config = (new SPCConfigUtil($this->builder))->config(
496+
[$this->getName()],
497+
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
498+
$this->builder->getOption('with-suggested-exts'),
499+
$this->builder->getOption('with-suggested-libs'),
500+
);
501+
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
502+
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
503+
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
504+
return [
505+
'CFLAGS' => $config['cflags'],
506+
'CXXFLAGS' => $config['cflags'],
507+
'LDFLAGS' => $config['ldflags'],
508+
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
509+
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
510+
];
511+
}
512+
515513
protected function addLibraryDependency(string $name, bool $optional = false): void
516514
{
517515
$depLib = $this->builder->getLib($name);
@@ -584,12 +582,12 @@ private function getLibraryDependencies(bool $recursive = false): array
584582
$added = 0;
585583
foreach ($ret as $depName => $dep) {
586584
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
587-
if (!in_array($depdepName, array_keys($deps), true)) {
585+
if (!array_key_exists($depdepName, $deps)) {
588586
$deps[$depdepName] = $depdep;
589587
++$added;
590588
}
591589
}
592-
if (!in_array($depName, array_keys($deps), true)) {
590+
if (!array_key_exists($depName, $deps)) {
593591
$deps[$depName] = $dep;
594592
}
595593
}

src/SPC/builder/extension/grpc.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,11 @@ public function patchBeforeMake(): bool
5656
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
5757
return true;
5858
}
59+
60+
protected function getSharedExtensionEnv(): array
61+
{
62+
$env = parent::getSharedExtensionEnv();
63+
$env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes';
64+
return $env;
65+
}
5966
}

src/SPC/builder/extension/simdjson.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
use SPC\builder\Extension;
88
use SPC\store\FileSystem;
9+
use SPC\toolchain\ToolchainManager;
10+
use SPC\toolchain\ZigToolchain;
911
use SPC\util\CustomExt;
1012

1113
#[CustomExt('simdjson')]
@@ -17,7 +19,7 @@ public function patchBeforeBuildconf(): bool
1719
FileSystem::replaceFileRegex(
1820
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
1921
'/php_version=(`.*`)$/m',
20-
'php_version=' . strval($php_ver)
22+
'php_version=' . $php_ver
2123
);
2224
FileSystem::replaceFileStr(
2325
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
@@ -31,4 +33,18 @@ public function patchBeforeBuildconf(): bool
3133
);
3234
return true;
3335
}
36+
37+
public function getSharedExtensionEnv(): array
38+
{
39+
$env = parent::getSharedExtensionEnv();
40+
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
41+
$extra = getenv('SPC_COMPILER_EXTRA');
42+
if (!str_contains((string) $extra, '-lstdc++')) {
43+
f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++'));
44+
}
45+
$env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
46+
$env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
47+
}
48+
return $env;
49+
}
3450
}

src/SPC/builder/linux/LinuxBuilder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
9595
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
9696
]);
9797

98+
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
99+
98100
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
99101
if ($embed_type !== 'static' && SPCTarget::isStatic()) {
100102
throw new WrongUsageException(
@@ -116,6 +118,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
116118
$json_74 .
117119
$zts .
118120
$maxExecutionTimers .
121+
"{$phpvars} " .
119122
$this->makeStaticExtensionArgs() . ' '
120123
));
121124

src/SPC/builder/unix/UnixBuilderBase.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,19 +291,18 @@ protected function buildFrankenphp(): void
291291
}
292292
}
293293
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
294-
$extLdFlags = "-extldflags '-pie{$dynamic_exports}'";
294+
$extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
295295
$muslTags = '';
296296
$staticFlags = '';
297297
if (SPCTarget::isStatic()) {
298-
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports}'";
298+
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports} {$this->arch_ld_flags}'";
299299
$muslTags = 'static_build,';
300300
$staticFlags = '-static-pie';
301301
}
302302

303303
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
304304
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
305305
$libs = $config['libs'];
306-
$libs .= PHP_OS_FAMILY === 'Linux' ? ' -lrt' : '';
307306
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
308307
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
309308
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&

0 commit comments

Comments
 (0)