Merge pull request #775 from crazywhalecc/sapi/frankenphp-prerequisites

Sapi/frankenphp prerequisites
This commit is contained in:
Marc
2025-06-19 08:54:42 +07:00
committed by GitHub
15 changed files with 213 additions and 128 deletions

View File

@@ -42,5 +42,17 @@
"extract-files": { "extract-files": {
"upx-*-win64/upx.exe": "{pkg_root_path}/bin/upx.exe" "upx-*-win64/upx.exe": "{pkg_root_path}/bin/upx.exe"
} }
},
"go-mod-frankenphp-x86_64-linux": {
"type": "custom"
},
"go-mod-frankenphp-aarch64-linux": {
"type": "custom"
},
"go-mod-frankenphp-x86_64-macos": {
"type": "custom"
},
"go-mod-frankenphp-aarch64-macos": {
"type": "custom"
} }
} }

View File

@@ -404,6 +404,9 @@ abstract class BuilderBase
if (($type & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) { if (($type & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) {
$ls[] = 'embed'; $ls[] = 'embed';
} }
if (($type & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) {
$ls[] = 'frankenphp';
}
return implode(', ', $ls); return implode(', ', $ls);
} }
@@ -510,6 +513,26 @@ abstract class BuilderBase
} }
} }
public function checkBeforeBuildPHP(int $rule): void
{
if (($rule & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) {
// frankenphp only support linux and macOS
if (!in_array(PHP_OS_FAMILY, ['Linux', 'Darwin'])) {
throw new WrongUsageException('FrankenPHP SAPI is only available on Linux and macOS!');
}
// frankenphp needs package go-mod-frankenphp installed
$pkg_dir = PKG_ROOT_PATH . '/go-mod-frankenphp-' . arch2gnu(php_uname('m')) . '-' . osfamily2shortname();
if (!file_exists("{$pkg_dir}/bin/go") || !file_exists("{$pkg_dir}/bin/xcaddy")) {
global $argv;
throw new WrongUsageException("FrankenPHP SAPI requires go-mod-frankenphp package, please install it first: {$argv[0]} install-pkg go-mod-frankenphp");
}
// frankenphp needs libxml2 libs
if (PHP_OS_FAMILY === 'Darwin' && !$this->getLib('libxml2')) {
throw new WrongUsageException('FrankenPHP SAPI for macOS requires libxml2 library, please include `xml` extension in your build.');
}
}
}
/** /**
* Generate micro extension test php code. * Generate micro extension test php code.
*/ */

View File

@@ -1,83 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\traits;
use SPC\doctor\CheckResult;
use SPC\exception\RuntimeException;
use SPC\store\Downloader;
use SPC\store\FileSystem;
trait UnixGoCheckTrait
{
private function checkGoAndXcaddy(): ?CheckResult
{
$paths = explode(PATH_SEPARATOR, getenv('PATH'));
$goroot = getenv('GOROOT') ?: '/usr/local/go';
$goBin = "{$goroot}/bin";
$paths[] = $goBin;
if ($this->findCommand('go', $paths) === null) {
$this->installGo();
}
$gobin = getenv('GOBIN') ?: (getenv('HOME') . '/go/bin');
putenv("GOBIN={$gobin}");
$paths[] = $gobin;
if ($this->findCommand('xcaddy', $paths) === null) {
shell(true)->exec('go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest');
}
return CheckResult::ok();
}
private function installGo(): bool
{
$prefix = '';
if (get_current_user() !== 'root') {
$prefix = 'sudo ';
logger()->warning('Current user is not root, using sudo for running command');
}
$arch = php_uname('m');
$go_arch = match ($arch) {
'x86_64' => 'amd64',
'aarch64' => 'arm64',
default => $arch
};
$os = strtolower(PHP_OS_FAMILY);
$go_version = '1.24.4';
$go_filename = "go{$go_version}.{$os}-{$go_arch}.tar.gz";
$go_url = "https://go.dev/dl/{$go_filename}";
logger()->info("Downloading Go {$go_version} for {$go_arch}");
try {
// Download Go binary
Downloader::downloadFile('go', $go_url, $go_filename);
// Extract the tarball
FileSystem::extractSource('go', SPC_SOURCE_ARCHIVE, DOWNLOAD_PATH . "/{$go_filename}");
// Move to /usr/local/go
logger()->info('Installing Go to /usr/local/go');
shell()->exec("{$prefix}rm -rf /usr/local/go");
shell()->exec("{$prefix}mv " . SOURCE_PATH . '/go /usr/local/');
if (!str_contains(getenv('PATH'), '/usr/local/go/bin')) {
logger()->info('Adding Go to PATH');
shell()->exec("{$prefix}echo 'export PATH=\$PATH:/usr/local/go/bin' >> /etc/profile");
putenv('PATH=' . getenv('PATH') . ':/usr/local/go/bin');
}
logger()->info('Go has been installed successfully');
return true;
} catch (RuntimeException $e) {
logger()->error('Failed to install Go: ' . $e->getMessage());
return false;
}
}
}

View File

@@ -219,6 +219,19 @@ abstract class UnixBuilderBase extends BuilderBase
throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output)); throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output));
} }
} }
// sanity check for frankenphp
if (($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) {
logger()->info('running frankenphp sanity check');
$frankenphp = BUILD_BIN_PATH . '/frankenphp';
if (!file_exists($frankenphp)) {
throw new RuntimeException('FrankenPHP binary not found: ' . $frankenphp);
}
[$ret, $output] = shell()->execWithResult("{$frankenphp} version");
if ($ret !== 0 || !str_contains(implode('', $output), 'FrankenPHP')) {
throw new RuntimeException('FrankenPHP failed sanity check: ret[' . $ret . ']. out[' . implode('', $output) . ']');
}
}
} }
/** /**
@@ -285,16 +298,19 @@ abstract class UnixBuilderBase extends BuilderBase
*/ */
protected function buildFrankenphp(): void protected function buildFrankenphp(): void
{ {
$path = getenv('PATH'); $os = match (PHP_OS_FAMILY) {
$xcaddyPath = getenv('GOBIN') ?: (getenv('HOME') . '/go/bin'); 'Linux' => 'linux',
if (!str_contains($path, $xcaddyPath)) { 'Windows' => 'win',
$path = $path . ':' . $xcaddyPath; 'Darwin' => 'macos',
} 'BSD' => 'freebsd',
$path = BUILD_BIN_PATH . ':' . $path; default => throw new RuntimeException('Unsupported OS: ' . PHP_OS_FAMILY),
f_putenv("PATH={$path}"); };
$arch = arch2gnu(php_uname('m'));
// define executables for go and xcaddy
$go_exec = PKG_ROOT_PATH . "/go-mod-frankenphp-{$arch}-{$os}/bin/go";
$xcaddy_exec = PKG_ROOT_PATH . "/go-mod-frankenphp-{$arch}-{$os}/bin/xcaddy";
$brotliLibs = $this->getLib('brotli') !== null ? '-lbrotlienc -lbrotlidec -lbrotlicommon' : '';
$watcherLibs = $this->getLib('watcher') !== null ? '-lwatcher-c' : '';
$nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : ''; $nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : '';
$nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : ''; $nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : '';
$xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES'); $xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES');
@@ -303,7 +319,7 @@ abstract class UnixBuilderBase extends BuilderBase
$xcaddyModules = '--with github.com/dunglas/frankenphp ' . $xcaddyModules; $xcaddyModules = '--with github.com/dunglas/frankenphp ' . $xcaddyModules;
} }
if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) { if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) {
logger()->warning('caddy-cbrotli module is enabled, but broli library is not built. Disabling caddy-cbrotli.'); logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.');
$xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules); $xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules);
} }
$lrt = PHP_OS_FAMILY === 'Linux' ? '-lrt' : ''; $lrt = PHP_OS_FAMILY === 'Linux' ? '-lrt' : '';
@@ -313,14 +329,20 @@ abstract class UnixBuilderBase extends BuilderBase
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
$libphpVersion = preg_replace('/\.\d$/', '', $libphpVersion); $libphpVersion = preg_replace('/\.\d$/', '', $libphpVersion);
} }
$debugFlags = $this->getOption('--with-debug') ? "'-w -s' " : ''; $debugFlags = $this->getOption('--with-debug') ? "'-w -s' " : '';
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list, with_dependencies: true);
$env = [ $env = [
'PATH' => PKG_ROOT_PATH . "/go-mod-frankenphp-{$arch}-{$os}/bin:" . getenv('PATH'),
'GOROOT' => PKG_ROOT_PATH . "/go-mod-frankenphp-{$arch}-{$os}",
'GOBIN' => PKG_ROOT_PATH . "/go-mod-frankenphp-{$arch}-{$os}/bin",
'GOPATH' => PKG_ROOT_PATH . '/go',
'CGO_ENABLED' => '1', 'CGO_ENABLED' => '1',
'CGO_CFLAGS' => '$(php-config --includes) -I$(php-config --include-dir)/..', 'CGO_CFLAGS' => $config['cflags'],
'CGO_LDFLAGS' => '$(php-config --ldflags) -L' . BUILD_LIB_PATH . " $(php-config --libs) {$brotliLibs} {$watcherLibs} -lphp {$lrt}", 'CGO_LDFLAGS' => "{$config['ldflags']} {$config['libs']} {$lrt}",
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' . 'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
'-ldflags \\"-linkmode=external -extldflags \'-pie\' '. $debugFlags . '-ldflags \"-linkmode=external -extldflags \'-pie\' ' . $debugFlags .
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' . '-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
"{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " . "{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
"-tags=nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}", "-tags=nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",
@@ -328,6 +350,6 @@ abstract class UnixBuilderBase extends BuilderBase
]; ];
shell()->cd(BUILD_BIN_PATH) shell()->cd(BUILD_BIN_PATH)
->setEnv($env) ->setEnv($env)
->exec('xcaddy build --output frankenphp ' . $xcaddyModules); ->exec("{$xcaddy_exec} build --output frankenphp {$xcaddyModules}");
} }
} }

