Compare commits

...

7 Commits

Author SHA1 Message Date
crazywhalecc
17e0265ed0
fix realpath getter 2023-03-21 01:52:40 +08:00
crazywhalecc
da03db051d
add libiconv source 2023-03-21 01:52:22 +08:00
crazywhalecc
357b25905b
fix bzip2, fix curl, add iconv, add libxml2, add and fix openssl 2023-03-21 01:51:52 +08:00
crazywhalecc
e62cefa9e5
add exception handler for command build:libs 2023-03-21 00:28:05 +08:00
crazywhalecc
fd835deb8d
add brotli,bzip2,curl,zlib for linux 2023-03-21 00:27:33 +08:00
crazywhalecc
063b55ae0d
add brotli,bzip2,curl,zlib for linux 2023-03-21 00:25:46 +08:00
crazywhalecc
79efecb5a9
change error message 2023-03-21 00:21:17 +08:00
18 changed files with 1360 additions and 71 deletions

View File

@ -154,6 +154,9 @@
"headers": [
"libxml2"
],
"lib-depends": [
"libiconv"
],
"lib-suggests": [
"icu",
"xz",
@ -166,6 +169,17 @@
"pthreads4w"
]
},
"libiconv": {
"source": "libiconv",
"static-libs-unix": [
"libiconv.a"
],
"headers": [
"iconv.h",
"libcharset.h",
"localcharset.h"
]
},
"libyaml": {
"source": "libyaml",
"static-libs-unix": [

View File

@ -223,6 +223,15 @@
"path": "LICENSE"
}
},
"libiconv":{
"type": "filelist",
"url": "https://ftp.gnu.org/gnu/libiconv/",
"regex": "/href=\"(?<file>libiconv-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "text",
"text": "TODO"
}
},
"xz": {
"type": "filelist",
"url": "https://tukaani.org/xz/",

View File

@ -5,59 +5,60 @@
> - empty: not supported yet
> - faulty with issue link: not supported yet due to issue
| | Linux | macOS | Windows |
|------------|-------|--------------------------------------------------------------------|---------|
| bcmath | | yes | |
| bz2 | | untested | |
| calendar | | yes | |
| ctype | | yes | |
| curl | | yes | |
| date | | yes | |
| dom | | untested | |
| event | | | |
| exif | | yes | |
| filter | | yes | |
| fileinfo | | | |
| ftp | | yes | |
| gd | | untested | |
| gmp | | untested | |
| hash | | yes | |
| iconv | | | |
| inotify | | | |
| json | | yes | |
| libxml | | yes | |
| mbstring | | yes | |
| mcrypt | | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
| mongodb | | | |
| mysqli | | | |
| mysqlnd | | yes | |
| openssl | | yes | |
| pcntl | | untested | |
| pcre | | yes | |
| pdo | | yes | |
| pdo_mysql | | yes | |
| pdo_sqlite | | yes | |
| pdo_pgsql | | | |
| phar | | yes | |
| posix | | yes | |
| protobuf | | | |
| readline | | | |
| redis | | yes | |
| Reflection | | yes | |
| session | | yes | |
| shmop | | | |
| simplexml | | untested | |
| soap | | | |
| sockets | | | |
| sqlite3 | | untested | |
| swow | | | |
| swoole | | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
| tokenizer | | yes | |
| xml | | yes | |
| xmlreader | | untested | |
| xmlwriter | | untested | |
| zip | | yes | |
| zlib | | yes | |
| | Linux | macOS | Windows |
|------------|----------|--------------------------------------------------------------------|---------|
| bcmath | yes | yes | |
| bz2 | yes | untested | |
| calendar | yes | yes | |
| ctype | yes | yes | |
| curl | untested | yes | |
| date | | yes | |
| dba | yes | yes | |
| dom | untested | untested | |
| event | | | |
| exif | | yes | |
| filter | | yes | |
| fileinfo | | | |
| ftp | | yes | |
| gd | | untested | |
| gmp | | untested | |
| hash | yes | yes | |
| iconv | untested | | |
| inotify | | | |
| json | yes | yes | |
| libxml | | yes | |
| mbstring | | yes | |
| mcrypt | | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
| mongodb | | | |
| mysqli | | | |
| mysqlnd | | yes | |
| openssl | untested | yes | |
| pcntl | untested | untested | |
| pcre | | yes | |
| pdo | | yes | |
| pdo_mysql | | yes | |
| pdo_sqlite | | yes | |
| pdo_pgsql | | | |
| phar | yes | yes | |
| posix | yes | yes | |
| protobuf | | | |
| readline | | | |
| redis | | yes | |
| Reflection | | yes | |
| session | | yes | |
| shmop | | | |
| simplexml | | untested | |
| soap | | | |
| sockets | | | |
| sqlite3 | | untested | |
| swow | | | |
| swoole | | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
| tokenizer | | yes | |
| xml | | yes | |
| xmlreader | | untested | |
| xmlwriter | | untested | |
| zip | | yes | |
| zlib | yes | yes | |
## Additional Requirements

View File

@ -31,12 +31,12 @@ class BuilderProvider
cxx: $input->getOption('cxx'),
arch: $input->getOption('arch'),
),
// 'Linux' => new LinuxBuilder(
// cc: $input->getOption('cc'),
// cxx: $input->getOption('cxx'),
// arch: $input->getOption('arch'),
// ),
default => throw new RuntimeException('Current OS is not supported yet'),
'Linux' => new LinuxBuilder(
cc: $input->getOption('cc'),
cxx: $input->getOption('cxx'),
arch: $input->getOption('arch'),
),
default => throw new RuntimeException('Current OS "' . PHP_OS_FAMILY . '" is not supported yet'),
};
}
}

