Merge pull request #883 from crazywhalecc/sapi/cgi

Add cgi support for macOS and Linux
This commit is contained in:
Marc 2025-09-05 11:52:26 +02:00 committed by GitHub
commit 8d303348d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 69 additions and 4 deletions

View File

@ -207,6 +207,7 @@ bin/spc --version
- `--build-micro`:构建 phpmicro 自执行二进制
- `--build-fpm`:构建 fpm
- `--build-embed`:构建 embedlibphp
- `--build-cgi`: 构建 cgi不推荐
- `--build-all`:构建所有
如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误:

View File

@ -218,6 +218,7 @@ Now we support `cli`, `micro`, `fpm` and `embed` SAPI. You can use one or more o
- `--build-micro`: build static phpmicro self-extracted executable
- `--build-fpm`: build static fpm binary
- `--build-embed`: build embed (libphp)
- `--build-cgi`: build cgi binary (not recommended)
- `--build-all`: build all
If anything goes wrong, use `--debug` option to display full terminal output:

View File

@ -103,7 +103,7 @@ SPC_MICRO_PATCHES=cli_checks,disable_huge_page
; buildconf command
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
; configure command
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --disable-all --disable-cgi --disable-phpdbg --with-pic"
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --disable-all --disable-phpdbg --with-pic"
; make command
SPC_CMD_PREFIX_PHP_MAKE="make -j${SPC_CONCURRENCY}"
@ -137,7 +137,7 @@ SPC_MICRO_PATCHES=cli_checks,macos_iconv
; buildconf command
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
; configure command
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg"
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-phpdbg"
; make command
SPC_CMD_PREFIX_PHP_MAKE="make -j${SPC_CONCURRENCY}"

View File

