Compare commits

..

14 Commits

Author SHA1 Message Date
crazywhalecc
eb00e0012f Add getLibVersion and getExtVersion method for extensions and libs 2024-06-30 23:25:58 +08:00
crazywhalecc
f645c8869a Add prefer-stable option for ghrel, ghtar, ghtagtar 2024-06-30 23:25:58 +08:00
crazywhalecc
351e391221 --ignore-cache-sources now support empty values (force all download) 2024-06-30 23:25:58 +08:00
crazywhalecc
1d78a231db Add target dir to extract hook 2024-06-30 23:25:58 +08:00
crazywhalecc
9463cf94ca Prevent constructing builder without --arch options error 2024-06-30 23:25:58 +08:00
crazywhalecc
ba127f4e00 Use extra files instead of internal patch block for libyaml 2024-06-30 23:25:58 +08:00
crazywhalecc
d4da18e869 Disable getCpuCount log 2024-06-30 23:25:58 +08:00
crazywhalecc
334a3bdf5d Add extension swow for Windows 2024-06-30 01:12:20 +08:00
crazywhalecc
a1f632e8c9 Add apcu test 2024-06-30 00:41:41 +08:00
crazywhalecc
3445a2cd58 Add extension tests 2024-06-30 00:41:41 +08:00
crazywhalecc
3100911802 Add several extensions and libs for windows
exts: bz2, sqlsrv, pdo_sqlsrv, yaml, zip, rar
libs: bzip2, libyaml, libzip, xz
2024-06-30 00:41:41 +08:00
crazywhalecc
a6236eb98c Bump version 2024-06-30 00:41:41 +08:00
crazywhalecc
c22488ec57 Add pcre as internal extension 2024-06-30 00:41:41 +08:00
Jerry Ma
0857a19c3c Increase memory_limit size (#485) 2024-06-28 12:14:36 +08:00
29 changed files with 518 additions and 91 deletions

View File

@@ -21,11 +21,9 @@
"type": "builtin"
},
"bz2": {
"support": {
"Windows": "wip"
},
"type": "builtin",
"arg-type": "with-prefix",
"arg-type-unix": "with-prefix",
"arg-type-windows": "with",
"lib-depends": [
"bzip2"
]
@@ -473,7 +471,6 @@
},
"pdo_sqlsrv": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"type": "external",
@@ -519,7 +516,6 @@
},
"rar": {
"support": {
"Windows": "wip",
"BSD": "wip",
"Darwin": "partial"
},
@@ -636,12 +632,11 @@
},
"sqlsrv": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"type": "external",
"source": "sqlsrv",
"lib-depends": [
"lib-depends-unix": [
"unixodbc"
],
"ext-depends-linux": [
@@ -738,7 +733,6 @@
},
"swow": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"notes": true,
@@ -925,26 +919,35 @@
},
"yaml": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"type": "external",
"source": "yaml",
"arg-type": "with-prefix",
"arg-type-unix": "with-prefix",
"arg-type-windows": "with",
"lib-depends": [
"libyaml"
]
},
"zip": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"type": "builtin",
"arg-type": "with-prefix",
"arg-type-windows": "enable",
"lib-depends": [
"lib-depends-unix": [
"libzip"
],
"ext-depends-windows": [
"zlib",
"bz2"
],
"lib-depends-windows": [
"libzip",
"zlib",
"bzip2",
"xz"
]
},
"zlib": {

View File

@@ -21,10 +21,8 @@
"libbz2.a"
],
"static-libs-windows": [
[
"libbz2.lib",
"libbz2_a.lib"
]
"libbz2.lib",
"libbz2_a.lib"
],
"headers": [
"bzlib.h"
@@ -448,23 +446,30 @@
"libzip.a"
],
"static-libs-windows": [
[
"zip.lib",
"libzip_a.lib"
]
"zip.lib",
"libzip_a.lib"
],
"headers": [
"zip.h",
"zipconf.h"
],
"lib-depends": [
"lib-depends-unix": [
"zlib"
],
"lib-suggests": [
"lib-suggests-unix": [
"bzip2",
"xz",
"zstd",
"openssl"
],
"lib-depends-windows": [
"zlib",
"bzip2",
"xz"
],
"lib-suggests-windows": [
"zstd",
"openssl"
]
},
"ncurses": {
@@ -625,10 +630,8 @@
"liblzma.a"
],
"static-libs-windows": [
[
"liblzma.lib",
"liblzma_a.lib"
]
"liblzma.lib",
"liblzma_a.lib"
],
"headers-unix": [
"lzma"
@@ -637,7 +640,7 @@
"lzma",
"lzma.h"
],
"lib-depends": [
"lib-depends-unix": [
"libiconv"
]
},

5
config/pre-built.json Normal file
View File

@@ -0,0 +1,5 @@
{
"repo": "static-php/static-php-cli-hosted",
"match-pattern": "{name}-{arch}-{os}.tgz",
"pack-config": {}
}

View File

@@ -47,6 +47,7 @@
"type": "ghrel",
"repo": "curl/curl",
"match": "curl.+\\.tar\\.xz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
@@ -194,6 +195,7 @@
"type": "ghrel",
"repo": "unicode-org/icu",
"match": "icu4c.+-src\\.tgz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -266,6 +268,7 @@
"type": "ghrel",
"repo": "c-ares/c-ares",
"match": "c-ares-.+\\.tar\\.gz",
"prefer-stable": true,
"alt": {
"type": "filelist",
"url": "https://c-ares.org/download/",
@@ -280,6 +283,7 @@
"type": "ghrel",
"repo": "libevent/libevent",
"match": "libevent.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -289,6 +293,7 @@
"type": "ghrel",
"repo": "libffi/libffi",
"match": "libffi.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -333,6 +338,7 @@
"type": "ghrel",
"repo": "lz4/lz4",
"match": "lz4-.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -369,6 +375,7 @@
"type": "ghrel",
"repo": "jedisct1/libsodium",
"match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -378,6 +385,7 @@
"type": "ghrel",
"repo": "libssh2/libssh2",
"match": "libssh2.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
@@ -444,6 +452,7 @@
"type": "ghrel",
"repo": "yaml/libyaml",
"match": "yaml-.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "License"
@@ -453,6 +462,7 @@
"type": "ghrel",
"repo": "nih-at/libzip",
"match": "libzip.+\\.tar\\.xz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -483,6 +493,7 @@
"repo": "mongodb/mongo-php-driver",
"path": "php-src/ext/mongodb",
"match": "mongodb.+\\.tgz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -501,6 +512,7 @@
"type": "ghrel",
"repo": "nghttp2/nghttp2",
"match": "nghttp2.+\\.tar\\.xz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
@@ -510,6 +522,7 @@
"type": "ghrel",
"repo": "kkos/oniguruma",
"match": "onig-.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
@@ -649,6 +662,7 @@
"type": "ghtar",
"path": "php-src/ext/swoole",
"repo": "swoole/swoole-src",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
@@ -734,6 +748,7 @@
"type": "ghrel",
"repo": "madler/zlib",
"match": "zlib.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "text",
"text": "(C) 1995-2022 Jean-loup Gailly and Mark Adler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n claim that you wrote the original software. If you use this software\n in a product, an acknowledgment in the product documentation would be\n appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution.\n\nJean-loup Gailly Mark Adler\njloup@gzip.org madler@alumni.caltech.edu"
@@ -743,6 +758,7 @@
"type": "ghrel",
"repo": "facebook/zstd",
"match": "zstd.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"

View File

@@ -8,7 +8,9 @@ use SPC\command\BuildCliCommand;
use SPC\command\BuildLibsCommand;
use SPC\command\DeleteDownloadCommand;
use SPC\command\dev\AllExtCommand;
use SPC\command\dev\ExtVerCommand;
use SPC\command\dev\GenerateExtDocCommand;
use SPC\command\dev\LibVerCommand;
use SPC\command\dev\PhpVerCommand;
use SPC\command\dev\SortConfigCommand;
use SPC\command\DoctorCommand;
@@ -25,7 +27,7 @@ use Symfony\Component\Console\Application;
*/
final class ConsoleApplication extends Application
{
public const VERSION = '2.2.4';
public const VERSION = '2.3.0';
public function __construct()
{
@@ -48,6 +50,8 @@ final class ConsoleApplication extends Application
// Dev commands
new AllExtCommand(),
new PhpVerCommand(),
new LibVerCommand(),
new ExtVerCommand(),
new SortConfigCommand(),
new GenerateExtDocCommand(),
]

View File

@@ -161,7 +161,7 @@ abstract class BuilderBase
* @throws WrongUsageException
* @internal
*/
public function proveExts(array $extensions): void
public function proveExts(array $extensions, bool $skip_check_deps = false): void
{
CustomExt::loadCustomExt();
$this->emitPatchPoint('before-php-extract');
@@ -181,6 +181,10 @@ abstract class BuilderBase
$this->addExt($ext);
}
if ($skip_check_deps) {
return;
}
foreach ($this->exts as $ext) {
$ext->checkDependency();
}

View File

@@ -27,7 +27,7 @@ class BuilderProvider
*/
public static function makeBuilderByInput(InputInterface $input): BuilderBase
{
ini_set('memory_limit', '2G');
ini_set('memory_limit', '4G');
self::$builder = match (PHP_OS_FAMILY) {
'Windows' => new WindowsBuilder($input->getOptions()),

View File

@@ -228,6 +228,16 @@ class Extension
// do nothing, just throw wrong usage exception if not valid
}
/**
* Get current extension version
*
* @return null|string Version string or null
*/
public function getExtVersion(): ?string
{
return null;
}
/**
* @throws RuntimeException
*/

View File

@@ -182,6 +182,16 @@ abstract class LibraryBase
// do nothing, just throw wrong usage exception if not valid
}
/**
* Get current lib version
*
* @return null|string Version string or null
*/
public function getLibVersion(): ?string
{
return null;
}
/**
* Get current builder object.
*/

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('sqlsrv')]
class sqlsrv extends Extension
{
private bool $pdo_sqlsrv_patched = false;
public function patchBeforeBuildconf(): bool
{
if (PHP_OS_FAMILY === 'Windows' && $this->builder->getExt('pdo_sqlsrv') === null) {
// support sqlsrv without pdo_sqlsrv
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/sqlsrv/config.w32', 'PHP_PDO_SQLSRV', '"no"');
$this->pdo_sqlsrv_patched = true;
return true;
}
return false;
}
public function patchBeforeConfigure(): bool
{
if ($this->pdo_sqlsrv_patched) {
// revert pdo_sqlsrv patch
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/sqlsrv/config.w32', '"no" == "no"', 'PHP_PDO_SQLSRV == "no"');
return true;
}
return false;
}
}

View File

@@ -10,6 +10,18 @@ use SPC\util\CustomExt;
#[CustomExt('swoole')]
class swoole extends Extension
{
public function getExtVersion(): ?string
{
// Get version from source directory
$file = SOURCE_PATH . '/php-src/ext/swoole/include/swoole_version.h';
// Match #define SWOOLE_VERSION "5.1.3"
$pattern = '/#define SWOOLE_VERSION "(.+)"/';
if (preg_match($pattern, file_get_contents($file), $matches)) {
return $matches[1];
}
return null;
}
public function getUnixConfigureArg(): string
{
// enable swoole

View File

@@ -18,7 +18,7 @@ class swow extends Extension
}
}
public function getUnixConfigureArg(): string
public function getConfigureArg(): string
{
$arg = '--enable-swow';
$arg .= $this->builder->getLib('openssl') ? ' --enable-swow-ssl' : ' --disable-swow-ssl';

View File

@@ -37,7 +37,7 @@ class MacOSBuilder extends UnixBuilderBase
$this->arch_c_flags = getenv('SPC_DEFAULT_C_FLAGS');
$this->arch_cxx_flags = getenv('SPC_DEFAULT_CXX_FLAGS');
// cmake toolchain
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->getOption('arch'), $this->arch_c_flags);
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->getOption('arch', php_uname('m')), $this->arch_c_flags);
// create pkgconfig and include dir (some libs cannot create them automatically)
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);

