Compare commits

...

4 Commits

Author SHA1 Message Date
crazywhalecc
b7f64e46c2
add ssh2 support 2023-05-10 02:32:27 +08:00
crazywhalecc
a329445701
add ssh2 support 2023-05-10 02:31:57 +08:00
crazywhalecc
7527f9f099
add imagemagick (imagick) for macos, pkg-config for unix.= 2023-05-10 02:04:08 +08:00
crazywhalecc
9daa10e939
sort config, add imagemagick 2023-05-10 00:46:57 +08:00
26 changed files with 357 additions and 47 deletions

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",
@ -294,6 +302,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": [

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",

View File

@ -26,6 +26,7 @@
| gettext | | | |
| gmp | yes | yes | |
| iconv | yes | yes | |
| imagick | | yes | |
| inotify | yes | yes | |
| mbstring | yes | yes | |
| mbregex | yes | yes | |
@ -50,13 +51,14 @@
| soap | yes | yes | |
| sockets | yes | yes | |
| sqlite3 | yes | yes | |
| ssh2 | | 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

@ -63,6 +63,9 @@ 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);

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

@ -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

@ -70,7 +70,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 +141,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 +172,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

@ -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,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

@ -49,6 +49,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 +146,7 @@ class MacOSBuilder extends BuilderBase
if ($this->getLib('libxml2') || $this->getExt('iconv')) {
$extra_libs .= ' -liconv';
}
if ($this->getPHPVersionID() < 80000) {
$json_74 = '--enable-json ';
} else {

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\store\FileSystem;
/**
* gmp is a template library class for unix
*/
class imagemagick extends MacOSLibraryBase
{
public const NAME = 'imagemagick';
protected function build(): void
{
$extra = '--without-jxl --without-xml --without-zstd ';
// 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

@ -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,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

@ -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

@ -47,6 +47,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

@ -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

@ -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

@ -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);