static-php-cli/src/SPC/doctor/item/MacOSToolCheckList.php

119 lines
3.8 KiB
PHP
Raw Normal View History

2023-04-22 21:23:12 +08:00
<?php
declare(strict_types=1);
namespace SPC\doctor\item;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\doctor\AsCheckItem;
use SPC\doctor\AsFixItem;
use SPC\doctor\CheckResult;
use SPC\exception\RuntimeException;
class MacOSToolCheckList
{
use UnixSystemUtilTrait;
/** @var string[] MacOS 环境下编译依赖的命令 */
public const REQUIRED_COMMANDS = [
'curl',
'make',
'bison',
're2c',
2023-04-22 21:23:12 +08:00
'flex',
'pkg-config',
'git',
'autoconf',
'automake',
'tar',
2023-12-16 15:07:04 +08:00
'libtool',
2023-04-22 21:23:12 +08:00
'unzip',
'xz',
'gzip',
'bzip2',
'cmake',
2024-02-07 01:19:54 +08:00
'glibtoolize',
2023-04-22 21:23:12 +08:00
];
#[AsCheckItem('if homebrew has installed', limit_os: 'Darwin', level: 998)]
public function checkBrew(): ?CheckResult
{
2024-04-12 15:55:36 +08:00
if (($path = $this->findCommand('brew')) === null) {
2023-04-22 21:23:12 +08:00
return CheckResult::fail('Homebrew is not installed', 'brew');
}
if ($path !== '/opt/homebrew/bin/brew' && getenv('GNU_ARCH') === 'aarch64') {
2024-04-12 15:55:36 +08:00
return CheckResult::fail('Current homebrew (/usr/local/bin/homebrew) is not installed for M1 Mac, please re-install homebrew in /opt/homebrew/ !');
}
2023-04-22 21:23:12 +08:00
return CheckResult::ok();
}
#[AsCheckItem('if necessary tools are installed', limit_os: 'Darwin')]
public function checkCliTools(): ?CheckResult
{
$missing = [];
foreach (self::REQUIRED_COMMANDS as $cmd) {
if ($this->findCommand($cmd) === null) {
$missing[] = $cmd;
}
}
if (!empty($missing)) {
return CheckResult::fail('missing system commands: ' . implode(', ', $missing), 'build-tools', [$missing]);
}
return CheckResult::ok();
}
#[AsCheckItem('if bison version is 3.0 or later', limit_os: 'Darwin')]
public function checkBisonVersion(array $command_path = []): ?CheckResult
{
// if the bison command is /usr/bin/bison, it is the system bison that may be too old
if (($bison = $this->findCommand('bison', $command_path)) === null) {
return CheckResult::fail('bison is not installed or too old', 'build-tools', [['bison']]);
}
// check version: bison (GNU Bison) x.y(.z)
$version = shell()->execWithResult("{$bison} --version", false);
if (preg_match('/bison \(GNU Bison\) (\d+)\.(\d+)(?:\.(\d+))?/', $version[1][0], $matches)) {
$major = (int) $matches[1];
// major should be 3 or later
if ($major < 3) {
// find homebrew keg-only bison
if ($command_path !== []) {
return CheckResult::fail("Current {$bison} version is too old: " . $matches[0]);
}
2025-07-31 00:09:13 +08:00
return $this->checkBisonVersion(['/opt/homebrew/opt/bison/bin', '/usr/local/opt/bison/bin']);
}
return CheckResult::ok($matches[0]);
}
return CheckResult::fail('bison version cannot be determined');
}
2023-04-22 21:23:12 +08:00
#[AsFixItem('brew')]
public function fixBrew(): bool
{
try {
shell(true)->exec('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
} catch (RuntimeException) {
return false;
}
return true;
}
#[AsFixItem('build-tools')]
public function fixBuildTools(array $missing): bool
{
2024-02-07 01:19:54 +08:00
$replacement = [
'glibtoolize' => 'libtool',
];
2023-04-22 21:23:12 +08:00
foreach ($missing as $cmd) {
try {
2024-02-07 01:19:54 +08:00
if (isset($replacement[$cmd])) {
$cmd = $replacement[$cmd];
}
shell(true)->exec('brew install --formula ' . escapeshellarg($cmd));
2023-04-22 21:23:12 +08:00
} catch (RuntimeException) {
return false;
}
}
return true;
}
}