View File

@@ -20,7 +20,7 @@ class SystemUtil
*/
public static function getCpuCount(): int
{
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu');
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu', false);
if ($ret !== 0) {
throw new RuntimeException('Failed to get cpu count');
}

View File

@@ -10,51 +10,27 @@ use SPC\store\FileSystem;
trait libyaml
{
public function getLibVersion(): ?string
{
// Match version from CMakeLists.txt:
// Format: set (YAML_VERSION_MAJOR 0)
// set (YAML_VERSION_MINOR 2)
// set (YAML_VERSION_PATCH 5)
$content = FileSystem::readFile($this->source_dir . '/CMakeLists.txt');
if (preg_match('/set \(YAML_VERSION_MAJOR (\d+)\)/', $content, $major)
&& preg_match('/set \(YAML_VERSION_MINOR (\d+)\)/', $content, $minor)
&& preg_match('/set \(YAML_VERSION_PATCH (\d+)\)/', $content, $patch)) {
return "{$major[1]}.{$minor[1]}.{$patch[1]}";
}
return null;
}
/**
* @throws RuntimeException
* @throws FileSystemException
*/
protected function build(): void
{
// prepare cmake/config.h.in
if (!is_file(SOURCE_PATH . '/libyaml/cmake/config.h.in')) {
f_mkdir(SOURCE_PATH . '/libyaml/cmake');
file_put_contents(
SOURCE_PATH . '/libyaml/cmake/config.h.in',
<<<'EOF'
#define YAML_VERSION_MAJOR @YAML_VERSION_MAJOR@
#define YAML_VERSION_MINOR @YAML_VERSION_MINOR@
#define YAML_VERSION_PATCH @YAML_VERSION_PATCH@
#define YAML_VERSION_STRING "@YAML_VERSION_STRING@"
EOF
);
}
// prepare yamlConfig.cmake.in
if (!is_file(SOURCE_PATH . '/libyaml/yamlConfig.cmake.in')) {
file_put_contents(
SOURCE_PATH . '/libyaml/yamlConfig.cmake.in',
<<<'EOF'
# Config file for the yaml library.
#
# It defines the following variables:
# yaml_LIBRARIES - libraries to link against
@PACKAGE_INIT@
set_and_check(yaml_TARGETS "@PACKAGE_CONFIG_DIR_CONFIG@/yamlTargets.cmake")
if(NOT yaml_TARGETS_IMPORTED)
set(yaml_TARGETS_IMPORTED 1)
include(${yaml_TARGETS})
endif()
set(yaml_LIBRARIES yaml)
EOF
);
}
[$lib, $include, $destdir] = SEPARATED_PATH;
FileSystem::resetDir($this->source_dir . '/build');

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
class bzip2 extends WindowsLibraryBase
{
public const NAME = 'bzip2';
protected function build(): void
{
$nmake = $this->builder->makeSimpleWrapper('nmake /nologo /f Makefile.msc CFLAGS="-DWIN32 -MT -Ox -D_FILE_OFFSET_BITS=64 -nologo"');
cmd()->cd($this->source_dir)
->execWithWrapper($nmake, 'clean')
->execWithWrapper($nmake, 'lib');
copy($this->source_dir . '\libbz2.lib', BUILD_LIB_PATH . '\libbz2.lib');
copy($this->source_dir . '\libbz2.lib', BUILD_LIB_PATH . '\libbz2_a.lib');
copy($this->source_dir . '\bzlib.h', BUILD_INCLUDE_PATH . '\bzlib.h');
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class libyaml extends WindowsLibraryBase
{
public const NAME = 'libyaml';
protected function build(): void
{
// reset cmake
FileSystem::resetDir($this->source_dir . '\build');
// check missing files: cmake\config.h.in and .\YamlConfig.cmake.in
if (!file_exists($this->source_dir . '\cmake\config.h.in')) {
FileSystem::createDir($this->source_dir . '\cmake');
copy(ROOT_DIR . '\src\globals\extra\libyaml_config.h.in', $this->source_dir . '\cmake\config.h.in');
}
if (!file_exists($this->source_dir . '\YamlConfig.cmake.in')) {
copy(ROOT_DIR . '\src\globals\extra\libyaml_YamlConfig.cmake.in', $this->source_dir . '\YamlConfig.cmake.in');
}
// start build
cmd()->cd($this->source_dir)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
'-B build ' .
'-A x64 ' .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DBUILD_TESTING=OFF ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
"--build build --config Release --target install -j{$this->builder->concurrency}"
);
}
}

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class libzip extends WindowsLibraryBase
{
public const NAME = 'libzip';
protected function build(): void
{
// reset cmake
FileSystem::resetDir($this->source_dir . '\build');
$openssl = $this->builder->getLib('openssl') ? 'ON' : 'OFF';
$zstd = $this->builder->getLib('zstd') ? 'ON' : 'OFF';
// start build
cmd()->cd($this->source_dir)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
'-B build ' .
'-A x64 ' .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DENABLE_BZIP2=ON ' .
'-DENABLE_LZMA=ON ' .
"-DENABLE_ZSTD={$zstd} " .
"-DENABLE_OPENSSL={$openssl} " .
'-DBUILD_TOOLS=OFF ' .
'-DBUILD_DOC=OFF ' .
'-DBUILD_EXAMPLES=OFF ' .
'-DBUILD_REGRESS=OFF ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
"--build build --config Release --target install -j{$this->builder->concurrency}"
);
copy(BUILD_LIB_PATH . '\zip.lib', BUILD_LIB_PATH . '\libzip_a.lib');
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class xz extends WindowsLibraryBase
{
public const NAME = 'xz';
protected function build(): void
{
// reset cmake
FileSystem::resetDir($this->source_dir . '\build');
// start build
cmd()->cd($this->source_dir)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
'-B build ' .
'-A x64 ' .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
"--build build --config Release --target install -j{$this->builder->concurrency}"
);
// copy liblzma.lib to liblzma_a.lib
copy(BUILD_LIB_PATH . '/liblzma.lib', BUILD_LIB_PATH . '/liblzma_a.lib');
// patch lzma.h
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '/lzma.h', 'defined(LZMA_API_STATIC)', 'defined(_WIN32)');
}
}

View File

@@ -38,7 +38,7 @@ class DownloadCommand extends BaseCommand
$this->addOption('for-extensions', 'e', InputOption::VALUE_REQUIRED, 'Fetch by extensions, e.g "openssl,mbstring"');
$this->addOption('for-libs', 'l', InputOption::VALUE_REQUIRED, 'Fetch by libraries, e.g "libcares,openssl,onig"');
$this->addOption('without-suggestions', null, null, 'Do not fetch suggested sources when using --for-extensions');
$this->addOption('ignore-cache-sources', null, InputOption::VALUE_REQUIRED, 'Ignore some source caches, comma separated, e.g "php-src,curl,openssl"', '');
$this->addOption('ignore-cache-sources', null, InputOption::VALUE_OPTIONAL, 'Ignore some source caches, comma separated, e.g "php-src,curl,openssl"', '');
$this->addOption('retry', 'R', InputOption::VALUE_REQUIRED, 'Set retry time when downloading failed (default: 0)', '0');
}
@@ -147,8 +147,12 @@ class DownloadCommand extends BaseCommand
}
$chosen_sources = array_map('trim', array_filter(explode(',', $this->getArgument('sources'))));
$force_list = array_map('trim', array_filter(explode(',', $this->getOption('ignore-cache-sources'))));
$force_all = empty($this->getOption('ignore-cache-sources'));
if (!$force_all) {
$force_list = array_map('trim', array_filter(explode(',', $this->getOption('ignore-cache-sources'))));
} else {
$force_list = [];
}
if ($this->getOption('all')) {
logger()->notice('Downloading with --all option will take more times to download, we recommend you to download with --for-extensions option !');
}
@@ -182,7 +186,7 @@ class DownloadCommand extends BaseCommand
Downloader::downloadSource($source, $new_config, true);
} else {
logger()->info("Fetching source {$source} [{$ni}/{$cnt}]");
Downloader::downloadSource($source, Config::getSource($source), in_array($source, $force_list));
Downloader::downloadSource($source, Config::getSource($source), $force_all || in_array($source, $force_list));
}
}
$time = round(microtime(true) - START_TIME, 3);

