55namespace SPC \builder ;
66
77use SPC \exception \EnvironmentException ;
8- use SPC \exception \FileSystemException ;
98use SPC \exception \SPCException ;
109use SPC \exception \ValidationException ;
1110use SPC \exception \WrongUsageException ;
1211use SPC \store \Config ;
1312use SPC \store \FileSystem ;
14- use SPC \toolchain \ClangNativeToolchain ;
15- use SPC \toolchain \GccNativeToolchain ;
16- use SPC \toolchain \ToolchainManager ;
17- use SPC \toolchain \ZigToolchain ;
1813use SPC \util \SPCConfigUtil ;
1914use 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 }
0 commit comments