View File

@ -0,0 +1,333 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux;
use SPC\builder\BuilderBase;
use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\builder\traits\UnixBuilderTrait;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\Patcher;
/**
* Linux 系统环境下的构建器
*/
class LinuxBuilder extends BuilderBase
{
/** 编译的 Unix 工具集 */
use UnixBuilderTrait;
/** @var string[] Linux 环境下编译依赖的命令 */
public const REQUIRED_COMMANDS = ['make', 'bison', 'flex', 'pkg-config', 'git', 'autoconf', 'automake', 'tar', 'unzip', /* 'xz', 好像不需要 */ 'gzip', 'bzip2', 'cmake'];
/** @var string 使用的 libc */
public string $libc;
/** @var array 特殊架构下的 cflags */
public array $tune_c_flags;
/** @var string pkg-config 环境变量 */
public string $pkgconf_env;
/** @var string 交叉编译变量 */
public string $cross_compile_prefix = '';
public string $note_section = "Je pense, donc je suis\0";
private bool $phar_patched = false;
/**
* @throws RuntimeException
*/
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null)
{
// 初始化一些默认参数
$this->cc = $cc ?? 'musl-gcc';
$this->cxx = $cxx ?? 'g++';
$this->arch = $arch ?? php_uname('m');
$this->gnu_arch = arch2gnu($this->arch);
$this->libc = 'musl'; // SystemUtil::selectLibc($this->cc);
// 根据 CPU 线程数设置编译进程数
$this->concurrency = SystemUtil::getCpuCount();
// 设置 cflags
$this->arch_c_flags = SystemUtil::getArchCFlags($this->cc, $this->arch);
$this->arch_cxx_flags = SystemUtil::getArchCFlags($this->cxx, $this->arch);
$this->tune_c_flags = SystemUtil::checkCCFlags(SystemUtil::getTuneCFlags($this->arch), $this->cc);
// 设置 cmake
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile(
os: 'Linux',
target_arch: $this->arch,
cflags: $this->arch_c_flags,
cc: $this->cc,
cxx: $this->cxx
);
// 设置 pkgconfig
$this->pkgconf_env = 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig"';
// 设置 configure 依赖的环境变量
$this->configure_env =
$this->pkgconf_env . ' ' .
"CC='{$this->cc}' " .
"CXX='{$this->cxx}' " .
(php_uname('m') === $this->arch ? '' : "CFLAGS='{$this->arch_c_flags}'");
// 交叉编译依赖的TODO
if (php_uname('m') !== $this->arch) {
$this->cross_compile_prefix = SystemUtil::getCrossCompilePrefix($this->cc, $this->arch);
logger()->info('using cross compile prefix: ' . $this->cross_compile_prefix);
$this->configure_env .= " CROSS_COMPILE='{$this->cross_compile_prefix}'";
}
$missing = [];
foreach (self::REQUIRED_COMMANDS as $cmd) {
if (SystemUtil::findCommand($cmd) === null) {
$missing[] = $cmd;
}
}
if (!empty($missing)) {
throw new RuntimeException('missing system commands: ' . implode(', ', $missing));
}
// 创立 pkg-config 和放头文件的目录
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
f_mkdir(BUILD_INCLUDE_PATH, recursive: true);
}
public function makeAutoconfArgs(string $name, array $libSpecs): string
{
$ret = '';
foreach ($libSpecs as $libName => $arr) {
$lib = $this->getLib($libName);
$arr = $arr ?? [];
$disableArgs = $arr[0] ?? null;
$prefix = $arr[1] ?? null;
if ($lib instanceof LinuxLibraryBase) {
logger()->info("{$name} \033[32;1mwith\033[0;1m {$libName} support");
$ret .= $lib->makeAutoconfEnv($prefix) . ' ';
} else {
logger()->info("{$name} \033[31;1mwithout\033[0;1m {$libName} support");
$ret .= ($disableArgs ?? "--with-{$libName}=no") . ' ';
}
}
return rtrim($ret);
}
/**
* @throws RuntimeException
* @throws FileSystemException
*/
public function buildPHP(int $build_micro_rule = BUILD_MICRO_NONE, bool $with_clean = false, bool $bloat = false)
{
if (!$bloat) {
$extra_libs = implode(' ', $this->getAllStaticLibFiles());
} else {
logger()->info('bloat linking');
$extra_libs = implode(
' ',
array_map(
fn ($x) => "-Xcompiler {$x}",
array_filter($this->getAllStaticLibFiles())
)
);
}
$envs = $this->pkgconf_env . ' ' .
"CC='{$this->cc}' " .
"CXX='{$this->cxx}' ";
$cflags = $this->arch_c_flags;
$use_lld = '';
switch ($this->libc) {
case 'musl_wrapper':
case 'glibc':
$cflags .= ' -static-libgcc -I"' . BUILD_INCLUDE_PATH . '"';
break;
case 'musl':
if (str_ends_with($this->cc, 'clang') && SystemUtil::findCommand('lld')) {
$use_lld = '-Xcompiler -fuse-ld=lld';
}
break;
default:
throw new RuntimeException('libc ' . $this->libc . ' is not implemented yet');
}
$envs = "{$envs} CFLAGS='{$cflags}' LIBS='-ldl -lpthread'";
Patcher::patchPHPBeforeConfigure($this);
f_passthru(
$this->set_x . ' && ' .
'cd ' . SOURCE_PATH . '/php-src && ' .
'./buildconf --force'
);
Patcher::patchPHPConfigure($this);
f_passthru(
$this->set_x . ' && ' .
'cd ' . SOURCE_PATH . '/php-src && ' .
'./configure ' .
'--prefix= ' .
'--with-valgrind=no ' .
'--enable-shared=no ' .
'--enable-static=yes ' .
"--host={$this->gnu_arch}-unknown-linux " .
'--disable-all ' .
'--disable-cgi ' .
'--disable-phpdbg ' .
'--enable-cli ' .
'--enable-micro=all-static ' .
($this->zts ? '--enable-zts' : '') . ' ' .
$this->makeExtensionArgs() . ' ' .
$envs
);
$extra_libs .= $this->generateExtraLibs();
file_put_contents('/tmp/comment', $this->note_section);
if ($with_clean) {
logger()->info('cleaning up');
f_passthru(
$this->set_x . ' && ' .
'cd ' . SOURCE_PATH . '/php-src && ' .
'make clean'
);
}
if ($bloat) {
logger()->info('bloat linking');
$extra_libs = "-Wl,--whole-archive {$extra_libs} -Wl,--no-whole-archive";
}
switch ($build_micro_rule) {
case BUILD_MICRO_NONE:
logger()->info('building cli');
$this->buildCli($extra_libs, $use_lld);
break;
case BUILD_MICRO_ONLY:
logger()->info('building micro');
$this->buildMicro($extra_libs, $use_lld, $cflags);
break;
case BUILD_MICRO_BOTH:
logger()->info('building cli and micro');
$this->buildCli($extra_libs, $use_lld);
$this->buildMicro($extra_libs, $use_lld, $cflags);
break;
}
if (php_uname('m') === $this->arch) {
$this->sanityCheck($build_micro_rule);
}
if ($this->phar_patched) {
f_passthru('cd ' . SOURCE_PATH . '/php-src && patch -p1 -R < sapi/micro/patches/phar.patch');
}
}
/**
* @throws RuntimeException
*/
public function buildCli(string $extra_libs, string $use_lld): void
{
f_passthru(
$this->set_x . ' && ' .
'cd ' . SOURCE_PATH . '/php-src && ' .
'sed -i "s|//lib|/lib|g" Makefile && ' .
"make -j{$this->concurrency} " .
'EXTRA_CFLAGS="-g -Os -fno-ident ' . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags)) . '" ' .
"EXTRA_LIBS=\"{$extra_libs}\" " .
"EXTRA_LDFLAGS_PROGRAM='{$use_lld}" .
' -all-static' .
"' " .
'cli && ' .
'cd sapi/cli && ' .
"{$this->cross_compile_prefix}objcopy --only-keep-debug php php.debug && " .
'elfedit --output-osabi linux php && ' .
"{$this->cross_compile_prefix}strip --strip-all php && " .
"{$this->cross_compile_prefix}objcopy --update-section .comment=/tmp/comment --add-gnu-debuglink=php.debug --remove-section=.note php"
);
}
/**
* @throws RuntimeException
*/
public function buildMicro(string $extra_libs, string $use_lld, string $cflags): void
{
if ($this->getExt('phar')) {
$this->phar_patched = true;
try {
f_passthru('cd ' . SOURCE_PATH . '/php-src && patch -p1 < sapi/micro/patches/phar.patch');
} catch (RuntimeException $e) {
logger()->error('failed to patch phat due to patch exit with code ' . $e->getCode());
$this->phar_patched = false;
}
}
$vars = [
'EXTRA_CFLAGS' => quote('-g -Os -fno-ident ' . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags))),
'EXTRA_LIBS' => quote($extra_libs),
'EXTRA_LDFLAGS_PROGRAM' => quote("{$cflags} {$use_lld}" . ' -all-static', "'"),
'POST_MICRO_BUILD_COMMANDS' => quote(
"sh -xc '" .
'cd sapi/micro && ' .
"{$this->cross_compile_prefix}objcopy --only-keep-debug micro.sfx micro.sfx.debug && " .
'elfedit --output-osabi linux micro.sfx && ' .
"{$this->cross_compile_prefix}strip --strip-all micro.sfx && " .
"{$this->cross_compile_prefix}objcopy --update-section .comment=/tmp/comment --add-gnu-debuglink=micro.sfx.debug --remove-section=.note micro.sfx'"
),
];
$var_cmdline = '';
foreach ($vars as $k => $v) {
$var_cmdline .= $k . '=' . $v . ' ';
}
f_passthru(
$this->set_x . ' && ' .
'cd ' . SOURCE_PATH . '/php-src && ' .
'sed -i "s|//lib|/lib|g" Makefile && ' .
"make -j{$this->concurrency} " .
$var_cmdline .
'micro'
);
}
/**
* @throws RuntimeException
*/
private function generateExtraLibs(): string
{
if ($this->libc === 'glibc') {
$glibc_libs = [
'rt',
'm',
'c',
'pthread',
'dl',
'nsl',
'anl',
// 'crypt',
'resolv',
'util',
];
$makefile = file_get_contents(SOURCE_PATH . '/php-src/Makefile');
preg_match('/^EXTRA_LIBS\s*=\s*(.*)$/m', $makefile, $matches);
if (!$matches) {
throw new RuntimeException('failed to find EXTRA_LIBS in Makefile');
}
$_extra_libs = [];
foreach (array_filter(explode(' ', $matches[1])) as $used) {
foreach ($glibc_libs as $libName) {
if ("-l{$libName}" === $used && !in_array("-l{$libName}", $_extra_libs, true)) {
array_unshift($_extra_libs, "-l{$libName}");
}
}
}
return ' ' . implode(' ', $_extra_libs);
}
return '';
}
}

