mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-17 20:34:51 +08:00
Merge branch 'main' into pgsql-18
This commit is contained in:
commit
ae1193ab16
@ -34,6 +34,7 @@
|
|||||||
; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
|
; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
|
||||||
; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
|
; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
|
||||||
; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
|
; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
|
||||||
|
; SPC_EXTRA_PHP_VARS: the extra vars for building php, used in `configure` and `make` command.
|
||||||
|
|
||||||
[global]
|
[global]
|
||||||
; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs.
|
; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs.
|
||||||
|
|||||||
@ -759,11 +759,9 @@
|
|||||||
},
|
},
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "custom",
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"ext-depends": [
|
||||||
"libxml2"
|
"libxml",
|
||||||
],
|
"session"
|
||||||
"ext-depends-windows": [
|
|
||||||
"xml"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sockets": {
|
"sockets": {
|
||||||
|
|||||||
@ -202,6 +202,7 @@
|
|||||||
"openssl",
|
"openssl",
|
||||||
"libcares"
|
"libcares"
|
||||||
],
|
],
|
||||||
|
"cpp-library": true,
|
||||||
"provide-pre-built": true,
|
"provide-pre-built": true,
|
||||||
"frameworks": [
|
"frameworks": [
|
||||||
"CoreFoundation"
|
"CoreFoundation"
|
||||||
@ -230,6 +231,7 @@
|
|||||||
},
|
},
|
||||||
"imagemagick": {
|
"imagemagick": {
|
||||||
"source": "imagemagick",
|
"source": "imagemagick",
|
||||||
|
"cpp-library": true,
|
||||||
"pkg-configs": [
|
"pkg-configs": [
|
||||||
"Magick++-7.Q16HDRI",
|
"Magick++-7.Q16HDRI",
|
||||||
"MagickCore-7.Q16HDRI",
|
"MagickCore-7.Q16HDRI",
|
||||||
@ -822,6 +824,7 @@
|
|||||||
},
|
},
|
||||||
"snappy": {
|
"snappy": {
|
||||||
"source": "snappy",
|
"source": "snappy",
|
||||||
|
"cpp-library": true,
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
"libsnappy.a"
|
"libsnappy.a"
|
||||||
],
|
],
|
||||||
@ -867,6 +870,7 @@
|
|||||||
},
|
},
|
||||||
"watcher": {
|
"watcher": {
|
||||||
"source": "watcher",
|
"source": "watcher",
|
||||||
|
"cpp-library": true,
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
"libwatcher-c.a"
|
"libwatcher-c.a"
|
||||||
],
|
],
|
||||||
|
|||||||
@ -324,7 +324,7 @@
|
|||||||
},
|
},
|
||||||
"grpc": {
|
"grpc": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"rev": "v1.68.x",
|
"rev": "v1.75.x",
|
||||||
"url": "https://github.com/grpc/grpc.git",
|
"url": "https://github.com/grpc/grpc.git",
|
||||||
"provide-pre-built": true,
|
"provide-pre-built": true,
|
||||||
"license": {
|
"license": {
|
||||||
|
|||||||
@ -128,27 +128,6 @@ abstract class BuilderBase
|
|||||||
return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic());
|
return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is a cpp extensions or libraries.
|
|
||||||
*/
|
|
||||||
public function hasCpp(): bool
|
|
||||||
{
|
|
||||||
// judge cpp-extension
|
|
||||||
$exts = array_keys($this->getExts(false));
|
|
||||||
foreach ($exts as $ext) {
|
|
||||||
if (Config::getExt($ext, 'cpp-extension', false) === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$libs = array_keys($this->getLibs());
|
|
||||||
foreach ($libs as $lib) {
|
|
||||||
if (Config::getLib($lib, 'cpp-library', false) === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set libs only mode.
|
* Set libs only mode.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -5,16 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace SPC\builder;
|
namespace SPC\builder;
|
||||||
|
|
||||||
use SPC\exception\EnvironmentException;
|
use SPC\exception\EnvironmentException;
|
||||||
use SPC\exception\FileSystemException;
|
|
||||||
use SPC\exception\SPCException;
|
use SPC\exception\SPCException;
|
||||||
use SPC\exception\ValidationException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\toolchain\ClangNativeToolchain;
|
|
||||||
use SPC\toolchain\GccNativeToolchain;
|
|
||||||
use SPC\toolchain\ToolchainManager;
|
|
||||||
use SPC\toolchain\ZigToolchain;
|
|
||||||
use SPC\util\SPCConfigUtil;
|
use SPC\util\SPCConfigUtil;
|
||||||
use SPC\util\SPCTarget;
|
use SPC\util\SPCTarget;
|
||||||
|
|
||||||
@ -226,12 +221,24 @@ class Extension
|
|||||||
public function patchBeforeSharedMake(): bool
|
public function patchBeforeSharedMake(): bool
|
||||||
{
|
{
|
||||||
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
|
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
|
||||||
[$staticLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
|
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
|
||||||
FileSystem::replaceFileRegex(
|
$lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null;
|
||||||
$this->source_dir . '/Makefile',
|
$lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '';
|
||||||
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
|
|
||||||
'$1 ' . trim($staticLibs)
|
$makefileContent = file_get_contents($this->source_dir . '/Makefile');
|
||||||
);
|
if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) {
|
||||||
|
$prefix = $matches[1];
|
||||||
|
$currentLibs = trim($matches[2]);
|
||||||
|
$newLibs = trim("{$currentLibs} {$staticLibs} {$lstdcpp}");
|
||||||
|
$deduplicatedLibs = deduplicate_flags($newLibs);
|
||||||
|
|
||||||
|
FileSystem::replaceFileRegex(
|
||||||
|
$this->source_dir . '/Makefile',
|
||||||
|
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
|
||||||
|
$prefix . $deduplicatedLibs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) {
|
if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) {
|
||||||
FileSystem::replaceFileRegex(
|
FileSystem::replaceFileRegex(
|
||||||
$this->source_dir . '/Makefile',
|
$this->source_dir . '/Makefile',
|
||||||
@ -405,42 +412,7 @@ class Extension
|
|||||||
*/
|
*/
|
||||||
public function buildUnixShared(): void
|
public function buildUnixShared(): void
|
||||||
{
|
{
|
||||||
$config = (new SPCConfigUtil($this->builder))->config(
|
$env = $this->getSharedExtensionEnv();
|
||||||
[$this->getName()],
|
|
||||||
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
|
|
||||||
$this->builder->getOption('with-suggested-exts'),
|
|
||||||
$this->builder->getOption('with-suggested-libs'),
|
|
||||||
);
|
|
||||||
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
|
|
||||||
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
|
|
||||||
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
|
|
||||||
$env = [
|
|
||||||
'CFLAGS' => $config['cflags'],
|
|
||||||
'CXXFLAGS' => $config['cflags'],
|
|
||||||
'LDFLAGS' => $config['ldflags'],
|
|
||||||
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
|
|
||||||
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
|
|
||||||
];
|
|
||||||
if (str_contains($env['LIBS'], '-lstdc++') && SPCTarget::getTargetOS() === 'Linux') {
|
|
||||||
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
|
|
||||||
$env['SPC_COMPILER_EXTRA'] = '-lstdc++';
|
|
||||||
} elseif (ToolchainManager::getToolchainClass() === GccNativeToolchain::class || ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) {
|
|
||||||
try {
|
|
||||||
$content = FileSystem::readFile($this->source_dir . '/config.m4');
|
|
||||||
if ($content && !str_contains($content, 'PHP_ADD_LIBRARY(stdc++')) {
|
|
||||||
$pattern = '/(PHP_NEW_EXTENSION\(' . $this->name . ',.*\))/m';
|
|
||||||
$replacement = "$1\nPHP_ADD_LIBRARY(stdc++, 1, " . strtoupper($this->name) . '_SHARED_LIBADD)';
|
|
||||||
FileSystem::replaceFileRegex(
|
|
||||||
$this->source_dir . '/config.m4',
|
|
||||||
$pattern,
|
|
||||||
$replacement
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (FileSystemException) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->patchBeforeSharedPhpize()) {
|
if ($this->patchBeforeSharedPhpize()) {
|
||||||
logger()->info("Extension [{$this->getName()}] patched before shared phpize");
|
logger()->info("Extension [{$this->getName()}] patched before shared phpize");
|
||||||
}
|
}
|
||||||
@ -455,13 +427,15 @@ class Extension
|
|||||||
logger()->info("Extension [{$this->getName()}] patched before shared configure");
|
logger()->info("Extension [{$this->getName()}] patched before shared configure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
|
||||||
|
|
||||||
shell()->cd($this->source_dir)
|
shell()->cd($this->source_dir)
|
||||||
->setEnv($env)
|
->setEnv($env)
|
||||||
->appendEnv($this->getExtraEnv())
|
->appendEnv($this->getExtraEnv())
|
||||||
->exec(
|
->exec(
|
||||||
'./configure ' . $this->getUnixConfigureArg(true) .
|
'./configure ' . $this->getUnixConfigureArg(true) .
|
||||||
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
|
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
|
||||||
'--enable-shared --disable-static'
|
"--enable-shared --disable-static {$phpvars}"
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($this->patchBeforeSharedMake()) {
|
if ($this->patchBeforeSharedMake()) {
|
||||||
@ -512,6 +486,30 @@ class Extension
|
|||||||
return $this->build_static;
|
return $this->build_static;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the environment variables a shared extension needs to be built.
|
||||||
|
* CFLAGS, CXXFLAGS, LDFLAGS and so on.
|
||||||
|
*/
|
||||||
|
protected function getSharedExtensionEnv(): array
|
||||||
|
{
|
||||||
|
$config = (new SPCConfigUtil($this->builder))->config(
|
||||||
|
[$this->getName()],
|
||||||
|
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
|
||||||
|
$this->builder->getOption('with-suggested-exts'),
|
||||||
|
$this->builder->getOption('with-suggested-libs'),
|
||||||
|
);
|
||||||
|
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
|
||||||
|
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
|
||||||
|
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
|
||||||
|
return [
|
||||||
|
'CFLAGS' => $config['cflags'],
|
||||||
|
'CXXFLAGS' => $config['cflags'],
|
||||||
|
'LDFLAGS' => $config['ldflags'],
|
||||||
|
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
|
||||||
|
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
protected function addLibraryDependency(string $name, bool $optional = false): void
|
protected function addLibraryDependency(string $name, bool $optional = false): void
|
||||||
{
|
{
|
||||||
$depLib = $this->builder->getLib($name);
|
$depLib = $this->builder->getLib($name);
|
||||||
@ -584,12 +582,12 @@ class Extension
|
|||||||
$added = 0;
|
$added = 0;
|
||||||
foreach ($ret as $depName => $dep) {
|
foreach ($ret as $depName => $dep) {
|
||||||
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
|
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
|
||||||
if (!in_array($depdepName, array_keys($deps), true)) {
|
if (!array_key_exists($depdepName, $deps)) {
|
||||||
$deps[$depdepName] = $depdep;
|
$deps[$depdepName] = $depdep;
|
||||||
++$added;
|
++$added;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!in_array($depName, array_keys($deps), true)) {
|
if (!array_key_exists($depName, $deps)) {
|
||||||
$deps[$depName] = $dep;
|
$deps[$depName] = $dep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,4 +56,11 @@ class grpc extends Extension
|
|||||||
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
|
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getSharedExtensionEnv(): array
|
||||||
|
{
|
||||||
|
$env = parent::getSharedExtensionEnv();
|
||||||
|
$env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes';
|
||||||
|
return $env;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@ namespace SPC\builder\extension;
|
|||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
|
use SPC\toolchain\ToolchainManager;
|
||||||
|
use SPC\toolchain\ZigToolchain;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
#[CustomExt('simdjson')]
|
#[CustomExt('simdjson')]
|
||||||
@ -17,7 +19,7 @@ class simdjson extends Extension
|
|||||||
FileSystem::replaceFileRegex(
|
FileSystem::replaceFileRegex(
|
||||||
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
|
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
|
||||||
'/php_version=(`.*`)$/m',
|
'/php_version=(`.*`)$/m',
|
||||||
'php_version=' . strval($php_ver)
|
'php_version=' . $php_ver
|
||||||
);
|
);
|
||||||
FileSystem::replaceFileStr(
|
FileSystem::replaceFileStr(
|
||||||
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
|
SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
|
||||||
@ -31,4 +33,18 @@ class simdjson extends Extension
|
|||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSharedExtensionEnv(): array
|
||||||
|
{
|
||||||
|
$env = parent::getSharedExtensionEnv();
|
||||||
|
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
|
||||||
|
$extra = getenv('SPC_COMPILER_EXTRA');
|
||||||
|
if (!str_contains((string) $extra, '-lstdc++')) {
|
||||||
|
f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++'));
|
||||||
|
}
|
||||||
|
$env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
|
||||||
|
$env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
|
||||||
|
}
|
||||||
|
return $env;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,6 +95,8 @@ class LinuxBuilder extends UnixBuilderBase
|
|||||||
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
|
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
|
||||||
|
|
||||||
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
|
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
|
||||||
if ($embed_type !== 'static' && SPCTarget::isStatic()) {
|
if ($embed_type !== 'static' && SPCTarget::isStatic()) {
|
||||||
throw new WrongUsageException(
|
throw new WrongUsageException(
|
||||||
@ -116,6 +118,7 @@ class LinuxBuilder extends UnixBuilderBase
|
|||||||
$json_74 .
|
$json_74 .
|
||||||
$zts .
|
$zts .
|
||||||
$maxExecutionTimers .
|
$maxExecutionTimers .
|
||||||
|
"{$phpvars} " .
|
||||||
$this->makeStaticExtensionArgs() . ' '
|
$this->makeStaticExtensionArgs() . ' '
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@ -291,11 +291,11 @@ abstract class UnixBuilderBase extends BuilderBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
|
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
|
||||||
$extLdFlags = "-extldflags '-pie{$dynamic_exports}'";
|
$extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
|
||||||
$muslTags = '';
|
$muslTags = '';
|
||||||
$staticFlags = '';
|
$staticFlags = '';
|
||||||
if (SPCTarget::isStatic()) {
|
if (SPCTarget::isStatic()) {
|
||||||
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports}'";
|
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports} {$this->arch_ld_flags}'";
|
||||||
$muslTags = 'static_build,';
|
$muslTags = 'static_build,';
|
||||||
$staticFlags = '-static-pie';
|
$staticFlags = '-static-pie';
|
||||||
}
|
}
|
||||||
@ -303,7 +303,6 @@ abstract class UnixBuilderBase extends BuilderBase
|
|||||||
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
|
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
|
||||||
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
|
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
|
||||||
$libs = $config['libs'];
|
$libs = $config['libs'];
|
||||||
$libs .= PHP_OS_FAMILY === 'Linux' ? ' -lrt' : '';
|
|
||||||
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
|
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
|
||||||
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
|
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
|
||||||
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&
|
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&
|
||||||
|
|||||||
@ -12,6 +12,11 @@ trait imagemagick
|
|||||||
{
|
{
|
||||||
protected function build(): void
|
protected function build(): void
|
||||||
{
|
{
|
||||||
|
$original_ldflags = $this->builder->arch_ld_flags;
|
||||||
|
if (str_contains($this->builder->arch_ld_flags, '-Wl,--as-needed')) {
|
||||||
|
$this->builder->arch_ld_flags = str_replace('-Wl,--as-needed', '', $original_ldflags);
|
||||||
|
}
|
||||||
|
|
||||||
$ac = UnixAutoconfExecutor::create($this)
|
$ac = UnixAutoconfExecutor::create($this)
|
||||||
->optionalLib('libzip', ...ac_with_args('zip'))
|
->optionalLib('libzip', ...ac_with_args('zip'))
|
||||||
->optionalLib('libjpeg', ...ac_with_args('jpeg'))
|
->optionalLib('libjpeg', ...ac_with_args('jpeg'))
|
||||||
@ -32,7 +37,7 @@ trait imagemagick
|
|||||||
);
|
);
|
||||||
|
|
||||||
// special: linux-static target needs `-static`
|
// special: linux-static target needs `-static`
|
||||||
$ldflags = SPCTarget::isStatic() ? ('-static -ldl') : '-ldl';
|
$ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl';
|
||||||
|
|
||||||
// special: macOS needs -iconv
|
// special: macOS needs -iconv
|
||||||
$libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : '';
|
$libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : '';
|
||||||
@ -45,6 +50,8 @@ trait imagemagick
|
|||||||
|
|
||||||
$ac->configure()->make();
|
$ac->configure()->make();
|
||||||
|
|
||||||
|
$this->builder->arch_ld_flags = $original_ldflags;
|
||||||
|
|
||||||
$filelist = [
|
$filelist = [
|
||||||
'ImageMagick.pc',
|
'ImageMagick.pc',
|
||||||
'ImageMagick-7.Q16HDRI.pc',
|
'ImageMagick-7.Q16HDRI.pc',
|
||||||
|
|||||||
@ -106,7 +106,7 @@ class DownloadCommand extends BaseCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
// retry
|
// retry
|
||||||
$retry = intval($this->getOption('retry'));
|
$retry = (int) $this->getOption('retry');
|
||||||
f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry);
|
f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry);
|
||||||
|
|
||||||
// Use shallow-clone can reduce git resource download
|
// Use shallow-clone can reduce git resource download
|
||||||
@ -265,7 +265,7 @@ class DownloadCommand extends BaseCommand
|
|||||||
f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH);
|
f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH);
|
||||||
}
|
}
|
||||||
// unzip command check
|
// unzip command check
|
||||||
if (PHP_OS_FAMILY !== 'Windows' && !$this->findCommand('unzip')) {
|
if (PHP_OS_FAMILY !== 'Windows' && !self::findCommand('unzip')) {
|
||||||
$this->output->writeln('Missing unzip command, you need to install it first !');
|
$this->output->writeln('Missing unzip command, you need to install it first !');
|
||||||
$this->output->writeln('You can use "bin/spc doctor" command to check and install required tools');
|
$this->output->writeln('You can use "bin/spc doctor" command to check and install required tools');
|
||||||
return static::FAILURE;
|
return static::FAILURE;
|
||||||
|
|||||||
@ -65,19 +65,19 @@ class Downloader
|
|||||||
url: "https://api.github.com/repos/{$source['repo']}/{$type}",
|
url: "https://api.github.com/repos/{$source['repo']}/{$type}",
|
||||||
hooks: [[CurlHook::class, 'setupGithubToken']],
|
hooks: [[CurlHook::class, 'setupGithubToken']],
|
||||||
retries: self::getRetryAttempts()
|
retries: self::getRetryAttempts()
|
||||||
), true);
|
), true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
|
||||||
$url = null;
|
$url = null;
|
||||||
for ($i = 0; $i < count($data); ++$i) {
|
foreach ($data as $rel) {
|
||||||
if (($data[$i]['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) {
|
if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!($source['match'] ?? null)) {
|
if (!($source['match'] ?? null)) {
|
||||||
$url = $data[$i]['tarball_url'] ?? null;
|
$url = $rel['tarball_url'] ?? null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (preg_match('|' . $source['match'] . '|', $data[$i]['tarball_url'])) {
|
if (preg_match('|' . $source['match'] . '|', $rel['tarball_url'])) {
|
||||||
$url = $data[$i]['tarball_url'];
|
$url = $rel['tarball_url'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +232,8 @@ class Downloader
|
|||||||
$quiet = !defined('DEBUG_MODE') ? '-q --quiet' : '';
|
$quiet = !defined('DEBUG_MODE') ? '-q --quiet' : '';
|
||||||
$git = SPC_GIT_EXEC;
|
$git = SPC_GIT_EXEC;
|
||||||
$shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : '';
|
$shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : '';
|
||||||
$recursive = ($submodules === null) ? '--recursive' : '';
|
$recursive = ($submodules === null && defined('GIT_SHALLOW_CLONE')) ? '--recursive --shallow-submodules' : null;
|
||||||
|
$recursive ??= $submodules === null ? '--recursive' : '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self::registerCancelEvent(function () use ($download_path) {
|
self::registerCancelEvent(function () use ($download_path) {
|
||||||
@ -243,8 +244,9 @@ class Downloader
|
|||||||
});
|
});
|
||||||
f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\"");
|
f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\"");
|
||||||
if ($submodules !== null) {
|
if ($submodules !== null) {
|
||||||
|
$depth_flag = defined('GIT_SHALLOW_CLONE') ? '--depth 1' : '';
|
||||||
foreach ($submodules as $submodule) {
|
foreach ($submodules as $submodule) {
|
||||||
f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule));
|
f_passthru("cd \"{$download_path}\" && {$git} submodule update --init {$depth_flag} " . escapeshellarg($submodule));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SPCException $e) {
|
} catch (SPCException $e) {
|
||||||
@ -399,7 +401,7 @@ class Downloader
|
|||||||
* Download source
|
* Download source
|
||||||
*
|
*
|
||||||
* @param string $name source name
|
* @param string $name source name
|
||||||
* @param null|array{
|
* @param null|array{
|
||||||
* type: string,
|
* type: string,
|
||||||
* repo: ?string,
|
* repo: ?string,
|
||||||
* url: ?string,
|
* url: ?string,
|
||||||
@ -414,7 +416,7 @@ class Downloader
|
|||||||
* path: ?string,
|
* path: ?string,
|
||||||
* text: ?string
|
* text: ?string
|
||||||
* }
|
* }
|
||||||
* } $source source meta info: [type, path, rev, url, filename, regex, license]
|
* } $source source meta info: [type, path, rev, url, filename, regex, license]
|
||||||
* @param bool $force Whether to force download (default: false)
|
* @param bool $force Whether to force download (default: false)
|
||||||
* @param int $download_as Lock source type (default: SPC_LOCK_SOURCE)
|
* @param int $download_as Lock source type (default: SPC_LOCK_SOURCE)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -19,9 +19,15 @@ while [[ $# -gt 0 ]]; do
|
|||||||
ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)"
|
ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)"
|
||||||
[[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG")
|
[[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG")
|
||||||
;;
|
;;
|
||||||
-march=*|-mcpu=*) # replace -march=x86-64 with -march=x86_64
|
-march=*|-mcpu=*)
|
||||||
OPT_NAME="${1%%=*}"
|
OPT_NAME="${1%%=*}"
|
||||||
OPT_VALUE="${1#*=}"
|
OPT_VALUE="${1#*=}"
|
||||||
|
# Skip armv8- flags entirely as Zig doesn't support them
|
||||||
|
if [[ "$OPT_VALUE" == armv8-* ]]; then
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# replace -march=x86-64 with -march=x86_64
|
||||||
OPT_VALUE="${OPT_VALUE//-/_}"
|
OPT_VALUE="${OPT_VALUE//-/_}"
|
||||||
PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}")
|
PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}")
|
||||||
shift
|
shift
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class PhpSource extends CustomSourceBase
|
|||||||
} elseif ($major === 'git') {
|
} elseif ($major === 'git') {
|
||||||
Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force);
|
Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force);
|
||||||
} else {
|
} else {
|
||||||
Downloader::downloadSource('php-src', self::getLatestPHPInfo($major), $force);
|
Downloader::downloadSource('php-src', $this->getLatestPHPInfo($major), $force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ class PhpSource extends CustomSourceBase
|
|||||||
// 查找最新的小版本号
|
// 查找最新的小版本号
|
||||||
$info = json_decode(Downloader::curlExec(
|
$info = json_decode(Downloader::curlExec(
|
||||||
url: "https://www.php.net/releases/index.php?json&version={$major_version}",
|
url: "https://www.php.net/releases/index.php?json&version={$major_version}",
|
||||||
retries: intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0)
|
retries: (int) getenv('SPC_DOWNLOAD_RETRIES') ?: 0
|
||||||
), true);
|
), true);
|
||||||
if (!isset($info['version'])) {
|
if (!isset($info['version'])) {
|
||||||
throw new DownloaderException("Version {$major_version} not found.");
|
throw new DownloaderException("Version {$major_version} not found.");
|
||||||
|
|||||||
@ -64,6 +64,11 @@ class ZigToolchain implements ToolchainInterface
|
|||||||
$extra_libs = trim($extra_libs . ' -lunwind');
|
$extra_libs = trim($extra_libs . ' -lunwind');
|
||||||
GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}");
|
GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}");
|
||||||
}
|
}
|
||||||
|
$cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: '';
|
||||||
|
$has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4');
|
||||||
|
if (!$has_avx512) {
|
||||||
|
GlobalEnvManager::putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCompilerInfo(): ?string
|
public function getCompilerInfo(): ?string
|
||||||
|
|||||||
@ -40,7 +40,12 @@ class GlobalEnvManager
|
|||||||
if (is_unix()) {
|
if (is_unix()) {
|
||||||
self::addPathIfNotExists(BUILD_BIN_PATH);
|
self::addPathIfNotExists(BUILD_BIN_PATH);
|
||||||
self::addPathIfNotExists(PKG_ROOT_PATH . '/bin');
|
self::addPathIfNotExists(PKG_ROOT_PATH . '/bin');
|
||||||
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
|
$pkgConfigPath = getenv('PKG_CONFIG_PATH');
|
||||||
|
if ($pkgConfigPath !== false) {
|
||||||
|
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . "/pkgconfig:{$pkgConfigPath}");
|
||||||
|
} else {
|
||||||
|
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ini = self::readIniFile();
|
$ini = self::readIniFile();
|
||||||
|
|||||||
@ -6,6 +6,7 @@ namespace SPC\util;
|
|||||||
|
|
||||||
use SPC\builder\BuilderBase;
|
use SPC\builder\BuilderBase;
|
||||||
use SPC\builder\BuilderProvider;
|
use SPC\builder\BuilderProvider;
|
||||||
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use Symfony\Component\Console\Input\ArgvInput;
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
@ -87,7 +88,7 @@ class SPCConfigUtil
|
|||||||
if (SPCTarget::getTargetOS() === 'Darwin') {
|
if (SPCTarget::getTargetOS() === 'Darwin') {
|
||||||
$libs .= " {$this->getFrameworksString($extensions)}";
|
$libs .= " {$this->getFrameworksString($extensions)}";
|
||||||
}
|
}
|
||||||
if ($this->builder->hasCpp()) {
|
if ($this->hasCpp($extensions, $libraries)) {
|
||||||
$libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++';
|
$libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++';
|
||||||
$libs = str_replace($libcpp, '', $libs) . " {$libcpp}";
|
$libs = str_replace($libcpp, '', $libs) . " {$libcpp}";
|
||||||
}
|
}
|
||||||
@ -123,6 +124,27 @@ class SPCConfigUtil
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function hasCpp(array $extensions, array $libraries): bool
|
||||||
|
{
|
||||||
|
// judge cpp-extension
|
||||||
|
$builderExtNames = array_keys($this->builder->getExts(false));
|
||||||
|
$exts = array_unique([...$builderExtNames, ...$extensions]);
|
||||||
|
|
||||||
|
foreach ($exts as $ext) {
|
||||||
|
if (Config::getExt($ext, 'cpp-extension', false) === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$builderLibNames = array_keys($this->builder->getLibs());
|
||||||
|
$libs = array_unique([...$builderLibNames, ...$libraries]);
|
||||||
|
foreach ($libs as $lib) {
|
||||||
|
if (Config::getLib($lib, 'cpp-library', false) === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private function getIncludesString(array $libraries): string
|
private function getIncludesString(array $libraries): string
|
||||||
{
|
{
|
||||||
$base = BUILD_INCLUDE_PATH;
|
$base = BUILD_INCLUDE_PATH;
|
||||||
|
|||||||
@ -245,6 +245,23 @@ function clean_spaces(string $string): string
|
|||||||
return trim(preg_replace('/\s+/', ' ', $string));
|
return trim(preg_replace('/\s+/', ' ', $string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deduplicate flags in a string. Only the last occurence of each flag will be kept.
|
||||||
|
* E.g. `-lintl -lstdc++ -lphp -lstdc++` becomes `-lintl -lphp -lstdc++`
|
||||||
|
*
|
||||||
|
* @param string $flags the string containing flags to deduplicate
|
||||||
|
* @return string the deduplicated string with no duplicate flags
|
||||||
|
*/
|
||||||
|
function deduplicate_flags(string $flags): string
|
||||||
|
{
|
||||||
|
$tokens = preg_split('/\s+/', trim($flags));
|
||||||
|
|
||||||
|
// Reverse, unique, reverse back - keeps last occurrence of duplicates
|
||||||
|
$deduplicated = array_reverse(array_unique(array_reverse($tokens)));
|
||||||
|
|
||||||
|
return implode(' ', $deduplicated);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a callback function to handle keyboard interrupts (Ctrl+C).
|
* Register a callback function to handle keyboard interrupts (Ctrl+C).
|
||||||
*
|
*
|
||||||
|
|||||||
@ -24,9 +24,9 @@ $test_php_version = [
|
|||||||
// test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available)
|
// test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available)
|
||||||
$test_os = [
|
$test_os = [
|
||||||
// 'macos-13', // bin/spc for x86_64
|
// 'macos-13', // bin/spc for x86_64
|
||||||
// 'macos-14', // bin/spc for arm64
|
'macos-14', // bin/spc for arm64
|
||||||
'macos-15', // bin/spc for arm64
|
'macos-15', // bin/spc for arm64
|
||||||
'ubuntu-latest', // bin/spc-alpine-docker for x86_64
|
// 'ubuntu-latest', // bin/spc-alpine-docker for x86_64
|
||||||
'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
|
'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
|
||||||
'ubuntu-24.04', // bin/spc for x86_64
|
'ubuntu-24.04', // bin/spc for x86_64
|
||||||
'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
|
'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
|
||||||
|
|||||||
@ -62,12 +62,6 @@ class BuilderTest extends TestCase
|
|||||||
$this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex'));
|
$this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHasCpp()
|
|
||||||
{
|
|
||||||
// mbregex doesn't have cpp
|
|
||||||
$this->assertFalse($this->builder->hasCpp());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testMakeExtensionArgs()
|
public function testMakeExtensionArgs()
|
||||||
{
|
{
|
||||||
$this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs());
|
$this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user