toolchain fixes forward port from v2-pgo

This commit is contained in:
henderkes
2026-05-10 19:27:36 +07:00
parent ca8a28a364
commit 4f7694267b
11 changed files with 260 additions and 35 deletions

View File

@@ -73,13 +73,20 @@ class LinuxMuslCheck
$prefix = 'sudo ';
logger()->warning('Current user is not root, using sudo for running command');
}
$sysEnv = ['CC' => 'gcc', 'CXX' => 'g++', 'AR' => 'ar', 'LD' => 'ld', 'RANLIB' => 'ranlib'];
$envFlags = '';
foreach ($sysEnv as $k => $v) {
$envFlags .= "{$k}={$v} ";
}
$envFlags = rtrim($envFlags);
$shell = shell()->cd(SOURCE_PATH . '/musl-wrapper')
->exec('CC=gcc CXX=g++ AR=ar LD=ld ./configure --disable-gcc-wrapper')
->exec('CC=gcc CXX=g++ AR=ar LD=ld make -j');
->setEnv($sysEnv)
->exec('./configure --disable-gcc-wrapper')
->exec('make -j');
if ($prefix !== '') {
f_passthru('cd ' . SOURCE_PATH . "/musl-wrapper && CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
f_passthru('cd ' . SOURCE_PATH . "/musl-wrapper && {$envFlags} {$prefix}make install");
} else {
$shell->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
$shell->exec("{$prefix}make install");
}
return true;
}

View File

@@ -274,14 +274,20 @@ class PhpExtensionPackage extends Package
$compiler_extra = trim($compiler_extra . ' -lcompiler_rt');
GlobalEnvManager::putenv("SPC_COMPILER_EXTRA={$compiler_extra}");
}
$config = (new SPCConfigUtil())->getExtensionConfig($this);
// include_suggests so transitive optional libs (e.g. librdkafka → lz4/zstd/ssl) are in the link line
$config = (new SPCConfigUtil())->getExtensionConfig($this, include_suggests: true);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
// -Wl,-Bsymbolic: bind zend_* refs to the .so's own copies, not via global lookup
$ldflags = (string) $config['ldflags'];
if (PHP_OS_FAMILY !== 'Darwin' && !str_contains($ldflags, '-Wl,-Bsymbolic')) {
$ldflags = clean_spaces($ldflags . ' -Wl,-Bsymbolic');
}
return [
'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'],
'LDFLAGS' => $ldflags,
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
@@ -303,10 +309,11 @@ class PhpExtensionPackage extends Package
public function configureForUnix(array $env, PhpExtensionPackage $package): void
{
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
// CustomPhpConfigureArg keys are OS names ('Linux'/'Darwin'), not platform strings
shell()->cd($package->getSourceDir())
->setEnv($env)
->exec(
'./configure ' . $this->getPhpConfigureArg(SystemTarget::getCurrentPlatformString(), true) .
'./configure ' . $this->getPhpConfigureArg(SystemTarget::getTargetOS(), true) .
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
"--enable-shared --disable-static {$phpvars}"
);
@@ -318,6 +325,8 @@ class PhpExtensionPackage extends Package
#[Stage]
public function makeForUnix(array $env, PhpExtensionPackage $package, PackageBuilder $builder): void
{
// phpize Makefile's _SHARED_LIBADD line misses our static archives — splice them in
$package->patchSharedLibAdd();
shell()->cd($package->getSourceDir())
->setEnv($env)
->exec('make clean')
@@ -325,6 +334,34 @@ class PhpExtensionPackage extends Package
->exec('make install');
}
public function patchSharedLibAdd(): void
{
// include_suggests so transitive optional libs (e.g. librdkafka → lz4/zstd/ssl) are in the link line
$config = (new SPCConfigUtil())->getExtensionConfig($this, include_suggests: true);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a')
? '-l:libstdc++.a'
: (str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '');
$makefile = $this->getSourceDir() . '/Makefile';
if (!is_file($makefile)) {
return;
}
$content = (string) file_get_contents($makefile);
if (!preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $content, $m)) {
return;
}
$prefix = $m[1];
$current = trim($m[2]);
$merged = clean_spaces("{$current} {$staticLibs} {$lstdcpp}");
$merged = deduplicate_flags($merged);
\StaticPHP\Util\FileSystem::replaceFileRegex(
$makefile,
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
$prefix . $merged
);
}
/**
* Build shared extension on Unix-like systems.
* Only for internal calling. For external use, call buildShared() instead.
@@ -333,6 +370,21 @@ class PhpExtensionPackage extends Package
*/
public function buildSharedForUnix(PackageBuilder $builder): void
{
// skip virtual addons (arg-type=none + display-name → owning ext); the parent ext built it
$argType = $this->extension_config['arg-type'] ?? null;
$displayName = $this->extension_config['display-name'] ?? null;
if ($argType === 'none' && $displayName !== null && $displayName !== $this->getExtensionName()) {
logger()->info("Skipping virtual extension [{$this->getName()}] — it's part of [{$displayName}].");
return;
}
if (!is_dir($this->getSourceDir())) {
throw new ValidationException(
"Extension source directory not found: {$this->getSourceDir()}",
validation_module: "Extension {$this->getName()} source"
);
}
$env = $this->getSharedExtensionEnv();
$this->runStage([$this, 'phpizeForUnix'], ['env' => $env]);

View File

@@ -230,7 +230,7 @@ class UnixCMakeExecutor extends Executor
// EXE linker flags: base system libs + framework flags for target packages
$exeLinkerFlags = SystemTarget::getRuntimeLibs();
if ($this->package instanceof TargetPackage) {
if ($this->package instanceof TargetPackage && SystemTarget::getTargetOS() === 'Darwin') {
$resolvedNames = array_keys($this->installer->getResolvedPackages());
$resolvedNames[] = $this->package->getName();
$fwFlags = new SPCConfigUtil()->getFrameworksString($resolvedNames);
@@ -302,9 +302,12 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES "{$include}")
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES "{$include}")
CMAKE;
// Whoops, linux may need CMAKE_AR sometimes
// pin AR/RANLIB so cmake uses zig-ar/zig-ranlib instead of system /usr/bin/ranlib (zig archives need it)
if (PHP_OS_FAMILY === 'Linux') {
$toolchain .= "\nSET(CMAKE_AR \"ar\")";
$ar = getenv('SPC_DEFAULT_AR') ?: getenv('AR') ?: 'ar';
$ranlib = getenv('SPC_DEFAULT_RANLIB') ?: (getenv('RANLIB') ?: 'ranlib');
$toolchain .= "\nSET(CMAKE_AR \"{$ar}\")";
$toolchain .= "\nSET(CMAKE_RANLIB \"{$ranlib}\")";
}
FileSystem::writeFile(SOURCE_PATH . '/toolchain.cmake', $toolchain);
return $created = realpath(SOURCE_PATH . '/toolchain.cmake');

View File

@@ -15,6 +15,7 @@ class ClangBrewToolchain extends ClangNativeToolchain
GlobalEnvManager::putenv("SPC_DEFAULT_CC={$homebrew_prefix}/opt/llvm/bin/clang");
GlobalEnvManager::putenv("SPC_DEFAULT_CXX={$homebrew_prefix}/opt/llvm/bin/clang++");
GlobalEnvManager::putenv("SPC_DEFAULT_AR={$homebrew_prefix}/opt/llvm/bin/llvm-ar");
GlobalEnvManager::putenv("SPC_DEFAULT_RANLIB={$homebrew_prefix}/opt/llvm/bin/llvm-ranlib");
GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld');
GlobalEnvManager::addPathIfNotExists("{$homebrew_prefix}/opt/llvm/bin");
}

