Refactor, supports shared extension build now !

This commit is contained in:
crazywhalecc
2025-03-24 23:50:12 +08:00
parent 76c353e790
commit aa4d4db11f
19 changed files with 218 additions and 103 deletions

View File

@@ -924,8 +924,8 @@
"support": { "support": {
"Windows": "wip", "Windows": "wip",
"BSD": "no", "BSD": "no",
"Darwin": "no", "Darwin": "partial",
"Linux": "wip" "Linux": "partial"
}, },
"notes": true "notes": true
}, },

View File

@@ -281,8 +281,7 @@
"headers-unix": [ "headers-unix": [
"ares.h", "ares.h",
"ares_dns.h", "ares_dns.h",
"ares_nameser.h", "ares_nameser.h"
"ares_rules.h"
] ]
}, },
"libde265": { "libde265": {

View File

@@ -122,9 +122,12 @@ abstract class BuilderBase
* *
* @return Extension[] * @return Extension[]
*/ */
public function getExts(): array public function getExts(bool $including_dynamic = true): array
{ {
return $this->exts; if ($including_dynamic) {
return $this->exts;
}
return array_filter($this->exts, fn ($ext) => !$ext->isBuildShared());
} }
/** /**
@@ -136,7 +139,7 @@ abstract class BuilderBase
public function hasCpp(): bool public function hasCpp(): bool
{ {
// judge cpp-extension // judge cpp-extension
$exts = array_keys($this->getExts()); $exts = array_keys($this->getExts(false));
foreach ($exts as $ext) { foreach ($exts as $ext) {
if (Config::getExt($ext, 'cpp-extension', false) === true) { if (Config::getExt($ext, 'cpp-extension', false) === true) {
return true; return true;
@@ -170,9 +173,20 @@ abstract class BuilderBase
* @throws \Throwable|WrongUsageException * @throws \Throwable|WrongUsageException
* @internal * @internal
*/ */
public function proveExts(array $extensions, bool $skip_check_deps = false): void public function proveExts(array $extensions, bool $skip_check_deps = false, array $shared_build_extensions = []): void
{ {
CustomExt::loadCustomExt(); CustomExt::loadCustomExt();
// judge ext
foreach ($extensions as $ext) {
// if extension does not support static && no shared build, throw exception
if (!in_array('static', Config::getExtTarget($ext)) && !in_array($ext, $shared_build_extensions)) {
throw new WrongUsageException('Extension [' . $ext . '] does not support static build !');
}
// if extension does not support shared && no static build, throw exception
if (!in_array('shared', Config::getExtTarget($ext)) && !in_array($ext, $shared_build_extensions)) {
throw new WrongUsageException('Extension [' . $ext . '] does not support shared build !');
}
}
$this->emitPatchPoint('before-php-extract'); $this->emitPatchPoint('before-php-extract');
SourceManager::initSource(sources: ['php-src']); SourceManager::initSource(sources: ['php-src']);
$this->emitPatchPoint('after-php-extract'); $this->emitPatchPoint('after-php-extract');
@@ -186,15 +200,21 @@ abstract class BuilderBase
$this->emitPatchPoint('after-exts-extract'); $this->emitPatchPoint('after-exts-extract');
foreach ($extensions as $extension) { foreach ($extensions as $extension) {
$class = CustomExt::getExtClass($extension); $class = CustomExt::getExtClass($extension);
/** @var Extension $ext */
$ext = new $class($extension, $this); $ext = new $class($extension, $this);
$this->addExt($ext); $this->addExt($ext);
if (in_array($extension, $shared_build_extensions)) {
$ext->setBuildShared();
} else {
$ext->setBuildStatic();
}
} }
if ($skip_check_deps) { if ($skip_check_deps) {
return; return;
} }
foreach ($this->exts as $ext) { foreach ($this->getExts() as $ext) {
$ext->checkDependency(); $ext->checkDependency();
} }
$this->ext_list = $extensions; $this->ext_list = $extensions;
@@ -207,6 +227,17 @@ abstract class BuilderBase
*/ */
abstract public function buildPHP(int $build_target = BUILD_TARGET_NONE); abstract public function buildPHP(int $build_target = BUILD_TARGET_NONE);
public function buildDynamicExts(): void
{
foreach ($this->getExts() as $ext) {
if (!$ext->isBuildShared()) {
continue;
}
logger()->info('Building extension [' . $ext->getName() . '] as shared extension (' . $ext->getName() . '.so)');
$ext->buildShared();
}
}
/** /**
* Generate extension enable arguments for configure. * Generate extension enable arguments for configure.
* e.g. --enable-mbstring * e.g. --enable-mbstring
@@ -214,10 +245,10 @@ abstract class BuilderBase
* @throws FileSystemException * @throws FileSystemException
* @throws WrongUsageException * @throws WrongUsageException
*/ */
public function makeExtensionArgs(): string public function makeStaticExtensionArgs(): string
{ {
$ret = []; $ret = [];
foreach ($this->exts as $ext) { foreach ($this->getExts(false) as $ext) {
logger()->info($ext->getName() . ' is using ' . $ext->getConfigureArg()); logger()->info($ext->getName() . ' is using ' . $ext->getConfigureArg());
$ret[] = trim($ext->getConfigureArg()); $ret[] = trim($ext->getConfigureArg());
} }
@@ -396,7 +427,7 @@ abstract class BuilderBase
foreach ($this->libs as $lib) { foreach ($this->libs as $lib) {
$lib->validate(); $lib->validate();
} }
foreach ($this->exts as $ext) { foreach ($this->getExts() as $ext) {
$ext->validate(); $ext->validate();
} }
} }
@@ -441,7 +472,7 @@ abstract class BuilderBase
{ {
$php = "<?php\n\necho '[micro-test-start]' . PHP_EOL;\n"; $php = "<?php\n\necho '[micro-test-start]' . PHP_EOL;\n";
foreach ($this->getExts() as $ext) { foreach ($this->getExts(false) as $ext) {
$ext_name = $ext->getDistName(); $ext_name = $ext->getDistName();
if (!empty($ext_name)) { if (!empty($ext_name)) {
$php .= "echo 'Running micro with {$ext_name} test' . PHP_EOL;\n"; $php .= "echo 'Running micro with {$ext_name} test' . PHP_EOL;\n";

View File

@@ -14,6 +14,12 @@ class Extension
{ {
protected array $dependencies = []; protected array $dependencies = [];
protected bool $build_shared = false;
protected bool $build_static = false;
protected string $source_dir;
/** /**
* @throws FileSystemException * @throws FileSystemException
* @throws RuntimeException * @throws RuntimeException
@@ -30,6 +36,18 @@ class Extension
if (PHP_OS_FAMILY === 'Windows' && $unix_only) { if (PHP_OS_FAMILY === 'Windows' && $unix_only) {
throw new RuntimeException("{$ext_type} extension {$name} is not supported on Windows platform"); throw new RuntimeException("{$ext_type} extension {$name} is not supported on Windows platform");
} }
// set source_dir for builtin
if ($ext_type === 'builtin') {
$this->source_dir = SOURCE_PATH . '/php-src/ext/' . $this->name;
} else {
$source = Config::getExt($this->name, 'source');
if ($source === null) {
throw new RuntimeException("{$ext_type} extension {$name} source not found");
}
$source_path = Config::getSource($source)['path'] ?? null;
$source_path = $source_path === null ? SOURCE_PATH . '/' . $source : SOURCE_PATH . '/' . $source_path;
$this->source_dir = $source_path;
}
} }
/** /**
@@ -167,6 +185,11 @@ class Extension
return false; return false;
} }
/**
* Run shared extension check when cli is enabled
*/
public function runSharedExtensionCheckUnix(): void {}
/** /**
* @throws RuntimeException * @throws RuntimeException
*/ */
@@ -231,6 +254,32 @@ class Extension
// do nothing, just throw wrong usage exception if not valid // do nothing, just throw wrong usage exception if not valid
} }
public function buildShared(): void
{
match (PHP_OS_FAMILY) {
'Darwin', 'Linux' => $this->buildUnixShared(),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
};
}
public function buildUnixShared(): void
{
// prepare configure args
shell()->cd($this->source_dir)
->setEnv(['CFLAGS' => $this->builder->arch_c_flags])
->execWithEnv(BUILD_BIN_PATH . '/phpize')
->execWithEnv('./configure ' . $this->getUnixConfigureArg() . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config --enable-static --disable-shared')
->execWithEnv('make clean')
->execWithEnv('make -j' . $this->builder->concurrency);
// copy shared library
copy($this->source_dir . '/modules/' . $this->getDistName() . '.so', BUILD_LIB_PATH . '/' . $this->getDistName() . '.so');
// check shared extension with php-cli
if (file_exists(BUILD_BIN_PATH . '/php')) {
$this->runSharedExtensionCheckUnix();
}
}
/** /**
* Get current extension version * Get current extension version
* *
@@ -241,6 +290,29 @@ class Extension
return null; return null;
} }
public function setBuildStatic(): void
{
$this->build_static = true;
}
public function setBuildShared(): void
{
if (!in_array('shared', Config::getExtTarget($this->name)) || Config::getExt($this->name, 'type') === 'builtin') {
throw new WrongUsageException("Extension [{$this->name}] does not support shared build !");
}
$this->build_shared = true;
}
public function isBuildShared(): bool
{
return $this->build_shared;
}
public function isBuildStatic(): bool
{
return $this->build_static;
}
/** /**
* @throws RuntimeException * @throws RuntimeException
*/ */

View File

@@ -5,7 +5,17 @@ declare(strict_types=1);
namespace SPC\builder\extension; namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\util\DynamicExt; use SPC\exception\RuntimeException;
use SPC\util\CustomExt;
#[DynamicExt] #[CustomExt('xdebug')]
class xdebug extends Extension {} class xdebug extends Extension
{
public function runSharedExtensionCheckUnix(): void
{
[$ret] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -d "zend_extension=' . BUILD_LIB_PATH . '/xdebug.so" --ri xdebug');
if ($ret !== 0) {
throw new RuntimeException('xdebug.so not found');
}
}
}

View File

@@ -118,7 +118,7 @@ class BSDBuilder extends UnixBuilderBase
$config_file_scan_dir . $config_file_scan_dir .
$json_74 . $json_74 .
$zts . $zts .
$this->makeExtensionArgs() $this->makeStaticExtensionArgs()
); );
$this->emitPatchPoint('before-php-make'); $this->emitPatchPoint('before-php-make');

View File

@@ -149,6 +149,7 @@ class LinuxBuilder extends UnixBuilderBase
$enable_fpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM; $enable_fpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enable_micro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; $enable_micro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enable_embed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; $enable_embed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
$emable_dev = ($build_target & BUILD_TARGET_DEV) === BUILD_TARGET_DEV;
$mimallocLibs = $this->getLib('mimalloc') !== null ? BUILD_LIB_PATH . '/mimalloc.o ' : ''; $mimallocLibs = $this->getLib('mimalloc') !== null ? BUILD_LIB_PATH . '/mimalloc.o ' : '';
// prepare build php envs // prepare build php envs
@@ -182,7 +183,7 @@ class LinuxBuilder extends UnixBuilderBase
$json_74 . $json_74 .
$zts . $zts .
$maxExecutionTimers . $maxExecutionTimers .
$this->makeExtensionArgs() . $this->makeStaticExtensionArgs() .
' ' . $envs_build_php . ' ' ' ' . $envs_build_php . ' '
); );
@@ -203,6 +204,11 @@ class LinuxBuilder extends UnixBuilderBase
logger()->info('building micro'); logger()->info('building micro');
$this->buildMicro(); $this->buildMicro();
} }
if ($emable_dev && !$enable_embed) {
// install dynamic php extension building
logger()->info('building dynamic php extension dev dependencies');
$this->buildPhpDev();
}
if ($enable_embed) { if ($enable_embed) {
logger()->info('building embed'); logger()->info('building embed');
if ($enable_micro) { if ($enable_micro) {
@@ -311,15 +317,15 @@ class LinuxBuilder extends UnixBuilderBase
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install"); ->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'"); $this->patchPhpScripts();
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#'); }
$php_config_str = FileSystem::readFile(BUILD_BIN_PATH . '/php-config');
str_replace('prefix=""', 'prefix="' . BUILD_ROOT_PATH . '"', $php_config_str); protected function buildPhpDev(): void
// move mimalloc to the beginning of libs {
$php_config_str = preg_replace('/(libs=")(.*?)\s*(' . preg_quote(BUILD_LIB_PATH, '/') . '\/mimalloc\.o)\s*(.*?)"/', '$1$3 $2 $4"', $php_config_str); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
// move lstdc++ to the end of libs shell()->cd(SOURCE_PATH . '/php-src')
$php_config_str = preg_replace('/(libs=")(.*?)\s*(-lstdc\+\+)\s*(.*?)"/', '$1$2 $4 $3"', $php_config_str); ->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install-build install-programs install-headers");
FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str); $this->patchPhpScripts();
} }
private function getMakeExtraVars(): array private function getMakeExtraVars(): array

View File

@@ -1,15 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\util\DynamicExt;
#[DynamicExt]
class xdebug extends LinuxLibraryBase
{
use \SPC\builder\unix\library\xdebug;
public const NAME = 'xdebug';
}

View File

@@ -146,6 +146,7 @@ class MacOSBuilder extends UnixBuilderBase
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM; $enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; $enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; $enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
$enableDev = ($build_target & BUILD_TARGET_DEV) === BUILD_TARGET_DEV;
// prepare build php envs // prepare build php envs
$mimallocLibs = $this->getLib('mimalloc') !== null ? BUILD_LIB_PATH . '/mimalloc.o ' : ''; $mimallocLibs = $this->getLib('mimalloc') !== null ? BUILD_LIB_PATH . '/mimalloc.o ' : '';
@@ -176,7 +177,7 @@ class MacOSBuilder extends UnixBuilderBase
$config_file_scan_dir . $config_file_scan_dir .
$json_74 . $json_74 .
$zts . $zts .
$this->makeExtensionArgs() . ' ' . $this->makeStaticExtensionArgs() . ' ' .
$envs_build_php $envs_build_php
); );
@@ -197,6 +198,11 @@ class MacOSBuilder extends UnixBuilderBase
logger()->info('building micro'); logger()->info('building micro');
$this->buildMicro(); $this->buildMicro();
} }
if ($enableDev && !$enableEmbed) {
// install dynamic php extension building
logger()->info('building dynamic php extension dev dependencies');
$this->buildPhpDev();
}
if ($enableEmbed) { if ($enableEmbed) {
logger()->info('building embed'); logger()->info('building embed');
if ($enableMicro) { if ($enableMicro) {
@@ -300,13 +306,15 @@ class MacOSBuilder extends UnixBuilderBase
->exec('rm ' . BUILD_ROOT_PATH . '/lib/libphp.a') ->exec('rm ' . BUILD_ROOT_PATH . '/lib/libphp.a')
->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o') ->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o')
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o'); ->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o');
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'"); $this->patchPhpScripts();
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#'); }
$php_config_str = FileSystem::readFile(BUILD_BIN_PATH . '/php-config');
str_replace('prefix=""', 'prefix="' . BUILD_ROOT_PATH . '"', $php_config_str); protected function buildPhpDev(): void
// move mimalloc to the beginning of libs {
$php_config_str = preg_replace('/(libs=")(.*?)\s*(' . preg_quote(BUILD_LIB_PATH, '/') . '\/mimalloc\.o)\s*(.*?)"/', '$1$3 $2 $4"', $php_config_str); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str); shell()->cd(SOURCE_PATH . '/php-src')
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install-build install-programs install-headers");
$this->patchPhpScripts();
} }
private function getMakeExtraVars(): array private function getMakeExtraVars(): array