View File

@@ -196,6 +196,9 @@ class BuildPHPCommand extends BuildCommand
// validate libs and extensions // validate libs and extensions
$builder->validateLibsAndExts(); $builder->validateLibsAndExts();
// check some things before building all the things
$builder->checkBeforeBuildPHP($rule);
// clean builds and sources // clean builds and sources
if ($this->input->getOption('with-clean')) { if ($this->input->getOption('with-clean')) {
logger()->info('Cleaning source and previous build dir...'); logger()->info('Cleaning source and previous build dir...');
@@ -316,7 +319,7 @@ class BuildPHPCommand extends BuildCommand
$rule |= BUILD_TARGET_EMBED; $rule |= BUILD_TARGET_EMBED;
f_putenv('SPC_CMD_VAR_PHP_EMBED_TYPE=' . ($embed === 'static' ? 'static' : 'shared')); f_putenv('SPC_CMD_VAR_PHP_EMBED_TYPE=' . ($embed === 'static' ? 'static' : 'shared'));
} }
$rule |= ($this->getOption('build-frankenphp') ? BUILD_TARGET_FRANKENPHP : BUILD_TARGET_NONE); $rule |= ($this->getOption('build-frankenphp') ? (BUILD_TARGET_FRANKENPHP | BUILD_TARGET_EMBED) : BUILD_TARGET_NONE);
$rule |= ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE); $rule |= ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE);
return $rule; return $rule;
} }

