mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-02 22:35:43 +08:00
Build the CC/CXX/AR/LD/RANLIB map once and hand it to shell()->setEnv() so the configure/make invocations don't have to repeat the same prefix on every line. For the sudo make-install path the env still needs to be on the command line (sudo strips the parent env), so the same map is rendered into $envFlags and prepended there. Also adds RANLIB, which the upstream Makefile honours.
116 lines
4.5 KiB
PHP
116 lines
4.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace StaticPHP\Doctor\Item;
|
|
|
|
use StaticPHP\Artifact\ArtifactCache;
|
|
use StaticPHP\Artifact\ArtifactDownloader;
|
|
use StaticPHP\Artifact\ArtifactExtractor;
|
|
use StaticPHP\Attribute\Doctor\CheckItem;
|
|
use StaticPHP\Attribute\Doctor\FixItem;
|
|
use StaticPHP\Attribute\Doctor\OptionalCheck;
|
|
use StaticPHP\DI\ApplicationContext;
|
|
use StaticPHP\Doctor\CheckResult;
|
|
use StaticPHP\Runtime\Shell\Shell;
|
|
use StaticPHP\Toolchain\Interface\ToolchainInterface;
|
|
use StaticPHP\Toolchain\MuslToolchain;
|
|
use StaticPHP\Toolchain\ZigToolchain;
|
|
use StaticPHP\Util\FileSystem;
|
|
use StaticPHP\Util\InteractiveTerm;
|
|
use StaticPHP\Util\SourcePatcher;
|
|
use StaticPHP\Util\System\LinuxUtil;
|
|
|
|
#[OptionalCheck([self::class, 'optionalCheck'])]
|
|
class LinuxMuslCheck
|
|
{
|
|
public static function optionalCheck(): bool
|
|
{
|
|
$toolchain = ApplicationContext::get(ToolchainInterface::class);
|
|
return $toolchain instanceof MuslToolchain || $toolchain instanceof ZigToolchain && !LinuxUtil::isMuslDist() && !str_contains(getenv('SPC_TARGET') ?: '', 'gnu');
|
|
}
|
|
|
|
/** @noinspection PhpUnused */
|
|
#[CheckItem('if musl-wrapper is installed', limit_os: 'Linux', level: 800)]
|
|
public function checkMusl(): ?CheckResult
|
|
{
|
|
$musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m'));
|
|
if (file_exists($musl_wrapper_lib) && (file_exists('/usr/local/musl/lib/libc.a') || getenv('SPC_TOOLCHAIN') === ZigToolchain::class)) {
|
|
return null;
|
|
}
|
|
return CheckResult::fail('musl-wrapper is not installed on your system', 'fix-musl-wrapper');
|
|
}
|
|
|
|
#[CheckItem('if musl-cross-make is installed', limit_os: 'Linux', level: 799)]
|
|
public function checkMuslCrossMake(): ?CheckResult
|
|
{
|
|
if (getenv('SPC_TOOLCHAIN') === ZigToolchain::class && !LinuxUtil::isMuslDist()) {
|
|
return null;
|
|
}
|
|
$arch = arch2gnu(php_uname('m'));
|
|
$cross_compile_lib = "/usr/local/musl/{$arch}-linux-musl/lib/libc.a";
|
|
$cross_compile_gcc = "/usr/local/musl/bin/{$arch}-linux-musl-gcc";
|
|
if (file_exists($cross_compile_lib) && file_exists($cross_compile_gcc)) {
|
|
return CheckResult::ok();
|
|
}
|
|
return CheckResult::fail('musl-cross-make is not installed on your system', 'fix-musl-cross-make');
|
|
}
|
|
|
|
#[FixItem('fix-musl-wrapper')]
|
|
public function fixMusl(): bool
|
|
{
|
|
$downloader = new ArtifactDownloader(interactive: false);
|
|
$downloader->add('musl-wrapper')->download();
|
|
$extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class));
|
|
$extractor->extract('musl-wrapper');
|
|
|
|
// Apply CVE-2025-26519 patch and install musl wrapper
|
|
SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0001.patch', SOURCE_PATH . '/musl-wrapper');
|
|
SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0002.patch', SOURCE_PATH . '/musl-wrapper');
|
|
|
|
$prefix = '';
|
|
if (get_current_user() !== 'root') {
|
|
$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')
|
|
->setEnv($sysEnv)
|
|
->exec('./configure --disable-gcc-wrapper')
|
|
->exec('make -j');
|
|
if ($prefix !== '') {
|
|
f_passthru('cd ' . SOURCE_PATH . "/musl-wrapper && {$envFlags} {$prefix}make install");
|
|
} else {
|
|
$shell->exec("{$prefix}make install");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#[FixItem('fix-musl-cross-make')]
|
|
public function fixMuslCrossMake(): bool
|
|
{
|
|
// sudo
|
|
$prefix = '';
|
|
if (get_current_user() !== 'root') {
|
|
$prefix = 'sudo ';
|
|
logger()->warning('Current user is not root, using sudo for running command');
|
|
}
|
|
Shell::passthruCallback(function () {
|
|
InteractiveTerm::advance();
|
|
});
|
|
$downloader = new ArtifactDownloader(interactive: false);
|
|
$extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class));
|
|
$downloader->add('musl-toolchain')->download();
|
|
$extractor->extract('musl-toolchain');
|
|
$pkg_root = PKG_ROOT_PATH . '/musl-toolchain';
|
|
f_passthru("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl");
|
|
FileSystem::removeDir($pkg_root);
|
|
return true;
|
|
}
|
|
}
|