Merge branch 'refactor' into feature_ext_mongodb

This commit is contained in:
jingjingxyk 2023-05-24 12:31:12 +08:00
commit 56b5c1b138
43 changed files with 528 additions and 83 deletions

View File

@ -114,3 +114,9 @@ jobs:
path: |
buildroot/build-extensions.json
buildroot/build-libraries.json
# Upload downloaded files
- uses: actions/upload-artifact@v3
with:
name: download-files
path: downloads/

View File

@ -114,3 +114,9 @@ jobs:
path: |
buildroot/build-extensions.json
buildroot/build-libraries.json
# Upload downloaded files
- uses: actions/upload-artifact@v3
with:
name: download-files
path: downloads/

View File

@ -11,14 +11,12 @@ This feature is provided by [dixyes/phpmicro](https://github.com/dixyes/phpmicro
<img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
> This branch is new version, if you are looking for old bash version of static-php-cli, see [bash-version](https://github.com/crazywhalecc/static-php-cli/tree/bash-version).
[![Version](https://img.shields.io/badge/Version-2.0--beta3-orange.svg?style=flat-square)]()
[![Version](https://img.shields.io/badge/Version-2.0--rc1-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/badge/Extension%20Counter-45+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/badge/Extension%20Counter-50+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]()
## Compilation Requirements
@ -129,6 +127,14 @@ 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.
```bash
./bin/spc build openssl,pcntl --build-all --enable-zts
```
Adding option `--no-strip` can produce binaries with debug symbols, in order to debug (using gdb). Disabling strip will increase the size of static binary.
### php-cli Usage
> php-cli is a single static binary, you can use it like normal php installed on your system.

View File

@ -12,13 +12,11 @@ If you are using English, see [English README](README-en.md).
<img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
> 此分支为重构的新版,如果你在找纯 Bash 编写的旧版本,请到 [bash-version 分支](https://github.com/crazywhalecc/static-php-cli/tree/bash-version)。
[![Version](https://img.shields.io/badge/Version-2.0--beta3-orange.svg?style=flat-square)]()
[![Version](https://img.shields.io/badge/Version-2.0--rc1-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/badge/Extension%20Counter-45+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/badge/Extension%20Counter-50+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]()
## 编译环境需求
@ -125,6 +123,14 @@ chmod +x bin/spc
./bin/spc fetch --all --debug
```
此外,默认编译的 PHP 为 NTS 版本。如需编译线程安全版本ZTS只需添加参数 `--enable-zts` 即可。
```bash
./bin/spc build openssl,pcntl --build-all --enable-zts
```
同时,你也可以使用参数 `--no-strip` 来关闭裁剪,关闭裁剪后可以使用 gdb 等工具调试,但这样会让静态二进制体积变大。
### 使用 php-cli
> php-cli 是一个静态的二进制文件,类似 Go、Rust 语言编译后的单个可移植的二进制文件。

View File

@ -25,7 +25,7 @@ __DIR__=$(cd "$(dirname "$0")" && pwd)
__PROJECT__=$(cd ${__DIR__}/../ && pwd)
# set download dir
__PHP_RUNTIME_URL__="https://dl.zhamao.xin/static-php-cli/php-8.2.5-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__PHP_RUNTIME_URL__="https://dl.zhamao.xin/static-php-cli/php-8.2.6-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.zhamao.xin/static-php-cli/php-8.2.5-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__PHP_RUNTIME_URL__="https://dl.zhamao.xin/static-php-cli/php-8.2.6-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__COMPOSER_URL__="https://mirrors.aliyun.com/composer/composer.phar"
;;

View File

@ -1,4 +1,8 @@
{
"apcu": {
"type": "external",
"source": "apcu"
},
"bcmath": {
"type": "builtin"
},
@ -35,10 +39,6 @@
"zlib"
]
},
"apcu": {
"type": "external",
"source": "apcu"
},
"event": {
"type": "external",
"source": "ext-event",
@ -114,6 +114,14 @@
"libiconv"
]
},
"imagick": {
"type": "external",
"source": "ext-imagick",
"arg-type": "custom",
"lib-depends": [
"imagemagick"
]
},
"imap": {
"type": "builtin",
"arg-type": "with",
@ -288,7 +296,7 @@
"type": "builtin",
"arg-type": "with",
"lib-depends": [
"sodium"
"libsodium"
]
},
"sqlite3": {
@ -298,6 +306,14 @@
"sqlite"
]
},
"ssh2": {
"type": "external",
"source": "ext-ssh2",
"arg-type": "with-prefix",
"lib-depends": [
"libssh2"
]
},
"swoole": {
"type": "external",
"source": "swoole",

View File

@ -15,21 +15,6 @@
"brotli"
]
},
"ncurses": {
"source": "ncurses",
"static-libs-unix": [
"libncurses.a"
]
},
"readline": {
"source": "readline",
"static-libs-unix": [
"libreadline.a"
],
"lib-depends": [
"ncurses"
]
},
"bzip2": {
"source": "bzip2",
"static-libs-unix": [
@ -111,6 +96,28 @@
"gmp.h"
]
},
"imagemagick": {
"source": "imagemagick",
"static-libs-unix": [
"libMagick++-7.Q16HDRI.a",
"libMagickCore-7.Q16HDRI.a",
"libMagickWand-7.Q16HDRI.a"
],
"lib-depends": [
"zlib",
"libpng",
"libjpeg",
"bzip2",
"libwebp",
"freetype"
],
"lib-suggests": [
"zstd",
"xz",
"libzip",
"libxml2"
]
},
"libavif": {
"source": "libavif",
"static-libs-unix": [
@ -294,6 +301,12 @@
"libmcrypt.a"
]
},
"ncurses": {
"source": "ncurses",
"static-libs-unix": [
"libncurses.a"
]
},
"nghttp2": {
"source": "nghttp2",
"static-libs-unix": [
@ -346,6 +359,9 @@
"zlib"
]
},
"pkg-config": {
"source": "pkg-config"
},
"postgresql": {
"source": "postgresql",
"static-libs-unix": [
@ -364,6 +380,15 @@
"semaphore.h"
]
},
"readline": {
"source": "readline",
"static-libs-unix": [
"libreadline.a"
],
"lib-depends": [
"ncurses"
]
},
"sqlite": {
"source": "sqlite",
"static-libs-unix": [
@ -429,5 +454,11 @@
"zstd.h",
"zstd_errors.h"
]
},
"libsodium": {
"source": "libsodium",
"static-libs-unix": [
"libsodium.a"
]
}
}

View File

@ -6,6 +6,16 @@
"path": "LICENSE"
}
},
"apcu": {
"type": "url",
"url": "http://pecl.php.net/get/APCu",
"path": "php-src/ext/apcu",
"filename": "apcu.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"brotli": {
"type": "ghtar",
"repo": "google/brotli",
@ -41,22 +51,24 @@
"path": "LICENSE"
}
},
"ncurses": {
"type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/ncurses/",
"regex": "/href=\"(?<file>ncurses-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"ext-imagick": {
"type": "url",
"url": "https://pecl.php.net/get/imagick",
"path": "php-src/ext/imagick",
"filename": "imagick.tgz",
"license": {
"type": "file",
"path": "COPYING"
"path": "LICENSE"
}
},
"readline": {
"type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/readline/",
"regex": "/href=\"(?<file>readline-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"ext-ssh2": {
"type": "url",
"url": "http://pecl.php.net/get/ssh2",
"path": "php-src/ext/ssh2",
"filename": "ssh2.tgz",
"license": {
"type": "file",
"path": "COPYING"
"path": "LICENSE"
}
},
"ext-zstd": {
@ -87,6 +99,14 @@
"text": "Since version 6, GMP is distributed under the dual licenses, GNU LGPL v3 and GNU GPL v2. These licenses make the library free to use, share, and improve, and allow you to pass on the result. The GNU licenses give freedoms, but also set firm restrictions on the use with non-free programs."
}
},
"imagemagick": {
"type": "ghtar",
"repo": "ImageMagick/ImageMagick",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"inotify": {
"type": "url",
"url": "http://pecl.php.net/get/inotify",
@ -209,16 +229,6 @@
"path": "LICENSE"
}
},
"apcu": {
"type": "url",
"url": "http://pecl.php.net/get/APCu",
"path": "php-src/ext/apcu",
"filename": "apcu.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"mcrypt": {
"type": "url",
"url": "https://jaist.dl.sourceforge.net/project/mcrypt/MCrypt/2.6.8/mcrypt-2.6.8.tar.gz",
@ -247,6 +257,15 @@
"path": "LICENSE"
}
},
"ncurses": {
"type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/ncurses/",
"regex": "/href=\"(?<file>ncurses-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "file",
"path": "COPYING"
}
},
"nghttp2": {
"type": "ghrel",
"repo": "nghttp2/nghttp2",
@ -274,6 +293,15 @@
"path": "LICENSE.txt"
}
},
"pkg-config": {
"type": "filelist",
"url": "https://pkgconfig.freedesktop.org/releases/",
"regex": "/href=\"(?<file>pkg-config-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "file",
"path": "COPYING"
}
},
"postgresql": {
"type": "custom",
"license": {
@ -300,6 +328,15 @@
"path": "LICENSE"
}
},
"readline": {
"type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/readline/",
"regex": "/href=\"(?<file>readline-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "file",
"path": "COPYING"
}
},
"redis": {
"type": "git",
"path": "php-src/ext/redis",
@ -374,5 +411,13 @@
"type": "file",
"path": "LICENSE"
}
},
"libsodium": {
"type": "url",
"url": "https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz",
"license": {
"type": "file",
"path": "LICENSE"
}
}
}

View File

@ -19,6 +19,7 @@
| enchant | | | |
| event | yes | yes | |
| exif | yes | yes | |
| ffi | | yes, [docs]() | |
| filter | yes | yes | |
| fileinfo | yes | yes | |
| ftp | yes | yes | |
@ -26,6 +27,7 @@
| gettext | | | |
| gmp | yes | yes | |
| iconv | yes | yes | |
| imagick | yes | yes | |
| inotify | yes | yes | |
| mbstring | yes | yes | |
| mbregex | yes | yes | |
@ -49,14 +51,16 @@
| simplexml | yes | yes | |
| soap | yes | yes | |
| sockets | yes | yes | |
| sodium | yes | yes | |
| sqlite3 | yes | yes | |
| ssh2 | yes, untested | yes, untested | |
| swow | yes | yes | |
| swoole | [partial](https://github.com/crazywhalecc/static-php-cli/issues/51) | yes | |
| tokenizer | yes | yes | |
| xml | yes | yes | |
| xmlreader | yes, untested | yes, untested | |
| xmlwriter | yes, untested | yes, untested | |
| zip | yes, untested | yes | |
| zip | yes, untested | yes, untested | |
| zlib | yes | yes | |
| zstd | yes | yes | |

View File

@ -16,7 +16,7 @@ use Symfony\Component\Console\Command\ListCommand;
*/
class ConsoleApplication extends Application
{
public const VERSION = '2.0-beta3';
public const VERSION = '2.0-rc1';
/**
* @throws \ReflectionException

View File

@ -38,6 +38,9 @@ abstract class BuilderBase
/** @var bool 本次编译是否只编译 libs不编译 PHP */
protected bool $libs_only = false;
/** @var bool 是否 strip 最终的二进制 */
protected bool $strip = true;
/**
* 构建指定列表的 libs
*
@ -63,16 +66,13 @@ abstract class BuilderBase
if ($libraries === [] && $this->isLibsOnly()) {
$libraries = array_keys($support_lib_list);
}
if (!in_array('pkg-config', $libraries)) {
array_unshift($libraries, 'pkg-config');
}
// 排序 libs根据依赖计算一个新的列表出来
$libraries = DependencyUtil::getLibsByDeps($libraries);
// 这里筛选 libraries比如纯静态模式排除掉ffi
if (defined('BUILD_ALL_STATIC') && BUILD_ALL_STATIC) {
$k = array_search('libffi', $libraries, true);
$k !== false && array_splice($libraries, $k, 1);
}
// 过滤不支持的库后添加
foreach ($libraries as $library) {
if (!isset($support_lib_list[$library])) {
@ -234,6 +234,11 @@ abstract class BuilderBase
return implode(', ', $ls);
}
public function setStrip(bool $strip): void
{
$this->strip = $strip;
}
/**
* 检查是否存在 lib 库对应的源码,如果不存在,则抛出异常
*

View File

@ -31,11 +31,13 @@ class BuilderProvider
cc: $input->getOption('cc'),
cxx: $input->getOption('cxx'),
arch: $input->getOption('arch'),
zts: $input->getOption('enable-zts'),
),
'Linux' => new LinuxBuilder(
cc: $input->getOption('cc'),
cxx: $input->getOption('cxx'),
arch: $input->getOption('arch'),
zts: $input->getOption('enable-zts'),
),
default => throw new WrongUsageException('Current OS "' . PHP_OS_FAMILY . '" is not supported yet'),
};

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\builder;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\Config;
@ -152,6 +153,11 @@ abstract class LibraryBase
return BUILD_STATUS_OK;
}
}
// pkg-config 做特殊处理,如果是 pkg-config 就检查有没有 pkg-config 二进制
if ($this instanceof MacOSLibraryBase && static::NAME === 'pkg-config' && !file_exists(BUILD_ROOT_PATH . '/bin/pkg-config')) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
// 到这里说明所有的文件都存在,就跳过编译
return BUILD_STATUS_ALREADY;
}

View File

@ -12,7 +12,6 @@ class ffi extends Extension
{
public function getUnixConfigureArg(): string
{
return '--with-ffi FFI_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
'FFI_LIBS="' . $this->getLibFilesString() . '"';
return '--with-ffi --enable-zend-signals';
}
}

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('imagick')]
class imagick extends Extension
{
public function getUnixConfigureArg(): string
{
return '--with-imagick=' . BUILD_ROOT_PATH;
}
}

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('opcache')]
class opcache extends Extension
{
public function getDistName(): string
{
return 'Zend Opcache';
}
}

View File

@ -43,7 +43,7 @@ class LinuxBuilder extends BuilderBase
* @throws RuntimeException
* @throws WrongUsageException
*/
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null)
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null, bool $zts = false)
{
// 初始化一些默认参数
$this->cc = $cc ?? match (SystemUtil::getOSRelease()['dist']) {
@ -53,6 +53,7 @@ class LinuxBuilder extends BuilderBase
$this->cxx = $cxx ?? 'g++';
$this->arch = $arch ?? php_uname('m');
$this->gnu_arch = arch2gnu($this->arch);
$this->zts = $zts;
$this->libc = 'musl'; // SystemUtil::selectLibc($this->cc);
// 根据 CPU 线程数设置编译进程数
@ -70,7 +71,7 @@ class LinuxBuilder extends BuilderBase
cxx: $this->cxx
);
// 设置 pkgconfig
$this->pkgconf_env = 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig"';
$this->pkgconf_env = 'PKG_CONFIG="' . BUILD_ROOT_PATH . '/bin/pkg-config" PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig"';
// 设置 configure 依赖的环境变量
$this->configure_env =
$this->pkgconf_env . ' ' .
@ -141,6 +142,9 @@ class LinuxBuilder extends BuilderBase
if ($this->getExt('swoole')) {
$extra_libs .= ' -lstdc++';
}
if ($this->getExt('imagick')) {
$extra_libs .= ' /usr/lib/libMagick++-7.Q16HDRI.a /usr/lib/libMagickCore-7.Q16HDRI.a /usr/lib/libMagickWand-7.Q16HDRI.a';
}
$envs = $this->pkgconf_env . ' ' .
"CC='{$this->cc}' " .
@ -169,7 +173,7 @@ class LinuxBuilder extends BuilderBase
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
SourcePatcher::patchPHPConfigure($this);
if ($this->getPHPVersionID() < 80000) {
$json_74 = '--enable-json ';
} else {

View File

@ -149,7 +149,7 @@ class SystemUtil
{
$paths = getenv('LIBPATH');
if (!$paths) {
$paths = '/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64';
$paths = '/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64:';
}
foreach (explode(':', $paths) as $path) {
if (file_exists("{$path}/{$name}")) {

View File

@ -61,6 +61,11 @@ abstract class LinuxLibraryBase extends LibraryBase
return BUILD_STATUS_OK;
}
}
// pkg-config 做特殊处理,如果是 pkg-config 就检查有没有 pkg-config 二进制
if (static::NAME === 'pkg-config' && !file_exists(BUILD_ROOT_PATH . '/bin/pkg-config')) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
// 到这里说明所有的文件都存在,就跳过编译
return BUILD_STATUS_ALREADY;
}

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
/**
* a template library class for unix
*/
class imagemagick extends LinuxLibraryBase
{
use \SPC\builder\unix\library\imagemagick;
public const NAME = 'imagemagick';
}

View File

@ -61,5 +61,6 @@ class libpng extends LinuxLibraryBase
->cd(BUILD_LIB_PATH)
->exec('ln -sf libpng16.a libpng.a');
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
class libsodium extends LinuxLibraryBase
{
use \SPC\builder\unix\library\libsodium;
public const NAME = 'libsodium';
}

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
/**
* gmp is a template library class for unix
*/
class pkgconfig extends LinuxLibraryBase
{
use \SPC\builder\unix\library\pkgconfig;
public const NAME = 'pkg-config';
}

View File

@ -31,7 +31,7 @@ class MacOSBuilder extends BuilderBase
* @throws RuntimeException
* @throws WrongUsageException
*/
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null)
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null, bool $zts = false)
{
// 如果是 Debug 模式,才使用 set -x 显示每条执行的命令
$this->set_x = defined('DEBUG_MODE') ? 'set -x' : 'true';
@ -40,6 +40,7 @@ class MacOSBuilder extends BuilderBase
$this->cxx = $cxx ?? 'clang++';
$this->arch = $arch ?? php_uname('m');
$this->gnu_arch = arch2gnu($this->arch);
$this->zts = $zts;
// 根据 CPU 线程数设置编译进程数
$this->concurrency = SystemUtil::getCpuCount();
// 设置 cflags
@ -49,6 +50,7 @@ class MacOSBuilder extends BuilderBase
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->arch, $this->arch_c_flags);
// 设置 configure 依赖的环境变量
$this->configure_env =
'PKG_CONFIG="' . BUILD_ROOT_PATH . '/bin/pkg-config" ' .
'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' .
"CC='{$this->cc}' " .
"CXX='{$this->cxx}' " .
@ -145,7 +147,7 @@ class MacOSBuilder extends BuilderBase
if ($this->getLib('libxml2') || $this->getExt('iconv')) {
$extra_libs .= ' -liconv';
}
if ($this->getPHPVersionID() < 80000) {
$json_74 = '--enable-json ';
} else {
@ -206,10 +208,11 @@ class MacOSBuilder extends BuilderBase
*/
public function buildCli(string $extra_libs): void
{
shell()->cd(SOURCE_PATH . '/php-src')
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" cli")
->exec('dsymutil -f sapi/cli/php')
->exec('strip sapi/cli/php');
$shell = shell()->cd(SOURCE_PATH . '/php-src');
$shell->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" cli");
if ($this->strip) {
$shell->exec('dsymutil -f sapi/cli/php')->exec('strip sapi/cli/php');
}
$this->deployBinary(BUILD_TARGET_CLI);
}
@ -229,7 +232,7 @@ class MacOSBuilder extends BuilderBase
}
shell()->cd(SOURCE_PATH . '/php-src')
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" STRIP=\"dsymutil -f \" micro");
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" " . ($this->strip ? 'STRIP="dsymutil -f " ' : '') . 'micro');
$this->deployBinary(BUILD_TARGET_MICRO);
}
@ -241,10 +244,11 @@ class MacOSBuilder extends BuilderBase
*/
public function buildFpm(string $extra_libs): void
{
shell()->cd(SOURCE_PATH . '/php-src')
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" fpm")
->exec('dsymutil -f sapi/fpm/php-fpm')
->exec('strip sapi/fpm/php-fpm');
$shell = shell()->cd(SOURCE_PATH . '/php-src');
$shell->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" fpm");
if ($this->strip) {
$shell->exec('dsymutil -f sapi/fpm/php-fpm')->exec('strip sapi/fpm/php-fpm');
}
$this->deployBinary(BUILD_TARGET_FPM);
}
}

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
/**
* gmp is a template library class for unix
*/
class imagemagick extends MacOSLibraryBase
{
use \SPC\builder\unix\library\imagemagick;
public const NAME = 'imagemagick';
}

View File

@ -34,11 +34,11 @@ class libffi extends MacOSLibraryBase
'--disable-shared ' .
"--host={$this->builder->arch}-apple-darwin " .
"--target={$this->builder->arch}-apple-darwin " .
'--prefix= ' . // use prefix=/
"--libdir={$lib}"
'--prefix= ' // use prefix=/
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
$this->patchPkgconfPrefix(['libffi.pc']);
}
}

View File

@ -55,5 +55,6 @@ class libpng extends MacOSLibraryBase
->cd(BUILD_LIB_PATH)
->exec('ln -sf libpng16.a libpng.a');
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
class libsodium extends MacOSLibraryBase
{
use \SPC\builder\unix\library\libsodium;
public const NAME = 'libsodium';
}

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
/**
* gmp is a template library class for unix
*/
class pkgconfig extends MacOSLibraryBase
{
use \SPC\builder\unix\library\pkgconfig;
public const NAME = 'pkg-config';
}

View File

@ -72,7 +72,7 @@ trait UnixBuilderTrait
}
foreach ($this->exts as $ext) {
logger()->debug('testing ext: ' . $ext->getName());
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri ' . $ext->getDistName(), false);
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "' . $ext->getDistName() . '"', false);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $ext->getName() . ' failed compile check');
}

View File

@ -77,4 +77,20 @@ trait UnixLibraryTrait
FileSystem::writeFile($realpath, $file);
}
}
/**
* remove libtool archive files
*
* @throws FileSystemException
* @throws RuntimeException
*/
public function cleanLaFiles(): void
{
foreach ($this->getStaticLibs() as $lib) {
$filename = pathinfo($lib, PATHINFO_FILENAME) . '.la';
if (file_exists(BUILD_LIB_PATH . '/' . $filename)) {
unlink(BUILD_LIB_PATH . '/' . $filename);
}
}
}
}

View File

@ -38,8 +38,6 @@ trait UnixSystemUtilTrait
$cxxLine = 'SET(CMAKE_CXX_COMPILER ' . self::findCommand($cxx) . ')';
}
$toolchain = <<<CMAKE
SET(CMAKE_SYSTEM_NAME {$os})
SET(CMAKE_SYSTEM_PROCESSOR {$target_arch})
{$ccLine}
{$cxxLine}
SET(CMAKE_C_FLAGS "{$cflags}")
@ -47,6 +45,7 @@ SET(CMAKE_CXX_FLAGS "{$cflags}")
SET(CMAKE_FIND_ROOT_PATH "{$root}")
SET(CMAKE_PREFIX_PATH "{$root}")
set(PKG_CONFIG_EXECUTABLE "{$root}/bin/pkg-config")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait freetype
{
protected function build()
@ -25,5 +27,13 @@ trait freetype
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['freetype2.pc']);
FileSystem::replaceFile(
BUILD_ROOT_PATH . '/lib/pkgconfig/freetype2.pc',
REPLACE_FILE_STR,
' -L/lib ',
' -L' . BUILD_ROOT_PATH . '/lib '
);
$this->cleanLaFiles();
}
}

View File

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait imagemagick
{
protected function build(): void
{
$extra = '--without-jxl --without-xml --without-zstd --without-x --disable-openmp ';
// libzip support
$extra .= $this->builder->getLib('libzip') ? '--with-zip ' : '--without-zip ';
// jpeg support
$extra .= $this->builder->getLib('libjpeg') ? '--with-jpeg ' : '';
// png support
$extra .= $this->builder->getLib('libpng') ? '--with-png ' : '';
// webp support
$extra .= $this->builder->getLib('libwebp') ? '--with-webp ' : '';
// zstd support
// $extra .= $this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ';
// freetype support
$extra .= $this->builder->getLib('freetype') ? '--with-freetype ' : '--without-freetype ';
shell()->cd($this->source_dir)
->exec(
"{$this->builder->configure_env} ./configure " .
'--enable-static --disable-shared ' .
$extra .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$filelist = [
'ImageMagick.pc',
'ImageMagick-7.Q16HDRI.pc',
'Magick++.pc',
'Magick++-7.Q16HDRI.pc',
'MagickCore.pc',
'MagickCore-7.Q16HDRI.pc',
'MagickWand.pc',
'MagickWand-7.Q16HDRI.pc',
];
$this->patchPkgconfPrefix($filelist);
foreach ($filelist as $file) {
FileSystem::replaceFile(
BUILD_LIB_PATH . '/pkgconfig/' . $file,
REPLACE_FILE_PREG,
'#includearchdir=/include/ImageMagick-7#m',
'includearchdir=${prefix}/include/ImageMagick-7'
);
}
}
}

View File

@ -24,5 +24,6 @@ trait libavif
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
// patch pkgconfig
$this->patchPkgconfPrefix(['libavif.pc']);
$this->cleanLaFiles();
}
}

View File

@ -24,5 +24,6 @@ trait libjpeg
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
// patch pkgconfig
$this->patchPkgconfPrefix(['libjpeg.pc', 'libturbojpeg.pc']);
$this->cleanLaFiles();
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
trait libsodium
{
protected function build()
{
$root = BUILD_ROOT_PATH;
shell()->cd($this->source_dir)
->exec("{$this->builder->configure_env} ./configure --enable-static --disable-shared --prefix={$root}")
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install');
}
}

View File

@ -28,5 +28,6 @@ trait libwebp
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . $destdir);
$this->patchPkgconfPrefix(['libsharpyuv.pc', 'libwebp.pc', 'libwebpdecoder.pc', 'libwebpdemux.pc', 'libwebpmux.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
}
}

View File

@ -15,8 +15,8 @@ trait libzip
$extra .= $this->builder->getLib('bzip2') ? '-DENABLE_BZIP2=ON ' : '-DENABLE_BZIP2=OFF ';
// lib:xz
$extra .= $this->builder->getLib('xz') ? '-DENABLE_LZMA=ON ' : '-DENABLE_LZMA=OFF ';
// lib:zstd
$extra .= $this->builder->getLib('zstd') ? '-DENABLE_ZSTD=ON ' : '-DENABLE_ZSTD=OFF ';
// lib:zstd (disabled due to imagemagick link issue
$extra .= /* $this->builder->getLib('zstd') ? '-DENABLE_ZSTD=ON ' : */ '-DENABLE_ZSTD=OFF ';
// lib:openssl
$extra .= $this->builder->getLib('openssl') ? '-DENABLE_OPENSSL=ON ' : '-DENABLE_OPENSSL=OFF ';

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
trait pkgconfig
{
protected function build()
{
$macos_env = 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' .
"CC='{$this->builder->cc}' " .
"CXX='{$this->builder->cxx}' " .
"CFLAGS='{$this->builder->arch_c_flags} -Wimplicit-function-declaration' ";
$linux_env = 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig" ' .
"CC='{$this->builder->cc}' " .
"CXX='{$this->builder->cxx}' ";
$extra = match (PHP_OS_FAMILY) {
'Darwin' => '',
default => '--with-internal-glib ',
};
shell()->cd($this->source_dir)
->exec(
match (PHP_OS_FAMILY) {
'Darwin' => $macos_env,
default => $linux_env,
} .
'./configure ' .
'--disable-shared ' .
'--enable-static ' .
$extra .
'--prefix=' . BUILD_ROOT_PATH . ' ' .
'--without-sysroot ' .
'--without-system-include-path ' .
'--without-system-library-path ' .
'--without-pc-path'
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install');
}
}

View File

@ -25,6 +25,8 @@ class BuildCliCommand extends BuildCommand
$this->addOption('build-cli', null, null, 'build cli');
$this->addOption('build-fpm', null, null, 'build fpm');
$this->addOption('build-all', null, null, 'build cli, micro, fpm');
$this->addOption('no-strip', null, null, 'build without strip, in order to debug and load external extensions');
$this->addOption('enable-zts', null, null, 'enable ZTS support');
}
public function handle(): int
@ -68,6 +70,8 @@ class BuildCliCommand extends BuildCommand
$builder->buildLibs($libraries);
// 执行扩展检测
$builder->proveExts($extensions);
// strip
$builder->setStrip(false);
// 构建
$builder->buildPHP($rule, $this->getOption('bloat'));
// 统计时间

View File

@ -6,6 +6,7 @@ namespace SPC\store;
use SPC\builder\BuilderBase;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\linux\SystemUtil;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
@ -84,6 +85,9 @@ class SourcePatcher
if ($readline = $builder->getExt('readline')) {
$patch[] = ['readline patch', '/-lncurses/', $readline->getLibFilesString()];
}
if ($ssh2 = $builder->getExt('ssh2')) {
$patch[] = ['ssh2 patch', '/-lssh2/', $ssh2->getLibFilesString()];
}
$patch[] = ['disable capstone', '/have_capstone="yes"/', 'have_capstone="no"'];
foreach ($patch as $item) {
logger()->info('Patching configure: ' . $item[0]);
@ -99,6 +103,24 @@ class SourcePatcher
'-lz',
BUILD_LIB_PATH . '/libz.a'
);
if (SystemUtil::getOSRelease()['dist'] === 'alpine') {
FileSystem::replaceFile(
SOURCE_PATH . '/libpng/configure',
REPLACE_FILE_STR,
'-lm',
'/usr/lib/libm.a'
);
}
}
public static function patchUnixSsh2(): void
{
FileSystem::replaceFile(
SOURCE_PATH . '/php-src/configure',
REPLACE_FILE_STR,
'-lssh2',
BUILD_LIB_PATH . '/libssh2.a'
);
}
public static function patchCurlMacOS(): void

View File

@ -66,6 +66,8 @@ function osfamily2dir(): string
}
/**
* 执行shell直接输出在终端出现错误抛出异常
*
* @throws \SPC\exception\RuntimeException
*/
function f_passthru(string $cmd): ?bool
@ -89,7 +91,13 @@ function f_passthru(string $cmd): ?bool
return $ret;
}
function f_exec(string $command, &$output, &$result_code)
/**
* 执行命令,不输出内容,返回执行结果和内容
*
* @param mixed $output
* @param mixed $result_code
*/
function f_exec(string $command, &$output, &$result_code): bool|string
{
logger()->debug('Running command (no output) : ' . $command);
return exec($command, $output, $result_code);