From 4ea1d95802821de6e4f6df937b4b54dc568f9cb0 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:06:47 +0800 Subject: [PATCH 01/11] Add embed spc-config output instead of php-config --- src/SPC/util/SPCConfigUtil.php | 104 +++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/SPC/util/SPCConfigUtil.php diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php new file mode 100644 index 00000000..1e60aa5a --- /dev/null +++ b/src/SPC/util/SPCConfigUtil.php @@ -0,0 +1,104 @@ +builder = BuilderProvider::makeBuilderByInput($input ?? new ArgvInput()); + } + } + + public function config(array $extensions = [], array $libraries = [], bool $include_suggest_ext = false, bool $include_suggest_lib = false): array + { + [$extensions, $libraries] = DependencyUtil::getExtsAndLibs($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); + + ob_start(); + $this->builder->proveLibs($libraries); + $this->builder->proveExts($extensions); + ob_get_clean(); + $ldflags = $this->getLdflagsString(); + $libs = $this->getLibsString($libraries); + $cflags = $this->getIncludesString(); + + // embed + $libs = '-lphp -lc ' . $libs; + $extra_env = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS'); + if (is_string($extra_env)) { + $libs .= ' ' . $extra_env; + } + // c++ + if ($this->builder->hasCpp()) { + $libs .= $this->builder instanceof MacOSBuilder ? ' -lc++' : ' -lstdc++'; + } + return [ + 'cflags' => $cflags, + 'ldflags' => $ldflags, + 'libs' => $libs, + ]; + } + + private function getIncludesString(): string + { + $base = BUILD_INCLUDE_PATH; + $php_embed_includes = [ + "-I{$base}", + "-I{$base}/php", + "-I{$base}/php/main", + "-I{$base}/php/TSRM", + "-I{$base}/php/Zend", + "-I{$base}/php/ext", + ]; + return implode(' ', $php_embed_includes); + } + + private function getLdflagsString(): string + { + return '-L' . BUILD_LIB_PATH; + } + + private function getLibsString(array $libraries): string + { + $short_name = []; + foreach (array_reverse($libraries) as $library) { + $libs = Config::getLib($library, 'static-libs', []); + foreach ($libs as $lib) { + $short_name[] = $this->getShortLibName($lib); + } + if (PHP_OS_FAMILY !== 'Darwin') { + continue; + } + foreach (Config::getLib($library, 'frameworks', []) as $fw) { + $ks = '-framework ' . $fw; + if (!in_array($ks, $short_name)) { + $short_name[] = $ks; + } + } + } + // patch: imagick (imagemagick wrapper) for linux needs -lgomp + if (in_array('imagemagick', $libraries) && PHP_OS_FAMILY === 'Linux') { + $short_name[] = '-lgomp'; + } + return implode(' ', $short_name); + } + + private function getShortLibName(string $lib): string + { + if (!str_starts_with($lib, 'lib') || !str_ends_with($lib, '.a')) { + return BUILD_LIB_PATH . '/' . $lib; + } + // get short name + return '-l' . substr($lib, 3, -2); + } +} From af9172aed80d3a12b7a82f844bba3926438665b5 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:08:01 +0800 Subject: [PATCH 02/11] Add embed sanity check --- src/SPC/builder/BuilderBase.php | 9 ++++++- src/SPC/builder/unix/UnixBuilderBase.php | 28 ++++++++++++++++++++++ src/SPC/builder/windows/WindowsBuilder.php | 1 + src/SPC/util/UnixShell.php | 3 +++ src/globals/common-tests/embed.c | 17 +++++++++++++ src/globals/common-tests/embed.php | 4 ++++ 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/globals/common-tests/embed.c create mode 100644 src/globals/common-tests/embed.php diff --git a/src/SPC/builder/BuilderBase.php b/src/SPC/builder/BuilderBase.php index b61a10e5..0456af8b 100644 --- a/src/SPC/builder/BuilderBase.php +++ b/src/SPC/builder/BuilderBase.php @@ -25,6 +25,12 @@ abstract class BuilderBase /** @var array extensions */ protected array $exts = []; + /** @var array extension names */ + protected array $ext_list = []; + + /** @var array library names */ + protected array $lib_list = []; + /** @var bool compile libs only (just mark it) */ protected bool $libs_only = false; @@ -161,7 +167,7 @@ public function setLibsOnly(bool $status = true): void * @throws FileSystemException * @throws RuntimeException * @throws \ReflectionException - * @throws WrongUsageException + * @throws \Throwable|WrongUsageException * @internal */ public function proveExts(array $extensions, bool $skip_check_deps = false): void @@ -191,6 +197,7 @@ public function proveExts(array $extensions, bool $skip_check_deps = false): voi foreach ($this->exts as $ext) { $ext->checkDependency(); } + $this->ext_list = $extensions; } /** diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 3ec21f06..347e1f16 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -12,6 +12,7 @@ use SPC\store\Config; use SPC\store\FileSystem; use SPC\util\DependencyUtil; +use SPC\util\SPCConfigUtil; abstract class UnixBuilderBase extends BuilderBase { @@ -128,6 +129,7 @@ public function proveLibs(array $sorted_libraries): void foreach ($this->libs as $lib) { $lib->calcDependency(); } + $this->lib_list = $sorted_libraries; } /** @@ -170,6 +172,32 @@ protected function sanityCheck(int $build_target): void } } } + + // sanity check for embed + if (($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) { + logger()->info('running embed sanity check'); + $sample_file_path = SOURCE_PATH . '/embed-test'; + if (!is_dir($sample_file_path)) { + @mkdir($sample_file_path); + } + // copy embed test files + copy(ROOT_DIR . '/src/globals/common-tests/embed.c', $sample_file_path . '/embed.c'); + copy(ROOT_DIR . '/src/globals/common-tests/embed.php', $sample_file_path . '/embed.php'); + $util = new SPCConfigUtil($this); + $config = $util->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); + $lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}"; + if (PHP_OS_FAMILY === 'Linux') { + $lens .= ' -static'; + } + [$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens); + if ($ret !== 0) { + throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out)); + } + [$ret, $output] = shell()->cd($sample_file_path)->execWithResult('./embed'); + if ($ret !== 0 || trim(implode('', $output)) !== 'hello') { + throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output)); + } + } } /** diff --git a/src/SPC/builder/windows/WindowsBuilder.php b/src/SPC/builder/windows/WindowsBuilder.php index bd391abb..46b8ac48 100644 --- a/src/SPC/builder/windows/WindowsBuilder.php +++ b/src/SPC/builder/windows/WindowsBuilder.php @@ -248,6 +248,7 @@ public function proveLibs(array $sorted_libraries): void foreach ($this->libs as $lib) { $lib->calcDependency(); } + $this->lib_list = $sorted_libraries; } /** diff --git a/src/SPC/util/UnixShell.php b/src/SPC/util/UnixShell.php index 16ae3f8c..44e97bfe 100644 --- a/src/SPC/util/UnixShell.php +++ b/src/SPC/util/UnixShell.php @@ -62,6 +62,9 @@ public function execWithResult(string $cmd, bool $with_log = true): array logger()->debug(ConsoleColor::blue('[EXEC] ') . ConsoleColor::gray($cmd)); } logger()->debug('Executed at: ' . debug_backtrace()[0]['file'] . ':' . debug_backtrace()[0]['line']); + if ($this->cd !== null) { + $cmd = 'cd ' . escapeshellarg($this->cd) . ' && ' . $cmd; + } exec($cmd, $out, $code); return [$code, $out]; } diff --git a/src/globals/common-tests/embed.c b/src/globals/common-tests/embed.c new file mode 100644 index 00000000..85c29921 --- /dev/null +++ b/src/globals/common-tests/embed.c @@ -0,0 +1,17 @@ +#include + +int main(int argc,char **argv){ + + PHP_EMBED_START_BLOCK(argc,argv) + + zend_file_handle file_handle; + + zend_stream_init_filename(&file_handle,"embed.php"); + + if(php_execute_script(&file_handle) == FAILURE){ + php_printf("Failed to execute PHP script.\n"); + } + + PHP_EMBED_END_BLOCK() + return 0; +} \ No newline at end of file diff --git a/src/globals/common-tests/embed.php b/src/globals/common-tests/embed.php new file mode 100644 index 00000000..aa1d7e41 --- /dev/null +++ b/src/globals/common-tests/embed.php @@ -0,0 +1,4 @@ + Date: Tue, 10 Dec 2024 23:08:11 +0800 Subject: [PATCH 03/11] Add spc-config command --- src/SPC/command/SPCConfigCommand.php | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/SPC/command/SPCConfigCommand.php diff --git a/src/SPC/command/SPCConfigCommand.php b/src/SPC/command/SPCConfigCommand.php new file mode 100644 index 00000000..0377ace9 --- /dev/null +++ b/src/SPC/command/SPCConfigCommand.php @@ -0,0 +1,53 @@ +addArgument('extensions', InputArgument::OPTIONAL, 'The extensions will be compiled, comma separated'); + $this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', ''); + $this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs'); + $this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts'); + $this->addOption('includes', null, null, 'Add additional include path'); + $this->addOption('libs', null, null, 'Add additional libs path'); + } + + /** + * @throws RuntimeException + */ + public function handle(): int + { + // transform string to array + $libraries = array_map('trim', array_filter(explode(',', $this->getOption('with-libs')))); + // transform string to array + $extensions = $this->getArgument('extensions') ? $this->parseExtensionList($this->getArgument('extensions')) : []; + $include_suggest_ext = $this->getOption('with-suggested-exts'); + $include_suggest_lib = $this->getOption('with-suggested-libs'); + + $util = new SPCConfigUtil(null, $this->input); + $config = $util->config($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); + + if ($this->getOption('includes')) { + $this->output->writeln($config['cflags']); + } elseif ($this->getOption('libs')) { + $this->output->writeln("{$config['ldflags']} {$config['libs']}"); + } else { + $this->output->writeln("{$config['cflags']} {$config['ldflags']} {$config['libs']}"); + } + + return 0; + } +} From abb3708208561ecc5cae88bbf567ecb588e4471d Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:08:23 +0800 Subject: [PATCH 04/11] Fix pgsql embed builds --- src/SPC/builder/extension/pgsql.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/SPC/builder/extension/pgsql.php b/src/SPC/builder/extension/pgsql.php index ff0c5a6e..d385554c 100644 --- a/src/SPC/builder/extension/pgsql.php +++ b/src/SPC/builder/extension/pgsql.php @@ -21,14 +21,6 @@ class pgsql extends Extension */ public function patchBeforeConfigure(): bool { - if ($this->builder->getPHPVersionID() >= 80400) { - FileSystem::replaceFileStr( - SOURCE_PATH . '/php-src/configure', - 'LIBS="-lpq', - 'LIBS="-lpq -lpgport -lpgcommon -lssl -lcrypto -lz -lm' - ); - return true; - } FileSystem::replaceFileRegex( SOURCE_PATH . '/php-src/configure', '/-lpq/', From c2ca11d0a6171096f17abec5273c464f01e03460 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:08:31 +0800 Subject: [PATCH 05/11] Fix gettext build --- src/SPC/builder/unix/library/gettext.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SPC/builder/unix/library/gettext.php b/src/SPC/builder/unix/library/gettext.php index 6a1995c4..e20dd4f6 100644 --- a/src/SPC/builder/unix/library/gettext.php +++ b/src/SPC/builder/unix/library/gettext.php @@ -19,6 +19,7 @@ protected function build(): void '--disable-java ' . '--disable-c+ ' . $extra . + '--with-included-gettext ' . '--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' . '--prefix=' . BUILD_ROOT_PATH ) From 9e53bb7530c61a0ccbf1921d0d6103bfd546a58f Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:08:49 +0800 Subject: [PATCH 06/11] Fix grpc redundant static lib --- config/lib.json | 1 - 1 file changed, 1 deletion(-) diff --git a/config/lib.json b/config/lib.json index 06b5cd2c..61334280 100644 --- a/config/lib.json +++ b/config/lib.json @@ -143,7 +143,6 @@ "source": "grpc", "static-libs-unix": [ "libgrpc.a", - "libboringssl.a", "libcares.a" ], "lib-depends": [ From e3206ce891116ad7908b891f51a2ed48c5198fc0 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:09:00 +0800 Subject: [PATCH 07/11] Add command, bump version --- src/SPC/ConsoleApplication.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php index cfebb831..1849a654 100644 --- a/src/SPC/ConsoleApplication.php +++ b/src/SPC/ConsoleApplication.php @@ -22,6 +22,7 @@ use SPC\command\ExtractCommand; use SPC\command\InstallPkgCommand; use SPC\command\MicroCombineCommand; +use SPC\command\SPCConfigCommand; use SPC\command\SwitchPhpVersionCommand; use Symfony\Component\Console\Application; @@ -30,7 +31,7 @@ */ final class ConsoleApplication extends Application { - public const VERSION = '2.4.1'; + public const VERSION = '2.4.2'; public function __construct() { @@ -52,6 +53,7 @@ public function __construct() new ExtractCommand(), new MicroCombineCommand(), new SwitchPhpVersionCommand(), + new SPCConfigCommand(), // Dev commands new AllExtCommand(), From 8469a553cb967ee1427becc1062f0804e099b342 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:09:21 +0800 Subject: [PATCH 08/11] Add embed build tests --- .github/workflows/tests.yml | 4 ++++ src/SPC/command/BuildCliCommand.php | 4 +++- src/globals/test-extensions.php | 18 ++++++++++++------ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6548fb88..fc91093c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -199,3 +199,7 @@ jobs: - name: "Run Build Tests (build)" run: php src/globals/test-extensions.php build_cmd ${{ matrix.os }} ${{ matrix.php }} + + - name: "Run Build Tests (build - embed for non-windows)" + if: matrix.os != 'windows-latest' + run: php src/globals/test-extensions.php build_embed_cmd ${{ matrix.os }} ${{ matrix.php }} diff --git a/src/SPC/command/BuildCliCommand.php b/src/SPC/command/BuildCliCommand.php index d8b7cf76..bc214760 100644 --- a/src/SPC/command/BuildCliCommand.php +++ b/src/SPC/command/BuildCliCommand.php @@ -181,7 +181,9 @@ public function handle(): int // compile stopwatch :P $time = round(microtime(true) - START_TIME, 3); - logger()->info('Build complete, used ' . $time . ' s !'); + logger()->info(''); + logger()->info(' Build complete, used ' . $time . ' s !'); + logger()->info(''); // ---------- When using bin/spc-alpine-docker, the build root path is different from the host system ---------- $build_root_path = BUILD_ROOT_PATH; diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index a08ebc7f..c7c661de 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -34,11 +34,11 @@ $upx = false; // prefer downloading pre-built packages to speed up the build process -$prefer_pre_built = false; +$prefer_pre_built = true; // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). $extensions = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'parallel', + 'Linux', 'Darwin' => 'apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,gmp,gettext,iconv,igbinary,imagick,intl,ldap,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,parallel,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,ssh2,sysvmsg,sysvsem,sysvshm,tidy,tokenizer,xlswriter,xml,xmlreader,xmlwriter,zip,zlib,yaml,zstd', 'Windows' => 'amqp,apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,ds,exif,ffi,fileinfo,filter,ftp,gd,iconv,igbinary,libxml,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pdo,pdo_mysql,pdo_sqlite,pdo_sqlsrv,phar,rar,redis,session,shmop,simdjson,simplexml,soap,sockets,sqlite3,sqlsrv,ssh2,swow,sysvshm,tokenizer,xml,xmlreader,xmlwriter,yac,yaml,zip,zlib', }; @@ -52,7 +52,7 @@ // You can use `common`, `bulk`, `minimal` or `none`. // note: combination is only available for *nix platform. Windows must use `none` combination $base_combination = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'minimal', + 'Linux', 'Darwin' => 'none', 'Windows' => 'none', }; @@ -121,7 +121,6 @@ function quote2(string $param): string $build_cmd .= $no_strip ? '--no-strip ' : ''; $build_cmd .= $upx ? '--with-upx-pack ' : ''; $build_cmd .= $final_libs === '' ? '' : ('--with-libs=' . quote2($final_libs) . ' '); - $build_cmd .= '--build-cli --build-micro '; $build_cmd .= str_starts_with($argv[2], 'windows-') ? '' : '--build-fpm '; $build_cmd .= '--debug '; } @@ -150,9 +149,16 @@ function quote2(string $param): string } } elseif ($argv[1] === 'build_cmd') { if (str_starts_with($argv[2], 'windows-')) { - passthru('powershell.exe -file .\bin\spc.ps1 ' . $build_cmd, $retcode); + passthru('powershell.exe -file .\bin\spc.ps1 ' . $build_cmd . ' --build-cli --build-micro', $retcode); } else { - passthru('./bin/spc ' . $build_cmd, $retcode); + passthru('./bin/spc ' . $build_cmd . ' --build-cli --build-micro', $retcode); + } +} elseif ($argv[1] === 'build_embed_cmd') { + if (str_starts_with($argv[2], 'windows-')) { + // windows does not accept embed SAPI + passthru('powershell.exe -file .\bin\spc.ps1 ' . $build_cmd . ' --build-cli', $retcode); + } else { + passthru('./bin/spc ' . $build_cmd . ' --build-embed', $retcode); } } From e0bb7d45f7667dbd79521204536b395bef962c89 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:39:13 +0800 Subject: [PATCH 09/11] Fix test --- src/globals/test-extensions.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index c7c661de..d7d81099 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -138,6 +138,7 @@ function quote2(string $param): string 'prefer_pre_built' => $prefer_pre_built ? '--prefer-pre-built' : '', 'download_cmd' => $down_cmd, 'build_cmd' => $build_cmd, + 'build_embed_cmd' => $build_cmd, default => '', }; From c42b98be58949fab35584c253c461d6b99614458 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 10 Dec 2024 23:55:33 +0800 Subject: [PATCH 10/11] Fix test --- src/globals/test-extensions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index d7d81099..8f0c32cc 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -114,7 +114,7 @@ function quote2(string $param): string } // generate build command -if ($argv[1] === 'build_cmd') { +if ($argv[1] === 'build_cmd' || $argv[1] === 'build_embed_cmd') { $build_cmd = 'build '; $build_cmd .= quote2($final_extensions) . ' '; $build_cmd .= $zts ? '--enable-zts ' : ''; From 2e56f441feb2a2d34c7972787a4985e5e693a214 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Fri, 13 Dec 2024 14:37:27 +0800 Subject: [PATCH 11/11] Addd embed docs --- docs/en/guide/manual-build.md | 73 +++++++++++++++++++++++++++++++++++ docs/zh/guide/manual-build.md | 72 ++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) diff --git a/docs/en/guide/manual-build.md b/docs/en/guide/manual-build.md index 74d75118..a0b02b08 100644 --- a/docs/en/guide/manual-build.md +++ b/docs/en/guide/manual-build.md @@ -553,3 +553,76 @@ If you need to build multiple times locally, the following method can save you t - If you want to rebuild once, but do not re-download the source code, you can first `rm -rf buildroot source` to delete the compilation directory and source code directory, and then rebuild. - If you want to update a version of a dependency, you can use `bin/spc del-download ` to delete the specified source code, and then use `download ` to download it again. - If you want to update all dependent versions, you can use `bin/spc download --clean` to delete all downloaded sources, and then download them again. + +## embed usage + +If you want to embed static-php into other C language programs, you can use `--build-embed` to build an embed version of PHP. + +```bash +bin/spc build {your extensions} --build-embed --debug +``` + +Under normal circumstances, PHP embed will generate `php-config` after compilation. +For static-php, we provide `spc-config` to obtain the parameters during compilation. +In addition, when using embed SAPI (libphp.a), you need to use the same compiler as libphp, otherwise there will be a link error. + +Here is the basic usage of spc-config: + +```bash +# output all flags and options +bin/spc spc-config curl,zlib,phar,openssl + +# output libs +bin/spc spc-config curl,zlib,phar,openssl --libs + +# output includes +bin/spc spc-config curl,zlib,phar,openssl --includes +``` + +By default, static-php uses the following compilers on different systems: + +- macOS: `clang` +- Linux (Alpine Linux): `gcc` +- Linux (glibc based distros, x86_64): `/usr/local/musl/bin/x86_64-linux-musl-gcc` +- Linux (glibc based distros, aarch64): `/usr/local/musl/bin/aarch64-linux-musl-gcc` +- FreeBSD: `clang` + +Here is an example of using embed SAPI: + +```c +// embed.c +#include + +int main(int argc,char **argv){ + + PHP_EMBED_START_BLOCK(argc,argv) + + zend_file_handle file_handle; + + zend_stream_init_filename(&file_handle,"embed.php"); + + if(php_execute_script(&file_handle) == FAILURE){ + php_printf("Failed to execute PHP script.\n"); + } + + PHP_EMBED_END_BLOCK() + return 0; +} +``` + + +```php +` 删除指定的源码,然后使用 `download ` 重新下载。 - 如果你想更新所有依赖的版本,可以使用 `bin/spc download --clean` 删除所有下载的源码,然后重新下载。 + +## embed 使用 + +如果你想将 static-php 嵌入到其他 C 语言程序中,可以使用 `--build-embed` 构建一个 embed 版本的 PHP。 + +```bash +bin/spc build {your extensions} --build-embed --debug +``` + +在通常的情况下,PHP embed 编译后会生成 `php-config`。对于 static-php,我们提供了 `spc-config`,用于获取编译时的参数。 +另外,在使用 embed SAPI(libphp.a)时,你需要使用和编译 libphp 相同的编译器,否则会出现链接错误。 + +下面是 spc-config 的基本用法: + +```bash +# output all flags and options +bin/spc spc-config curl,zlib,phar,openssl + +# output libs +bin/spc spc-config curl,zlib,phar,openssl --libs + +# output includes +bin/spc spc-config curl,zlib,phar,openssl --includes +``` + +默认情况下,static-php 在不同系统使用的编译器分别是: + +- macOS: `clang` +- Linux (Alpine Linux): `gcc` +- Linux (glibc based distros, x86_64): `/usr/local/musl/bin/x86_64-linux-musl-gcc` +- Linux (glibc based distros, aarch64): `/usr/local/musl/bin/aarch64-linux-musl-gcc` +- FreeBSD: `clang` + +下面是一个使用 embed SAPI 的例子: + +```c +// embed.c +#include + +int main(int argc,char **argv){ + + PHP_EMBED_START_BLOCK(argc,argv) + + zend_file_handle file_handle; + + zend_stream_init_filename(&file_handle,"embed.php"); + + if(php_execute_script(&file_handle) == FAILURE){ + php_printf("Failed to execute PHP script.\n"); + } + + PHP_EMBED_END_BLOCK() + return 0; +} +``` + + +```php +