diff --git a/src/SPC/doctor/item/LinuxMuslCheck.php b/src/SPC/doctor/item/LinuxMuslCheck.php index 80276ea1..d4bc2c8f 100644 --- a/src/SPC/doctor/item/LinuxMuslCheck.php +++ b/src/SPC/doctor/item/LinuxMuslCheck.php @@ -18,23 +18,68 @@ use SPC\store\FileSystem; class LinuxMuslCheck { /** @noinspection PhpUnused */ - /** - * @throws WrongUsageException - */ - #[AsCheckItem('if musl-libc is installed', limit_os: 'Linux')] + #[AsCheckItem('if musl-wrapper is installed', limit_os: 'Linux', level: 800)] public function checkMusl(): CheckResult { if (SystemUtil::isMuslDist()) { + return CheckResult::ok('musl-based distro, skipped'); + } + + $musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m')); + if (file_exists($musl_wrapper_lib)) { return CheckResult::ok(); } + return CheckResult::fail('musl-wrapper is not installed on your system', 'fix-musl-wrapper'); + } + + #[AsCheckItem('if musl-cross-make is installed', limit_os: 'Linux', level: 799)] + public function checkMuslCrossMake(): CheckResult + { + if (SystemUtil::isMuslDist()) { + return CheckResult::ok('musl-based distro, skipped'); + } $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"; - $musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m')); - if (file_exists($musl_wrapper_lib) && file_exists($cross_compile_lib) && file_exists($cross_compile_gcc)) { + if (file_exists($cross_compile_lib) && file_exists($cross_compile_gcc)) { return CheckResult::ok(); } - return CheckResult::fail('musl-libc is not installed on your system', 'fix-musl'); + return CheckResult::fail('musl-cross-make is not installed on your system', 'fix-musl-cross-make'); + } + + /** @noinspection PhpUnused */ + /** + * @throws DownloaderException + * @throws FileSystemException + */ + #[AsFixItem('fix-musl-wrapper')] + public function fixMusl(): bool + { + try { + $prefix = ''; + if (get_current_user() !== 'root') { + $prefix = 'sudo '; + logger()->warning('Current user is not root, using sudo for running command'); + } + // The hardcoded version here is to be consistent with the version compiled by `musl-cross-toolchain`. + $musl_version_name = 'musl-1.2.4'; + $musl_source = [ + 'type' => 'url', + 'url' => "https://musl.libc.org/releases/{$musl_version_name}.tar.gz", + ]; + logger()->info('Downloading ' . $musl_source['url']); + Downloader::downloadSource($musl_version_name, $musl_source); + FileSystem::extractSource($musl_version_name, DOWNLOAD_PATH . "/{$musl_version_name}.tar.gz"); + logger()->info('Installing musl wrapper'); + shell(true)->cd(SOURCE_PATH . "/{$musl_version_name}") + ->exec('./configure') + ->exec('make -j') + ->exec("{$prefix}make install"); + // TODO: add path using putenv instead of editing /etc/profile + return true; + } catch (RuntimeException) { + return false; + } } /** @noinspection PhpUnused */ @@ -43,74 +88,28 @@ class LinuxMuslCheck * @throws FileSystemException * @throws WrongUsageException */ - #[AsFixItem('fix-musl')] - public function fixMusl(): bool + #[AsFixItem('fix-musl-cross-make')] + public function fixMuslCrossMake(): bool { - $arch = arch2gnu(php_uname('m')); - $musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', 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"; - try { - if (!file_exists(DOWNLOAD_PATH)) { - FileSystem::createDir(DOWNLOAD_PATH); + $prefix = ''; + if (get_current_user() !== 'root') { + $prefix = 'sudo '; + logger()->warning('Current user is not root, using sudo for running command'); } - if (!file_exists($musl_wrapper_lib)) { - $this->installMuslWrapper(); - } - if (!file_exists($cross_compile_lib) || !file_exists($cross_compile_gcc)) { - $this->installMuslCrossMake(); - } - // TODO: add path using putenv instead of editing /etc/profile + $arch = arch2gnu(php_uname('m')); + $musl_compile_source = [ + 'type' => 'url', + 'url' => "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/{$arch}-musl-toolchain.tgz", + ]; + logger()->info('Downloading ' . $musl_compile_source['url']); + Downloader::downloadSource('musl-compile', $musl_compile_source); + logger()->info('Extracting musl-cross'); + FileSystem::extractSource('musl-compile', DOWNLOAD_PATH . "/{$arch}-musl-toolchain.tgz"); + shell(true)->exec($prefix . 'cp -rf ' . SOURCE_PATH . '/musl-compile/* /usr/local/musl'); return true; } catch (RuntimeException) { return false; } } - - /** - * @throws DownloaderException - * @throws RuntimeException - * @throws FileSystemException - */ - public function installMuslWrapper(): void - { - $prefix = ''; - if (get_current_user() !== 'root') { - $prefix = 'sudo '; - logger()->warning('Current user is not root, using sudo for running command'); - } - // The hardcoded version here is to be consistent with the version compiled by `musl-cross-toolchain`. - $musl_version_name = 'musl-1.2.4'; - $musl_source = [ - 'type' => 'url', - 'url' => "https://musl.libc.org/releases/{$musl_version_name}.tar.gz", - ]; - Downloader::downloadSource($musl_version_name, $musl_source); - FileSystem::extractSource($musl_version_name, DOWNLOAD_PATH . "/{$musl_version_name}.tar.gz"); - shell(true)->cd(SOURCE_PATH . "/{$musl_version_name}") - ->exec('./configure') - ->exec('make -j') - ->exec("{$prefix}make install"); - } - - /** - * @throws DownloaderException - * @throws FileSystemException - * @throws RuntimeException - * @throws WrongUsageException - */ - public function installMuslCrossMake(): void - { - $arch = arch2gnu(php_uname('m')); - $musl_compile_source = [ - 'type' => 'url', - 'url' => "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/{$arch}-musl-toolchain.tgz", - ]; - logger()->info('Downloading ' . $musl_compile_source['url']); - Downloader::downloadSource('musl-compile', $musl_compile_source); - logger()->info('Extracting musl-cross'); - FileSystem::extractSource('musl-compile', DOWNLOAD_PATH . "/{$arch}-musl-toolchain.tgz"); - shell(true)->exec('cp -rf ' . SOURCE_PATH . '/musl-compile/* /usr/local/musl'); - } } diff --git a/src/SPC/store/Downloader.php b/src/SPC/store/Downloader.php index b421acfb..2a2dd522 100644 --- a/src/SPC/store/Downloader.php +++ b/src/SPC/store/Downloader.php @@ -261,10 +261,13 @@ class Downloader if ($source === null) { logger()->warning('Source {name} unknown. Skipping.', ['name' => $name]); - return; } + if (!is_dir(DOWNLOAD_PATH)) { + FileSystem::createDir(DOWNLOAD_PATH); + } + // load lock file if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) { $lock = []; diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php index 9ae82889..0480ff14 100644 --- a/src/SPC/store/FileSystem.php +++ b/src/SPC/store/FileSystem.php @@ -152,6 +152,9 @@ class FileSystem if (self::$_extract_hook === []) { SourcePatcher::init(); } + if (!is_dir(SOURCE_PATH)) { + self::createDir(SOURCE_PATH); + } if ($move_path !== null) { $move_path = SOURCE_PATH . '/' . $move_path; }