View File

@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace SPC\command\dev;
use SPC\builder\BuilderProvider;
use SPC\command\BaseCommand;
use SPC\store\Config;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand('dev:ext-version', 'Returns version of extension from source directory', ['dev:ext-ver'])]
class ExtVerCommand extends BaseCommand
{
public function configure()
{
$this->addArgument('extension', InputArgument::REQUIRED, 'The library name');
}
public function initialize(InputInterface $input, OutputInterface $output): void
{
$this->no_motd = true;
parent::initialize($input, $output);
}
public function handle(): int
{
// Get lib object
$builder = BuilderProvider::makeBuilderByInput($this->input);
$ext_conf = Config::getExt($this->getArgument('extension'));
$builder->proveExts([$this->getArgument('extension')], true);
// Check whether lib is extracted
// if (!is_dir(SOURCE_PATH . '/' . $this->getArgument('library'))) {
// $this->output->writeln("<error>Library {$this->getArgument('library')} is not extracted</error>");
// return static::FAILURE;
// }
$version = $builder->getExt($this->getArgument('extension'))->getExtVersion();
if ($version === null) {
$this->output->writeln("<error>Failed to get version of extension {$this->getArgument('extension')}</error>");
return static::FAILURE;
}
$this->output->writeln("<info>{$version}</info>");
return static::SUCCESS;
}
}