View File

@ -0,0 +1,241 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux;
use JetBrains\PhpStorm\ArrayShape;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\exception\RuntimeException;
class SystemUtil
{
use UnixSystemUtilTrait;
/**
* 查找并选择编译器命令
*
* @throws RuntimeException
*/
public static function selectCC(): string
{
logger()->debug('Choose cc');
if (self::findCommand('clang')) {
logger()->info('using clang');
return 'clang';
}
if (self::findCommand('gcc')) {
logger()->info('using gcc');
return 'gcc';
}
throw new RuntimeException('no supported cc found');
}
/**
* 查找并选择编译器命令
*
* @throws RuntimeException
*/
public static function selectCXX(): string
{
logger()->debug('Choose cxx');
if (self::findCommand('clang++')) {
logger()->info('using clang++');
return 'clang++';
}
if (self::findCommand('g++')) {
logger()->info('using g++');
return 'g++';
}
return self::selectCC();
}
#[ArrayShape(['dist' => 'mixed|string', 'ver' => 'mixed|string'])]
public static function getOSRelease(): array
{
$ret = [
'dist' => 'unknown',
'ver' => 'unknown',
];
switch (true) {
case file_exists('/etc/os-release'):
$lines = file('/etc/os-release');
foreach ($lines as $line) {
if (preg_match('/^ID=(.*)$/', $line, $matches)) {
$ret['dist'] = $matches[1];
}
if (preg_match('/^VERSION_ID=(.*)$/', $line, $matches)) {
$ret['ver'] = $matches[1];
}
}
$ret['dist'] = trim($ret['dist'], '"\'');
$ret['ver'] = trim($ret['ver'], '"\'');
if (strcasecmp($ret['dist'], 'centos') === 0) {
$ret['dist'] = 'redhat';
}
break;
case file_exists('/etc/centos-release'):
$lines = file('/etc/centos-release');
goto rh;
case file_exists('/etc/redhat-release'):
$lines = file('/etc/redhat-release');
rh:
foreach ($lines as $line) {
if (preg_match('/release\s+(\d+(\.\d+)*)/', $line, $matches)) {
$ret['dist'] = 'redhat';
$ret['ver'] = $matches[1];
}
}
break;
}
return $ret;
}
public static function getCpuCount(): int
{
$ncpu = 1;
if (is_file('/proc/cpuinfo')) {
$cpuinfo = file_get_contents('/proc/cpuinfo');
preg_match_all('/^processor/m', $cpuinfo, $matches);
$ncpu = count($matches[0]);
}
return $ncpu;
}
/**
* @throws RuntimeException
*/
public static function getCCType(string $cc): string
{
return match (true) {
str_ends_with($cc, 'c++'), str_ends_with($cc, 'cc'), str_ends_with($cc, 'g++'), str_ends_with($cc, 'gcc') => 'gcc',
$cc === 'clang++', $cc === 'clang', str_starts_with($cc, 'musl-clang') => 'clang',
default => throw new RuntimeException("unknown cc type: {$cc}"),
};
}
/**
* @throws RuntimeException
*/
public static function getArchCFlags(string $cc, string $arch): string
{
if (php_uname('m') === $arch) {
return '';
}
return match (static::getCCType($cc)) {
'clang' => match ($arch) {
'x86_64' => '--target=x86_64-unknown-linux',
'arm64', 'aarch64' => '--target=arm64-unknown-linux',
default => throw new RuntimeException('unsupported arch: ' . $arch),
},
'gcc' => '',
default => throw new RuntimeException('cc compiler ' . $cc . ' is not supported'),
};
}
/**
* @throws RuntimeException
*/
public static function getTuneCFlags(string $arch): array
{
return match ($arch) {
'x86_64' => [
'-march=corei7',
'-mtune=core-avx2',
],
'arm64', 'aarch64' => [],
default => throw new RuntimeException('unsupported arch: ' . $arch),
};
}
public static function checkCCFlags(array $flags, string $cc): array
{
return array_filter($flags, fn ($flag) => static::checkCCFlag($flag, $cc));
}
public static function checkCCFlag(string $flag, string $cc): string
{
$ret = 0;
f_exec("echo | {$cc} -E -x c - {$flag}", $dummy, $ret);
if ($ret != 0) {
return '';
}
return $flag;
}
/**
* @throws RuntimeException
*/
public static function getCrossCompilePrefix(string $cc, string $arch): string
{
return match (static::getCCType($cc)) {
// guessing clang toolchains
'clang' => match ($arch) {
'x86_64' => 'x86_64-linux-gnu-',
'arm64', 'aarch64' => 'aarch64-linux-gnu-',
default => throw new RuntimeException('unsupported arch: ' . $arch),
},
// remove gcc postfix
'gcc' => str_replace('-cc', '', str_replace('-gcc', '', $cc)) . '-',
default => throw new RuntimeException('unsupported cc'),
};
}
public static function findStaticLib(string $name): ?array
{
$paths = getenv('LIBPATH');
if (!$paths) {
$paths = '/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64';
}
foreach (explode(':', $paths) as $path) {
if (file_exists("{$path}/{$name}")) {
return ["{$path}", "{$name}"];
}
}
return null;
}
public static function findStaticLibs(array $names): ?array
{
$ret = [];
foreach ($names as $name) {
$path = static::findStaticLib($name);
if (!$path) {
logger()->warning("static library {$name} not found");
return null;
}
$ret[] = $path;
}
return $ret;
}
public static function findHeader(string $name): ?array
{
$paths = getenv('INCLUDEPATH');
if (!$paths) {
$paths = '/include:/usr/include:/usr/local/include';
}
foreach (explode(':', $paths) as $path) {
if (file_exists("{$path}/{$name}") || is_dir("{$path}/{$name}")) {
return ["{$path}", "{$name}"];
}
}
return null;
}
public static function findHeaders(array $names): ?array
{
$ret = [];
foreach ($names as $name) {
$path = static::findHeader($name);
if (!$path) {
logger()->warning("header {$name} not found");
return null;
}
$ret[] = $path;
}
return $ret;
}
}

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\builder\BuilderBase;
use SPC\builder\LibraryBase;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\traits\UnixLibraryTrait;
use SPC\exception\RuntimeException;
abstract class LinuxLibraryBase extends LibraryBase
{
use UnixLibraryTrait;
protected array $static_libs = [];
protected array $headers;
protected array $pkgconfs;
/**
* 依赖的名字及是否可选例如curl => true,代表依赖 curl 但可选
*/
protected array $dep_names;
public function __construct(protected LinuxBuilder $builder)
{
parent::__construct();
}
public function getBuilder(): BuilderBase
{
return $this->builder;
}
/**
* @throws RuntimeException
*/
public function tryBuild(bool $force_build = false): int
{
// 传入 true表明直接编译
if ($force_build) {
$this->build();
return BUILD_STATUS_OK;
}
// 看看这些库是不是存在,如果不存在,则调用编译并返回结果状态
foreach ($this->getStaticLibs() as $name) {
if (!file_exists(BUILD_LIB_PATH . "/{$name}")) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
}
// 头文件同理
foreach ($this->getHeaders() as $name) {
if (!file_exists(BUILD_INCLUDE_PATH . "/{$name}")) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
}
// 到这里说明所有的文件都存在,就跳过编译
return BUILD_STATUS_ALREADY;
}
protected function makeFakePkgconfs()
{
$workspace = BUILD_ROOT_PATH;
if ($workspace === '/') {
$workspace = '';
}
foreach ($this->pkgconfs as $name => $content) {
file_put_contents(BUILD_LIB_PATH . "/pkgconfig/{$name}", "prefix={$workspace}\n" . $content);
}
}
}

