2023-03-18 17:32:21 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
|
|
namespace SPC\command;
|
|
|
|
|
|
|
|
|
|
|
|
use SPC\builder\BuilderProvider;
|
|
|
|
|
|
use SPC\exception\ExceptionHandler;
|
2023-03-29 21:39:36 +08:00
|
|
|
|
use SPC\exception\WrongUsageException;
|
2023-08-02 22:14:45 +08:00
|
|
|
|
use SPC\store\SourcePatcher;
|
2023-03-18 17:32:21 +08:00
|
|
|
|
use SPC\util\DependencyUtil;
|
2023-04-15 18:46:46 +08:00
|
|
|
|
use SPC\util\LicenseDumper;
|
2023-04-22 17:45:43 +08:00
|
|
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
2023-03-18 17:32:21 +08:00
|
|
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
|
|
|
|
use Symfony\Component\Console\Input\InputOption;
|
2023-04-23 20:31:58 +08:00
|
|
|
|
use ZM\Logger\ConsoleColor;
|
2023-03-18 17:32:21 +08:00
|
|
|
|
|
2023-04-22 17:45:43 +08:00
|
|
|
|
#[AsCommand('build', 'build CLI binary')]
|
2023-03-18 17:32:21 +08:00
|
|
|
|
class BuildCliCommand extends BuildCommand
|
|
|
|
|
|
{
|
|
|
|
|
|
public function configure()
|
|
|
|
|
|
{
|
|
|
|
|
|
$this->addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated');
|
|
|
|
|
|
$this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
2023-04-23 20:31:58 +08:00
|
|
|
|
$this->addOption('build-micro', null, null, 'build micro');
|
|
|
|
|
|
$this->addOption('build-cli', null, null, 'build cli');
|
|
|
|
|
|
$this->addOption('build-fpm', null, null, 'build fpm');
|
|
|
|
|
|
$this->addOption('build-all', null, null, 'build cli, micro, fpm');
|
2023-05-10 21:59:33 +08:00
|
|
|
|
$this->addOption('no-strip', null, null, 'build without strip, in order to debug and load external extensions');
|
2023-05-17 22:19:28 +08:00
|
|
|
|
$this->addOption('enable-zts', null, null, 'enable ZTS support');
|
2023-08-02 22:14:45 +08:00
|
|
|
|
$this->addOption('with-hardcoded-ini', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Patch PHP source code, inject hardcoded INI');
|
2023-03-18 17:32:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-22 17:45:43 +08:00
|
|
|
|
public function handle(): int
|
2023-03-18 17:32:21 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 从参数中获取要编译的 libraries,并转换为数组
|
2023-04-22 17:45:43 +08:00
|
|
|
|
$libraries = array_map('trim', array_filter(explode(',', $this->getOption('with-libs'))));
|
2023-03-18 17:32:21 +08:00
|
|
|
|
// 从参数中获取要编译的 extensions,并转换为数组
|
2023-04-22 17:45:43 +08:00
|
|
|
|
$extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions'))));
|
2023-03-18 17:32:21 +08:00
|
|
|
|
|
|
|
|
|
|
define('BUILD_ALL_STATIC', true);
|
|
|
|
|
|
|
2023-04-23 20:31:58 +08:00
|
|
|
|
$rule = BUILD_TARGET_NONE;
|
|
|
|
|
|
$rule = $rule | ($this->getOption('build-cli') ? BUILD_TARGET_CLI : BUILD_TARGET_NONE);
|
|
|
|
|
|
$rule = $rule | ($this->getOption('build-micro') ? BUILD_TARGET_MICRO : BUILD_TARGET_NONE);
|
|
|
|
|
|
$rule = $rule | ($this->getOption('build-fpm') ? BUILD_TARGET_FPM : BUILD_TARGET_NONE);
|
|
|
|
|
|
$rule = $rule | ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE);
|
|
|
|
|
|
if ($rule === BUILD_TARGET_NONE) {
|
|
|
|
|
|
$this->output->writeln('<error>Please add at least one build target!</error>');
|
|
|
|
|
|
$this->output->writeln("<comment>\t--build-cli\tBuild php-cli SAPI</comment>");
|
|
|
|
|
|
$this->output->writeln("<comment>\t--build-micro\tBuild phpmicro SAPI</comment>");
|
|
|
|
|
|
$this->output->writeln("<comment>\t--build-fpm\tBuild php-fpm SAPI</comment>");
|
|
|
|
|
|
$this->output->writeln("<comment>\t--build-all\tBuild all SAPI: cli, micro, fpm</comment>");
|
|
|
|
|
|
return 1;
|
2023-03-18 17:32:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 构建对象
|
2023-04-22 17:45:43 +08:00
|
|
|
|
$builder = BuilderProvider::makeBuilderByInput($this->input);
|
2023-03-18 17:32:21 +08:00
|
|
|
|
// 根据提供的扩展列表获取依赖库列表并编译
|
|
|
|
|
|
[$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions, $libraries);
|
2023-04-23 20:31:58 +08:00
|
|
|
|
/* @phpstan-ignore-next-line */
|
|
|
|
|
|
logger()->info('Build target: ' . ConsoleColor::yellow($builder->getBuildTypeName($rule)));
|
|
|
|
|
|
/* @phpstan-ignore-next-line */
|
|
|
|
|
|
logger()->info('Enabled extensions: ' . ConsoleColor::yellow(implode(', ', $extensions)));
|
|
|
|
|
|
/* @phpstan-ignore-next-line */
|
|
|
|
|
|
logger()->info('Required libraries: ' . ConsoleColor::yellow(implode(', ', $libraries)));
|
2023-03-18 17:32:21 +08:00
|
|
|
|
if (!empty($not_included)) {
|
|
|
|
|
|
logger()->warning('some extensions will be enabled due to dependencies: ' . implode(',', $not_included));
|
|
|
|
|
|
}
|
|
|
|
|
|
sleep(2);
|
|
|
|
|
|
// 编译和检查库是否完整
|
|
|
|
|
|
$builder->buildLibs($libraries);
|
|
|
|
|
|
// 执行扩展检测
|
|
|
|
|
|
$builder->proveExts($extensions);
|
2023-05-10 21:59:33 +08:00
|
|
|
|
// strip
|
2023-07-27 18:42:05 +08:00
|
|
|
|
$builder->setStrip(!$this->getOption('no-strip'));
|
2023-08-02 22:14:45 +08:00
|
|
|
|
// Process -I option
|
|
|
|
|
|
$custom_ini = [];
|
|
|
|
|
|
foreach ($this->input->getOption('with-hardcoded-ini') as $value) {
|
|
|
|
|
|
[$source_name, $ini_value] = explode('=', $value, 2);
|
|
|
|
|
|
$custom_ini[$source_name] = $ini_value;
|
|
|
|
|
|
logger()->info('Adding hardcoded INI [' . $source_name . ' = ' . $ini_value . ']');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!empty($custom_ini)) {
|
|
|
|
|
|
SourcePatcher::patchHardcodedINI($custom_ini);
|
|
|
|
|
|
}
|
2023-03-18 17:32:21 +08:00
|
|
|
|
// 构建
|
2023-04-22 17:45:43 +08:00
|
|
|
|
$builder->buildPHP($rule, $this->getOption('bloat'));
|
2023-03-18 17:32:21 +08:00
|
|
|
|
// 统计时间
|
|
|
|
|
|
$time = round(microtime(true) - START_TIME, 3);
|
|
|
|
|
|
logger()->info('Build complete, used ' . $time . ' s !');
|
2023-04-30 12:42:19 +08:00
|
|
|
|
$build_root_path = BUILD_ROOT_PATH;
|
|
|
|
|
|
$cwd = getcwd();
|
|
|
|
|
|
$fixed = '';
|
|
|
|
|
|
if (!empty(getenv('SPC_FIX_DEPLOY_ROOT'))) {
|
|
|
|
|
|
str_replace($cwd, '', $build_root_path);
|
|
|
|
|
|
$build_root_path = getenv('SPC_FIX_DEPLOY_ROOT') . $build_root_path;
|
|
|
|
|
|
$fixed = ' (host system)';
|
|
|
|
|
|
}
|
2023-04-23 20:31:58 +08:00
|
|
|
|
if (($rule & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
2023-04-30 12:42:19 +08:00
|
|
|
|
logger()->info('Static php binary path' . $fixed . ': ' . $build_root_path . '/bin/php');
|
2023-03-18 17:32:21 +08:00
|
|
|
|
}
|
2023-04-23 20:31:58 +08:00
|
|
|
|
if (($rule & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
2023-04-30 12:42:19 +08:00
|
|
|
|
logger()->info('phpmicro binary path' . $fixed . ': ' . $build_root_path . '/bin/micro.sfx');
|
2023-03-18 17:32:21 +08:00
|
|
|
|
}
|
2023-04-23 20:31:58 +08:00
|
|
|
|
if (($rule & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
2023-04-30 12:42:19 +08:00
|
|
|
|
logger()->info('Static php-fpm binary path' . $fixed . ': ' . $build_root_path . '/bin/php-fpm');
|
2023-04-23 20:31:58 +08:00
|
|
|
|
}
|
2023-04-15 18:46:46 +08:00
|
|
|
|
// 导出相关元数据
|
|
|
|
|
|
file_put_contents(BUILD_ROOT_PATH . '/build-extensions.json', json_encode($extensions, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
|
|
|
|
|
file_put_contents(BUILD_ROOT_PATH . '/build-libraries.json', json_encode($libraries, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
|
|
|
|
|
// 导出 LICENSE
|
|
|
|
|
|
$dumper = new LicenseDumper();
|
|
|
|
|
|
$dumper->addExts($extensions)->addLibs($libraries)->addSources(['php-src'])->dump(BUILD_ROOT_PATH . '/license');
|
2023-04-30 12:42:19 +08:00
|
|
|
|
logger()->info('License path' . $fixed . ': ' . $build_root_path . '/license/');
|
2023-03-18 17:32:21 +08:00
|
|
|
|
return 0;
|
2023-03-29 21:39:36 +08:00
|
|
|
|
} catch (WrongUsageException $e) {
|
|
|
|
|
|
logger()->critical($e->getMessage());
|
|
|
|
|
|
return 1;
|
2023-03-18 17:32:21 +08:00
|
|
|
|
} catch (\Throwable $e) {
|
2023-04-22 17:45:43 +08:00
|
|
|
|
if ($this->getOption('debug')) {
|
2023-03-18 17:32:21 +08:00
|
|
|
|
ExceptionHandler::getInstance()->handle($e);
|
|
|
|
|
|
} else {
|
2023-03-21 00:21:17 +08:00
|
|
|
|
logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage());
|
|
|
|
|
|
logger()->critical('Please check with --debug option to see more details.');
|
2023-03-18 17:32:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|