From 2f09ace82fca4091506823ef8fb612a8a807d781 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 8 Dec 2025 09:49:11 +0800 Subject: [PATCH] Add LinuxToolCheck --- src/StaticPHP/Doctor/Item/LinuxToolCheck.php | 147 +++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/StaticPHP/Doctor/Item/LinuxToolCheck.php diff --git a/src/StaticPHP/Doctor/Item/LinuxToolCheck.php b/src/StaticPHP/Doctor/Item/LinuxToolCheck.php new file mode 100644 index 00000000..09161c74 --- /dev/null +++ b/src/StaticPHP/Doctor/Item/LinuxToolCheck.php @@ -0,0 +1,147 @@ + '/usr/share/perl5/FindBin.pm', + 'binutils-gold' => 'ld.gold', + 'base-devel' => 'automake', + 'gettext-devel' => 'gettextize', + 'gettext-dev' => 'gettextize', + 'perl-IPC-Cmd' => '/usr/share/perl5/vendor_perl/IPC/Cmd.pm', + 'perl-Time-Piece' => '/usr/lib64/perl5/Time/Piece.pm', + ]; + + /** @noinspection PhpUnused */ + #[CheckItem('if necessary tools are installed', limit_os: 'Linux', level: 999)] + public function checkCliTools(): ?CheckResult + { + $distro = LinuxUtil::getOSRelease(); + + $required = match ($distro['dist']) { + 'alpine' => self::TOOLS_ALPINE, + 'redhat' => self::TOOLS_RHEL, + 'centos' => array_merge(self::TOOLS_RHEL, ['perl-IPC-Cmd', 'perl-Time-Piece']), + 'arch' => self::TOOLS_ARCH, + default => self::TOOLS_DEBIAN, + }; + $missing = []; + foreach ($required as $package) { + if (LinuxUtil::findCommand(self::PROVIDED_COMMAND[$package] ?? $package) === null) { + $missing[] = $package; + } + } + if (!empty($missing)) { + return CheckResult::fail(implode(', ', $missing) . ' not installed on your system', 'install-linux-tools', [$distro, $missing]); + } + return CheckResult::ok(); + } + + #[CheckItem('if cmake version >= 3.22', limit_os: 'Linux')] + public function checkCMakeVersion(): ?CheckResult + { + $ver = get_cmake_version(); + if ($ver === null) { + return CheckResult::fail('Failed to get cmake version'); + } + if (version_compare($ver, '3.22.0') < 0) { + return CheckResult::fail('cmake version is too low (' . $ver . '), please update it manually!'); + } + return CheckResult::ok($ver); + } + + /** @noinspection PhpUnused */ + #[CheckItem('if necessary linux headers are installed', limit_os: 'Linux')] + public function checkSystemOSPackages(): ?CheckResult + { + if (LinuxUtil::isMuslDist()) { + // check linux-headers installation + if (!file_exists('/usr/include/linux/mman.h')) { + return CheckResult::fail('linux-headers not installed on your system', 'install-linux-tools', [LinuxUtil::getOSRelease(), ['linux-headers']]); + } + } + return CheckResult::ok(); + } + + #[FixItem('install-linux-tools')] + public function fixBuildTools(array $distro, array $missing): bool + { + $install_cmd = match ($distro['dist']) { + 'ubuntu', 'debian', 'Deepin', 'neon' => 'apt-get install -y', + 'alpine' => 'apk add', + 'redhat' => 'dnf install -y', + 'centos' => 'yum install -y', + 'arch' => 'pacman -S --noconfirm', + default => null, + }; + if ($install_cmd === null) { + // try family + $family = explode(' ', strtolower($distro['family'])); + if (in_array('debian', $family)) { + $install_cmd = 'apt-get install -y'; + } elseif (in_array('rhel', $family) || in_array('fedora', $family)) { + $install_cmd = 'dnf install -y'; + } else { + throw new EnvironmentException( + "Current linux distro [{$distro['dist']}] does not have an auto-install script for packages yet.", + 'You can submit an issue to request support: https://github.com/crazywhalecc/static-php-cli/issues' + ); + } + } + $prefix = ''; + if (($user = exec('whoami')) !== 'root') { + $prefix = 'sudo '; + logger()->warning("Current user ({$user}) is not root, using sudo for running command (may require password input)"); + } + + $is_debian = LinuxUtil::isDebianDist(); + $to_install = $is_debian ? str_replace('xz', 'xz-utils', $missing) : $missing; + // debian, alpine libtool -> libtoolize + $to_install = str_replace('libtoolize', 'libtool', $to_install); + shell()->exec($prefix . $install_cmd . ' ' . implode(' ', $to_install)); + + return true; + } +}