static-php-cli/src/SPC/builder/traits/UnixBuilderTrait.php

157 lines
5.5 KiB
PHP
Raw Normal View History

2023-03-18 17:32:21 +08:00
<?php
declare(strict_types=1);
namespace SPC\builder\traits;
use SPC\builder\linux\LinuxBuilder;
use SPC\exception\FileSystemException;
2023-03-18 17:32:21 +08:00
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
2023-03-18 17:32:21 +08:00
trait UnixBuilderTrait
{
/** @var string cflags */
2023-03-18 17:32:21 +08:00
public string $arch_c_flags;
/** @var string C++ flags */
2023-03-18 17:32:21 +08:00
public string $arch_cxx_flags;
/** @var string cmake toolchain file */
public string $cmake_toolchain_file;
/** @var string configure environments */
2023-03-18 17:32:21 +08:00
public string $configure_env;
/**
* @throws WrongUsageException
* @throws FileSystemException
*/
2023-03-18 17:32:21 +08:00
public function getAllStaticLibFiles(): array
{
$libs = [];
// reorder libs
foreach ($this->libs as $lib) {
foreach ($lib->getDependencies() as $dep) {
$libs[] = $dep;
}
$libs[] = $lib;
}
$libFiles = [];
$libNames = [];
// merge libs
foreach ($libs as $lib) {
if (!in_array($lib::NAME, $libNames, true)) {
$libNames[] = $lib::NAME;
array_unshift($libFiles, ...$lib->getStaticLibs());
}
}
return array_map(fn ($x) => realpath(BUILD_LIB_PATH . "/{$x}"), $libFiles);
}
/**
2023-04-23 20:31:58 +08:00
* Sanity check after build complete
*
2023-03-18 17:32:21 +08:00
* @throws RuntimeException
*/
2023-04-23 20:31:58 +08:00
public function sanityCheck(int $build_target): void
2023-03-18 17:32:21 +08:00
{
2023-04-23 20:31:58 +08:00
// sanity check for php-cli
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
logger()->info('running cli sanity check');
[$ret, $output] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "echo \"hello\";"');
2023-03-18 17:32:21 +08:00
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
throw new RuntimeException('cli failed sanity check');
}
2023-03-18 17:32:21 +08:00
foreach ($this->exts as $ext) {
logger()->debug('testing ext: ' . $ext->getName());
2023-05-17 15:24:08 +08:00
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "' . $ext->getDistName() . '"', false);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $ext->getName() . ' failed compile check');
}
2023-03-18 17:32:21 +08:00
if (file_exists(ROOT_DIR . '/src/globals/tests/' . $ext->getName() . '.php')) {
// Trim additional content & escape special characters to allow inline usage
$test = str_replace(
['<?php', 'declare(strict_types=1);', "\n", '"', '$'],
['', '', '', '\"', '\$'],
file_get_contents(ROOT_DIR . '/src/globals/tests/' . $ext->getName() . '.php')
);
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "' . trim($test) . '"');
2023-03-18 17:32:21 +08:00
if ($ret !== 0) {
throw new RuntimeException('extension ' . $ext->getName() . ' failed sanity check');
}
}
}
}
2023-04-23 20:31:58 +08:00
// sanity check for phpmicro
if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
2023-03-18 17:32:21 +08:00
if (file_exists(SOURCE_PATH . '/hello.exe')) {
@unlink(SOURCE_PATH . '/hello.exe');
}
file_put_contents(
SOURCE_PATH . '/hello.exe',
file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx') .
'<?php echo "hello";'
);
chmod(SOURCE_PATH . '/hello.exe', 0755);
[$ret, $output2] = shell()->execWithResult(SOURCE_PATH . '/hello.exe');
2023-03-18 17:32:21 +08:00
if ($ret !== 0 || trim($out = implode('', $output2)) !== 'hello') {
throw new RuntimeException('micro failed sanity check, ret[' . $ret . '], out[' . ($out ?? 'NULL') . ']');
}
}
}
/**
* 将编译好的二进制文件发布到 buildroot
*
* @param int $type 发布类型
* @throws RuntimeException
* @throws FileSystemException
*/
public function deployBinary(int $type): bool
{
$src = match ($type) {
2023-04-23 20:31:58 +08:00
BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
default => throw new RuntimeException('Deployment does not accept type ' . $type),
};
2023-04-23 20:31:58 +08:00
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
FileSystem::createDir(BUILD_ROOT_PATH . '/bin');
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_ROOT_PATH . '/bin/'));
return true;
}
/**
* Run php clean
*
* @throws RuntimeException
*/
public function cleanMake(): void
{
logger()->info('cleaning up');
shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean');
}
/**
* Return generic cmake options when configuring cmake projects
*/
public function makeCmakeArgs(): string
{
[$lib, $include] = SEPARATED_PATH;
$extra = $this instanceof LinuxBuilder ? '-DCMAKE_C_COMPILER=' . $this->getOption('cc') . ' ' : '';
return $extra . '-DCMAKE_BUILD_TYPE=Release ' .
'-DCMAKE_INSTALL_PREFIX=/ ' .
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
"-DCMAKE_TOOLCHAIN_FILE={$this->cmake_toolchain_file}";
}
2023-03-18 17:32:21 +08:00
}