mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-06 08:15:39 +08:00
toolchain fixes forward port from v2-pgo
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user