View File

@@ -146,7 +146,7 @@ abstract class UnixBuilderBase extends BuilderBase
throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]"); throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]");
} }
foreach ($this->exts as $ext) { foreach ($this->getExts(false) as $ext) {
logger()->debug('testing ext: ' . $ext->getName()); logger()->debug('testing ext: ' . $ext->getName());
$ext->runCliCheckUnix(); $ext->runCliCheckUnix();
} }
@@ -238,4 +238,29 @@ abstract class UnixBuilderBase extends BuilderBase
logger()->info('cleaning up'); logger()->info('cleaning up');
shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean'); shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean');
} }
/**
* Patch phpize and php-config if needed
* @throws FileSystemException
*/
protected function patchPhpScripts(): void
{
// patch phpize
if (file_exists(BUILD_BIN_PATH . '/phpize')) {
logger()->debug('Patching phpize prefix');
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'");
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#');
}
// patch php-config
if (file_exists(BUILD_BIN_PATH . '/php-config')) {
logger()->debug('Patching php-config prefix and libs order');
$php_config_str = FileSystem::readFile(BUILD_BIN_PATH . '/php-config');
$php_config_str = str_replace('prefix=""', 'prefix="' . BUILD_ROOT_PATH . '"', $php_config_str);
// move mimalloc to the beginning of libs
$php_config_str = preg_replace('/(libs=")(.*?)\s*(' . preg_quote(BUILD_LIB_PATH, '/') . '\/mimalloc\.o)\s*(.*?)"/', '$1$3 $2 $4"', $php_config_str);
// move lstdc++ to the end of libs
$php_config_str = preg_replace('/(libs=")(.*?)\s*(-lstdc\+\+)\s*(.*?)"/', '$1$2 $4 $3"', $php_config_str);
FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str);
}
}
} }

