diff --git a/README-zh.md b/README-zh.md index 402fd635..b159a5c3 100755 --- a/README-zh.md +++ b/README-zh.md @@ -207,6 +207,7 @@ bin/spc --version - `--build-micro`:构建 phpmicro 自执行二进制 - `--build-fpm`:构建 fpm - `--build-embed`:构建 embed(libphp) +- `--build-cgi`: 构建 cgi(不推荐) - `--build-all`:构建所有 如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误: diff --git a/README.md b/README.md index 22eda03f..e405edf4 100755 --- a/README.md +++ b/README.md @@ -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: diff --git a/config/env.ini b/config/env.ini index 3641d54b..4b9f294a 100644 --- a/config/env.ini +++ b/config/env.ini @@ -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}" diff --git a/docs/en/guide/manual-build.md b/docs/en/guide/manual-build.md index 2b00358e..28f0ec87 100644 --- a/docs/en/guide/manual-build.md +++ b/docs/en/guide/manual-build.md @@ -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 diff --git a/docs/zh/guide/manual-build.md b/docs/zh/guide/manual-build.md index b7291e85..4c24cab8 100644 --- a/docs/zh/guide/manual-build.md +++ b/docs/zh/guide/manual-build.md @@ -249,6 +249,7 @@ bin/spc doctor --auto-fix - `--build-cli`: 构建一个 cli sapi(命令行界面,可在命令行执行 PHP 代码) - `--build-fpm`: 构建一个 fpm sapi(php-fpm,用于和其他传统的 fpm 架构的软件如 nginx 配合使用) +- `--build-cgi`: 构建一个 cgi sapi(cgi,可用于传统的 cgi 架构的软件如 apache 配合使用) - `--build-micro`: 构建一个 micro sapi(用于构建一个包含 PHP 代码的独立可执行二进制) - `--build-embed`: 构建一个 embed sapi(用于嵌入到其他 C 语言程序中) - `--build-frankenphp`: 构建一个 [frankenphp](https://github.com/php/frankenphp) 二进制 diff --git a/src/SPC/builder/BuilderBase.php b/src/SPC/builder/BuilderBase.php index 3bd0b538..b410aab3 100644 --- a/src/SPC/builder/BuilderBase.php +++ b/src/SPC/builder/BuilderBase.php @@ -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); } diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 3d8a30f7..c4eb2b05 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -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 */ diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index 66e9a399..13a978d3 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -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 */ diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 3beca8bf..5309636f 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -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 'Hello, World!\";' | " . 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'); diff --git a/src/SPC/command/BuildPHPCommand.php b/src/SPC/command/BuildPHPCommand.php index 58b6059b..3ffc54ce 100644 --- a/src/SPC/command/BuildPHPCommand.php +++ b/src/SPC/command/BuildPHPCommand.php @@ -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; } diff --git a/src/globals/defines.php b/src/globals/defines.php index 71d6277b..36ffba79 100644 --- a/src/globals/defines.php +++ b/src/globals/defines.php @@ -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 diff --git a/tests/SPC/builder/BuilderTest.php b/tests/SPC/builder/BuilderTest.php index 4181b693..d28bd4d3 100644 --- a/tests/SPC/builder/BuilderTest.php +++ b/tests/SPC/builder/BuilderTest.php @@ -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'], ]; }