mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-12 03:15:35 +08:00
[v3] Add musl-wrapper and musl-toolchain installation support (#984)
This commit is contained in:
@@ -8,6 +8,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"musl-wrapper": {
|
||||||
|
"source": "https://musl.libc.org/releases/musl-1.2.5.tar.gz"
|
||||||
|
},
|
||||||
"php-src": {
|
"php-src": {
|
||||||
"source": {
|
"source": {
|
||||||
"type": "php-release"
|
"type": "php-release"
|
||||||
@@ -28,8 +31,16 @@
|
|||||||
},
|
},
|
||||||
"musl-toolchain": {
|
"musl-toolchain": {
|
||||||
"binary": {
|
"binary": {
|
||||||
"linux-x86_64": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/x86_64-musl-toolchain.tgz",
|
"linux-x86_64": {
|
||||||
"linux-aarch64": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/aarch64-musl-toolchain.tgz"
|
"type": "url",
|
||||||
|
"url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/x86_64-musl-toolchain.tgz",
|
||||||
|
"extract": "{pkg_root_path}/musl-toolchain"
|
||||||
|
},
|
||||||
|
"linux-aarch64": {
|
||||||
|
"type": "url",
|
||||||
|
"url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/aarch64-musl-toolchain.tgz",
|
||||||
|
"extract": "{pkg_root_path}/musl-toolchain"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pkg-config": {
|
"pkg-config": {
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ class ArtifactDownloader
|
|||||||
$skipped = [];
|
$skipped = [];
|
||||||
foreach ($this->artifacts as $artifact) {
|
foreach ($this->artifacts as $artifact) {
|
||||||
++$current;
|
++$current;
|
||||||
if ($this->downloadWithType($artifact, $current, $count) === SPC_DOWNLOAD_STATUS_SKIPPED) {
|
if ($this->downloadWithType($artifact, $current, $count, interactive: $interactive) === SPC_DOWNLOAD_STATUS_SKIPPED) {
|
||||||
$skipped[] = $artifact->getName();
|
$skipped[] = $artifact->getName();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -358,7 +358,7 @@ class ArtifactDownloader
|
|||||||
return $this->options[$name] ?? $default;
|
return $this->options[$name] ?? $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function downloadWithType(Artifact $artifact, int $current, int $total, bool $parallel = false): int
|
private function downloadWithType(Artifact $artifact, int $current, int $total, bool $parallel = false, bool $interactive = true): int
|
||||||
{
|
{
|
||||||
$queue = $this->generateQueue($artifact);
|
$queue = $this->generateQueue($artifact);
|
||||||
// already downloaded
|
// already downloaded
|
||||||
@@ -379,7 +379,7 @@ class ArtifactDownloader
|
|||||||
};
|
};
|
||||||
$try_h = $try ? 'Try downloading' : 'Downloading';
|
$try_h = $try ? 'Try downloading' : 'Downloading';
|
||||||
logger()->info("{$try_h} artifact '{$artifact->getName()}' {$item['display']} ...");
|
logger()->info("{$try_h} artifact '{$artifact->getName()}' {$item['display']} ...");
|
||||||
if ($parallel === false) {
|
if ($parallel === false && $interactive) {
|
||||||
InteractiveTerm::indicateProgress("[{$current}/{$total}] Downloading artifact " . ConsoleColor::green($artifact->getName()) . " {$item['display']} from {$type_display_name} ...");
|
InteractiveTerm::indicateProgress("[{$current}/{$total}] Downloading artifact " . ConsoleColor::green($artifact->getName()) . " {$item['display']} from {$type_display_name} ...");
|
||||||
}
|
}
|
||||||
// is valid download type
|
// is valid download type
|
||||||
@@ -413,13 +413,13 @@ class ArtifactDownloader
|
|||||||
}
|
}
|
||||||
// process lock
|
// process lock
|
||||||
ApplicationContext::get(ArtifactCache::class)->lock($artifact, $item['lock'], $lock, SystemTarget::getCurrentPlatformString());
|
ApplicationContext::get(ArtifactCache::class)->lock($artifact, $item['lock'], $lock, SystemTarget::getCurrentPlatformString());
|
||||||
if ($parallel === false) {
|
if ($parallel === false && $interactive) {
|
||||||
$ver = $lock->hasVersion() ? (' (' . ConsoleColor::yellow($lock->version) . ')') : '';
|
$ver = $lock->hasVersion() ? (' (' . ConsoleColor::yellow($lock->version) . ')') : '';
|
||||||
InteractiveTerm::finish('Downloaded ' . ($verified ? 'and verified ' : '') . 'artifact ' . ConsoleColor::green($artifact->getName()) . $ver . " {$item['display']} .");
|
InteractiveTerm::finish('Downloaded ' . ($verified ? 'and verified ' : '') . 'artifact ' . ConsoleColor::green($artifact->getName()) . $ver . " {$item['display']} .");
|
||||||
}
|
}
|
||||||
return SPC_DOWNLOAD_STATUS_SUCCESS;
|
return SPC_DOWNLOAD_STATUS_SUCCESS;
|
||||||
} catch (DownloaderException|ExecutionException $e) {
|
} catch (DownloaderException|ExecutionException $e) {
|
||||||
if ($parallel === false) {
|
if ($parallel === false && $interactive) {
|
||||||
InteractiveTerm::finish("Download artifact {$artifact->getName()} {$item['display']} failed !", false);
|
InteractiveTerm::finish("Download artifact {$artifact->getName()} {$item['display']} failed !", false);
|
||||||
InteractiveTerm::error("Failed message: {$e->getMessage()}", true);
|
InteractiveTerm::error("Failed message: {$e->getMessage()}", true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,12 +78,17 @@ class ArtifactExtractor
|
|||||||
/**
|
/**
|
||||||
* Extract a single artifact.
|
* Extract a single artifact.
|
||||||
*
|
*
|
||||||
* @param Artifact $artifact The artifact to extract
|
* @param Artifact|string $artifact The artifact to extract
|
||||||
* @param bool $force_source If true, always extract source (ignore binary)
|
* @param bool $force_source If true, always extract source (ignore binary)
|
||||||
*/
|
*/
|
||||||
public function extract(Artifact $artifact, bool $force_source = false): int
|
public function extract(Artifact|string $artifact, bool $force_source = false): int
|
||||||
{
|
{
|
||||||
$name = $artifact->getName();
|
if (is_string($artifact)) {
|
||||||
|
$name = $artifact;
|
||||||
|
$artifact = ArtifactLoader::getArtifactInstance($name);
|
||||||
|
} else {
|
||||||
|
$name = $artifact->getName();
|
||||||
|
}
|
||||||
|
|
||||||
// Already extracted in this session
|
// Already extracted in this session
|
||||||
if (isset($this->extracted[$name])) {
|
if (isset($this->extracted[$name])) {
|
||||||
|
|||||||
@@ -4,13 +4,20 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace StaticPHP\Doctor\Item;
|
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\CheckItem;
|
||||||
use StaticPHP\Attribute\Doctor\FixItem;
|
use StaticPHP\Attribute\Doctor\FixItem;
|
||||||
use StaticPHP\Attribute\Doctor\OptionalCheck;
|
use StaticPHP\Attribute\Doctor\OptionalCheck;
|
||||||
|
use StaticPHP\DI\ApplicationContext;
|
||||||
use StaticPHP\Doctor\CheckResult;
|
use StaticPHP\Doctor\CheckResult;
|
||||||
|
use StaticPHP\Runtime\Shell\Shell;
|
||||||
use StaticPHP\Toolchain\MuslToolchain;
|
use StaticPHP\Toolchain\MuslToolchain;
|
||||||
use StaticPHP\Toolchain\ZigToolchain;
|
use StaticPHP\Toolchain\ZigToolchain;
|
||||||
use StaticPHP\Util\FileSystem;
|
use StaticPHP\Util\FileSystem;
|
||||||
|
use StaticPHP\Util\InteractiveTerm;
|
||||||
|
use StaticPHP\Util\SourcePatcher;
|
||||||
use StaticPHP\Util\System\LinuxUtil;
|
use StaticPHP\Util\System\LinuxUtil;
|
||||||
|
|
||||||
#[OptionalCheck([self::class, 'optionalCheck'])]
|
#[OptionalCheck([self::class, 'optionalCheck'])]
|
||||||
@@ -51,23 +58,46 @@ class LinuxMuslCheck
|
|||||||
#[FixItem('fix-musl-wrapper')]
|
#[FixItem('fix-musl-wrapper')]
|
||||||
public function fixMusl(): bool
|
public function fixMusl(): bool
|
||||||
{
|
{
|
||||||
// TODO: implement musl-wrapper installation
|
$downloader = new ArtifactDownloader();
|
||||||
// This should:
|
$downloader->add('musl-wrapper')->download(false);
|
||||||
// 1. Download musl source using Downloader::downloadSource()
|
$extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class));
|
||||||
// 2. Extract the source using FileSystem::extractSource()
|
$extractor->extract('musl-wrapper');
|
||||||
// 3. Apply CVE patches using SourcePatcher::patchFile()
|
|
||||||
// 4. Build and install musl wrapper
|
// Apply CVE-2025-26519 patch and install musl wrapper
|
||||||
// 5. Add path using putenv instead of editing /etc/profile
|
SourcePatcher::patchFile('musl-1.2.5_CVE-2025-26519_0001.patch', SOURCE_PATH . '/musl-wrapper');
|
||||||
return false;
|
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');
|
||||||
|
}
|
||||||
|
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')
|
||||||
|
->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[FixItem('fix-musl-cross-make')]
|
#[FixItem('fix-musl-cross-make')]
|
||||||
public function fixMuslCrossMake(): bool
|
public function fixMuslCrossMake(): bool
|
||||||
{
|
{
|
||||||
// TODO: implement musl-cross-make installation
|
// sudo
|
||||||
// This should:
|
$prefix = '';
|
||||||
// 1. Install musl-toolchain package using PackageManager::installPackage()
|
if (get_current_user() !== 'root') {
|
||||||
// 2. Copy toolchain files to /usr/local/musl
|
$prefix = 'sudo ';
|
||||||
return false;
|
logger()->warning('Current user is not root, using sudo for running command');
|
||||||
|
}
|
||||||
|
Shell::passthruCallback(function () {
|
||||||
|
InteractiveTerm::advance();
|
||||||
|
});
|
||||||
|
$downloader = new ArtifactDownloader();
|
||||||
|
$extractor = new ArtifactExtractor(ApplicationContext::get(ArtifactCache::class));
|
||||||
|
$downloader->add('musl-toolchain')->download(false);
|
||||||
|
$extractor->extract('musl-toolchain');
|
||||||
|
$pkg_root = PKG_ROOT_PATH . '/musl-toolchain';
|
||||||
|
shell()->exec("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl");
|
||||||
|
FileSystem::removeDir($pkg_root);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class LinuxUtil extends UnixUtil
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
// debian-like
|
// debian-like
|
||||||
'debian', 'ubuntu', 'Deepin',
|
'debian', 'ubuntu', 'Deepin', 'neon',
|
||||||
// rhel-like
|
// rhel-like
|
||||||
'redhat',
|
'redhat',
|
||||||
// centos
|
// centos
|
||||||
|
|||||||
Reference in New Issue
Block a user