@ -289,6 +289,7 @@ You need to specify a compilation target, choose from the following parameters:
- `--build-cli`: Build a cli sapi (command line interface, which can execute PHP code on the command line)
- `--build-fpm`: Build a fpm sapi (php-fpm, used in conjunction with other traditional fpm architecture software such as nginx)
- `--build-cgi`: Build a cgi sapi (cgi, rarely used)
- `--build-micro`: Build a micro sapi (used to build a standalone executable binary containing PHP code)
- `--build-embed`: Build an embed sapi (used to embed into other C language programs)
- `--build-frankenphp`: Build a [FrankenPHP](https://github.com/php/frankenphp) executable

View File

@ -249,6 +249,7 @@ bin/spc doctor --auto-fix
- `--build-cli`: 构建一个 cli sapi命令行界面可在命令行执行 PHP 代码)
- `--build-fpm`: 构建一个 fpm sapiphp-fpm用于和其他传统的 fpm 架构的软件如 nginx 配合使用)
- `--build-cgi`: 构建一个 cgi sapicgi可用于传统的 cgi 架构的软件如 apache 配合使用)
- `--build-micro`: 构建一个 micro sapi用于构建一个包含 PHP 代码的独立可执行二进制)
- `--build-embed`: 构建一个 embed sapi用于嵌入到其他 C 语言程序中)
- `--build-frankenphp`: 构建一个 [frankenphp](https://github.com/php/frankenphp) 二进制

View File

@ -392,6 +392,9 @@ abstract class BuilderBase
if (($type & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) {
$ls[] = 'frankenphp';
}
if (($type & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) {
$ls[] = 'cgi';
}
return implode(', ', $ls);
}

View File

@ -84,6 +84,7 @@ class LinuxBuilder extends UnixBuilderBase
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
$enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP;
$enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI;
// prepare build php envs
// $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__';
@ -110,6 +111,7 @@ class LinuxBuilder extends UnixBuilderBase
($enableFpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') .
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
($enableCgi ? '--enable-cgi ' : '--disable-cgi ') .
$config_file_path .
$config_file_scan_dir .
$json_74 .
@ -131,6 +133,10 @@ class LinuxBuilder extends UnixBuilderBase
logger()->info('building fpm');
$this->buildFpm();
}
if ($enableCgi) {
logger()->info('building cgi');
$this->buildCgi();
}
if ($enableMicro) {
logger()->info('building micro');
$this->buildMicro();
@ -182,6 +188,25 @@ class LinuxBuilder extends UnixBuilderBase
$this->deployBinary(BUILD_TARGET_CLI);
}
protected function buildCgi(): void
{
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cgi");
if (!$this->getOption('no-strip', false)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')->exec('strip --strip-unneeded php-cgi');
}
if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')
->exec(getenv('UPX_EXEC') . ' --best php-cgi');
}
$this->deployBinary(BUILD_TARGET_CGI);
}
/**
* Build phpmicro sapi
*/

View File

@ -100,6 +100,7 @@ class MacOSBuilder extends UnixBuilderBase
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
$enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP;
$enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI;
// prepare build php envs
$envs_build_php = SystemUtil::makeEnvVarString([
@ -124,6 +125,7 @@ class MacOSBuilder extends UnixBuilderBase
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
($enableCgi ? '--enable-cgi ' : '--disable-cgi ') .
$config_file_path .
$config_file_scan_dir .
$json_74 .
@ -145,6 +147,10 @@ class MacOSBuilder extends UnixBuilderBase
logger()->info('building fpm');
$this->buildFpm();
}
if ($enableCgi) {
logger()->info('building cgi');
$this->buildCgi();
}
if ($enableMicro) {
logger()->info('building micro');
$this->buildMicro();
@ -189,6 +195,19 @@ class MacOSBuilder extends UnixBuilderBase
$this->deployBinary(BUILD_TARGET_CLI);
}
protected function buildCgi(): void
{
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$shell = shell()->cd(SOURCE_PATH . '/php-src');
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
$shell->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cgi");
if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/cgi/php-cgi')->exec('strip -S sapi/cgi/php-cgi');
}
$this->deployBinary(BUILD_TARGET_CGI);
}
/**
* Build phpmicro sapi
*/

View File

@ -120,6 +120,16 @@ abstract class UnixBuilderBase extends BuilderBase
}
}
// sanity check for php-cgi
if (($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) {
logger()->info('running cgi sanity check');
[$ret, $output] = shell()->execWithResult("echo '<?php echo \"<h1>Hello, World!</h1>\";' | " . BUILD_BIN_PATH . '/php-cgi -n');
$raw_output = implode('', $output);
if ($ret !== 0 || !str_contains($raw_output, 'Hello, World!') || !str_contains($raw_output, 'text/html')) {
throw new ValidationException("cgi failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cgi sanity check');
}
}
// sanity check for embed
if (($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) {
logger()->info('running embed sanity check');
@ -207,6 +217,7 @@ abstract class UnixBuilderBase extends BuilderBase
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',
BUILD_TARGET_CGI => SOURCE_PATH . '/php-src/sapi/cgi/php-cgi',
default => throw new SPCInternalException("Deployment does not accept type {$type}"),
};
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');

View File

@ -33,6 +33,7 @@ class BuildPHPCommand extends BuildCommand
$this->addOption('build-fpm', null, null, 'Build fpm SAPI (not available on Windows)');
$this->addOption('build-embed', null, null, 'Build embed SAPI (not available on Windows)');
$this->addOption('build-frankenphp', null, null, 'Build FrankenPHP SAPI (not available on Windows)');
$this->addOption('build-cgi', null, null, 'Build cgi SAPI (not available on Windows)');
$this->addOption('build-all', null, null, 'Build all SAPI');
$this->addOption('no-strip', null, null, 'build without strip, keep symbols to debug');
$this->addOption('disable-opcache-jit', null, null, 'disable opcache jit');
@ -274,6 +275,7 @@ class BuildPHPCommand extends BuildCommand
$rule |= ($this->getOption('build-fpm') ? BUILD_TARGET_FPM : BUILD_TARGET_NONE);
$rule |= $this->getOption('build-embed') || !empty($shared_extensions) ? BUILD_TARGET_EMBED : BUILD_TARGET_NONE;
$rule |= ($this->getOption('build-frankenphp') ? (BUILD_TARGET_FRANKENPHP | BUILD_TARGET_EMBED) : BUILD_TARGET_NONE);
$rule |= ($this->getOption('build-cgi') ? BUILD_TARGET_CGI : BUILD_TARGET_NONE);
$rule |= ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE);
return $rule;
}

View File

@ -63,7 +63,8 @@ const BUILD_TARGET_MICRO = 2; // build micro
const BUILD_TARGET_FPM = 4; // build fpm
const BUILD_TARGET_EMBED = 8; // build embed
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_CGI = 32; // build cgi
const BUILD_TARGET_ALL = BUILD_TARGET_CLI | BUILD_TARGET_MICRO | BUILD_TARGET_FPM | BUILD_TARGET_EMBED | BUILD_TARGET_FRANKENPHP | BUILD_TARGET_CGI; // build all
// doctor error fix policy
const FIX_POLICY_DIE = 1; // die directly

View File

@ -160,7 +160,7 @@ class BuilderTest extends TestCase
[BUILD_TARGET_MICRO, 'micro'],
[BUILD_TARGET_EMBED, 'embed'],
[BUILD_TARGET_FRANKENPHP, 'frankenphp'],
[BUILD_TARGET_ALL, 'cli, micro, fpm, embed, frankenphp'],
[BUILD_TARGET_ALL, 'cli, micro, fpm, embed, frankenphp, cgi'],
[BUILD_TARGET_CLI | BUILD_TARGET_EMBED, 'cli, embed'],
];
}