mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-09 01:45:36 +08:00
Compare commits
17 Commits
f2e483540b
...
2.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97eff64b5b | ||
|
|
e522258693 | ||
|
|
b84c68fe11 | ||
|
|
8505feaa66 | ||
|
|
41f49c20ff | ||
|
|
1912ae36e6 | ||
|
|
08efc81cf0 | ||
|
|
a3b09c69cc | ||
|
|
5cf105c3a5 | ||
|
|
7408781d13 | ||
|
|
0afc8ea2c3 | ||
|
|
67b073776c | ||
|
|
8b48cf7f70 | ||
|
|
63287dd9c4 | ||
|
|
fc7ac921e2 | ||
|
|
57e3193a2a | ||
|
|
388f547878 |
12
README-en.md
12
README-en.md
@@ -37,7 +37,11 @@ Here is the architecture support status, where `CI` represents support for GitHu
|
||||
|
||||
Currently supported PHP versions for compilation are: `7.4`, `8.0`, `8.1`, `8.2`.
|
||||
|
||||
## Usage
|
||||
## Docs
|
||||
|
||||
docs here: <https://static-php-cli.zhamao.me>.
|
||||
|
||||
## Simple Usage
|
||||
|
||||
Please first select the extension you want to compile based on the extension list below.
|
||||
|
||||
@@ -49,7 +53,7 @@ If you don't compile yourself, you can download pre-compiled artifact from Actio
|
||||
|
||||
### Supported Extensions
|
||||
|
||||
[Supported Extension List](/ext-support.md)
|
||||
[Supported Extension List](https://static-php-cli.zhamao.me/en/guide/extensions.html)
|
||||
|
||||
> If there is no extension you need here, you can submit an issue.
|
||||
|
||||
@@ -100,7 +104,7 @@ Basic usage for building php and micro with some extensions:
|
||||
cd static-php-cli
|
||||
composer update
|
||||
chmod +x bin/spc
|
||||
# Check system tool dependencies, fix them automatically (only support macOS) (TODO: Linux distro support)
|
||||
# Check system tool dependencies, fix them automatically
|
||||
./bin/spc doctor
|
||||
# fetch all libraries
|
||||
./bin/spc fetch --all
|
||||
@@ -217,6 +221,8 @@ The basic principles for contributing are as follows:
|
||||
camelCase and underscore formats should be followed, and mixing within the same module is prohibited.
|
||||
- When compiling external libraries and creating patches, compatibility with different operating systems should be considered.
|
||||
|
||||
If you want to contribute document content, please go to [crazywhalecc/static-php-cli-docs](https://github.com/crazywhalecc/static-php-cli-docs).
|
||||
|
||||
## Sponsor this project
|
||||
|
||||
You can sponsor my project on [this page](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md).
|
||||
|
||||
10
README.md
10
README.md
@@ -36,6 +36,10 @@ If you are using English, see [English README](README-en.md).
|
||||
|
||||
目前支持编译的 PHP 版本为:`7.4`,`8.0`,`8.1`,`8.2`。
|
||||
|
||||
## 文档
|
||||
|
||||
点击这里查看文档:<https://static-php-cli.zhamao.me>。
|
||||
|
||||
## 使用
|
||||
|
||||
请先根据下方扩展列表选择你要编译的扩展。
|
||||
@@ -48,7 +52,7 @@ If you are using English, see [English README](README-en.md).
|
||||
|
||||
### 支持的扩展情况
|
||||
|
||||
[扩展支持列表](/ext-support.md)
|
||||
[扩展支持列表](https://static-php-cli.zhamao.me/zh/guide/extensions.html)
|
||||
|
||||
> 如果这里没有你需要的扩展,可以提交 Issue。
|
||||
|
||||
@@ -94,7 +98,7 @@ chmod +x bin/setup-runtime
|
||||
cd static-php-cli
|
||||
composer update
|
||||
chmod +x bin/spc
|
||||
# 检查环境依赖,并根据提示的命令安装缺失的编译工具(目前仅支持 macOS,Linux 后续会支持)
|
||||
# 检查环境依赖,并根据提示的命令安装缺失的编译工具
|
||||
./bin/spc doctor
|
||||
# 拉取所有依赖库
|
||||
./bin/spc fetch --all
|
||||
@@ -200,6 +204,8 @@ cat micro.sfx code.php > single-app && chmod +x single-app
|
||||
|
||||
另外,添加新扩展的贡献方式,可以参考下方 `进阶`。
|
||||
|
||||
如果你想贡献文档内容,请到项目仓库 [crazywhalecc/static-php-cli-docs](https://github.com/crazywhalecc/static-php-cli-docs) 贡献。
|
||||
|
||||
## 赞助本项目
|
||||
|
||||
你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。
|
||||
|
||||
111
ext-support.md
111
ext-support.md
@@ -1,112 +1,3 @@
|
||||
# Extension List
|
||||
|
||||
> - yes: supported and tested
|
||||
> - untested: supported, but not tested
|
||||
> - empty: not supported yet
|
||||
> - no with issue link: not supported yet due to issue
|
||||
> - partial with issue link: supported but not perfect due to issue
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
|-----------------|---------------------------------------------------------------------|----------------------------------------------------------------|---------|
|
||||
| apcu | yes, untested | yes, untested | |
|
||||
| bcmath | yes | yes | |
|
||||
| bz2 | yes | yes | |
|
||||
| calendar | yes | yes | |
|
||||
| ctype | yes | yes | |
|
||||
| curl | yes | yes | |
|
||||
| dba | yes | yes | |
|
||||
| dom | yes | yes | |
|
||||
| enchant | | | |
|
||||
| event | yes | yes | |
|
||||
| exif | yes | yes | |
|
||||
| ffi | | yes, [docs]() | |
|
||||
| filter | yes | yes | |
|
||||
| fileinfo | yes | yes | |
|
||||
| ftp | yes | yes | |
|
||||
| gd | yes | yes | |
|
||||
| gettext | | | |
|
||||
| gmp | yes | yes | |
|
||||
| iconv | yes | yes | |
|
||||
| imagick | yes | yes | |
|
||||
| inotify | yes | yes | |
|
||||
| intl | [partial](https://github.com/crazywhalecc/static-php-cli/issues/66) | yes | |
|
||||
| mbstring | yes | yes | |
|
||||
| mbregex | yes | yes | |
|
||||
| mcrypt | | [no](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
|
||||
| mongodb | yes | yes | |
|
||||
| mysqli | yes | yes | |
|
||||
| mysqlnd | yes | yes | |
|
||||
| opcache | yes | yes | |
|
||||
| openssl | yes | yes | |
|
||||
| password-argon2 | | | |
|
||||
| pcntl | yes | yes | |
|
||||
| pdo | yes | yes | |
|
||||
| pdo_mysql | yes | yes | |
|
||||
| pdo_sqlite | yes | yes | |
|
||||
| pdo_pgsql | | | |
|
||||
| phar | yes | yes | |
|
||||
| posix | yes | yes | |
|
||||
| protobuf | yes | yes | |
|
||||
| readline | yes, untested | yes, untested | |
|
||||
| redis | yes | yes | |
|
||||
| session | yes | yes | |
|
||||
| shmop | yes | yes | |
|
||||
| simplexml | yes | yes | |
|
||||
| soap | yes | yes | |
|
||||
| sockets | yes | yes | |
|
||||
| sodium | yes | yes | |
|
||||
| sqlite3 | yes | yes | |
|
||||
| ssh2 | yes, untested | yes, untested | |
|
||||
| swow | yes | yes | |
|
||||
| swoole | [partial](https://github.com/crazywhalecc/static-php-cli/issues/51) | yes | |
|
||||
| tokenizer | yes | yes | |
|
||||
| xlswriter | yes | yes | |
|
||||
| xml | yes | yes | |
|
||||
| xmlreader | yes, untested | yes, untested | |
|
||||
| xmlwriter | yes, untested | yes, untested | |
|
||||
| zip | yes, untested | yes, untested | |
|
||||
| zlib | yes | yes | |
|
||||
| zstd | yes | yes | |
|
||||
|
||||
## Additional Requirements
|
||||
|
||||
- phpmicro requires PHP >= 8.0
|
||||
- swoole >= 5.0 requires PHP >= 8.0
|
||||
- swow requires PHP >= 8.0
|
||||
|
||||
## Typical Extension List Example
|
||||
|
||||
Here are some extension list example for different use.
|
||||
|
||||
- For general use: `"bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,ftp,filter,gd,iconv,xml,mbstring,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip"`
|
||||
- For static-php-cli self: `"posix,pcntl,phar,tokenizer,iconv,zlib"`
|
||||
- For static-php-cli self (with dev dependencies): `"posix,pcntl,phar,tokenizer,iconv,zlib,xml,dom,xmlwriter,xmlreader,fileinfo"`
|
||||
- Minimum, with no extension: `""`
|
||||
|
||||
Compile with all supported extensions (exclude `swow`, `swoole`, because these will change the default behavior of php):
|
||||
|
||||
```bash
|
||||
bin/spc build --build-all bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,mbregex,mbstring,mongodb,mysqli,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,protobuf,redis,session,shmop,simplexml,soap,sockets,sqlite3,tokenizer,xml,xmlreader,xmlwriter,yaml,zip,zlib,zstd --with-libs=libjpeg,freetype,libwebp,libavif --debug
|
||||
```
|
||||
|
||||
## Additional Libraries
|
||||
|
||||
Some extensions have soft dependencies, you can enable extra features by adding these libs using `--with-libs`.
|
||||
|
||||
For example, to compile with gd extension, with `libwebp, libgif, libavif, libjpeg, freetype` extra features:
|
||||
|
||||
```bash
|
||||
bin/spc build gd --with-libs=libjpeg,freetype,libwebp,libavif --build-cli
|
||||
```
|
||||
|
||||
> If you don't add them, your compilation will not enable these features.
|
||||
|
||||
## Limitations
|
||||
|
||||
- swow and swoole cannot be compiled at the same time.
|
||||
- openssl needs manual configuration for ssl certificate. (TODO: I will write a wiki about it)
|
||||
- some extensions need system configuration, e.g. `curl` and `openssl` will search ssl certificate on your system.
|
||||
|
||||
## Bugs and TODOs
|
||||
|
||||
See [#32](https://github.com/crazywhalecc/static-php-cli/issues/32).
|
||||
See: [Docs - Extensions](https://static-php-cli.zhamao.me/en/guide/extensions.html)
|
||||
|
||||
@@ -21,7 +21,7 @@ class LinuxBuilder extends BuilderBase
|
||||
use UnixBuilderTrait;
|
||||
|
||||
/** @var string[] Linux 环境下编译依赖的命令 */
|
||||
public const REQUIRED_COMMANDS = ['make', 'bison', 'flex', 'pkg-config', 'git', 'autoconf', 'automake', 'tar', 'unzip', /* 'xz', 好像不需要 */ 'gzip', 'bzip2', 'cmake'];
|
||||
public const REQUIRED_COMMANDS = ['make', 'bison', 'flex', 'git', 'autoconf', 'automake', 'tar', 'unzip', /* 'xz', 好像不需要 */ 'gzip', 'bzip2', 'cmake'];
|
||||
|
||||
/** @var string 使用的 libc */
|
||||
public string $libc;
|
||||
|
||||
@@ -40,6 +40,7 @@ class libpng extends MacOSLibraryBase
|
||||
};
|
||||
shell()->cd($this->source_dir)
|
||||
->exec('chmod +x ./configure')
|
||||
->exec('chmod +x ./install-sh')
|
||||
->exec(
|
||||
"{$this->builder->configure_env} ./configure " .
|
||||
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
||||
|
||||
@@ -10,11 +10,16 @@ use Symfony\Component\Console\Attribute\AsCommand;
|
||||
#[AsCommand('doctor', 'Diagnose whether the current environment can compile normally')]
|
||||
class DoctorCommand extends BaseCommand
|
||||
{
|
||||
public function configure()
|
||||
{
|
||||
$this->addOption('auto-fix', null, null, 'Automatically fix failed items (if possible)');
|
||||
}
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
try {
|
||||
$checker = new CheckListHandler($this->input, $this->output);
|
||||
$checker->runCheck(FIX_POLICY_PROMPT);
|
||||
$checker->runCheck($this->input->getOption('auto-fix') ? FIX_POLICY_AUTOFIX : FIX_POLICY_PROMPT);
|
||||
$this->output->writeln('<info>Doctor check complete !</info>');
|
||||
} catch (\Throwable $e) {
|
||||
$this->output->writeln('<error>' . $e->getMessage() . '</error>');
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\command;
|
||||
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
@@ -18,6 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
#[AsCommand('download', 'Download required sources', ['fetch'])]
|
||||
class DownloadCommand extends BaseCommand
|
||||
{
|
||||
use UnixSystemUtilTrait;
|
||||
|
||||
protected string $php_major_ver;
|
||||
|
||||
public function configure()
|
||||
@@ -28,12 +31,13 @@ class DownloadCommand extends BaseCommand
|
||||
$this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format like 8.1', '8.1');
|
||||
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
|
||||
$this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed');
|
||||
$this->addOption('from-zip', 'Z', InputOption::VALUE_REQUIRED, 'Fetch from zip archive');
|
||||
}
|
||||
|
||||
public function initialize(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
// --all 等于 "" "",也就是所有东西都要下载
|
||||
if ($input->getOption('all') || $input->getOption('clean')) {
|
||||
if ($input->getOption('all') || $input->getOption('clean') || $input->getOption('from-zip')) {
|
||||
$input->setArgument('sources', '');
|
||||
}
|
||||
parent::initialize($input, $output);
|
||||
@@ -66,6 +70,44 @@ class DownloadCommand extends BaseCommand
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --from-zip
|
||||
if ($path = $this->getOption('from-zip')) {
|
||||
if (!file_exists($path)) {
|
||||
logger()->critical('File ' . $path . ' not exist or not a zip archive.');
|
||||
return 1;
|
||||
}
|
||||
// remove old download files first
|
||||
if (is_dir(DOWNLOAD_PATH)) {
|
||||
logger()->warning('You are doing some operations that not recoverable: removing directories below');
|
||||
logger()->warning(DOWNLOAD_PATH);
|
||||
logger()->alert('I will remove these dir after 5 seconds !');
|
||||
sleep(5);
|
||||
f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH);
|
||||
}
|
||||
// unzip command check
|
||||
if (PHP_OS_FAMILY !== 'Windows' && !$this->findCommand('unzip')) {
|
||||
logger()->critical('Missing unzip command, you need to install it first !');
|
||||
logger()->critical('You can use "bin/spc doctor" command to check and install required tools');
|
||||
return 1;
|
||||
}
|
||||
// create downloads
|
||||
try {
|
||||
if (PHP_OS_FAMILY !== 'Windows') {
|
||||
f_passthru('mkdir ' . DOWNLOAD_PATH . ' && cd ' . DOWNLOAD_PATH . ' && unzip ' . escapeshellarg($path));
|
||||
}
|
||||
// Windows TODO
|
||||
|
||||
if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) {
|
||||
throw new RuntimeException('.lock.json not exist in "downloads/"');
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
logger()->critical('Extract failed: ' . $e->getMessage());
|
||||
return 1;
|
||||
}
|
||||
logger()->info('Extract success');
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Define PHP major version
|
||||
$ver = $this->php_major_ver = $this->getOption('with-php') ?? '8.1';
|
||||
define('SPC_BUILD_PHP_VERSION', $ver);
|
||||
|
||||
116
src/SPC/command/MicroCombineCommand.php
Normal file
116
src/SPC/command/MicroCombineCommand.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\command;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
#[AsCommand('micro:combine', 'Combine micro.sfx and php code together')]
|
||||
class MicroCombineCommand extends BaseCommand
|
||||
{
|
||||
public function configure()
|
||||
{
|
||||
$this->addArgument('file', InputArgument::REQUIRED, 'The php or phar file to be combined');
|
||||
$this->addOption('with-micro', 'M', InputOption::VALUE_REQUIRED, 'Customize your micro.sfx file');
|
||||
$this->addOption('with-ini-set', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'ini to inject into micro.sfx when combining');
|
||||
$this->addOption('with-ini-file', 'N', InputOption::VALUE_REQUIRED, 'ini file to inject into micro.sfx when combining');
|
||||
$this->addOption('output', 'O', InputOption::VALUE_REQUIRED, 'Customize your output binary file name');
|
||||
}
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
// 0. Initialize path variables
|
||||
$internal = FileSystem::convertPath(BUILD_ROOT_PATH . '/bin/micro.sfx');
|
||||
$micro_file = $this->input->getOption('with-micro');
|
||||
$file = $this->getArgument('file');
|
||||
$ini_set = $this->input->getOption('with-ini-set');
|
||||
$ini_file = $this->input->getOption('with-ini-file');
|
||||
$target_ini = [];
|
||||
$output = $this->input->getOption('output') ?? 'my-app';
|
||||
$ini_part = '';
|
||||
// 1. Make sure specified micro.sfx file exists
|
||||
if ($micro_file !== null && !file_exists($micro_file)) {
|
||||
$this->output->writeln('<error>The micro.sfx file you specified is incorrect or does not exist!</error>');
|
||||
return 1;
|
||||
}
|
||||
// 2. Make sure buildroot/bin/micro.sfx exists
|
||||
if ($micro_file === null && !file_exists($internal)) {
|
||||
$this->output->writeln('<error>You haven\'t compiled micro.sfx yet, please use "build" command and "--build-micro" to compile phpmicro first!</error>');
|
||||
return 1;
|
||||
}
|
||||
// 3. Use buildroot/bin/micro.sfx
|
||||
if ($micro_file === null) {
|
||||
$micro_file = $internal;
|
||||
}
|
||||
// 4. Make sure php or phar file exists
|
||||
if (!is_file(FileSystem::convertPath($file))) {
|
||||
$this->output->writeln('<error>The file to combine does not exist!</error>');
|
||||
return 1;
|
||||
}
|
||||
// 5. Confirm ini files (ini-set has higher priority)
|
||||
if ($ini_file !== null) {
|
||||
// Check file exist first
|
||||
if (!file_exists($ini_file)) {
|
||||
$this->output->writeln('<error>The ini file to combine does not exist! (' . $ini_file . ')</error>');
|
||||
return 1;
|
||||
}
|
||||
$arr = parse_ini_file($ini_file);
|
||||
if ($arr === false) {
|
||||
$this->output->writeln('<error>Cannot parse ini file</error>');
|
||||
return 1;
|
||||
}
|
||||
$target_ini = array_merge($target_ini, $arr);
|
||||
}
|
||||
// 6. Confirm ini sets
|
||||
if ($ini_set !== []) {
|
||||
foreach ($ini_set as $item) {
|
||||
$arr = parse_ini_string($item);
|
||||
if ($arr === false) {
|
||||
$this->output->writeln('<error>--with-ini-set parse failed</error>');
|
||||
return 1;
|
||||
}
|
||||
$target_ini = array_merge($target_ini, $arr);
|
||||
}
|
||||
}
|
||||
// 7. Generate ini injection parts
|
||||
if (!empty($target_ini)) {
|
||||
$ini_str = $this->encodeINI($target_ini);
|
||||
logger()->debug('Injecting ini parts: ' . PHP_EOL . $ini_str);
|
||||
$ini_part = "\xfd\xf6\x69\xe6";
|
||||
$ini_part .= pack('N', strlen($ini_str));
|
||||
$ini_part .= $ini_str;
|
||||
}
|
||||
// 8. Combine !
|
||||
$output = FileSystem::isRelativePath($output) ? (WORKING_DIR . '/' . $output) : $output;
|
||||
$file_target = file_get_contents($micro_file) . $ini_part . file_get_contents($file);
|
||||
$result = file_put_contents($output, $file_target);
|
||||
if ($result === false) {
|
||||
$this->output->writeln('<error>Combine failed.</error>');
|
||||
return 1;
|
||||
}
|
||||
// 9. chmod +x
|
||||
chmod($output, 0755);
|
||||
$this->output->writeln('<info>Combine success! Binary file: ' . $output . '</info>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function encodeINI(array $array): string
|
||||
{
|
||||
$res = [];
|
||||
foreach ($array as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$res[] = "[{$key}]";
|
||||
foreach ($val as $skey => $sval) {
|
||||
$res[] = "{$skey}=" . (is_numeric($sval) ? $sval : '"' . $sval . '"');
|
||||
}
|
||||
} else {
|
||||
$res[] = "{$key}=" . (is_numeric($val) ? $val : '"' . $val . '"');
|
||||
}
|
||||
}
|
||||
return implode("\n", $res);
|
||||
}
|
||||
}
|
||||
90
src/SPC/doctor/item/LinuxToolCheckList.php
Normal file
90
src/SPC/doctor/item/LinuxToolCheckList.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\doctor\item;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
class LinuxToolCheckList
|
||||
{
|
||||
use UnixSystemUtilTrait;
|
||||
|
||||
public const TOOLS_ALPINE = [
|
||||
'make', 'bison', 'flex',
|
||||
'git', 'autoconf', 'automake',
|
||||
'tar', 'unzip', 'gzip',
|
||||
'bzip2', 'cmake', 'gcc',
|
||||
'g++', 'patch',
|
||||
];
|
||||
|
||||
public const TOOLS_DEBIAN = [
|
||||
'make', 'bison', 'flex',
|
||||
'git', 'autoconf', 'automake',
|
||||
'tar', 'unzip', 'gzip',
|
||||
'bzip2', 'cmake', 'patch',
|
||||
];
|
||||
|
||||
#[AsCheckItem('if necessary tools are installed', limit_os: 'Linux')]
|
||||
public function checkCliTools(): ?CheckResult
|
||||
{
|
||||
$distro = SystemUtil::getOSRelease();
|
||||
|
||||
$required = match ($distro['dist']) {
|
||||
'alpine' => self::TOOLS_ALPINE,
|
||||
default => self::TOOLS_DEBIAN,
|
||||
};
|
||||
$missing = [];
|
||||
foreach ($required as $cmd) {
|
||||
if ($this->findCommand($cmd) === null) {
|
||||
$missing[] = $cmd;
|
||||
}
|
||||
}
|
||||
if (!empty($missing)) {
|
||||
return match ($distro['dist']) {
|
||||
'ubuntu', 'alpine', 'debian' => CheckResult::fail(implode(', ', $missing) . ' not installed on your system', 'install-linux-tools', [$distro, $missing]),
|
||||
default => CheckResult::fail(implode(', ', $missing) . ' not installed on your system'),
|
||||
};
|
||||
}
|
||||
return CheckResult::ok();
|
||||
}
|
||||
|
||||
#[AsCheckItem('if necessary packages are installed', limit_os: 'Linux')]
|
||||
public function checkSystemOSPackages(): ?CheckResult
|
||||
{
|
||||
$distro = SystemUtil::getOSRelease();
|
||||
if ($distro['dist'] === 'alpine') {
|
||||
// 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', [$distro, ['linux-headers']]);
|
||||
}
|
||||
}
|
||||
return CheckResult::ok();
|
||||
}
|
||||
|
||||
#[AsFixItem('install-linux-tools')]
|
||||
public function fixBuildTools(array $distro, array $missing): bool
|
||||
{
|
||||
$install_cmd = match ($distro['dist']) {
|
||||
'ubuntu', 'debian' => 'apt install -y',
|
||||
'alpine' => 'apk add',
|
||||
default => throw new RuntimeException('Current linux distro is not supported for auto-install musl packages'),
|
||||
};
|
||||
$prefix = '';
|
||||
if (get_current_user() !== 'root') {
|
||||
$prefix = 'sudo ';
|
||||
logger()->warning('Current user is not root, using sudo for running command');
|
||||
}
|
||||
try {
|
||||
shell(true)->exec($prefix . $install_cmd . ' ' . implode(' ', $missing));
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -439,6 +439,20 @@ class FileSystem
|
||||
self::$_extract_hook[$name][] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the path is a relative path (judging according to whether the first character is "/")
|
||||
*
|
||||
* @param string $path Path
|
||||
*/
|
||||
public static function isRelativePath(string $path): bool
|
||||
{
|
||||
// 适配 Windows 的多盘符目录形式
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
return !(strlen($path) > 2 && ctype_alpha($path[0]) && $path[1] === ':');
|
||||
}
|
||||
return strlen($path) > 0 && $path[0] !== '/';
|
||||
}
|
||||
|
||||
private static function emitSourceExtractHook(string $name)
|
||||
{
|
||||
foreach ((self::$_extract_hook[$name] ?? []) as $hook) {
|
||||
|
||||
Reference in New Issue
Block a user