View File

@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace SPC\command\dev;
use SPC\builder\BuilderProvider;
use SPC\command\BaseCommand;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand('dev:lib-version', 'Returns version of library from source directory', ['dev:lib-ver'])]
class LibVerCommand extends BaseCommand
{
public function configure()
{
$this->addArgument('library', InputArgument::REQUIRED, 'The library name');
}
public function initialize(InputInterface $input, OutputInterface $output): void
{
$this->no_motd = true;
parent::initialize($input, $output);
}
public function handle(): int
{
// Get lib object
$builder = BuilderProvider::makeBuilderByInput($this->input);
$builder->setLibsOnly();
// check lib name exist in lib.json
try {
Config::getLib($this->getArgument('library'));
} catch (WrongUsageException $e) {
$this->output->writeln("<error>Library {$this->getArgument('library')} is not supported yet</error>");
return static::FAILURE;
}
$builder->proveLibs([$this->getArgument('library')]);
// Check whether lib is extracted
if (!is_dir(SOURCE_PATH . '/' . $this->getArgument('library'))) {
$this->output->writeln("<error>Library {$this->getArgument('library')} is not extracted</error>");
return static::FAILURE;
}
$version = $builder->getLib($this->getArgument('library'))->getLibVersion();
if ($version === null) {
$this->output->writeln("<error>Failed to get version of library {$this->getArgument('library')}</error>");
return static::FAILURE;
}
$this->output->writeln("<info>{$version}</info>");
return static::SUCCESS;
}
}