View File

@@ -26,9 +26,9 @@ trait libcares
{ {
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()])
->execWithEnv('./configure --prefix= --enable-static --disable-shared --disable-tests') ->execWithEnv('./configure --prefix= --enable-static --disable-shared --disable-tests --with-pic')
->execWithEnv("make -j {$this->builder->concurrency}") ->execWithEnv("make -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH); ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['libcares.pc'], PKGCONF_PATCH_PREFIX); $this->patchPkgconfPrefix(['libcares.pc'], PKGCONF_PATCH_PREFIX);
} }

View File

@@ -1,26 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
trait xdebug
{
/**
* @throws RuntimeException
* @throws FileSystemException
*/
public function build(): void
{
shell()->cd($this->source_dir)
->exec(BUILD_BIN_PATH . '/phpize')
->exec('./configure --with-php-config=' . BUILD_BIN_PATH . '/php-config')
->exec('make clean')
->exec("make -j{$this->builder->concurrency}");
copy($this->source_dir . '/modules/xdebug.so', BUILD_LIB_PATH . '/xdebug.so');
copy($this->source_dir . '/modules/xdebug.la', BUILD_LIB_PATH . '/xdebug.la');
}
}

View File

@@ -119,7 +119,7 @@ class WindowsBuilder extends BuilderBase
($enableMicro ? ('--enable-micro=yes ' . $micro_logo . $micro_w32) : '--enable-micro=no ') . ($enableMicro ? ('--enable-micro=yes ' . $micro_logo . $micro_w32) : '--enable-micro=no ') .
($enableEmbed ? '--enable-embed=yes ' : '--enable-embed=no ') . ($enableEmbed ? '--enable-embed=yes ' : '--enable-embed=no ') .
$config_file_scan_dir . $config_file_scan_dir .
"{$this->makeExtensionArgs()} " . "{$this->makeStaticExtensionArgs()} " .
$zts . $zts .
'"' '"'
); );
@@ -286,7 +286,7 @@ class WindowsBuilder extends BuilderBase
throw new RuntimeException('cli failed sanity check'); throw new RuntimeException('cli failed sanity check');
} }
foreach ($this->exts as $ext) { foreach ($this->getExts(false) as $ext) {
logger()->debug('testing ext: ' . $ext->getName()); logger()->debug('testing ext: ' . $ext->getName());
$ext->runCliCheckWindows(); $ext->runCliCheckWindows();
} }