View File

@ -0,0 +1,59 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class brotli extends LinuxLibraryBase
{
public const NAME = 'brotli';
/**
* @throws RuntimeException
*/
public function build()
{
[$lib, $include, $destdir] = SEPARATED_PATH;
f_passthru(
"{$this->builder->set_x} && " .
"cd {$this->source_dir} && " .
'rm -rf build && ' .
'mkdir -p build && ' .
'cd build && ' .
"{$this->builder->configure_env} " . ' cmake ' .
// '--debug-find ' .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DCMAKE_INSTALL_PREFIX=/ ' .
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'.. && ' .
"cmake --build . -j {$this->builder->concurrency} --target brotlicommon-static && " .
"cmake --build . -j {$this->builder->concurrency} --target brotlidec-static && " .
"cmake --build . -j {$this->builder->concurrency} --target brotlienc-static && " .
'cp libbrotlidec-static.a ' . BUILD_LIB_PATH . ' && ' .
'cp libbrotlienc-static.a ' . BUILD_LIB_PATH . ' && ' .
'cp libbrotlicommon-static.a ' . BUILD_LIB_PATH . ' && ' .
'cp -r ../c/include/brotli ' . BUILD_INCLUDE_PATH
);
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class bzip2 extends LinuxLibraryBase
{
public const NAME = 'bzip2';
protected array $dep_names = [];
/**
* @throws RuntimeException
*/
public function build()
{
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
"make {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' clean" . ' && ' .
"make -j{$this->builder->concurrency} {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' libbz2.a" . ' && ' .
// make install may fail when cross-compiling, so we copy files.
'cp libbz2.a ' . BUILD_LIB_PATH . ' && ' .
'cp bzlib.h ' . BUILD_INCLUDE_PATH
);
// $this->makeFakePkgconfs();
}
}

View File

@ -0,0 +1,163 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class curl extends LinuxLibraryBase
{
public const NAME = 'curl';
protected array $static_libs = ['libcurl.a'];
protected array $headers = ['curl'];
protected array $pkgconfs = [
'libcurl.pc' => <<<'EOF'
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
supported_protocols="DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS MQTT POP3 POP3S RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP"
supported_features="AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets alt-svc brotli libz zstd"
Name: libcurl
URL: https://curl.se/
Description: Library to transfer files with ftp, http, etc.
Version: 7.83.0
Libs: -L${libdir} -lcurl
Libs.private: -lnghttp2 -lidn2 -lssh2 -lssh2 -lpsl -lssl -lcrypto -lssl -lcrypto -lgssapi_krb5 -lzstd -lbrotlidec -lz
Cflags: -I${includedir}
EOF
];
protected array $dep_names = [
'zlib' => false,
'libssh2' => true,
'brotli' => true,
'nghttp2' => true,
'zstd' => true,
'openssl' => true,
'idn2' => true,
'psl' => true,
];
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
{
$libs = parent::getStaticLibFiles($style, $recursive);
if ($this->builder->getLib('openssl')) {
$libs .= ' -ldl -lpthread';
}
return $libs;
}
/**
* @throws RuntimeException
*/
public function build()
{
$extra = '';
// lib:openssl
$openssl = $this->builder->getLib('openssl');
if ($openssl instanceof LinuxLibraryBase) {
$extra .= '-DCURL_USE_OPENSSL=ON -DCURL_ENABLE_SSL=ON ';
} else {
$extra .= '-DCURL_USE_OPENSSL=OFF -DCURL_ENABLE_SSL=OFF ';
}
// lib:zlib
$zlib = $this->builder->getLib('zlib');
if ($zlib instanceof LinuxLibraryBase) {
$extra .= '-DZLIB_LIBRARIES="' . $zlib->getStaticLibFiles(style: 'cmake') . '" ' .
'-DZLIB_INCLUDE_DIRS="' . BUILD_INCLUDE_PATH . '" ';
}
// lib:libssh2
$libssh2 = $this->builder->getLib('libssh2');
if ($libssh2 instanceof LinuxLibraryBase) {
$extra .= '-DLIBSSH2_LIBRARY="' . $libssh2->getStaticLibFiles(style: 'cmake') . '" ' .
'-DLIBSSH2_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DCURL_USE_LIBSSH2=OFF ';
}
// lib:brotli
$brotli = $this->builder->getLib('brotli');
if ($brotli) {
$extra .= '-DCURL_BROTLI=ON ' .
'-DBROTLIDEC_LIBRARY="' . realpath(BUILD_LIB_PATH . '/libbrotlidec-static.a') . ';' . realpath(BUILD_LIB_PATH . '/libbrotlicommon-static.a') . '" ' .
'-DBROTLICOMMON_LIBRARY="' . realpath(BUILD_LIB_PATH . '/libbrotlicommon-static.a') . '" ' .
'-DBROTLI_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DCURL_BROTLI=OFF ';
}
// lib:nghttp2
$nghttp2 = $this->builder->getLib('nghttp2');
if ($nghttp2 instanceof LinuxLibraryBase) {
$extra .= '-DUSE_NGHTTP2=ON ' .
'-DNGHTTP2_LIBRARY="' . $nghttp2->getStaticLibFiles(style: 'cmake') . '" ' .
'-DNGHTTP2_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DUSE_NGHTTP2=OFF ';
}
// lib:ldap
$ldap = $this->builder->getLib('ldap');
if ($ldap instanceof LinuxLibraryBase) {
// $extra .= '-DCURL_DISABLE_LDAP=OFF ';
// TODO: LDAP support
throw new RuntimeException('LDAP support is not implemented yet');
}
$extra .= '-DCURL_DISABLE_LDAP=ON ';
// lib:zstd
$zstd = $this->builder->getLib('zstd');
if ($zstd instanceof LinuxLibraryBase) {
$extra .= '-DCURL_ZSTD=ON ' .
'-DZstd_LIBRARY="' . $zstd->getStaticLibFiles(style: 'cmake') . '" ' .
'-DZstd_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DCURL_ZSTD=OFF ';
}
// lib:idn2
$idn2 = $this->builder->getLib('idn2');
$extra .= $idn2 instanceof LinuxLibraryBase ? '-DUSE_LIBIDN2=ON ' : '-DUSE_LIBIDN2=OFF ';
// lib:psl
$libpsl = $this->builder->getLib('psl');
$extra .= $libpsl instanceof LinuxLibraryBase ? '-DCURL_USE_LIBPSL=ON ' : '-DCURL_USE_LIBPSL=OFF ';
[$lib, $include, $destdir] = SEPARATED_PATH;
// compile
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
'rm -rf build && ' .
'mkdir -p build && ' .
'cd build && ' .
"{$this->builder->configure_env} " . ' cmake ' .
// '--debug-find ' .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
$extra .
'-DCMAKE_INSTALL_PREFIX=/ ' .
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'.. && ' .
"make -j{$this->builder->concurrency} && " .
'make install DESTDIR="' . $destdir . '"'
);
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class libiconv extends LinuxLibraryBase
{
public const NAME = 'libiconv';
protected array $dep_names = [];
/**
* @throws RuntimeException
*/
public function build()
{
[,,$destdir] = SEPARATED_PATH;
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
"{$this->builder->configure_env} ./configure " .
'--enable-static ' .
'--disable-shared ' .
'--prefix= && ' . // use prefix=/
'make clean && ' .
"make -j{$this->builder->concurrency} && " .
'make install DESTDIR=' . $destdir
);
}
}

View File

@ -0,0 +1,104 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
class libxml2 extends LinuxLibraryBase
{
public const NAME = 'libxml2';
protected array $static_libs = ['libxml2.a'];
protected array $headers = [
'libxml2',
];
protected array $pkgconfs = [
'libxml-2.0.pc' => <<<'EOF'
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
modules=1
Name: libXML
Version: 2.9.14
Description: libXML library version2.
Requires:
Libs: -L${libdir} -lxml2
Cflags: -I${includedir}/libxml2
EOF
];
protected array $dep_names = [
'icu' => true,
'xz' => true,
'zlib' => true,
];
/**
* @throws RuntimeException
*/
public function build()
{
$enable_zlib = $this->builder->getLib('zlib') ? 'ON' : 'OFF';
$enable_icu = $this->builder->getLib('icu') ? 'ON' : 'OFF';
$enable_xz = $this->builder->getLib('xz') ? 'ON' : 'OFF';
[$lib, $include, $destdir] = SEPARATED_PATH;
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
'rm -rf build && ' .
'mkdir -p build && ' .
'cd build && ' .
"{$this->builder->configure_env} " . ' cmake ' .
// '--debug-find ' .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DLIBXML2_WITH_ICONV=ON ' .
'-DIconv_IS_BUILT_IN=OFF ' .
"-DLIBXML2_WITH_ZLIB={$enable_zlib} " .
"-DLIBXML2_WITH_ICU={$enable_icu} " .
"-DLIBXML2_WITH_LZMA={$enable_xz} " .
'-DLIBXML2_WITH_PYTHON=OFF ' .
'-DLIBXML2_WITH_PROGRAMS=OFF ' .
'-DLIBXML2_WITH_TESTS=OFF ' .
'-DCMAKE_INSTALL_PREFIX=/ ' .
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'.. && ' .
"cmake --build . -j {$this->builder->concurrency} && " .
'make install DESTDIR="' . $destdir . '"'
);
if (is_dir(BUILD_INCLUDE_PATH . '/libxml2/libxml')) {
if (is_dir(BUILD_INCLUDE_PATH . '/libxml')) {
f_passthru('rm -rf "' . BUILD_INCLUDE_PATH . '/libxml"');
}
$path = FileSystem::convertPath(BUILD_INCLUDE_PATH . '/libxml2/libxml');
$dst_path = FileSystem::convertPath(BUILD_INCLUDE_PATH . '/');
f_passthru('mv "' . $path . '" "' . $dst_path . '"');
}
}
}

