diff --git a/README-zh.md b/README-zh.md index e8aac2c3..da571330 100755 --- a/README-zh.md +++ b/README-zh.md @@ -28,9 +28,11 @@ Build single static PHP binary, with PHP project together, with popular extensio ## 自托管直接下载 -如果你不想自行编译 PHP,可以从本项目现有的示例 Action 下载 Artifact,也可以从自托管的服务器下载:[进入](https://dl.static-php.dev/static-php-cli/common/) +如果你不想自行编译 PHP,可以从本项目现有的示例 Action 下载 Artifact,也可以从自托管的服务器下载。 -> 自托管的服务器默认包含的扩展有:`bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip` +- [扩展组合 - common](https://dl.static-php.dev/static-php-cli/common/):common 组合包含了约 [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) 个常用扩展,体积为 22MB 左右。 +- [扩展组合 - bulk](https://dl.static-php.dev/static-php-cli/bulk/):bulk 组合包含了 [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) 个扩展,体积为 70MB 左右。 +- [扩展组合 - minimal](https://dl.static-php.dev/static-php-cli/minimal/):minimal 组合包含了 [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) 个扩展,体积为 6MB 左右。 ## 使用 static-php-cli 构建 PHP diff --git a/README.md b/README.md index cd714f70..970be43e 100755 --- a/README.md +++ b/README.md @@ -18,22 +18,26 @@ You can also use the micro binary file to combine php binary and php source code [![Version](https://img.shields.io/badge/Version-2.0--rc8-pink.svg?style=flat-square)]() [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]() -[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-linux-x86_64.yml?branch=refactor&label=Linux%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) -[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-macos-x86_64.yml?branch=refactor&label=macOS%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) +[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml) -[![](https://img.shields.io/badge/Extension%20Counter-65+-yellow.svg?style=flat-square)]() +[![](https://img.shields.io/badge/Extension%20Counter-65+-yellow.svg?style=flat-square)]([https://static-php.dev/](https://static-php.dev/en/guide/extensions.html)) [![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]() -## Docs +## Documentation The current README contains basic usage. For all the features of static-php-cli, see . ## Direct Download -If you don't want to compile yourself, you can download example pre-compiled artifact from [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-common.yml), or from [self-hosted server](https://dl.static-php.dev/static-php-cli/common/). +If you don't want to compile yourself, you can download example pre-compiled artifact from [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-common.yml), or from self-hosted server. -> self-hosted server contains extensions: `bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip` +Below are several precompiled static-php binaries with different extension combinations, +which can be downloaded directly according to your needs. + +- [Extension-Combination - common](https://dl.static-php.dev/static-php-cli/common/): `common` contains about [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) commonly used extensions, and the size is about 22MB. +- [Extension-Combination - bulk](https://dl.static-php.dev/static-php-cli/bulk/): `bulk` contains [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) extensions and is about 70MB in size. +- [Extension-Combination - minimal](https://dl.static-php.dev/static-php-cli/minimal/): `minimal` contains [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) extensions and is about 6MB in size. ## Use static-php-cli to build PHP @@ -135,7 +139,7 @@ Basic usage for building php and micro with some extensions: > If you are using the packaged `spc` binary, you need to replace `bin/spc` with `./spc` in the following commands. ```bash -# Check system tool dependencies, fix them automatically +# Check system tool dependencies, fix them if possible ./bin/spc doctor # fetch all libraries ./bin/spc download --all @@ -167,7 +171,7 @@ If anything goes wrong, use `--debug` option to display full terminal output: ./bin/spc fetch --all --debug ``` -In addition, we build NTS by default. If you are going to build ZTS version, just add `--enable-zts` option. +In addition, we build NTS (non-thread-safe) by default. If you are going to build ZTS version, just add `--enable-zts` option. ```bash ./bin/spc build openssl,pcntl --build-all --enable-zts @@ -228,7 +232,7 @@ cat buildroot/bin/micro.sfx my-app.phar > my-app && chmod +x my-app bin/spc micro:combine my-app.phar -I "memory_limit=4G" -I "disable_functions=system" --output my-app-2 ``` -> In some cases, PHAR files may not run in a micro environment. +> In some cases, PHAR files may not run in a micro environment. Overall, micro is not production ready. ### Use fpm @@ -236,7 +240,7 @@ When using the parameter `--build-all` or `--build-fpm`, the final compilation result will output a file named `./php-fpm`, This file will be located in the path `buildroot/bin/`, simply copy it out for use. -In normal Linux distributions and macOS systems, the package manager will automatically generate a default fpm configuration file after installing php-fpm. +In common Linux distributions and macOS systems, the package manager will automatically generate a default fpm configuration file after installing php-fpm. Because php-fpm must specify a configuration file before running, the php-fpm compiled by this project will not have any configuration files, so you need to write `php-fpm.conf` and `pool.conf` configuration files yourself. Specifying `php-fpm.conf` can use the command parameter `-y`, for example: `./php-fpm -y php-fpm.conf`. @@ -262,10 +266,6 @@ If you want to contribute documentation, please go to [static-php/static-php-cli Now there is a [static-php](https://github.com/static-php) organization, which is used to store the repo related to the project. -Part of the English document is written by me, and part is translated by Google, -and there may be inaccurate descriptions, strange or offensive expressions. -If you are a native English speaker, some corrections to the documentation are welcome. - ## Sponsor this project You can sponsor my project on [this page](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md). @@ -288,8 +288,3 @@ and they all have their own open source licenses. Please use the `bin/spc dump-license` command to export the open source licenses used in the project after compilation, and comply with the corresponding project's LICENSE. -## Advanced - -The refactoring branch of this project is written modularly. -If you are interested in this project and want to join the development, -you can refer to the [Contribution Guide](https://static-php.dev) of the documentation to contribute code or documentation. diff --git a/bin/setup-runtime b/bin/setup-runtime index b344bab5..b914c1ba 100755 --- a/bin/setup-runtime +++ b/bin/setup-runtime @@ -25,7 +25,7 @@ __DIR__=$(cd "$(dirname "$0")" && pwd) __PROJECT__=$(cd "${__DIR__}"/../ && pwd) # set download dir -__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/common/php-8.2.12-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz" +__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.2.13-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz" __COMPOSER_URL__="https://getcomposer.org/download/latest-stable/composer.phar" # use china mirror @@ -46,7 +46,7 @@ done case "$mirror" in china) - __PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/common/php-8.2.12-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz" + __PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.2.13-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz" __COMPOSER_URL__="https://mirrors.aliyun.com/composer/composer.phar" ;; diff --git a/bin/spc-alpine-docker b/bin/spc-alpine-docker index e807a2df..87e52968 100755 --- a/bin/spc-alpine-docker +++ b/bin/spc-alpine-docker @@ -73,6 +73,7 @@ RUN apk update; \ git \ jq \ libgcc \ + libtool \ libstdc++ \ linux-headers \ m4 \ diff --git a/config/ext.json b/config/ext.json index e38bacb6..26bb9e94 100644 --- a/config/ext.json +++ b/config/ext.json @@ -228,7 +228,8 @@ ] }, "opcache": { - "type": "builtin" + "type": "builtin", + "arg-type": "custom" }, "openssl": { "type": "builtin", @@ -241,6 +242,13 @@ "zlib" ] }, + "password-argon2": { + "type": "builtin", + "arg-type": "with-prefix", + "lib-depends": [ + "libargon2" + ] + }, "pcntl": { "type": "builtin", "unix-only": true @@ -383,6 +391,17 @@ "sqlite" ] }, + "sqlsrv": { + "type": "external", + "source": "sqlsrv", + "lib-depends": [ + "unixodbc" + ], + "cpp-extension": true, + "ext-depends-linux": [ + "pcntl" + ] + }, "ssh2": { "type": "external", "source": "ext-ssh2", diff --git a/config/lib.json b/config/lib.json index 7abff12c..73c5aee2 100644 --- a/config/lib.json +++ b/config/lib.json @@ -156,12 +156,19 @@ "liblber.a", "libldap.a" ], - "lib-suggests": [ + "lib-depends": [ "openssl", + "zlib", "gmp", "libsodium" ] }, + "libargon2": { + "source": "libargon2", + "static-libs-unix": [ + "libargon2.a" + ] + }, "libavif": { "source": "libavif", "static-libs-unix": [ @@ -489,6 +496,17 @@ "libtidy.a" ] }, + "unixodbc": { + "source": "unixodbc", + "static-libs-unix": [ + "libodbc.a", + "libodbccr.a", + "libodbcinst.a" + ], + "lib-depends": [ + "libiconv" + ] + }, "xz": { "source": "xz", "static-libs-unix": [ diff --git a/config/source.json b/config/source.json index 143e1874..276cb4bd 100644 --- a/config/source.json +++ b/config/source.json @@ -172,6 +172,15 @@ "path": "LICENSE" } }, + "libargon2": { + "type": "git", + "rev": "master", + "url": "https://github.com/mpociot/phc-winner-argon2", + "license": { + "type": "file", + "path": "LICENSE" + } + }, "libavif": { "type": "ghtar", "repo": "AOMediaCodec/libavif", @@ -376,9 +385,8 @@ } }, "pkg-config": { - "type": "filelist", - "url": "https://pkgconfig.freedesktop.org/releases/", - "regex": "/href=\"(?pkg-config-(?[^\"]+)\\.tar\\.gz)\"/", + "type": "url", + "url": "https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz", "license": { "type": "file", "path": "COPYING" @@ -386,7 +394,7 @@ }, "postgresql": { "type": "url", - "url": "https://ftp.postgresql.org/pub/source/v15.1/postgresql-15.1.tar.gz", + "url": "https://ftp.postgresql.org/pub/source/v16.1/postgresql-16.1.tar.gz", "license": { "type": "file", "path": "COPYRIGHT" @@ -449,6 +457,16 @@ "text": "The author disclaims copyright to this source code. In place of\na legal notice, here is a blessing:\n\n * May you do good and not evil.\n * May you find forgiveness for yourself and forgive others.\n * May you share freely, never taking more than you give." } }, + "sqlsrv": { + "type": "url", + "url": "https://pecl.php.net/get/sqlsrv", + "path": "php-src/ext/sqlsrv", + "filename": "sqlsrv.tgz", + "license": { + "type": "file", + "path": "LICENSE" + } + }, "swoole": { "type": "ghtar", "path": "php-src/ext/swoole", @@ -478,6 +496,14 @@ "path": "README/LICENSE.md" } }, + "unixodbc": { + "type": "url", + "url": "https://www.unixodbc.org/unixODBC-2.3.12.tar.gz", + "license": { + "type": "file", + "path": "COPYING" + } + }, "xlswriter": { "type": "url", "url": "https://pecl.php.net/get/xlswriter", diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php index 2de132e0..73b354be 100644 --- a/src/SPC/ConsoleApplication.php +++ b/src/SPC/ConsoleApplication.php @@ -23,7 +23,7 @@ use Symfony\Component\Console\Command\ListCommand; */ final class ConsoleApplication extends Application { - public const VERSION = '2.0.0-rc8'; + public const VERSION = '2.0.0-rc9'; public function __construct() { diff --git a/src/SPC/builder/BuilderBase.php b/src/SPC/builder/BuilderBase.php index d214b859..72db5961 100644 --- a/src/SPC/builder/BuilderBase.php +++ b/src/SPC/builder/BuilderBase.php @@ -259,6 +259,19 @@ abstract class BuilderBase throw new RuntimeException('PHP version file format is malformed, please remove it and download again'); } + public function getPHPVersion(): string + { + if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) { + throw new WrongUsageException('PHP source files are not available, you need to download them first'); + } + $file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h'); + if (preg_match('/PHP_VERSION "(.*)"/', $file, $match) !== 0) { + return $match[1]; + } + + throw new RuntimeException('PHP version file format is malformed, please remove it and download again'); + } + /** * Get build type name string to display. * diff --git a/src/SPC/builder/extension/mongodb.php b/src/SPC/builder/extension/mongodb.php index 2096de05..e6f12d54 100644 --- a/src/SPC/builder/extension/mongodb.php +++ b/src/SPC/builder/extension/mongodb.php @@ -5,11 +5,20 @@ declare(strict_types=1); namespace SPC\builder\extension; use SPC\builder\Extension; +use SPC\store\FileSystem; use SPC\util\CustomExt; #[CustomExt('mongodb')] class mongodb extends Extension { + public function patchBeforeBuildconf(): bool + { + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/mongodb/config.m4', 'if test -z "$PHP_CONFIG"; then', 'if false; then'); + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/mongodb/config.m4', 'PHP_MONGODB_PHP_VERSION=`${PHP_CONFIG} --version`', 'PHP_MONGODB_PHP_VERSION=' . $this->builder->getPHPVersion()); + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/mongodb/config.m4', 'PHP_MONGODB_PHP_VERSION_ID=`${PHP_CONFIG} --vernum`', 'PHP_MONGODB_PHP_VERSION_ID=' . $this->builder->getPHPVersionID()); + return true; + } + public function getUnixConfigureArg(): string { $arg = ' --enable-mongodb '; diff --git a/src/SPC/builder/extension/opcache.php b/src/SPC/builder/extension/opcache.php index f592303a..82efc853 100644 --- a/src/SPC/builder/extension/opcache.php +++ b/src/SPC/builder/extension/opcache.php @@ -5,11 +5,25 @@ declare(strict_types=1); namespace SPC\builder\extension; use SPC\builder\Extension; +use SPC\exception\RuntimeException; +use SPC\exception\WrongUsageException; use SPC\util\CustomExt; #[CustomExt('opcache')] class opcache extends Extension { + /** + * @throws WrongUsageException + * @throws RuntimeException + */ + public function getUnixConfigureArg(): string + { + if ($this->builder->getPHPVersionID() < 80000) { + throw new WrongUsageException('Statically compiled PHP with Zend Opcache only available for PHP >= 8.0 !'); + } + return '--enable-opcache'; + } + public function getDistName(): string { return 'Zend Opcache'; diff --git a/src/SPC/builder/extension/password_argon2.php b/src/SPC/builder/extension/password_argon2.php new file mode 100644 index 00000000..fb3c4b04 --- /dev/null +++ b/src/SPC/builder/extension/password_argon2.php @@ -0,0 +1,21 @@ +execWithResult(BUILD_ROOT_PATH . '/bin/php -r "assert(defined(\'PASSWORD_ARGON2I\'));"'); + if ($ret !== 0) { + throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check'); + } + } +} diff --git a/src/SPC/builder/extension/swoole.php b/src/SPC/builder/extension/swoole.php index a9c1199f..3dd570a1 100644 --- a/src/SPC/builder/extension/swoole.php +++ b/src/SPC/builder/extension/swoole.php @@ -17,7 +17,8 @@ class swoole extends Extension $arg .= ' --disable-swoole-pgsql'; $arg .= $this->builder->getLib('openssl') ? ' --enable-openssl' : ' --disable-openssl --without-openssl'; $arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : ' --disable-brotli'; - $arg .= $this->builder->getExt('curl') ? ' --enable-swoole-curl' : ' --disable-swoole-curl'; + // swoole curl hook is buggy for php 8.0 + $arg .= $this->builder->getExt('curl') && $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl'; return $arg; } } diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index da7f793d..a757c661 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -144,6 +144,7 @@ class LinuxBuilder extends BuilderBase // prepare build php envs $envs_build_php = SystemUtil::makeEnvVarString([ 'CFLAGS' => $cflags, + 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, 'LIBS' => '-ldl -lpthread', ]); diff --git a/src/SPC/builder/linux/library/libargon2.php b/src/SPC/builder/linux/library/libargon2.php new file mode 100644 index 00000000..ca4a72ac --- /dev/null +++ b/src/SPC/builder/linux/library/libargon2.php @@ -0,0 +1,25 @@ +builder->getLib('libsodium') !== null) { + throw new WrongUsageException('libargon2 (required by password-argon2) conflicts with the libsodium library !'); + } + FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'LIBRARY_REL ?= lib/x86_64-linux-gnu', 'LIBRARY_REL ?= lib'); + return true; + } +} diff --git a/src/SPC/builder/linux/library/unixodbc.php b/src/SPC/builder/linux/library/unixodbc.php new file mode 100644 index 00000000..0741d264 --- /dev/null +++ b/src/SPC/builder/linux/library/unixodbc.php @@ -0,0 +1,12 @@ +arch_c_flags} -Werror=unknown-warning-option' " . + "CPPFLAGS='-I" . BUILD_INCLUDE_PATH . "' " . '--disable-all ' . '--disable-cgi ' . '--disable-phpdbg ' . diff --git a/src/SPC/builder/macos/library/libargon2.php b/src/SPC/builder/macos/library/libargon2.php new file mode 100644 index 00000000..f39afa4f --- /dev/null +++ b/src/SPC/builder/macos/library/libargon2.php @@ -0,0 +1,12 @@ +builder->getLib('gmp') ? '--with-mp=gmp ' : ''; // libsodium support $alt .= $this->builder->getLib('libsodium') ? '--with-argon2=libsodium ' : ''; + f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config'); + f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); shell()->cd($this->source_dir) ->exec( $this->builder->makeAutoconfFlags(AUTOCONF_LDFLAGS | AUTOCONF_CPPFLAGS) . diff --git a/src/SPC/builder/unix/library/libargon2.php b/src/SPC/builder/unix/library/libargon2.php new file mode 100644 index 00000000..222e8b43 --- /dev/null +++ b/src/SPC/builder/unix/library/libargon2.php @@ -0,0 +1,26 @@ +cd($this->source_dir) + ->exec("make PREFIX='' clean") + ->exec("make -j{$this->builder->concurrency} PREFIX=''") + ->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH); + + $this->patchPkgconfPrefix(['libargon2.pc']); + + foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { + if (str_starts_with($filename, 'libargon2') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) { + unlink(BUILD_ROOT_PATH . '/lib/' . $filename); + } + } + } +} diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php index 5769c106..2448f656 100644 --- a/src/SPC/builder/unix/library/postgresql.php +++ b/src/SPC/builder/unix/library/postgresql.php @@ -20,16 +20,22 @@ trait postgresql { $builddir = BUILD_ROOT_PATH; $envs = ''; - $packages = 'openssl zlib readline libxml-2.0 zlib'; + $packages = 'zlib openssl readline libxml-2.0'; $optional_packages = [ 'zstd' => 'libzstd', - 'ldap' => 'ldap', + // 'ldap' => 'ldap', 'libxslt' => 'libxslt', 'icu' => 'icu-i18n', ]; + + f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config'); + f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); + foreach ($optional_packages as $lib => $pkg) { if ($this->getBuilder()->getLib($lib)) { $packages .= ' ' . $pkg; + $output = shell()->execWithResult("pkg-config --static {$pkg}"); + logger()->info(var_export($output[1], true)); } } @@ -58,8 +64,8 @@ trait postgresql # 有静态链接配置 参考文件: src/interfaces/libpq/Makefile shell()->cd($this->source_dir . '/build') ->exec('sed -i.backup "s/invokes exit\'; exit 1;/invokes exit\';/" ../src/interfaces/libpq/Makefile') - ->exec('sed -i.backup "293 s/^/#$/" ../src/Makefile.shlib') - ->exec('sed -i.backup "441 s/^/#$/" ../src/Makefile.shlib'); + ->exec('sed -i.backup "278 s/^/# /" ../src/Makefile.shlib') + ->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib'); // configure shell()->cd($this->source_dir . '/build') @@ -72,7 +78,7 @@ trait postgresql '--with-readline ' . '--with-libxml ' . ($this->builder->getLib('icu') ? '--with-icu ' : '--without-icu ') . - ($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') . + '--without-ldap ' . ($this->builder->getLib('libxslt') ? '--with-libxslt ' : '--without-libxslt ') . ($this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ') . '--without-lz4 ' . @@ -82,15 +88,14 @@ trait postgresql '--without-bonjour ' . '--without-tcl ' ); + // ($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') . // build shell()->cd($this->source_dir . '/build') ->exec($envs . ' make -C src/bin/pg_config install') ->exec($envs . ' make -C src/include install') ->exec($envs . ' make -C src/common install') - ->exec($envs . ' make -C src/backend/port install') ->exec($envs . ' make -C src/port install') - ->exec($envs . ' make -C src/backend/libpq install') ->exec($envs . ' make -C src/interfaces/libpq install'); // remove dynamic libs diff --git a/src/SPC/builder/unix/library/unixodbc.php b/src/SPC/builder/unix/library/unixodbc.php new file mode 100644 index 00000000..f89eb0a4 --- /dev/null +++ b/src/SPC/builder/unix/library/unixodbc.php @@ -0,0 +1,35 @@ +cd($this->source_dir) + ->exec( + './configure ' . + '--enable-static --disable-shared ' . + '--disable-debug ' . + '--disable-dependency-tracking ' . + '--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' . + '--with-included-ltdl ' . + '--enable-gui=no ' . + '--prefix=' + ) + ->exec('make clean') + ->exec("make -j{$this->builder->concurrency}") + ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + $this->patchPkgconfPrefix(['odbc.pc', 'odbccr.pc', 'odbcinst.pc']); + $this->cleanLaFiles(); + } +} diff --git a/src/SPC/command/BuildCliCommand.php b/src/SPC/command/BuildCliCommand.php index 72235847..5bd0bba3 100644 --- a/src/SPC/command/BuildCliCommand.php +++ b/src/SPC/command/BuildCliCommand.php @@ -16,7 +16,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use ZM\Logger\ConsoleColor; -#[AsCommand('build', 'build CLI binary')] +#[AsCommand('build', 'build PHP')] class BuildCliCommand extends BuildCommand { public function configure(): void @@ -33,6 +33,8 @@ class BuildCliCommand extends BuildCommand $this->addOption('disable-opcache-jit', null, null, 'disable opcache jit'); $this->addOption('with-hardcoded-ini', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Patch PHP source code, inject hardcoded INI'); $this->addOption('with-micro-fake-cli', null, null, 'Enable phpmicro fake cli'); + $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'); } public function handle(): int @@ -42,12 +44,9 @@ class BuildCliCommand extends BuildCommand // transform string to array $extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions')))); - $rule = BUILD_TARGET_NONE; - $rule |= ($this->getOption('build-cli') ? BUILD_TARGET_CLI : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-micro') ? BUILD_TARGET_MICRO : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-fpm') ? BUILD_TARGET_FPM : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-embed') ? BUILD_TARGET_EMBED : BUILD_TARGET_NONE); - $rule |= ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE); + // parse rule with options + $rule = $this->parseRules(); + if ($rule === BUILD_TARGET_NONE) { $this->output->writeln('Please add at least one build target!'); $this->output->writeln("\t--build-cli\tBuild php-cli SAPI"); @@ -62,16 +61,27 @@ class BuildCliCommand extends BuildCommand $builder = BuilderProvider::makeBuilderByInput($this->input); // calculate dependencies [$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions, $libraries); - /* @phpstan-ignore-next-line */ - logger()->info('Build target: ' . ConsoleColor::yellow($builder->getBuildTypeName($rule))); - /* @phpstan-ignore-next-line */ - logger()->info('Enabled extensions: ' . ConsoleColor::yellow(implode(', ', $extensions))); - /* @phpstan-ignore-next-line */ - logger()->info('Required libraries: ' . ConsoleColor::yellow(implode(', ', $libraries))); - if (!empty($not_included)) { - logger()->warning('some extensions will be enabled due to dependencies: ' . implode(',', $not_included)); + + // print info + $indent_texts = [ + 'Build OS' => PHP_OS_FAMILY . ' (' . php_uname('m') . ')', + 'Build SAPI' => $builder->getBuildTypeName($rule), + 'Extensions (' . count($extensions) . ')' => implode(', ', $extensions), + 'Libraries (' . count($libraries) . ')' => implode(', ', $libraries), + 'Strip Binaries' => $builder->getOption('no-strip') ? 'no' : 'yes', + 'Enable ZTS' => $builder->getOption('enable-zts') ? 'yes' : 'no', + ]; + if (!empty($this->input->getOption('with-hardcoded-ini'))) { + $indent_texts['Hardcoded INI'] = $this->input->getOption('with-hardcoded-ini'); } + $this->printFormatInfo($indent_texts); + + if (!empty($not_included)) { + logger()->warning('Some extensions will be enabled due to dependencies: ' . implode(',', $not_included)); + } + logger()->info('Build will start after 2s ...'); sleep(2); + if ($this->input->getOption('with-clean')) { logger()->info('Cleaning source dir...'); FileSystem::removeDir(SOURCE_PATH); @@ -140,4 +150,41 @@ class BuildCliCommand extends BuildCommand return static::FAILURE; } } + + /** + * Parse build options to rule int. + */ + private function parseRules(): int + { + $rule = BUILD_TARGET_NONE; + $rule |= ($this->getOption('build-cli') ? BUILD_TARGET_CLI : BUILD_TARGET_NONE); + $rule |= ($this->getOption('build-micro') ? BUILD_TARGET_MICRO : BUILD_TARGET_NONE); + $rule |= ($this->getOption('build-fpm') ? BUILD_TARGET_FPM : BUILD_TARGET_NONE); + $rule |= ($this->getOption('build-embed') ? BUILD_TARGET_EMBED : BUILD_TARGET_NONE); + $rule |= ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE); + return $rule; + } + + private function printFormatInfo(array $indent_texts): void + { + // calculate space count for every line + $maxlen = 0; + foreach ($indent_texts as $k => $v) { + $maxlen = max(strlen($k), $maxlen); + } + foreach ($indent_texts as $k => $v) { + if (is_string($v)) { + /* @phpstan-ignore-next-line */ + logger()->info($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow($v)); + } elseif (is_array($v) && !is_assoc_array($v)) { + $first = array_shift($v); + /* @phpstan-ignore-next-line */ + logger()->info($k . ': ' . str_pad('', $maxlen - strlen($k)) . ConsoleColor::yellow($first)); + foreach ($v as $vs) { + /* @phpstan-ignore-next-line */ + logger()->info(str_pad('', $maxlen + 2) . ConsoleColor::yellow($vs)); + } + } + } + } } diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php index 33aa0639..01df03d6 100644 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ b/src/SPC/doctor/item/LinuxToolCheckList.php @@ -21,6 +21,7 @@ class LinuxToolCheckList 'tar', 'unzip', 'gzip', 'bzip2', 'cmake', 'gcc', 'g++', 'patch', 'binutils-gold', + 'libtoolize', ]; public const TOOLS_DEBIAN = [ @@ -102,7 +103,8 @@ class LinuxToolCheckList try { $is_debian = in_array($distro['dist'], ['debian', 'ubuntu']); $to_install = $is_debian ? str_replace('xz', 'xz-utils', $missing) : $missing; - $to_install = $is_debian ? str_replace('libtoolize', 'libtool', $to_install) : $to_install; + // debian, alpine libtool -> libtoolize + $to_install = str_replace('libtoolize', 'libtool', $to_install); shell(true)->exec($prefix . $install_cmd . ' ' . implode(' ', $to_install)); } catch (RuntimeException) { return false; diff --git a/src/SPC/doctor/item/MacOSToolCheckList.php b/src/SPC/doctor/item/MacOSToolCheckList.php index df1e6ed4..9f43e8fb 100644 --- a/src/SPC/doctor/item/MacOSToolCheckList.php +++ b/src/SPC/doctor/item/MacOSToolCheckList.php @@ -25,6 +25,7 @@ class MacOSToolCheckList 'autoconf', 'automake', 'tar', + 'libtool', 'unzip', 'xz', 'gzip', diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index b0edc303..426f978a 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -134,6 +134,12 @@ class SourcePatcher $patch_file = ROOT_DIR . "/src/globals/patch/{$patch_name}"; $patch_str = str_replace('/', DIRECTORY_SEPARATOR, $patch_file); + // copy patch from phar + if (\Phar::running() !== '') { + file_put_contents(SOURCE_PATH . '/' . $patch_name, file_get_contents($patch_file)); + $patch_str = str_replace('/', DIRECTORY_SEPARATOR, SOURCE_PATH . '/' . $patch_name); + } + f_passthru( 'cd ' . $cwd . ' && ' . (PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . $patch_str . ' | patch -p1 ' . ($reverse ? '-R' : '') diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index b1c96f55..ce05d33e 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -3,6 +3,10 @@ declare(strict_types=1); # If you want to test new extensions here, just modify it. -$extensions = 'apcu,bcmath,calendar,ctype,curl,dba,dom,exif,filter,fileinfo,gd,iconv,intl,mbstring,mbregex,mysqli,mysqlnd,openssl,opcache,pcntl,pdo,pdo_mysql,pdo_sqlite,pdo_pgsql,pgsql,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib,bz2,event,gmp,imagick,imap,ldap,protobuf,shmop,snappy,soap,swoole,sysvmsg,sysvsem,sysvshm,tidy,zstd'; +$extensions = 'sqlsrv,apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,event,exif,fileinfo,filter,ftp,gd,gmp,iconv,imagick,imap,intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sqlite3,swoole,sysvmsg,sysvsem,sysvshm,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib'; + +if (PHP_OS_FAMILY === 'Darwin') { + $extensions .= ',sodium'; +} echo $extensions;