View File

@@ -61,6 +61,18 @@ class BuildPHPCommand extends BuildCommand
// parse rule with options // parse rule with options
$rule = $this->parseRules($dynamic_extensions); $rule = $this->parseRules($dynamic_extensions);
// check dynamic extension build env
// macOS must use --no-strip option
if (!empty($dynamic_extensions) && PHP_OS_FAMILY === 'Darwin' && !$this->getOption('no-strip')) {
$this->output->writeln('MacOS does not support dynamic extension loading with stripped binary, please use --no-strip option!');
return static::FAILURE;
}
// linux must build with glibc
if (!empty($dynamic_extensions) && PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') !== 'glibc') {
$this->output->writeln('Linux does not support dynamic extension loading with musl-libc full-static build, please build with glibc!');
return static::FAILURE;
}
if ($rule === BUILD_TARGET_NONE || $rule === BUILD_TARGET_DEV) { if ($rule === BUILD_TARGET_NONE || $rule === BUILD_TARGET_DEV) {
$this->output->writeln('<error>Please add at least one build SAPI!</error>'); $this->output->writeln('<error>Please add at least one build SAPI!</error>');
$this->output->writeln("<comment>\t--build-cli\tBuild php-cli SAPI</comment>"); $this->output->writeln("<comment>\t--build-cli\tBuild php-cli SAPI</comment>");
@@ -124,7 +136,7 @@ class BuildPHPCommand extends BuildCommand
'Strip Binaries' => $builder->getOption('no-strip') ? 'no' : 'yes', 'Strip Binaries' => $builder->getOption('no-strip') ? 'no' : 'yes',
'Enable ZTS' => $builder->getOption('enable-zts') ? 'yes' : 'no', 'Enable ZTS' => $builder->getOption('enable-zts') ? 'yes' : 'no',
]; ];
if (!empty($dynamic_exts) || ($rule & BUILD_TARGET_EMBED) || ($rule & BUILD_TARGET_DEV)) { if (!empty($dynamic_extensions) || ($rule & BUILD_TARGET_EMBED) || ($rule & BUILD_TARGET_DEV)) {
$indent_texts['Build Dev'] = 'yes'; $indent_texts['Build Dev'] = 'yes';
} }
if (!empty($this->input->getOption('with-config-file-path'))) { if (!empty($this->input->getOption('with-config-file-path'))) {
@@ -192,7 +204,8 @@ class BuildPHPCommand extends BuildCommand
$builder->buildPHP($rule); $builder->buildPHP($rule);
// build dynamic extensions if needed // build dynamic extensions if needed
if (!empty($dynamic_exts)) { if (!empty($dynamic_extensions)) {
logger()->info('Building dynamic extensions ...');
$builder->buildDynamicExts(); $builder->buildDynamicExts();
} }
@@ -224,6 +237,12 @@ class BuildPHPCommand extends BuildCommand
$path = FileSystem::convertPath("{$build_root_path}/bin/php-fpm"); $path = FileSystem::convertPath("{$build_root_path}/bin/php-fpm");
logger()->info("Static php-fpm binary path{$fixed}: {$path}"); logger()->info("Static php-fpm binary path{$fixed}: {$path}");
} }
if (!empty($dynamic_extensions)) {
foreach ($dynamic_extensions as $ext) {
$path = FileSystem::convertPath("{$build_root_path}/ext/{$ext}.so");
logger()->info("Dynamic extension path{$fixed}: {$path}");
}
}
// export metadata // export metadata
file_put_contents(BUILD_ROOT_PATH . '/build-extensions.json', json_encode($extensions, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); file_put_contents(BUILD_ROOT_PATH . '/build-extensions.json', json_encode($extensions, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));

View File

@@ -127,10 +127,6 @@ class Downloader
if (!$match_result) { if (!$match_result) {
return $release['assets']; return $release['assets'];
} }
if ($source['match'] === 'Source code') {
$url = $release['tarball_url'];
break;
}
foreach ($release['assets'] as $asset) { foreach ($release['assets'] as $asset) {
if (preg_match('|' . $source['match'] . '|', $asset['name'])) { if (preg_match('|' . $source['match'] . '|', $asset['name'])) {
$url = $asset['browser_download_url']; $url = $asset['browser_download_url'];
@@ -143,9 +139,6 @@ class Downloader
throw new DownloaderException("failed to find {$name} release metadata"); throw new DownloaderException("failed to find {$name} release metadata");
} }
$filename = basename($url); $filename = basename($url);
if ($source['match'] === 'Source code') {
$filename = $name . $filename . '.tar.gz';
}
return [$url, $filename]; return [$url, $filename];
} }

View File

@@ -43,7 +43,7 @@ class SourcePatcher
*/ */
public static function patchBeforeBuildconf(BuilderBase $builder): void public static function patchBeforeBuildconf(BuilderBase $builder): void
{ {
foreach ($builder->getExts() as $ext) { foreach ($builder->getExts(false) as $ext) {
if ($ext->patchBeforeBuildconf() === true) { if ($ext->patchBeforeBuildconf() === true) {
logger()->info('Extension [' . $ext->getName() . '] patched before buildconf'); logger()->info('Extension [' . $ext->getName() . '] patched before buildconf');
} }
@@ -86,7 +86,7 @@ class SourcePatcher
*/ */
public static function patchBeforeConfigure(BuilderBase $builder): void public static function patchBeforeConfigure(BuilderBase $builder): void
{ {
foreach ($builder->getExts() as $ext) { foreach ($builder->getExts(false) as $ext) {
if ($ext->patchBeforeConfigure() === true) { if ($ext->patchBeforeConfigure() === true) {
logger()->info('Extension [' . $ext->getName() . '] patched before configure'); logger()->info('Extension [' . $ext->getName() . '] patched before configure');
} }
@@ -253,7 +253,7 @@ class SourcePatcher
// } // }
// call extension patch before make // call extension patch before make
foreach ($builder->getExts() as $ext) { foreach ($builder->getExts(false) as $ext) {
if ($ext->patchBeforeMake() === true) { if ($ext->patchBeforeMake() === true) {
logger()->info('Extension [' . $ext->getName() . '] patched before make'); logger()->info('Extension [' . $ext->getName() . '] patched before make');
} }

View File

@@ -1,8 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\util;
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)]
class DynamicExt {}

View File

@@ -61,7 +61,8 @@ const BUILD_TARGET_CLI = 1; // build cli
const BUILD_TARGET_MICRO = 2; // build micro const BUILD_TARGET_MICRO = 2; // build micro
const BUILD_TARGET_FPM = 4; // build fpm const BUILD_TARGET_FPM = 4; // build fpm
const BUILD_TARGET_EMBED = 8; // build embed const BUILD_TARGET_EMBED = 8; // build embed
const BUILD_TARGET_ALL = 15; // build all const BUILD_TARGET_DEV = 16; // build dev
const BUILD_TARGET_ALL = 31; // build all
// doctor error fix policy // doctor error fix policy
const FIX_POLICY_DIE = 1; // die directly const FIX_POLICY_DIE = 1; // die directly

View File

@@ -72,7 +72,7 @@ class BuilderTest extends TestCase
public function testMakeExtensionArgs() public function testMakeExtensionArgs()
{ {
$this->assertStringContainsString('--enable-mbstring', $this->builder->makeExtensionArgs()); $this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs());
} }
public function testIsLibsOnly() public function testIsLibsOnly()