View File

@@ -21,6 +21,7 @@ class ClangNativeToolchain implements UnixToolchainInterface
GlobalEnvManager::putenv('SPC_DEFAULT_CC=clang');
GlobalEnvManager::putenv('SPC_DEFAULT_CXX=clang++');
GlobalEnvManager::putenv('SPC_DEFAULT_AR=ar');
GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=ranlib');
GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld');
}

View File

@@ -18,6 +18,7 @@ class GccNativeToolchain implements UnixToolchainInterface
GlobalEnvManager::putenv('SPC_DEFAULT_CC=gcc');
GlobalEnvManager::putenv('SPC_DEFAULT_CXX=g++');
GlobalEnvManager::putenv('SPC_DEFAULT_AR=ar');
GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=ranlib');
GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld');
}

View File

@@ -16,28 +16,8 @@ class ZigToolchain implements UnixToolchainInterface
GlobalEnvManager::putenv('SPC_DEFAULT_CC=zig-cc');
GlobalEnvManager::putenv('SPC_DEFAULT_CXX=zig-c++');
GlobalEnvManager::putenv('SPC_DEFAULT_AR=zig-ar');
GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=zig-ranlib');
GlobalEnvManager::putenv('SPC_DEFAULT_LD=zig-ld.lld');
// Generate additional objects needed for zig toolchain
$paths = ['/usr/lib/gcc', '/usr/local/lib/gcc'];
$objects = ['crtbeginS.o', 'crtendS.o'];
$found = [];
foreach ($objects as $obj) {
$located = null;
foreach ($paths as $base) {
$output = shell_exec("find {$base} -name {$obj} 2>/dev/null | grep -v '/32/' | head -n 1");
$line = trim((string) $output);
if ($line !== '') {
$located = $line;
break;
}
}
if ($located) {
$found[] = $located;
}
}
GlobalEnvManager::putenv('SPC_EXTRA_RUNTIME_OBJECTS=' . implode(' ', $found));
}
public function afterInit(): void