View File

@@ -47,12 +47,6 @@ class BSDToolCheckList
return CheckResult::ok(); return CheckResult::ok();
} }
#[AsCheckItem('if xcaddy is installed', limit_os: 'BSD')]
public function checkXcaddy(): ?CheckResult
{
return $this->checkGoAndXcaddy();
}
#[AsFixItem('build-tools-bsd')] #[AsFixItem('build-tools-bsd')]
public function fixBuildTools(array $missing): bool public function fixBuildTools(array $missing): bool
{ {

View File

@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace SPC\doctor\item; namespace SPC\doctor\item;
use SPC\builder\linux\SystemUtil; use SPC\builder\linux\SystemUtil;
use SPC\builder\traits\UnixGoCheckTrait;
use SPC\builder\traits\UnixSystemUtilTrait; use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\doctor\AsCheckItem; use SPC\doctor\AsCheckItem;
use SPC\doctor\AsFixItem; use SPC\doctor\AsFixItem;
@@ -15,7 +14,6 @@ use SPC\exception\RuntimeException;
class LinuxToolCheckList class LinuxToolCheckList
{ {
use UnixSystemUtilTrait; use UnixSystemUtilTrait;
use UnixGoCheckTrait;
public const TOOLS_ALPINE = [ public const TOOLS_ALPINE = [
'make', 'bison', 'flex', 'make', 'bison', 'flex',
@@ -89,12 +87,6 @@ class LinuxToolCheckList
return CheckResult::ok(); return CheckResult::ok();
} }
#[AsCheckItem('if xcaddy is installed', limit_os: 'Linux')]
public function checkXcaddy(): ?CheckResult
{
return $this->checkGoAndXcaddy();
}
#[AsCheckItem('if cmake version >= 3.18', limit_os: 'Linux')] #[AsCheckItem('if cmake version >= 3.18', limit_os: 'Linux')]
public function checkCMakeVersion(): ?CheckResult public function checkCMakeVersion(): ?CheckResult
{ {

View File

@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace SPC\doctor\item; namespace SPC\doctor\item;
use SPC\builder\traits\UnixGoCheckTrait;
use SPC\builder\traits\UnixSystemUtilTrait; use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\doctor\AsCheckItem; use SPC\doctor\AsCheckItem;
use SPC\doctor\AsFixItem; use SPC\doctor\AsFixItem;
@@ -14,7 +13,6 @@ use SPC\exception\RuntimeException;
class MacOSToolCheckList class MacOSToolCheckList
{ {
use UnixSystemUtilTrait; use UnixSystemUtilTrait;
use UnixGoCheckTrait;
/** @var string[] MacOS 环境下编译依赖的命令 */ /** @var string[] MacOS 环境下编译依赖的命令 */
public const REQUIRED_COMMANDS = [ public const REQUIRED_COMMANDS = [
@@ -36,12 +34,6 @@ class MacOSToolCheckList
'glibtoolize', 'glibtoolize',
]; ];
#[AsCheckItem('if xcaddy is installed', limit_os: 'Darwin')]
public function checkXcaddy(): ?CheckResult
{
return $this->checkGoAndXcaddy();
}
#[AsCheckItem('if homebrew has installed', limit_os: 'Darwin', level: 998)] #[AsCheckItem('if homebrew has installed', limit_os: 'Darwin', level: 998)]
public function checkBrew(): ?CheckResult public function checkBrew(): ?CheckResult
{ {

View File

@@ -9,6 +9,7 @@ use SPC\exception\DownloaderException;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\pkg\CustomPackage;
use SPC\store\source\CustomSourceBase; use SPC\store\source\CustomSourceBase;
/** /**
@@ -385,10 +386,13 @@ class Downloader
]); ]);
break; break;
case 'custom': // Custom download method, like API-based download or other case 'custom': // Custom download method, like API-based download or other
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\store\source'); $classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg');
foreach ($classes as $class) { foreach ($classes as $class) {
if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) { if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) {
(new $class())->fetch($force); $cls = new $class();
if (in_array($name, $cls->getSupportName())) {
(new $class())->fetch($name, $force, $pkg);
}
break; break;
} }
} }
@@ -708,7 +712,6 @@ class Downloader
} }
} }
// If lock file exists for current arch and glibc target, skip downloading // If lock file exists for current arch and glibc target, skip downloading
if (!$force && $download_as === SPC_DOWNLOAD_PRE_BUILT && isset($lock[$lock_name = self::getPreBuiltLockName($name)])) { if (!$force && $download_as === SPC_DOWNLOAD_PRE_BUILT && isset($lock[$lock_name = self::getPreBuiltLockName($name)])) {
// lock name with env // lock name with env
if ( if (
@@ -719,6 +722,17 @@ class Downloader
return true; return true;
} }
} }
// If lock file exists, skip downloading for source mode
if (!$force && $download_as === SPC_DOWNLOAD_PACKAGE && isset($lock[$name])) {
if (
$lock[$name]['source_type'] === SPC_SOURCE_ARCHIVE && file_exists(DOWNLOAD_PATH . '/' . $lock[$name]['filename']) ||
$lock[$name]['source_type'] === SPC_SOURCE_GIT && is_dir(DOWNLOAD_PATH . '/' . $lock[$name]['dirname'])
) {
logger()->notice("Package [{$name}] already downloaded: " . ($lock[$name]['filename'] ?? $lock[$name]['dirname']));
return true;
}
}
return false; return false;
} }
} }

View File

@@ -6,6 +6,7 @@ namespace SPC\store;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\pkg\CustomPackage;
class PackageManager class PackageManager
{ {
@@ -32,6 +33,20 @@ class PackageManager
// Download package // Download package
Downloader::downloadPackage($pkg_name, $config, $force); Downloader::downloadPackage($pkg_name, $config, $force);
if (Config::getPkg($pkg_name)['type'] === 'custom') {
// Custom extract function
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg');
foreach ($classes as $class) {
if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) {
$cls = new $class();
if (in_array($pkg_name, $cls->getSupportName())) {
(new $class())->extract($pkg_name);
break;
}
}
}
return;
}
// After download, read lock file name // After download, read lock file name
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true); $lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true);
$source_type = $lock[$pkg_name]['source_type']; $source_type = $lock[$pkg_name]['source_type'];

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace SPC\store\pkg;
abstract class CustomPackage
{
abstract public function getSupportName(): array;
abstract public function fetch(string $name, bool $force = false, ?array $config = null): void;
public function extract(string $name): void
{
throw new \RuntimeException("Extract method not implemented for package: {$name}");
}
}

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace SPC\store\pkg;
use SPC\store\Downloader;
use SPC\store\FileSystem;
class GoModFrankenphp extends CustomPackage
{
public function getSupportName(): array
{
return [
'go-mod-frankenphp-x86_64-linux',
'go-mod-frankenphp-x86_64-macos',
'go-mod-frankenphp-aarch64-linux',
'go-mod-frankenphp-aarch64-macos',
];
}
public function fetch(string $name, bool $force = false, ?array $config = null): void
{
$arch = match (explode('-', $name)[3]) {
'x86_64' => 'amd64',
'aarch64' => 'arm64',
default => throw new \InvalidArgumentException('Unsupported architecture: ' . $name),
};
$os = match (explode('-', $name)[4]) {
'linux' => 'linux',
'macos' => 'darwin',
default => throw new \InvalidArgumentException('Unsupported OS: ' . $name),
};
$go_version = '1.24.4';
$config = [
'type' => 'url',
'url' => "https://go.dev/dl/go{$go_version}.{$os}-{$arch}.tar.gz",
];
Downloader::downloadPackage($name, $config, $force);
}
public function extract(string $name): void
{
$pkgroot = PKG_ROOT_PATH;
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true);
$source_type = $lock[$name]['source_type'];
$filename = DOWNLOAD_PATH . '/' . ($lock[$name]['filename'] ?? $lock[$name]['dirname']);
$extract = $lock[$name]['move_path'] === null ? (PKG_ROOT_PATH . "{$pkgroot}/{$name}") : $lock[$name]['move_path'];
FileSystem::extractPackage($name, $source_type, $filename, $extract);
// install xcaddy
$go_exec = PKG_ROOT_PATH . "{$pkgroot}/{$name}/bin/go";
// $xcaddy_exec = PKG_ROOT_PATH . "$pkgroot/$name/bin/xcaddy";
shell()->appendEnv([
'PATH' => "{$pkgroot}/{$name}/bin:" . getenv('PATH'),
'GOROOT' => "{$pkgroot}/{$name}",
'GOBIN' => "{$pkgroot}/{$name}/bin",
'GOPATH' => "{$pkgroot}/go",
])
->exec("{$go_exec} install github.com/caddyserver/xcaddy/cmd/xcaddy@latest");
// TODO: Here to download dependencies for xcaddy and frankenphp first
}
}

View File

@@ -62,7 +62,7 @@ const BUILD_TARGET_CLI = 1; // build cli
const BUILD_TARGET_MICRO = 2; // build micro const BUILD_TARGET_MICRO = 2; // build micro
const BUILD_TARGET_FPM = 4; // build fpm const BUILD_TARGET_FPM = 4; // build fpm
const BUILD_TARGET_EMBED = 8; // build embed const BUILD_TARGET_EMBED = 8; // build embed
const BUILD_TARGET_FRANKENPHP = BUILD_TARGET_EMBED | 16; // build frankenphp const BUILD_TARGET_FRANKENPHP = 16; // build frankenphp
const BUILD_TARGET_ALL = BUILD_TARGET_CLI | BUILD_TARGET_MICRO | BUILD_TARGET_FPM | BUILD_TARGET_EMBED | BUILD_TARGET_FRANKENPHP; // build all const BUILD_TARGET_ALL = BUILD_TARGET_CLI | BUILD_TARGET_MICRO | BUILD_TARGET_FPM | BUILD_TARGET_EMBED | BUILD_TARGET_FRANKENPHP; // build all
// doctor error fix policy // doctor error fix policy

View File

@@ -102,6 +102,17 @@ function osfamily2dir(): string
}; };
} }
function osfamily2shortname(): string
{
return match (PHP_OS_FAMILY) {
'Windows' => 'win',
'Darwin' => 'macos',
'Linux' => 'linux',
'BSD' => 'bsd',
default => throw new WrongUsageException('Not support os: ' . PHP_OS_FAMILY),
};
}
function shell(?bool $debug = null): UnixShell function shell(?bool $debug = null): UnixShell
{ {
/* @noinspection PhpUnhandledExceptionInspection */ /* @noinspection PhpUnhandledExceptionInspection */

View File

@@ -40,6 +40,9 @@ $no_strip = false;
// compress with upx // compress with upx
$upx = false; $upx = false;
// whether to test frankenphp build, only available for macos and linux
$frankenphp = true;
// prefer downloading pre-built packages to speed up the build process // prefer downloading pre-built packages to speed up the build process
$prefer_pre_built = false; $prefer_pre_built = false;
@@ -177,7 +180,7 @@ if ($argv[1] === 'build_cmd' || $argv[1] === 'build_embed_cmd') {
$build_cmd .= $no_strip ? '--no-strip ' : ''; $build_cmd .= $no_strip ? '--no-strip ' : '';
$build_cmd .= $upx ? '--with-upx-pack ' : ''; $build_cmd .= $upx ? '--with-upx-pack ' : '';
$build_cmd .= $final_libs === '' ? '' : ('--with-libs=' . quote2($final_libs) . ' '); $build_cmd .= $final_libs === '' ? '' : ('--with-libs=' . quote2($final_libs) . ' ');
$build_cmd .= str_starts_with($argv[2], 'windows-') ? '' : '--build-fpm --build-frankenphp'; $build_cmd .= str_starts_with($argv[2], 'windows-') ? '' : '--build-fpm ';
$build_cmd .= '--debug '; $build_cmd .= '--debug ';
} }
@@ -208,7 +211,13 @@ switch ($argv[1] ?? null) {
passthru($prefix . $build_cmd . ' --build-cli --build-micro', $retcode); passthru($prefix . $build_cmd . ' --build-cli --build-micro', $retcode);
break; break;
case 'build_embed_cmd': case 'build_embed_cmd':
passthru($prefix . $build_cmd . (str_starts_with($argv[2], 'windows-') ? ' --build-cli' : ' --build-embed'), $retcode); if ($frankenphp) {
passthru("{$prefix}install-pkg go-mod-frankenphp --debug", $retcode);
if ($retcode !== 0) {
break;
}
}
passthru($prefix . $build_cmd . (str_starts_with($argv[2], 'windows-') ? ' --build-cli' : (' --build-embed' . ($frankenphp ? ' --build-frankenphp' : ''))), $retcode);
break; break;
case 'doctor_cmd': case 'doctor_cmd':
passthru($prefix . $doctor_cmd, $retcode); passthru($prefix . $doctor_cmd, $retcode);