View File

@@ -16,7 +16,7 @@ use SPC\store\source\CustomSourceBase;
class Downloader
{
/**
* Get latest version from BitBucket tag
* Get latest version from BitBucket tag (type = bitbuckettag)
*
* @param string $name source name
* @param array $source source meta info: [repo]
@@ -51,7 +51,7 @@ class Downloader
}
/**
* Get latest version from GitHub tarball
* Get latest version from GitHub tarball (type = ghtar / ghtagtar)
*
* @param string $name source name
* @param array $source source meta info: [repo]
@@ -68,7 +68,16 @@ class Downloader
hooks: [[CurlHook::class, 'setupGithubToken']],
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
), true);
$url = $data[0]['tarball_url'];
if (($source['prefer-stable'] ?? false) === true) {
$url = $data[0]['tarball_url'];
} else {
$id = 0;
while ($data[$id]['prerelease'] === true) {
++$id;
}
$url = $data[$id]['tarball_url'] ?? null;
}
if (!$url) {
throw new DownloaderException("failed to find {$name} source");
}
@@ -106,7 +115,7 @@ class Downloader
), true);
$url = null;
foreach ($data as $release) {
if ($release['prerelease'] === true) {
if (($source['prefer-stable'] ?? false) === true && $release['prerelease'] === true) {
continue;
}
foreach ($release['assets'] as $asset) {

View File

@@ -195,7 +195,7 @@ class FileSystem
}
try {
self::extractArchive($filename, $target);
self::emitSourceExtractHook($name);
self::emitSourceExtractHook($name, $target);
} catch (RuntimeException $e) {
if (PHP_OS_FAMILY === 'Windows') {
f_passthru('rmdir /s /q ' . $target);
@@ -518,10 +518,10 @@ class FileSystem
return file_put_contents($filename, $file);
}
private static function emitSourceExtractHook(string $name): void
private static function emitSourceExtractHook(string $name, string $target): void
{
foreach ((self::$_extract_hook[$name] ?? []) as $hook) {
if ($hook() === true) {
if ($hook($name, $target) === true) {
logger()->info('Patched source [' . $name . '] after extracted');
}
}

View File

@@ -9,6 +9,7 @@ use SPC\builder\linux\LinuxBuilder;
use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
class SourcePatcher
{
@@ -20,12 +21,19 @@ class SourcePatcher
FileSystem::addSourceExtractHook('swoole', [SourcePatcher::class, 'patchSwoole']);
FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchPhpLibxml212']);
FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchGDWin32']);
FileSystem::addSourceExtractHook('sqlsrv', [SourcePatcher::class, 'patchSQLSRVWin32']);
FileSystem::addSourceExtractHook('pdo_sqlsrv', [SourcePatcher::class, 'patchSQLSRVWin32']);
FileSystem::addSourceExtractHook('yaml', [SourcePatcher::class, 'patchYamlWin32']);
FileSystem::addSourceExtractHook('libyaml', [SourcePatcher::class, 'patchLibYaml']);
}
/**
* Source patcher runner before buildconf
*
* @param BuilderBase $builder Builder
* @param BuilderBase $builder Builder
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public static function patchBeforeBuildconf(BuilderBase $builder): void
{
@@ -77,7 +85,7 @@ class SourcePatcher
* @throws RuntimeException
* @throws FileSystemException
*/
public static function patchMicro(?array $list = null, bool $reverse = false): bool
public static function patchMicro(): bool
{
if (!file_exists(SOURCE_PATH . '/php-src/sapi/micro/php_micro.c')) {
return false;
@@ -112,7 +120,7 @@ class SourcePatcher
if (PHP_OS_FAMILY === 'Darwin') {
$default[] = 'macos_iconv';
}
$patch_list = $list ?? $default;
$patch_list = $default;
$patches = [];
$serial = ['80', '81', '82', '83', '84'];
foreach ($patch_list as $patchName) {
@@ -135,7 +143,7 @@ class SourcePatcher
f_passthru(
'cd ' . SOURCE_PATH . '/php-src && ' .
(PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . $patchesStr . ' | patch -p1 ' . ($reverse ? '-R' : '')
(PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . $patchesStr . ' | patch -p1 '
);
return true;
@@ -183,6 +191,9 @@ class SourcePatcher
return false;
}
/**
* @throws FileSystemException
*/
public static function patchSwoole(): bool
{
// swoole hook needs pdo/pdo.h
@@ -281,6 +292,9 @@ class SourcePatcher
return $result;
}
/**
* @throws FileSystemException
*/
public static function patchMicroPhar(int $version_id): void
{
FileSystem::backupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c');
@@ -306,11 +320,47 @@ class SourcePatcher
}
}
/**
* @throws RuntimeException
*/
public static function unpatchMicroPhar(): void
{
FileSystem::restoreBackupFile(SOURCE_PATH . '/php-src/ext/phar/phar.c');
}
/**
* Fix the compilation issue of sqlsrv and pdo_sqlsrv on Windows (/sdl check is too strict and will cause Zend compilation to fail)
*
* @throws FileSystemException
*/
public static function patchSQLSRVWin32(string $source_name): bool
{
$source_name = preg_replace('/[^a-z_]/', '', $source_name);
if (file_exists(SOURCE_PATH . '/php-src/ext/' . $source_name . '/config.w32')) {
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/' . $source_name . '/config.w32', '/sdl', '');
return true;
}
return false;
}
public static function patchYamlWin32(): bool
{
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/yaml/config.w32', "lib.substr(lib.length - 6, 6) == '_a.lib'", "lib.substr(lib.length - 6, 6) == '_a.lib' || 'yes' == 'yes'");
return true;
}
public static function patchLibYaml(string $name, string $target): bool
{
if (!file_exists("{$target}\\cmake\\config.h.in")) {
FileSystem::createDir("{$target}\\cmake");
copy(ROOT_DIR . '\src\globals\extra\libyaml_config.h.in', "{$target}\\cmake\\config.h.in");
}
if (!file_exists("{$target}\\YamlConfig.cmake.in")) {
copy(ROOT_DIR . '\src\globals\extra\libyaml_YamlConfig.cmake.in', "{$target}\\YamlConfig.cmake.in");
}
return true;
}
/**
* Patch cli SAPI Makefile for Windows.
*
@@ -325,7 +375,7 @@ class SourcePatcher
$line_num = 0;
$found = false;
foreach ($lines as $v) {
if (strpos($v, '$(BUILD_DIR)\php.exe:') !== false) {
if (str_contains($v, '$(BUILD_DIR)\php.exe:')) {
$found = $line_num;
break;
}
@@ -339,6 +389,9 @@ class SourcePatcher
FileSystem::writeFile(SOURCE_PATH . '/php-src/Makefile', implode("\r\n", $lines));
}
/**
* @throws RuntimeException
*/
public static function patchPhpLibxml212(): bool
{
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
@@ -360,6 +413,9 @@ class SourcePatcher
return false;
}
/**
* @throws FileSystemException
*/
public static function patchGDWin32(): bool
{
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
@@ -393,6 +449,9 @@ class SourcePatcher
}
}
/**
* @throws FileSystemException
*/
public static function patchMicroWin32(): void
{
// patch micro win32

View File

@@ -43,6 +43,7 @@ const SPC_INTERNAL_EXTENSIONS = [
'core',
'hash',
'json',
'pcre',
'reflection',
'spl',
'standard',

View File

@@ -0,0 +1,10 @@
@PACKAGE_INIT@
set_and_check(yaml_TARGETS "@PACKAGE_CONFIG_DIR_CONFIG@/yamlTargets.cmake")
if(NOT yaml_TARGETS_IMPORTED)
set(yaml_TARGETS_IMPORTED 1)
include(${yaml_TARGETS})
endif()
set(yaml_LIBRARIES yaml)

View File

@@ -0,0 +1,4 @@
#define YAML_VERSION_MAJOR @YAML_VERSION_MAJOR@
#define YAML_VERSION_MINOR @YAML_VERSION_MINOR@
#define YAML_VERSION_PATCH @YAML_VERSION_PATCH@
#define YAML_VERSION_STRING "@YAML_VERSION_STRING@"

View File

@@ -20,13 +20,13 @@ $upx = 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' => 'sockets',
'Windows' => 'mbstring,pdo_sqlite,mbregex,gd',
'Windows' => 'mbstring,pdo_sqlite,mbregex,bz2,sqlsrv,pdo_sqlsrv,yaml,zip,rar,apcu,swow',
};
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).
$with_libs = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => '',
'Windows' => 'libjpeg,libwebp,libavif,freetype',
'Windows' => '',
};
// Please change your test base combination. We recommend testing with `common`.