View File

@ -0,0 +1,127 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\builder\linux\SystemUtil;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
class openssl extends LinuxLibraryBase
{
public const NAME = 'openssl';
protected array $static_libs = [
'libssl.a',
'libcrypto.a',
];
protected array $headers = ['openssl'];
protected array $pkgconfs = [
'openssl.pc' => <<<'EOF'
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: OpenSSL
Description: Secure Sockets Layer and cryptography libraries and tools
Version: 3.0.3
Requires: libssl libcrypto
EOF,
'libssl.pc' => <<<'EOF'
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: OpenSSL-libssl
Description: Secure Sockets Layer and cryptography libraries
Version: 3.0.3
Requires.private: libcrypto
Libs: -L${libdir} -lssl
Cflags: -I${includedir}
EOF,
'libcrypto.pc' => <<<'EOF'
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
enginesdir=${libdir}/engines-3
Name: OpenSSL-libcrypto
Description: OpenSSL cryptography library
Version: 3.0.3
Libs: -L${libdir} -lcrypto
Libs.private: -lz -ldl -pthread
Cflags: -I${includedir}
EOF,
];
protected array $dep_names = ['zlib' => true];
/**
* @throws RuntimeException
* @throws FileSystemException
*/
public function build()
{
[$lib,$include,$destdir] = SEPARATED_PATH;
$extra = '';
$ex_lib = '-ldl -pthread';
$env = $this->builder->pkgconf_env . " CFLAGS='{$this->builder->arch_c_flags}'";
$env .= " CC='{$this->builder->cc} --static -static-libgcc -idirafter " . BUILD_INCLUDE_PATH .
' -idirafter /usr/include/ ' .
' -idirafter /usr/include/' . $this->builder->arch . '-linux-gnu/ ' .
"' ";
// lib:zlib
$zlib = $this->builder->getLib('zlib');
if ($zlib instanceof LinuxLibraryBase) {
$extra = 'zlib';
$ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib);
$zlib_extra =
'--with-zlib-include=' . BUILD_INCLUDE_PATH . ' ' .
'--with-zlib-lib=' . BUILD_LIB_PATH . ' ';
} else {
$zlib_extra = '';
}
$ex_lib = trim($ex_lib);
$clang_postfix = SystemUtil::getCCType($this->builder->cc) === 'clang' ? '-clang' : '';
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
"{$this->builder->configure_env} {$env} ./Configure no-shared {$extra} " .
'--prefix=/ ' . // use prefix=/
"--libdir={$lib} " .
'--static -static ' .
"{$zlib_extra}" .
'no-legacy ' .
"linux-{$this->builder->arch}{$clang_postfix} && " .
'make clean && ' .
"make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\" && " .
'make install_sw DESTDIR=' . $destdir
// remove liblegacy
// 'ar t lib/libcrypto.a | grep -e \'^liblegacy-\' | xargs ar d lib/libcrypto.a'
);
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class zlib extends LinuxLibraryBase
{
public const NAME = 'zlib';
/**
* @throws RuntimeException
*/
public function build()
{
[,,$destdir] = SEPARATED_PATH;
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
"{$this->builder->configure_env} ./configure " .
'--static ' .
'--prefix= && ' . // use prefix=/
'make clean && ' .
"make -j{$this->builder->concurrency} && " .
'make install DESTDIR=' . $destdir
);
}
}

View File

@ -7,6 +7,7 @@ namespace SPC\builder\traits;
use SPC\builder\LibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
trait UnixLibraryTrait
{
@ -33,7 +34,7 @@ trait UnixLibraryTrait
foreach ($libs as $lib) {
$libFiles = [];
foreach ($lib->getStaticLibs() as $name) {
$name = str_replace(' ', '\ ', realpath(BUILD_LIB_PATH . "/{$name}"));
$name = str_replace(' ', '\ ', FileSystem::convertPath(BUILD_LIB_PATH . "/{$name}"));
$name = str_replace('"', '\"', $name);
$libFiles[] = $name;
}

View File

@ -44,6 +44,10 @@ SET(CMAKE_C_FLAGS "{$cflags}")
SET(CMAKE_CXX_FLAGS "{$cflags}")
SET(CMAKE_FIND_ROOT_PATH "{$root}")
CMAKE;
// 有时候系统的 cmake 找不到 ar 命令,真奇怪
if (PHP_OS_FAMILY === 'Linux') {
$toolchain .= "\nSET(CMAKE_AR \"ar\")";
}
file_put_contents(SOURCE_PATH . '/toolchain.cmake', $toolchain);
return realpath(SOURCE_PATH . '/toolchain.cmake');
}

View File

@ -77,8 +77,8 @@ class BuildCliCommand extends BuildCommand
if ($input->getOption('debug')) {
ExceptionHandler::getInstance()->handle($e);
} else {
logger()->critical('Build failed, please check terminal output, or build with --debug option to see more details.');
logger()->critical($e->getMessage());
logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage());
logger()->critical('Please check with --debug option to see more details.');
}
return 1;
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\command;
use SPC\builder\BuilderProvider;
use SPC\exception\ExceptionHandler;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
@ -30,6 +31,7 @@ class BuildLibsCommand extends BuildCommand
if ($input->getOption('all')) {
$input->setArgument('libraries', '');
}
parent::initialize($input, $output);
}
/**
@ -55,15 +57,25 @@ class BuildLibsCommand extends BuildCommand
}
}
// 构建对象
$builder = BuilderProvider::makeBuilderByInput($input);
// 只编译 library 的情况下,标记
$builder->setLibsOnly();
// 编译和检查库完整
$builder->buildLibs($libraries);
try {
// 构建对象
$builder = BuilderProvider::makeBuilderByInput($input);
// 只编译 library 的情况下,标记
$builder->setLibsOnly();
// 编译和检查库完整
$builder->buildLibs($libraries);
$time = round(microtime(true) - START_TIME, 3);
logger()->info('Build libs complete, used ' . $time . ' s !');
return 0;
$time = round(microtime(true) - START_TIME, 3);
logger()->info('Build libs complete, used ' . $time . ' s !');
return 0;
} catch (\Throwable $e) {
if ($input->getOption('debug')) {
ExceptionHandler::getInstance()->handle($e);
} else {
logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage());
logger()->critical('Please check with --debug option to see more details.');
}
return 1;
}
}
}