Merge pull request #726 from crazywhalecc/fix/icurel

Fix PIC errors when building libphp.so | extensive extension building rework
This commit is contained in:
Marc 2025-06-12 11:48:33 +07:00 committed by GitHub
commit 289f4b300a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
125 changed files with 2365 additions and 1473 deletions

3
.gitignore vendored
View File

@ -10,6 +10,9 @@ docker/source/
# default source extract directory
/source/**
# built by shared embed tests
/locale/
# default source download directory
/downloads/**

View File

@ -72,6 +72,7 @@ RUN yum update -y && \
yum install -y devtoolset-10-gcc-*
RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc
RUN source /etc/bashrc
RUN yum install -y which
RUN curl -o cmake.tgz -fsSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$BASE_ARCH.tar.gz && \
mkdir /cmake && \

View File

@ -68,8 +68,8 @@ CXX=${SPC_LINUX_DEFAULT_CXX}
AR=${SPC_LINUX_DEFAULT_AR}
LD=ld.gold
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="-fPIC"
SPC_DEFAULT_CXX_FLAGS=
SPC_DEFAULT_C_FLAGS="-fpic -Os"
SPC_DEFAULT_CXX_FLAGS="-fpic -Os"
; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated)
SPC_EXTRA_LIBS=
; upx executable path
@ -81,7 +81,7 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime
; buildconf command
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
; configure command
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg --with-pic"
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --disable-all --disable-cgi --disable-phpdbg --with-pic"
; make command
SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}"
; embed type for php, static (libphp.a) or shared (libphp.so)
@ -89,7 +89,7 @@ SPC_CMD_VAR_PHP_EMBED_TYPE="static"
; *** default build vars for building php ***
; CFLAGS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -fPIE"
SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -fpie"
; CPPFLAGS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}"
; LDFLAGS for configuring php
@ -97,9 +97,11 @@ SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}"
; LIBS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_LIBS="-ldl -lpthread -lm"
; EXTRA_CFLAGS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Os -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fno-ident -fPIE -fPIC"
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fpie ${SPC_DEFAULT_C_FLAGS}"
; EXTRA_LIBS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm"
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
; EXTRA_LDFLAGS_PROGRAM for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie"
@ -108,8 +110,8 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie"
CC=clang
CXX=clang++
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin"
SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin"
SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated)
SPC_EXTRA_LIBS=
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
@ -131,7 +133,7 @@ SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}"
; LDFLAGS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}"
; EXTRA_CFLAGS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Os -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie ${SPC_DEFAULT_C_FLAGS}"
; EXTRA_LIBS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-lresolv"
; embed type for php, static (libphp.a) or shared (libphp.dylib)

View File

@ -24,6 +24,14 @@
"bcmath": {
"type": "builtin"
},
"brotli": {
"type": "external",
"source": "ext-brotli",
"arg-type": "enable",
"lib-depends": [
"brotli"
]
},
"bz2": {
"type": "builtin",
"arg-type-unix": "with-prefix",
@ -95,7 +103,10 @@
"ev": {
"type": "external",
"source": "ev",
"arg-type-windows": "with"
"arg-type-windows": "with",
"ext-depends": [
"sockets"
]
},
"event": {
"support": {
@ -124,10 +135,6 @@
"Linux": "partial",
"BSD": "wip"
},
"target": [
"static",
"shared"
],
"notes": true,
"arg-type": "custom",
"type": "builtin",
@ -323,6 +330,16 @@
"openssl"
]
},
"libxml": {
"support": {
"BSD": "wip"
},
"type": "builtin",
"arg-type": "none",
"target": [
"static"
]
},
"lz4": {
"support": {
"Windows": "wip",
@ -335,19 +352,12 @@
"liblz4"
]
},
"libxml": {
"support": {
"BSD": "wip"
},
"type": "builtin",
"arg-type": "none",
"ext-depends": [
"xml"
]
},
"mbregex": {
"type": "builtin",
"arg-type": "custom",
"target": [
"static"
],
"ext-depends": [
"mbstring"
],
@ -380,13 +390,13 @@
"ext-depends": [
"zlib",
"session"
]
],
"build-with-php": true
},
"memcached": {
"support": {
"Windows": "wip",
"BSD": "wip",
"Linux": "no"
"BSD": "wip"
},
"type": "external",
"source": "memcached",
@ -395,6 +405,10 @@
"lib-depends": [
"libmemcached"
],
"lib-depends-unix": [
"libmemcached",
"fastlz"
],
"ext-depends": [
"session",
"zlib"
@ -413,6 +427,10 @@
"openssl",
"zstd",
"zlib"
],
"frameworks": [
"CoreFoundation",
"Security"
]
},
"msgpack": {
@ -422,7 +440,10 @@
"type": "external",
"source": "msgpack",
"arg-type-unix": "with",
"arg-type-win": "enable"
"arg-type-win": "enable",
"ext-depends": [
"session"
]
},
"mysqli": {
"type": "builtin",
@ -461,7 +482,8 @@
},
"opcache": {
"type": "builtin",
"arg-type-unix": "custom"
"arg-type-unix": "custom",
"zend-extension": true
},
"openssl": {
"notes": true,
@ -650,6 +672,9 @@
"arg-type": "with-prefix",
"lib-depends": [
"readline"
],
"target": [
"static"
]
},
"redis": {
@ -669,10 +694,12 @@
]
},
"session": {
"type": "builtin"
"type": "builtin",
"build-with-php": true
},
"shmop": {
"type": "builtin"
"type": "builtin",
"build-with-php": true
},
"simdjson": {
"type": "external",
@ -690,7 +717,8 @@
],
"ext-depends-windows": [
"xml"
]
],
"build-with-php": true
},
"snappy": {
"support": {
@ -783,7 +811,7 @@
"lib-depends": [
"libssh2"
],
"ext-depends-windows": [
"ext-depends": [
"openssl",
"zlib"
]
@ -793,9 +821,6 @@
"Windows": "no",
"BSD": "wip"
},
"target": [
"static"
],
"notes": true,
"type": "external",
"source": "swoole",
@ -913,7 +938,8 @@
]
},
"tokenizer": {
"type": "builtin"
"type": "builtin",
"build-with-php": true
},
"uuid": {
"support": {
@ -954,7 +980,8 @@
"Darwin": "partial",
"Linux": "partial"
},
"notes": true
"notes": true,
"zend-extension": true
},
"xhprof": {
"support": {
@ -966,7 +993,8 @@
"source": "xhprof",
"ext-depends": [
"ctype"
]
],
"build-with-php": true
},
"xlswriter": {
"support": {
@ -996,7 +1024,8 @@
],
"ext-depends-windows": [
"iconv"
]
],
"build-with-php": true
},
"xmlreader": {
"support": {
@ -1010,7 +1039,8 @@
"ext-depends-windows": [
"xml",
"dom"
]
],
"build-with-php": true
},
"xmlwriter": {
"support": {
@ -1023,7 +1053,8 @@
],
"ext-depends-windows": [
"xml"
]
],
"build-with-php": true
},
"xsl": {
"support": {
@ -1040,6 +1071,14 @@
"dom"
]
},
"xz": {
"type": "external",
"source": "ext-xz",
"arg-type": "with",
"lib-depends": [
"xz"
]
},
"yac": {
"support": {
"BSD": "wip"
@ -1047,6 +1086,9 @@
"type": "external",
"source": "yac",
"arg-type-unix": "custom",
"lib-depends-unix": [
"fastlz"
],
"ext-depends-unix": [
"igbinary"
]
@ -1067,9 +1109,6 @@
"support": {
"BSD": "wip"
},
"target": [
"static"
],
"type": "builtin",
"arg-type": "with-prefix",
"arg-type-windows": "enable",
@ -1093,6 +1132,9 @@
"arg-type-windows": "enable",
"lib-depends": [
"zlib"
],
"target": [
"static"
]
},
"zstd": {

View File

@ -101,6 +101,15 @@
"SystemConfiguration"
]
},
"fastlz": {
"source": "fastlz",
"static-libs-unix": [
"libfastlz.a"
],
"headers": [
"fastlz/fastlz.h"
]
},
"freetype": {
"source": "freetype",
"static-libs-unix": [
@ -234,8 +243,8 @@
"ldap": {
"source": "ldap",
"static-libs-unix": [
"liblber.a",
"libldap.a"
"libldap.a",
"liblber.a"
],
"lib-depends": [
"openssl",
@ -389,7 +398,9 @@
"source": "libmemcached",
"static-libs-unix": [
"libmemcached.a",
"libmemcachedutil.a"
"libmemcachedprotocol.a",
"libmemcachedutil.a",
"libhashkit.a"
]
},
"libpng": {

View File

@ -50,8 +50,9 @@
}
},
"brotli": {
"type": "ghtar",
"type": "ghtagtar",
"repo": "google/brotli",
"match": "v1\\.\\d.*",
"provide-pre-built": true,
"license": {
"type": "file",
@ -102,6 +103,16 @@
"path": "LICENSE"
}
},
"ext-brotli": {
"type": "git",
"path": "php-src/ext/brotli",
"rev": "master",
"url": "https://github.com/kjdev/php-ext-brotli",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-ds": {
"type": "url",
"url": "https://pecl.php.net/get/ds",
@ -241,6 +252,16 @@
"path": "LICENSE"
}
},
"ext-xz": {
"type": "git",
"path": "php-src/ext/xz",
"rev": "main",
"url": "https://github.com/codemasher/php-ext-xz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-zstd": {
"type": "git",
"path": "php-src/ext/zstd",
@ -251,6 +272,15 @@
"path": "LICENSE"
}
},
"fastlz": {
"type": "git",
"url": "https://github.com/ariya/FastLZ.git",
"rev": "master",
"license": {
"type": "file",
"path": "LICENSE.MIT"
}
},
"freetype": {
"type": "git",
"rev": "VER-2-13-2",
@ -507,12 +537,12 @@
}
},
"libmemcached": {
"type": "git",
"url": "https://github.com/static-php/libmemcached-macos.git",
"rev": "master",
"type": "ghtagtar",
"repo": "awesomized/libmemcached",
"match": "1.\\d.\\d",
"license": {
"type": "file",
"path": "COPYING"
"path": "LICENSE"
}
},
"libpng": {
@ -801,8 +831,9 @@
}
},
"postgresql": {
"type": "url",
"url": "https://ftp.postgresql.org/pub/source/v16.2/postgresql-16.2.tar.bz2",
"type": "ghtagtar",
"repo": "postgres/postgres",
"match": "REL_16_\\d+",
"license": {
"type": "file",
"path": "COPYRIGHT"

View File

@ -30,6 +30,7 @@
</div>
</div>
<div class="my-btn" v-if="selectedSystem !== 'windows'" @click="selectCommon">{{ I18N[lang].selectCommon }}</div>
<div class="my-btn" v-if="selectedSystem !== 'windows'" @click="selectAll">{{ I18N[lang].selectAll }}</div>
<div class="my-btn" @click="checkedExts = []">{{ I18N[lang].selectNone }}</div>
<details class="details custom-block" open>
@ -44,6 +45,7 @@
<div class="tip custom-block">
<p class="custom-block-title">TIP</p>
<p>{{ I18N[lang].depTips }}</p>
<p>{{ I18N[lang].depTips2 }}</p>
</div>
<h2>{{ I18N[lang].buildTarget }}</h2>
<div class="box">
@ -252,6 +254,7 @@ const I18N = {
no: '否',
resultShow: '结果展示',
selectCommon: '选择常用扩展',
selectAll: '选择全部',
selectNone: '全部取消选择',
useZTS: '是否编译线程安全版',
hardcodedINI: '硬编码 INI 选项',
@ -267,6 +270,7 @@ const I18N = {
selectedSystem: '选择操作系统',
buildLibs: '要构建的库',
depTips: '选择扩展后,不可选中的项目为必需的依赖,编译的依赖库列表中可选的为现有扩展和依赖库的可选依赖。选择可选依赖后,将生成 --with-libs 参数。',
depTips2: '无法同时构建所有扩展,因为有些扩展之间相互冲突。请根据需要选择扩展。',
microUnavailable: 'micro 不支持 PHP 7.4 及更早版本!',
windowsSAPIUnavailable: 'Windows 目前不支持 fpm、embed 构建!',
useUPX: '是否开启 UPX 压缩(减小二进制体积)',
@ -286,6 +290,7 @@ const I18N = {
no: 'No',
resultShow: 'Result',
selectCommon: 'Select common extensions',
selectAll: 'Select all',
selectNone: 'Unselect all',
useZTS: 'Enable ZTS',
hardcodedINI: 'Hardcoded INI options',
@ -301,6 +306,7 @@ const I18N = {
selectedSystem: 'Select Build OS',
buildLibs: 'Select Dependencies',
depTips: 'After selecting the extensions, the unselectable items are essential dependencies. In the compiled dependencies list, optional dependencies consist of existing extensions and optional dependencies of libraries. Optional dependencies will be added in --with-libs parameter.',
depTips2: 'It is not possible to build all extensions at the same time, as some extensions conflict with each other. Please select the extensions you need.',
microUnavailable: 'Micro does not support PHP 7.4 and earlier versions!',
windowsSAPIUnavailable: 'Windows does not support fpm and embed build!',
useUPX: 'Enable UPX compression (reduce binary size)',
@ -337,6 +343,10 @@ const selectCommon = () => {
];
};
const selectAll = () => {
checkedExts.value = extFilter.value;
};
const extList = computed(() => {
return checkedExts.value.join(',');
});
@ -364,7 +374,7 @@ const checkedTargets = ref(['cli']);
const selectedEnv = ref('spc');
// chosen php version
const selectedPhpVersion = ref('8.2');
const selectedPhpVersion = ref('8.4');
// chosen debug
const debug = ref(0);

View File

@ -151,8 +151,7 @@ Parallel is only supported on PHP 8.0 ZTS and above.
## spx
1. The [SPX extension](https://github.com/NoiseByNorthwest/php-spx) only supports NTS mode.
2. SPX does not support Windows, and the official repository does not support static compilation. static-php-cli uses a [modified version](https://github.com/static-php/php-spx).
1. SPX does not support Windows, and the official repository does not support static compilation. static-php-cli uses a [modified version](https://github.com/static-php/php-spx).
## mimalloc

View File

@ -141,8 +141,7 @@ parallel 扩展只支持 PHP 8.0 及以上版本,并只支持 ZTS 构建(`--
## spx
1. [SPX 扩展](https://github.com/NoiseByNorthwest/php-spx) 只支持非线程模式。
2. SPX 目前不支持 Windows且官方仓库也不支持静态编译static-php-cli 使用了 [修改版本](https://github.com/static-php/php-spx)。
1. SPX 目前不支持 Windows且官方仓库也不支持静态编译static-php-cli 使用了 [修改版本](https://github.com/static-php/php-spx)。
## mimalloc

View File

@ -5,7 +5,7 @@
"docs:preview": "vitepress preview docs"
},
"devDependencies": {
"vitepress": "^1.0.0-rc.35",
"vitepress": "^2.0.0-alpha.5",
"vue": "^3.2.47"
}
}

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\builder;
use PharIo\FileSystem\File;
use SPC\exception\ExceptionHandler;
use SPC\exception\FileSystemException;
use SPC\exception\InterruptException;
@ -127,7 +128,7 @@ abstract class BuilderBase
if ($including_shared) {
return $this->exts;
}
return array_filter($this->exts, fn ($ext) => !$ext->isBuildShared());
return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic());
}
/**
@ -233,15 +234,52 @@ abstract class BuilderBase
*/
abstract public function buildPHP(int $build_target = BUILD_TARGET_NONE);
/**
* Test PHP
*/
abstract public function testPHP(int $build_target = BUILD_TARGET_NONE);
/**
* @throws WrongUsageException
* @throws RuntimeException
* @throws FileSystemException
*/
public function buildSharedExts(): void
{
foreach ($this->getExts() as $ext) {
if (!$ext->isBuildShared()) {
continue;
$lines = file(BUILD_BIN_PATH . '/php-config');
$extension_dir_line = null;
foreach ($lines as $key => $value) {
if (str_starts_with($value, 'extension_dir=')) {
$lines[$key] = 'extension_dir="' . BUILD_MODULES_PATH . '"' . PHP_EOL;
$extension_dir_line = $value;
break;
}
logger()->info('Building extension [' . $ext->getName() . '] as shared extension (' . $ext->getName() . '.so)');
$ext->buildShared();
}
file_put_contents(BUILD_BIN_PATH . '/php-config', implode('', $lines));
FileSystem::createDir(BUILD_MODULES_PATH);
try {
foreach ($this->getExts() as $ext) {
if (!$ext->isBuildShared()) {
continue;
}
if (Config::getExt($ext->getName(), 'type') === 'builtin' || Config::getExt($ext->getName(), 'build-with-php') === true) {
if (file_exists(BUILD_MODULES_PATH . '/' . $ext->getName() . '.so')) {
logger()->info('Shared extension [' . $ext->getName() . '] was already built by php-src/configure (' . $ext->getName() . '.so)');
continue;
}
if (Config::getExt($ext->getName(), 'build-with-php') === true) {
logger()->warning('Shared extension [' . $ext->getName() . '] did not build with php-src/configure (' . $ext->getName() . '.so)');
logger()->warning('Try deleting your build and source folders and running `spc build`` again.');
continue;
}
}
$ext->buildShared();
}
} catch (RuntimeException $e) {
FileSystem::replaceFileLineContainsString(BUILD_BIN_PATH . '/php-config', 'extension_dir=', $extension_dir_line);
throw $e;
}
FileSystem::replaceFileLineContainsString(BUILD_BIN_PATH . '/php-config', 'extension_dir=', $extension_dir_line);
}
/**
@ -254,9 +292,21 @@ abstract class BuilderBase
public function makeStaticExtensionArgs(): string
{
$ret = [];
foreach ($this->getExts(false) as $ext) {
logger()->info($ext->getName() . ' is using ' . $ext->getConfigureArg());
$ret[] = trim($ext->getConfigureArg());
foreach ($this->getExts() as $ext) {
$arg = $ext->getConfigureArg();
if ($ext->isBuildShared() && !$ext->isBuildStatic()) {
if (
(Config::getExt($ext->getName(), 'type') === 'builtin' &&
!file_exists(SOURCE_PATH . '/php-src/ext/' . $ext->getName() . '/config.m4')) ||
Config::getExt($ext->getName(), 'build-with-php') === true
) {
$arg = $ext->getConfigureArg(true);
} else {
continue;
}
}
logger()->info($ext->getName() . ' is using ' . $arg);
$ret[] = trim($arg);
}
logger()->debug('Using configure: ' . implode(' ', $ret));
return implode(' ', $ret);

View File

@ -53,26 +53,26 @@ class Extension
}
}
public function getFrameworks(): array
{
return Config::getExt($this->getName(), 'frameworks', []);
}
/**
* 获取开启该扩展的 PHP 编译添加的参数
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getConfigureArg(): string
public function getConfigureArg(bool $shared = false): string
{
$arg = $this->getEnableArg();
switch (PHP_OS_FAMILY) {
case 'Windows':
$arg .= $this->getWindowsConfigureArg();
break;
case 'Darwin':
case 'Linux':
case 'BSD':
$arg .= $this->getUnixConfigureArg();
break;
}
return $arg;
return match (PHP_OS_FAMILY) {
'Windows' => $this->getWindowsConfigureArg($shared),
'Darwin',
'Linux',
'BSD' => $this->getUnixConfigureArg($shared),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build is not supported yet'),
};
}
/**
@ -81,13 +81,13 @@ class Extension
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getEnableArg(): string
public function getEnableArg(bool $shared = false): string
{
$_name = str_replace('_', '-', $this->name);
return match ($arg_type = Config::getExt($this->name, 'arg-type', 'enable')) {
'enable' => '--enable-' . $_name . ' ',
'with' => '--with-' . $_name . ' ',
'with-prefix' => '--with-' . $_name . '="' . BUILD_ROOT_PATH . '" ',
'enable' => '--enable-' . $_name . ($shared ? '=shared' : '') . ' ',
'with' => '--with-' . $_name . ($shared ? '=shared' : '') . ' ',
'with-prefix' => '--with-' . $_name . '=' . ($shared ? 'shared,' : '') . '"' . BUILD_ROOT_PATH . '" ',
'none', 'custom' => '',
default => throw new WrongUsageException("argType does not accept {$arg_type}, use [enable/with/with-prefix] ."),
};
@ -147,15 +147,15 @@ class Extension
return $this->name;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
return '';
return $this->getEnableArg();
// Windows is not supported yet
}
public function getUnixConfigureArg(bool $shared = false): string
{
return '';
return $this->getEnableArg($shared);
}
/**
@ -189,18 +189,70 @@ class Extension
}
/**
* Run shared extension check when cli is enabled
* @throws RuntimeException
* Patch code before shared extension phpize
* If you need to patch some code, overwrite this
* return true if you patched something, false if not
*/
public function runSharedExtensionCheckUnix(): void
public function patchBeforeSharedBuild(): bool
{
[$ret] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -d "extension=' . BUILD_LIB_PATH . '/' . $this->getName() . '.so" --ri ' . $this->getName());
if ($ret !== 0) {
throw new RuntimeException($this->getName() . '.so failed to load');
return false;
}
/**
* Patch code before shared extension ./configure
* If you need to patch some code, overwrite this
* return true if you patched something, false if not
*/
public function patchBeforeSharedConfigure(): bool
{
return false;
}
/**
* @return string
* returns a command line string with all required shared extensions to load
* i.e.; pdo_pgsql would return:
*
* `-d "extension=pgsql" -d "extension=pdo_pgsql"`
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getSharedExtensionLoadString(): string
{
$loaded = [];
$order = [];
$resolve = function ($extension) use (&$resolve, &$loaded, &$order) {
if (isset($loaded[$extension->getName()])) {
return;
}
$loaded[$extension->getName()] = true;
foreach ($this->dependencies as $dependency) {
$resolve($dependency);
}
$order[] = $extension;
};
$resolve($this);
$ret = '';
foreach ($order as $ext) {
if ($ext instanceof Extension && $ext->isBuildShared()) {
if (Config::getExt($ext->getName(), 'zend-extension', false) === true) {
$ret .= " -d \"zend_extension={$ext->getName()}\"";
} else {
$ret .= " -d \"extension={$ext->getName()}\"";
}
}
}
if ($this->isBuildStatic()) {
logger()->warning($this->getName() . '.so test succeeded, but has little significance since it is also compiled in statically.');
if ($ret !== '') {
$ret = ' -d "extension_dir=' . BUILD_MODULES_PATH . '"' . $ret;
}
return $ret;
}
/**
@ -211,7 +263,8 @@ class Extension
// Run compile check if build target is cli
// If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php
// If check failed, throw RuntimeException
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "' . $this->getDistName() . '"', false);
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
}
@ -224,7 +277,7 @@ class Extension
file_get_contents(ROOT_DIR . '/src/globals/ext-tests/' . $this->getName() . '.php')
);
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n -r "' . trim($test) . '"');
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' -r "' . trim($test) . '"');
if ($ret !== 0) {
if ($this->builder->getOption('debug')) {
var_dump($out);
@ -275,6 +328,20 @@ class Extension
*/
public function buildShared(): void
{
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
logger()->info('extension ' . $this->getName() . ' already built, skipping');
return;
}
foreach ($this->dependencies as $dependency) {
if (!$dependency instanceof Extension) {
continue;
}
if (!$dependency->isBuildStatic()) {
logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName());
$dependency->buildShared();
}
}
match (PHP_OS_FAMILY) {
'Darwin', 'Linux' => $this->buildUnixShared(),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
@ -292,26 +359,44 @@ class Extension
*/
public function buildUnixShared(): void
{
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()]);
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], with_dependencies: true);
[$staticLibString, $sharedLibString] = $this->getStaticAndSharedLibs();
$env = [
'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'],
'LIBS' => $config['libs'],
'LIBS' => '-Wl,-Bstatic -Wl,--start-group ' . $staticLibString . ' -Wl,--end-group -Wl,-Bdynamic ' . $sharedLibString,
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
// prepare configure args
shell()->cd($this->source_dir)
->setEnv($env)
->exec(BUILD_BIN_PATH . '/phpize')
->exec('./configure ' . $this->getUnixConfigureArg(true) . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config --enable-shared --disable-static')
->exec('make clean')
->exec('make -j' . $this->builder->concurrency);
->exec(BUILD_BIN_PATH . '/phpize');
// 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();
if ($this->patchBeforeSharedConfigure()) {
logger()->info('ext [ . ' . $this->getName() . '] patching before shared configure');
}
shell()->cd($this->source_dir)
->setEnv($env)
->exec(
'./configure ' . $this->getUnixConfigureArg(true) .
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
'--enable-shared --disable-static'
);
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
'$1 ' . $staticLibString
);
shell()->cd($this->source_dir)
->setEnv($env)
->exec('make clean')
->exec('make -j' . $this->builder->concurrency)
->exec('make install');
}
/**
@ -382,6 +467,37 @@ class Extension
}
}
/**
* Get required static and shared libraries as a pair of strings in format -l{libname} -l{libname2}
*
* @return array [staticLibString, sharedLibString]
*/
private function getStaticAndSharedLibs(): array
{
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], with_dependencies: true);
$sharedLibString = '';
$staticLibString = '';
$staticLibs = $this->getLibFilesString();
$staticLibs = str_replace(BUILD_LIB_PATH . '/lib', '-l', $staticLibs);
$staticLibs = str_replace('.a', '', $staticLibs);
$staticLibs = explode('-l', $staticLibs . ' ' . $config['libs']);
foreach ($staticLibs as $lib) {
$lib = trim($lib);
if ($lib === '') {
continue;
}
$static_lib = 'lib' . $lib . '.a';
if (file_exists(BUILD_LIB_PATH . '/' . $static_lib)) {
if (!str_contains($staticLibString, '-l' . $lib . ' ')) {
$staticLibString .= '-l' . $lib . ' ';
}
} elseif (!str_contains($sharedLibString, '-l' . $lib . ' ')) {
$sharedLibString .= '-l' . $lib . ' ';
}
}
return [trim($staticLibString), trim($sharedLibString)];
}
private function getLibraryDependencies(bool $recursive = false): array
{
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);
@ -407,6 +523,11 @@ class Extension
}
}
if (array_key_exists(0, $deps)) {
$zero = [0 => $deps[0]];
unset($deps[0]);
return $zero + $deps;
}
return $deps;
}
}

View File

@ -11,9 +11,12 @@ use SPC\store\Config;
use SPC\store\Downloader;
use SPC\store\FileSystem;
use SPC\store\SourceManager;
use SPC\util\GlobalValueTrait;
abstract class LibraryBase
{
use GlobalValueTrait;
/** @var string */
public const NAME = 'unknown';
@ -31,7 +34,7 @@ abstract class LibraryBase
if (static::NAME === 'unknown') {
throw new RuntimeException('no unknown!!!!!');
}
$this->source_dir = $source_dir ?? (SOURCE_PATH . '/' . static::NAME);
$this->source_dir = $source_dir ?? (SOURCE_PATH . '/' . Config::getLib(static::NAME, 'source'));
}
/**
@ -328,21 +331,6 @@ abstract class LibraryBase
return false;
}
public function getIncludeDir(): string
{
return BUILD_INCLUDE_PATH;
}
public function getBuildRootPath(): string
{
return BUILD_ROOT_PATH;
}
public function getLibDir(): string
{
return BUILD_LIB_PATH;
}
/**
* Build this library.
*

View File

@ -25,10 +25,10 @@ class amqp extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
return '--with-amqp --with-librabbitmq-dir=' . BUILD_ROOT_PATH;
return '--with-amqp' . ($shared ? '=shared' : '') . ' --with-librabbitmq-dir=' . BUILD_ROOT_PATH;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg($shared = false): string
{
return '--with-amqp';
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException;
@ -21,7 +22,7 @@ class curl extends Extension
{
logger()->info('patching before-configure for curl checks');
$file1 = "AC_DEFUN([PHP_CHECK_LIBRARY], [\n $3\n])";
$files = FileSystem::readFile(SOURCE_PATH . '/php-src/ext/curl/config.m4');
$files = FileSystem::readFile($this->source_dir . '/config.m4');
$file2 = 'AC_DEFUN([PHP_CHECK_LIBRARY], [
save_old_LDFLAGS=$LDFLAGS
ac_stuff="$5"
@ -40,7 +41,7 @@ class curl extends Extension
$4
])dnl
])';
file_put_contents(SOURCE_PATH . '/php-src/ext/curl/config.m4', $file1 . "\n" . $files . "\n" . $file2);
file_put_contents($this->source_dir . '/config.m4', $file1 . "\n" . $files . "\n" . $file2);
return true;
}
@ -52,6 +53,72 @@ class curl extends Extension
{
$frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : '';
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-lcurl/', $this->getLibFilesString() . $frameworks);
$this->patchBeforeSharedConfigure();
return true;
}
public function patchBeforeSharedConfigure(): bool
{
$file = $this->source_dir . '/config.m4';
$content = FileSystem::readFile($file);
// Inject patch before it
$patch = ' save_LIBS="$LIBS"
LIBS="$LIBS $CURL_LIBS"
';
// Check if already patched
if (str_contains($content, $patch)) {
return false; // Already patched
}
// Match the line containing PHP_CHECK_LIBRARY for curl
$pattern = '/(PHP_CHECK_LIBRARY\(\[curl],\s*\[curl_easy_perform],)/';
// Restore LIBS after the check — append this just after the macro block
$restore = '
LIBS="$save_LIBS"';
// Apply patch
$patched = preg_replace_callback($pattern, function ($matches) use ($patch) {
return $patch . $matches[1];
}, $content, 1);
// Inject restore after the matching PHP_CHECK_LIBRARY block
$patched = preg_replace(
'/(PHP_CHECK_LIBRARY\(\[curl],\s*\[curl_easy_perform],.*?\)\n)/s',
"$1{$restore}\n",
$patched,
1
);
if ($patched === null) {
throw new \RuntimeException('Failed to patch config.m4 due to a regex error');
}
FileSystem::writeFile($file, $patched);
return true;
}
public function buildUnixShared(): void
{
if (!$this->builder instanceof LinuxBuilder) {
parent::buildUnixShared();
return;
}
FileSystem::replaceFileStr(
$this->source_dir . '/config.m4',
['$ext_dir/phar.1', '$ext_dir/phar.phar.1'],
['${ext_dir}phar.1', '${ext_dir}phar.phar.1']
);
try {
parent::buildUnixShared();
} finally {
FileSystem::replaceFileStr(
$this->source_dir . '/config.m4',
['${ext_dir}phar.1', '${ext_dir}phar.phar.1'],
['$ext_dir/phar.1', '$ext_dir/phar.phar.1']
);
}
}
}

View File

@ -12,11 +12,11 @@ class dba extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
$qdbm = $this->builder->getLib('qdbm') ? (' --with-qdbm=' . BUILD_ROOT_PATH) : '';
return '--enable-dba' . $qdbm;
$qdbm = $this->builder->getLib('qdbm') ? (' --with-qdbm=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH) : '';
return '--enable-dba' . ($shared ? '=shared' : '') . $qdbm;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
$qdbm = $this->builder->getLib('qdbm') ? ' --with-qdbm' : '';
return '--with-dba' . $qdbm;

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('dom')]
class dom extends Extension
{
/**
* @throws RuntimeException
*/
public function getUnixConfigureArg(bool $shared = false): string
{
$arg = '--enable-dom' . ($shared ? '=shared' : '');
$arg .= ' --with-libxml="' . BUILD_ROOT_PATH . '"';
return $arg;
}
public function patchBeforeBuildconf(): bool
{
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/win32/build/config.w32', 'dllmain.c ', '');
return true;
}
public function getWindowsConfigureArg($shared = false): string
{
return '--with-dom';
}
}

View File

@ -12,10 +12,10 @@ class ffi extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
return '--with-ffi --enable-zend-signals';
return '--with-ffi' . ($shared ? '=shared' : '') . ' --enable-zend-signals';
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
return '--with-ffi';
}

View File

@ -12,7 +12,7 @@ class gd extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
$arg = '--enable-gd';
$arg = '--enable-gd' . ($shared ? '=shared' : '');
$arg .= $this->builder->getLib('freetype') ? ' --with-freetype' : '';
$arg .= $this->builder->getLib('libjpeg') ? ' --with-jpeg' : '';
$arg .= $this->builder->getLib('libwebp') ? ' --with-webp' : '';

View File

@ -35,7 +35,7 @@ class glfw extends Extension
return '--enable-glfw --with-glfw-dir=' . BUILD_ROOT_PATH;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
return '--enable-glfw=static';
}

View File

@ -12,10 +12,13 @@ class imagick extends Extension
{
public function patchBeforeMake(): bool
{
if (getenv('SPC_LIBC') !== 'musl') {
if (PHP_OS_FAMILY !== 'Linux') {
return false;
}
// imagick with calls omp_pause_all which requires -lgomp, on non-musl we build imagick without openmp
if (getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) {
return false;
}
// imagick with calls omp_pause_all, which requires openmp, on non-musl we build imagick without openmp
$extra_libs = trim(getenv('SPC_EXTRA_LIBS') . ' -lgomp');
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
return true;
@ -23,7 +26,7 @@ class imagick extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
$disable_omp = getenv('SPC_LIBC') === 'musl' ? '' : ' ac_cv_func_omp_pause_resource_all=no';
return '--with-imagick=' . BUILD_ROOT_PATH . $disable_omp;
$disable_omp = !(getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) ? '' : ' ac_cv_func_omp_pause_resource_all=no';
return '--with-imagick=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $disable_omp;
}
}

View File

@ -18,9 +18,12 @@ class intl extends Extension
// Also need to use clang++ -std=c++17 to force override the default C++ standard
if (is_string($env = getenv('CXX')) && !str_contains($env, 'std=c++17')) {
f_putenv('CXX=' . $env . ' -std=c++17');
} else {
f_putenv('CXX=clang++ -std=c++17');
}
return true;
}
public function patchBeforeSharedBuild(): bool
{
return $this->patchBeforeBuildconf();
}
}

View File

@ -15,7 +15,7 @@ class lz4 extends Extension
return '--enable-lz4' . ($shared ? '=shared' : '') . ' --with-lz4-includedir=' . BUILD_ROOT_PATH;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
return '--enable-lz4';
}

View File

@ -16,7 +16,7 @@ class mbregex extends Extension
return 'mbstring';
}
public function getConfigureArg(): string
public function getConfigureArg(bool $shared = false): string
{
return '';
}
@ -26,7 +26,8 @@ class mbregex extends Extension
*/
public function runCliCheckUnix(): void
{
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "mbstring" | grep regex', false);
$sharedext = $this->builder->getExt('mbstring')->isBuildShared() ? '-d "extension_dir=' . BUILD_MODULES_PATH . '" -d "extension=mbstring"' : '';
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $sharedext . ' --ri "mbstring" | grep regex', false);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !');
}

View File

@ -10,9 +10,20 @@ use SPC\util\CustomExt;
#[CustomExt('mbstring')]
class mbstring extends Extension
{
public function getConfigureArg(): string
public function getConfigureArg(bool $shared = false): string
{
$arg = '--enable-mbstring';
$arg = '--enable-mbstring' . ($shared ? '=shared' : '');
if ($this->builder->getExt('mbregex') === null) {
$arg .= ' --disable-mbregex';
} else {
$arg .= ' --enable-mbregex';
}
return $arg;
}
public function getUnixConfigureArg(bool $shared = false): string
{
$arg = '--enable-mbstring' . ($shared ? '=shared' : '');
if ($this->builder->getExt('mbregex') === null) {
$arg .= ' --disable-mbregex';
} else {

View File

@ -14,7 +14,7 @@ class memcache extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
return '--enable-memcache --with-zlib-dir=' . BUILD_ROOT_PATH;
return '--enable-memcache' . ($shared ? '=shared' : '') . ' --with-zlib-dir=' . BUILD_ROOT_PATH;
}
/**

View File

@ -12,8 +12,11 @@ class memcached extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
$rootdir = BUILD_ROOT_PATH;
$zlib_dir = $this->builder->getPHPVersionID() >= 80400 ? '' : "--with-zlib-dir={$rootdir}";
return "--enable-memcached {$zlib_dir} --with-libmemcached-dir={$rootdir} --disable-memcached-sasl --enable-memcached-json";
return '--enable-memcached' . ($shared ? '=shared' : '') . ' ' .
'--with-zlib-dir=' . BUILD_ROOT_PATH . ' ' .
'--with-libmemcached-dir=' . BUILD_ROOT_PATH . ' ' .
'--disable-memcached-sasl ' .
'--enable-memcached-json ' .
'--with-system-fastlz';
}
}

View File

@ -12,6 +12,6 @@ class odbc extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
return '--with-unixODBC=' . BUILD_ROOT_PATH;
return '--with-unixODBC=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH;
}
}

View File

@ -26,6 +26,6 @@ class openssl extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
$openssl_dir = $this->builder->getPHPVersionID() >= 80400 ? '' : ' --with-openssl-dir=' . BUILD_ROOT_PATH;
return '--with-openssl=' . BUILD_ROOT_PATH . $openssl_dir;
return '--with-openssl=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $openssl_dir;
}
}

View File

@ -19,10 +19,10 @@ class pdo_odbc extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
return '--with-pdo-odbc=unixODBC,' . BUILD_ROOT_PATH;
return '--with-pdo-odbc=' . ($shared ? 'shared,' : '') . 'unixODBC,' . BUILD_ROOT_PATH;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
return '--with-pdo-odbc';
}

View File

@ -10,7 +10,7 @@ use SPC\util\CustomExt;
#[CustomExt('pdo_pgsql')]
class pdo_pgsql extends Extension
{
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
return '--with-pdo-pgsql=yes';
}

View File

@ -36,16 +36,21 @@ class pgsql extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
if ($this->builder->getPHPVersionID() >= 80400) {
return '--with-pgsql PGSQL_CFLAGS=-I' . BUILD_INCLUDE_PATH . ' PGSQL_LIBS="-L' . BUILD_LIB_PATH . ' -lpq -lpgport -lpgcommon"';
$libfiles = $this->getLibFilesString();
$libfiles = str_replace(BUILD_LIB_PATH . '/lib', '-l', $libfiles);
$libfiles = str_replace('.a', '', $libfiles);
return '--with-pgsql' . ($shared ? '=shared' : '') .
' PGSQL_CFLAGS=-I' . BUILD_INCLUDE_PATH .
' PGSQL_LIBS="-L' . BUILD_LIB_PATH . ' ' . $libfiles . '"';
}
return '--with-pgsql=' . BUILD_ROOT_PATH;
return '--with-pgsql=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH;
}
/**
* @throws WrongUsageException
* @throws RuntimeException
*/
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
if ($this->builder->getPHPVersionID() >= 80400) {
return '--with-pgsql';

View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\linux\LinuxBuilder;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('phar')]
class phar extends Extension
{
public function buildUnixShared(): void
{
if (!$this->builder instanceof LinuxBuilder) {
parent::buildUnixShared();
return;
}
FileSystem::replaceFileStr(
$this->source_dir . '/config.m4',
['$ext_dir/phar.1', '$ext_dir/phar.phar.1'],
['${ext_dir}phar.1', '${ext_dir}phar.phar.1']
);
try {
parent::buildUnixShared();
} finally {
FileSystem::replaceFileStr(
$this->source_dir . '/config.m4',
['${ext_dir}phar.1', '${ext_dir}phar.phar.1'],
['$ext_dir/phar.1', '$ext_dir/phar.phar.1']
);
}
}
}

View File

@ -11,6 +11,13 @@ use SPC\util\CustomExt;
#[CustomExt('rdkafka')]
class rdkafka extends Extension
{
public function patchBeforeBuildconf(): bool
{
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\n", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm \$RDKAFKA_LIBS\n");
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\"\n", '-L$RDKAFKA_DIR/$PHP_LIBDIR -lm $RDKAFKA_LIBS"');
return true;
}
public function patchBeforeMake(): bool
{
// when compiling rdkafka with inline builds, it shows some errors, I don't know why.
@ -27,10 +34,10 @@ class rdkafka extends Extension
return true;
}
public function getConfigureArg(): string
public function getUnixConfigureArg(bool $shared = false): string
{
$pkgconf_libs = shell()->execWithResult('pkg-config --libs --static rdkafka')[1];
$pkgconf_libs = trim(implode('', $pkgconf_libs));
return '--with-rdkafka=' . BUILD_ROOT_PATH . ' LIBS="' . $pkgconf_libs . '"';
return '--with-rdkafka=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . ' RDKAFKA_LIBS="' . $pkgconf_libs . '"';
}
}

View File

@ -24,4 +24,18 @@ class readline extends Extension
);
return true;
}
public function getUnixConfigureArg(bool $shared = false): string
{
return '--without-libedit --with-readline=' . BUILD_ROOT_PATH;
}
public function buildUnixShared(): void
{
if (!file_exists(BUILD_BIN_PATH . '/php') || !file_exists(BUILD_INCLUDE_PATH . '/php/sapi/cli/cli.h')) {
logger()->warning('CLI mode is not enabled, skipping readline build');
return;
}
parent::buildUnixShared();
}
}

View File

@ -24,7 +24,7 @@ class redis extends Extension
return $arg;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
$arg = '--enable-redis';
$arg .= $this->builder->getExt('session') ? ' --enable-redis-session' : ' --disable-redis-session';

View File

@ -5,28 +5,28 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('spx')]
class spx extends Extension
{
/**
* @throws WrongUsageException
*/
public function validate(): void
{
if ($this->builder->getOption('enable-zts')) {
throw new WrongUsageException('ext-spx is not thread safe, do not build it with ZTS builds');
}
}
public function getUnixConfigureArg(bool $shared = false): string
{
$arg = '--enable-spx';
if ($this->builder->getExt('zlib') === null) {
$arg = '--enable-spx' . ($shared ? '=shared' : '');
if ($this->builder->getLib('zlib') !== null) {
$arg .= ' --with-zlib-dir=' . BUILD_ROOT_PATH;
}
return $arg;
}
public function patchBeforeConfigure(): bool
{
FileSystem::replaceFileStr(
$this->source_dir . '/Makefile.frag',
'@cp -r assets/web-ui/*',
'@cp -r ' . $this->source_dir . '/assets/web-ui/*',
);
return true;
}
}

View File

@ -29,7 +29,7 @@ class swoole_hook_mysql extends Extension
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "swoole"', false);
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $this->getSharedExtensionLoadString() . ' --ri "swoole"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);

View File

@ -37,7 +37,8 @@ class swoole_hook_pgsql extends Extension
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "swoole"', false);
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);

View File

@ -37,7 +37,8 @@ class swoole_hook_sqlite extends Extension
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "swoole"', false);
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);

View File

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

View File

@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\util\CustomExt;
#[CustomExt('xdebug')]
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 failed to load.');
}
}
}

View File

@ -20,7 +20,7 @@ class xlswriter extends Extension
return $arg;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
return '--with-xlswriter';
}

View File

@ -13,7 +13,6 @@ use SPC\util\CustomExt;
#[CustomExt('soap')]
#[CustomExt('xmlreader')]
#[CustomExt('xmlwriter')]
#[CustomExt('dom')]
#[CustomExt('simplexml')]
class xml extends Extension
{
@ -27,11 +26,10 @@ class xml extends Extension
'soap' => '--enable-soap',
'xmlreader' => '--enable-xmlreader',
'xmlwriter' => '--enable-xmlwriter',
'dom' => '--enable-dom',
'simplexml' => '--enable-simplexml',
default => throw new RuntimeException('Not accept non-xml extension'),
};
$arg .= ' --with-libxml="' . BUILD_ROOT_PATH . '"';
$arg .= ($shared ? '=shared' : '') . ' --with-libxml="' . BUILD_ROOT_PATH . '"';
return $arg;
}
@ -41,14 +39,13 @@ class xml extends Extension
return true;
}
public function getWindowsConfigureArg(): string
public function getWindowsConfigureArg(bool $shared = false): string
{
$arg = match ($this->name) {
'xml' => '--with-xml',
'soap' => '--enable-soap',
'xmlreader' => '--enable-xmlreader',
'xmlwriter' => '--enable-xmlwriter',
'dom' => '--with-dom',
'simplexml' => '--with-simplexml',
default => throw new RuntimeException('Not accept non-xml extension'),
};

View File

@ -21,6 +21,6 @@ class yac extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
return '--enable-yac --enable-igbinary --enable-json';
return '--enable-yac ' . ($shared ? '=shared' : '') . ' --enable-igbinary --enable-json --with-system-fastlz';
}
}

View File

@ -143,7 +143,10 @@ class BSDBuilder extends UnixBuilderBase
}
$this->buildEmbed();
}
}
public function testPHP(int $build_target = BUILD_TARGET_NONE)
{
if (php_uname('m') === $this->getOption('arch')) {
$this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target);

View File

@ -10,9 +10,9 @@ class curl extends BSDLibraryBase
public const NAME = 'curl';
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true, bool $include_self = true): string
{
$libs = parent::getStaticLibFiles($style, $recursive);
$libs = parent::getStaticLibFiles($style, $recursive, $include_self);
if ($this->builder->getLib('openssl')) {
$this->builder->setOption('extra-libs', $this->builder->getOption('extra-libs') . ' /usr/lib/libpthread.a /usr/lib/libdl.a');
}

View File

@ -48,7 +48,7 @@ class openssl extends BSDLibraryBase
$ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib);
}
shell()->cd($this->source_dir)
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
"./Configure no-shared {$extra} " .
'--prefix=/ ' . // use prefix=/

View File

@ -175,7 +175,10 @@ class LinuxBuilder extends UnixBuilderBase
}
$this->buildEmbed();
}
}
public function testPHP(int $build_target = BUILD_TARGET_NONE)
{
$this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target);
}
@ -189,9 +192,10 @@ class LinuxBuilder extends UnixBuilderBase
protected function buildCli(): void
{
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("\$SPC_CMD_PREFIX_PHP_MAKE {$vars} cli");
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli");
if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')
@ -227,10 +231,11 @@ class LinuxBuilder extends UnixBuilderBase
// patch fake cli for micro
$vars['EXTRA_CFLAGS'] .= $enable_fake_cli;
$vars = SystemUtil::makeEnvVarString($vars);
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("\$SPC_CMD_PREFIX_PHP_MAKE {$vars} micro");
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} micro");
$this->processMicroUPX();
@ -250,9 +255,10 @@ class LinuxBuilder extends UnixBuilderBase
protected function buildFpm(): void
{
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("\$SPC_CMD_PREFIX_PHP_MAKE {$vars} fpm");
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} fpm");
if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')
@ -275,7 +281,20 @@ class LinuxBuilder extends UnixBuilderBase
shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
$ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS');
if (preg_match('/-release\s+(\S+)/', $ldflags, $matches)) {
$release = $matches[1];
$realLibName = 'libphp-' . $release . '.so';
$realLib = BUILD_LIB_PATH . '/' . $realLibName;
rename(BUILD_LIB_PATH . '/libphp.so', $realLib);
$cwd = getcwd();
chdir(BUILD_LIB_PATH);
symlink($realLibName, 'libphp.so');
chdir($cwd);
}
$this->patchPhpScripts();
}
@ -284,6 +303,7 @@ class LinuxBuilder extends UnixBuilderBase
return [
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
'EXTRA_LIBS' => getenv('SPC_EXTRA_LIBS') . ' ' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS'),
'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'),
'EXTRA_LDFLAGS_PROGRAM' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM'),
];
}

View File

@ -11,6 +11,8 @@ class SystemUtil
{
use UnixSystemUtilTrait;
public static ?string $libc_version = null;
/** @noinspection PhpMissingBreakStatementInspection */
public static function getOSRelease(): array
{
@ -188,6 +190,9 @@ class SystemUtil
*/
public static function getLibcVersionIfExists(): ?string
{
if (self::$libc_version !== null) {
return self::$libc_version;
}
if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'glibc') {
$result = shell()->execWithResult('ldd --version', false);
if ($result[0] !== 0) {
@ -198,7 +203,8 @@ class SystemUtil
// match ldd version: "ldd (some useless text) 2.17" match 2.17
$pattern = '/ldd\s+\(.*?\)\s+(\d+\.\d+)/';
if (preg_match($pattern, $first_line, $matches)) {
return $matches[1];
self::$libc_version = $matches[1];
return self::$libc_version;
}
return null;
}
@ -212,7 +218,8 @@ class SystemUtil
// match ldd version: "Version 1.2.3" match 1.2.3
$pattern = '/Version\s+(\d+\.\d+\.\d+)/';
if (preg_match($pattern, $result[1][1] ?? '', $matches)) {
return $matches[1];
self::$libc_version = $matches[1];
return self::$libc_version;
}
}
return null;

View File

@ -10,9 +10,9 @@ class curl extends LinuxLibraryBase
public const NAME = 'curl';
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true, bool $include_self = true): string
{
$libs = parent::getStaticLibFiles($style, $recursive);
$libs = parent::getStaticLibFiles($style, $recursive, $include_self);
if ($this->builder->getLib('openssl')) {
$libs .= ' -ldl -lpthread';
}

View File

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

View File

@ -14,10 +14,10 @@ class icu extends LinuxLibraryBase
protected function build(): void
{
$cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1 -fPIC -fPIE -fno-ident"';
$cxxflags = 'CXXFLAGS="-std=c++17"';
$cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1 -DPIC -fPIC"';
$cxxflags = 'CXXFLAGS="-std=c++17 -DPIC -fPIC -fno-ident"';
$ldflags = getenv('SPC_LIBC') !== 'glibc' ? 'LDFLAGS="-static"' : '';
shell()->cd($this->source_dir . '/source')
shell()->cd($this->source_dir . '/source')->initializeEnv($this)
->exec(
"{$cppflags} {$cxxflags} {$ldflags} " .
'./runConfigureICU Linux ' .

View File

@ -6,6 +6,7 @@ namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
class libffi extends LinuxLibraryBase
{
@ -17,23 +18,14 @@ class libffi extends LinuxLibraryBase
*/
public function build(): void
{
[$lib, , $destdir] = SEPARATED_PATH;
$arch = getenv('SPC_ARCH');
shell()->cd($this->source_dir)
->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
"--host={$arch}-unknown-linux " .
"--target={$arch}-unknown-linux " .
'--prefix= ' .
"--libdir={$lib}"
UnixAutoconfExecutor::create($this)
->configure(
"--host={$arch}-unknown-linux",
"--target={$arch}-unknown-linux",
"--libdir={$this->getLibDir()}"
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
->make();
if (is_file(BUILD_ROOT_PATH . '/lib64/libffi.a')) {
copy(BUILD_ROOT_PATH . '/lib64/libffi.a', BUILD_ROOT_PATH . '/lib/libffi.a');

View File

@ -4,17 +4,14 @@ declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixCMakeExecutor;
/**
* gmp is a template library class for unix
*/
class libmemcached extends LinuxLibraryBase
{
public const NAME = 'libmemcached';
public function build()
public function build(): void
{
throw new RuntimeException('libmemcached is currently not supported on Linux platform');
UnixCMakeExecutor::create($this)->build();
}
}

View File

@ -24,6 +24,7 @@ namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
class libpng extends LinuxLibraryBase
{
@ -36,28 +37,22 @@ class libpng extends LinuxLibraryBase
*/
public function build(): void
{
$optimizations = match (getenv('SPC_ARCH')) {
'x86_64' => '--enable-intel-sse ',
'aarch64' => '--enable-arm-neon ',
default => '',
};
shell()->cd($this->source_dir)->initializeEnv($this)
UnixAutoconfExecutor::create($this)
->exec('chmod +x ./configure')
->exec('chmod +x ./install-sh')
->exec(
'LDFLAGS="-L' . BUILD_LIB_PATH . '" ' .
'./configure ' .
'--disable-shared ' .
'--enable-static ' .
'--enable-hardware-optimizations ' .
'--with-zlib-prefix="' . BUILD_ROOT_PATH . '" ' .
$optimizations .
'--prefix='
->appendEnv(['LDFLAGS' => "-L{$this->getLibDir()}"])
->configure(
'--enable-hardware-optimizations',
"--with-zlib-prefix={$this->getBuildRootPath()}",
match (getenv('SPC_ARCH')) {
'x86_64' => '--enable-intel-sse',
'aarch64' => '--enable-arm-neon',
default => '',
}
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency} DEFAULT_INCLUDES='-I{$this->source_dir} -I" . BUILD_INCLUDE_PATH . "' LIBS= libpng16.la")
->exec('make install-libLTLIBRARIES install-data-am DESTDIR=' . BUILD_ROOT_PATH);
->make('libpng16.la', 'install-libLTLIBRARIES install-data-am', after_env_vars: ['DEFAULT_INCLUDES' => "-I{$this->source_dir} -I{$this->getIncludeDir()}"]);
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
$this->patchLaDependencyPrefix();
}
}

View File

@ -92,9 +92,9 @@ class openssl extends LinuxLibraryBase
FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/cmake/OpenSSL/OpenSSLConfig.cmake', '/set\(OPENSSL_LIBCRYPTO_DEPENDENCIES .*\)/m', 'set(OPENSSL_LIBCRYPTO_DEPENDENCIES "${OPENSSL_LIBRARY_DIR}/libz.a")');
}
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true, bool $include_self = true): string
{
$libFiles = parent::getStaticLibFiles($style, $recursive);
$libFiles = parent::getStaticLibFiles($style, $recursive, $include_self);
if (!str_contains('-ldl -lpthread', $libFiles)) {
$libFiles .= ' -ldl -lpthread';
}

View File

@ -67,6 +67,10 @@ class MacOSBuilder extends UnixBuilderBase
array_push($frameworks, ...$lib->getFrameworks());
}
foreach ($this->exts as $ext) {
array_push($frameworks, ...$ext->getFrameworks());
}
if ($asString) {
return implode(' ', array_map(fn ($x) => "-framework {$x}", $frameworks));
}
@ -181,6 +185,12 @@ class MacOSBuilder extends UnixBuilderBase
$this->sanityCheck($build_target);
}
public function testPHP(int $build_target = BUILD_TARGET_NONE)
{
$this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target);
}
/**
* Build cli sapi
*
@ -192,7 +202,8 @@ class MacOSBuilder extends UnixBuilderBase
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$shell = shell()->cd(SOURCE_PATH . '/php-src');
$shell->exec("\$SPC_CMD_PREFIX_PHP_MAKE {$vars} cli");
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
$shell->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli");
if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/cli/php')->exec('strip sapi/cli/php');
}
@ -263,15 +274,12 @@ class MacOSBuilder extends UnixBuilderBase
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
shell()->cd(SOURCE_PATH . '/php-src')
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install")
// Workaround for https://github.com/php/php-src/issues/12082
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o')
->exec('mkdir ' . BUILD_ROOT_PATH . '/lib/php-o')
->cd(BUILD_ROOT_PATH . '/lib/php-o')
->exec('ar x ' . 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('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o');
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
shell()->cd(SOURCE_PATH . '/php-src')
->exec('ar -t ' . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 ar d " . BUILD_LIB_PATH . '/libphp.a');
}
$this->patchPhpScripts();
}

View File

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

View File

@ -6,6 +6,7 @@ namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
class libffi extends MacOSLibraryBase
{
@ -17,20 +18,13 @@ class libffi extends MacOSLibraryBase
*/
protected function build(): void
{
[, , $destdir] = SEPARATED_PATH;
$arch = getenv('SPC_ARCH');
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
"--host={$arch}-apple-darwin " .
"--target={$arch}-apple-darwin " .
'--prefix= ' // use prefix=/
UnixAutoconfExecutor::create($this)
->configure(
"--host={$arch}-apple-darwin",
"--target={$arch}-apple-darwin",
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
->make();
$this->patchPkgconfPrefix(['libffi.pc']);
}
}

View File

@ -4,24 +4,9 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\store\FileSystem;
class libheif extends MacOSLibraryBase
{
use \SPC\builder\unix\library\libheif;
public const NAME = 'libheif';
public function patchBeforeBuild(): bool
{
if (!str_contains(file_get_contents($this->source_dir . '/CMakeLists.txt'), 'libbrotlienc')) {
FileSystem::replaceFileStr(
$this->source_dir . '/CMakeLists.txt',
'list(APPEND REQUIRES_PRIVATE "libbrotlidec")',
'list(APPEND REQUIRES_PRIVATE "libbrotlidec")' . "\n" . ' list(APPEND REQUIRES_PRIVATE "libbrotlienc")'
);
return true;
}
return false;
}
}

View File

@ -4,28 +4,14 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
/**
* gmp is a template library class for unix
*/
use SPC\util\executor\UnixCMakeExecutor;
class libmemcached extends MacOSLibraryBase
{
public const NAME = 'libmemcached';
public function build(): void
{
$rootdir = BUILD_ROOT_PATH;
shell()->cd($this->source_dir)
->exec('chmod +x configure')
->exec(
'./configure ' .
'--enable-static --disable-shared ' .
'--disable-sasl ' .
"--prefix={$rootdir}"
)
->exec('make clean')
->exec('sed -ie "s/-Werror//g" ' . $this->source_dir . '/Makefile')
->exec("make -j{$this->builder->concurrency}")
->exec('make install');
UnixCMakeExecutor::create($this)->build();
}
}

View File

@ -24,6 +24,7 @@ namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
class libpng extends MacOSLibraryBase
{
@ -36,29 +37,25 @@ class libpng extends MacOSLibraryBase
*/
protected function build(): void
{
$optimizations = match (php_uname('m')) {
'x86_64' => '--enable-intel-sse ',
'arm64' => '--enable-arm-neon ',
default => '',
};
shell()->cd($this->source_dir)
$arch = arch2gnu(php_uname('m'));
UnixAutoconfExecutor::create($this)
->exec('chmod +x ./configure')
->exec('chmod +x ./install-sh')
->exec(
'./configure ' .
'--host=' . arch2gnu(php_uname('m')) . '-apple-darwin ' .
'--disable-shared ' .
'--enable-static ' .
'--enable-hardware-optimizations ' .
$optimizations .
'--prefix='
->appendEnv(['LDFLAGS' => "-L{$this->getLibDir()}"])
->configure(
"--host={$arch}-apple-darwin",
'--enable-hardware-optimizations',
"--with-zlib-prefix={$this->getBuildRootPath()}",
match (getenv('SPC_ARCH')) {
'x86_64' => '--enable-intel-sse',
'aarch64' => '--enable-arm-neon',
default => '',
}
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency} DEFAULT_INCLUDES='-I. -I" . BUILD_INCLUDE_PATH . "' LIBS= libpng16.la")
->exec('make install-libLTLIBRARIES install-data-am DESTDIR=' . BUILD_ROOT_PATH)
->cd(BUILD_LIB_PATH)
->exec('ln -sf libpng16.a libpng.a');
->make('libpng16.la', 'install-libLTLIBRARIES install-data-am', after_env_vars: ['DEFAULT_INCLUDES' => "-I{$this->source_dir} -I{$this->getIncludeDir()}"]);
shell()->cd(BUILD_LIB_PATH)->exec('ln -sf libpng16.a libpng.a');
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
$this->patchLaDependencyPrefix();
}
}

View File

@ -17,9 +17,9 @@ trait UnixLibraryTrait
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true, bool $include_self = true): string
{
$libs = [$this];
$libs = $include_self ? [$this] : [];
if ($recursive) {
array_unshift($libs, ...array_values($this->getDependencies(recursive: true)));
}
@ -84,19 +84,34 @@ trait UnixLibraryTrait
}
}
/**
* remove libtool archive files
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function cleanLaFiles(): void
public function patchLaDependencyPrefix(?array $files = null): void
{
foreach ($this->getStaticLibs() as $lib) {
$filename = pathinfo($lib, PATHINFO_FILENAME) . '.la';
if (file_exists(BUILD_LIB_PATH . '/' . $filename)) {
unlink(BUILD_LIB_PATH . '/' . $filename);
logger()->info('Patching library [' . static::NAME . '] la files');
$throwOnMissing = true;
if ($files === null) {
$files = $this->getStaticLibs();
$files = array_map(fn ($name) => str_replace('.a', '.la', $name), $files);
$throwOnMissing = false;
}
foreach ($files as $name) {
$realpath = realpath(BUILD_LIB_PATH . '/' . $name);
if ($realpath === false) {
if ($throwOnMissing) {
throw new RuntimeException('Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
}
logger()->warning('Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
continue;
}
logger()->debug('Patching ' . $realpath);
// replace prefix
$file = FileSystem::readFile($realpath);
$file = str_replace(
' /lib/',
' ' . BUILD_LIB_PATH . '/',
$file
);
$file = preg_replace('/^libdir=.*$/m', "libdir='" . BUILD_LIB_PATH . "'", $file);
FileSystem::writeFile($realpath, $file);
}
}

View File

@ -153,13 +153,13 @@ abstract class UnixBuilderBase extends BuilderBase
// sanity check for php-cli
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
logger()->info('running cli sanity check');
[$ret, $output] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n -r "echo \"hello\";"');
[$ret, $output] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -r "echo \"hello\";"');
$raw_output = implode('', $output);
if ($ret !== 0 || trim($raw_output) !== 'hello') {
throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]");
}
foreach ($this->getExts(false) as $ext) {
foreach ($this->getExts() as $ext) {
logger()->debug('testing ext: ' . $ext->getName());
$ext->runCliCheckUnix();
}
@ -236,8 +236,8 @@ abstract class UnixBuilderBase extends BuilderBase
default => throw new RuntimeException('Deployment does not accept type ' . $type),
};
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
FileSystem::createDir(BUILD_ROOT_PATH . '/bin');
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_ROOT_PATH . '/bin/'));
FileSystem::createDir(BUILD_BIN_PATH);
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_BIN_PATH));
return true;
}
@ -263,6 +263,7 @@ abstract class UnixBuilderBase extends BuilderBase
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#');
FileSystem::replaceFileStr(BUILD_LIB_PATH . '/php/build/phpize.m4', 'test "[$]$1" = "no" && $1=yes', '# test "[$]$1" = "no" && $1=yes');
}
// patch php-config
if (file_exists(BUILD_BIN_PATH . '/php-config')) {

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait attr
{
@ -13,14 +14,11 @@ trait attr
*/
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->appendEnv(['CFLAGS' => "-I{$this->getIncludeDir()}", 'LDFLAGS' => "-L{$this->getLibDir()}"])
UnixAutoconfExecutor::create($this)
->exec('libtoolize --force --copy')
->exec('./autogen.sh || autoreconf -if')
->exec('./configure --prefix= --enable-static --disable-shared --with-pic --disable-nls')
->exec("make -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
->configure('--disable-nls')
->make();
$this->patchPkgconfPrefix(['libattr.pc'], PKGCONF_PATCH_PREFIX);
}
}

View File

@ -23,6 +23,8 @@ trait brotli
->build();
$this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']);
FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlidec.pc', 'Libs: -L${libdir} -lbrotlidec', 'Libs: -L${libdir} -lbrotlidec -lbrotlicommon');
FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlienc.pc', 'Libs: -L${libdir} -lbrotlienc', 'Libs: -L${libdir} -lbrotlienc -lbrotlicommon');
shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a');
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
trait fastlz
{
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->exec((getenv('CC') ?: 'cc') . ' -c -O3 -fPIC fastlz.c -o fastlz.o')
->exec((getenv('AR') ?: 'ar') . ' rcs libfastlz.a fastlz.o');
if (!copy($this->source_dir . '/fastlz.h', BUILD_INCLUDE_PATH . '/fastlz.h')) {
throw new \RuntimeException('Failed to copy fastlz.h');
}
if (!copy($this->source_dir . '/libfastlz.a', BUILD_LIB_PATH . '/libfastlz.a')) {
throw new \RuntimeException('Failed to copy libfastlz.a');
}
}
}

View File

@ -38,7 +38,5 @@ trait freetype
' -L/lib ',
' -L' . BUILD_ROOT_PATH . '/lib '
);
$this->cleanLaFiles();
}
}

View File

@ -4,34 +4,34 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait gettext
{
protected function build(): void
{
$extra = $this->builder->getLib('ncurses') ? ('--with-libncurses-prefix=' . BUILD_ROOT_PATH . ' ') : '';
$extra .= $this->builder->getLib('libxml2') ? ('--with-libxml2-prefix=' . BUILD_ROOT_PATH . ' ') : '';
$autoconf = UnixAutoconfExecutor::create($this)
->optionalLib('ncurses', "--with-libncurses-prefix={$this->getBuildRootPath()}")
->optionalLib('libxml2', "--with-libxml2-prefix={$this->getBuildRootPath()}")
->addConfigureArgs(
'--disable-java',
'--disable-c++',
'--with-included-gettext',
"--with-iconv-prefix={$this->getBuildRootPath()}",
);
$zts = $this->builder->getOption('enable-zts') ? '--enable-threads=isoc+posix ' : '--disable-threads ';
// zts
if ($this->builder->getOption('enable-zts')) {
$autoconf->addConfigureArgs('--enable-threads=isoc+posix')
->appendEnv([
'CFLAGS' => '-lpthread -D_REENTRANT',
'LDFLGAS' => '-lpthread',
]);
} else {
$autoconf->addConfigureArgs('--disable-threads');
}
$cflags = $this->builder->getOption('enable-zts') ? '-lpthread -D_REENTRANT' : '';
$ldflags = $this->builder->getOption('enable-zts') ? '-lpthread' : '';
shell()->cd($this->source_dir)->initializeEnv($this)
->appendEnv(['CFLAGS' => $cflags, 'LDFLAGS' => $ldflags])
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--disable-java ' .
'--disable-c++ ' .
$zts .
$extra .
'--with-included-gettext ' .
'--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' .
'--prefix=' . BUILD_ROOT_PATH
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install');
$autoconf->configure()->make(with_clean: true);
$this->patchLaDependencyPrefix();
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait gmp
{
@ -15,15 +16,7 @@ trait gmp
*/
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static --disable-shared ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
UnixAutoconfExecutor::create($this)->configure()->make();
$this->patchPkgconfPrefix(['gmp.pc']);
}
}

View File

@ -9,6 +9,7 @@ use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait imagemagick
{
@ -18,45 +19,39 @@ trait imagemagick
*/
protected function build(): void
{
// TODO: glibc rh 10 toolset's libgomp.a was built without -fPIC -fPIE so we can't use openmp without depending on libgomp.so
$openmp = getenv('SPC_LIBC') === 'musl' ? '--enable-openmp' : '--disable-openmp';
$extra = "--without-jxl --without-x {$openmp} ";
$required_libs = '';
$optional_libs = [
'libzip' => 'zip',
'libjpeg' => 'jpeg',
'libpng' => 'png',
'libwebp' => 'webp',
'libxml2' => 'xml',
'libheif' => 'heic',
'zlib' => 'zlib',
'xz' => 'lzma',
'zstd' => 'zstd',
'freetype' => 'freetype',
'bzip2' => 'bzlib',
];
foreach ($optional_libs as $lib => $option) {
$extra .= $this->builder->getLib($lib) ? "--with-{$option} " : "--without-{$option} ";
if ($this->builder->getLib($lib) instanceof LinuxLibraryBase) {
$required_libs .= ' ' . $this->builder->getLib($lib)->getStaticLibFiles();
}
}
$ac = UnixAutoconfExecutor::create($this)
->optionalLib('libzip', ...ac_with_args('zip'))
->optionalLib('libjpeg', ...ac_with_args('jpeg'))
->optionalLib('libpng', ...ac_with_args('png'))
->optionalLib('libwebp', ...ac_with_args('webp'))
->optionalLib('libxml2', ...ac_with_args('xml'))
->optionalLib('libheif', ...ac_with_args('heic'))
->optionalLib('zlib', ...ac_with_args('zlib'))
->optionalLib('xz', ...ac_with_args('lzma'))
->optionalLib('zstd', ...ac_with_args('zstd'))
->optionalLib('freetype', ...ac_with_args('freetype'))
->optionalLib('bzip2', ...ac_with_args('bzlib'))
->addConfigureArgs(
// TODO: glibc rh 10 toolset's libgomp.a was built without -fPIC so we can't use openmp without depending on libgomp.so
getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10') ? '--disable-openmp' : '--enable-openmp',
'--without-jxl',
'--without-x',
);
// special: linux musl needs `-static`
$ldflags = ($this instanceof LinuxLibraryBase) && getenv('SPC_LIBC') !== 'glibc' ? ('-static -ldl') : '-ldl';
// libxml iconv patch
$required_libs .= $this instanceof MacOSLibraryBase ? ('-liconv') : '';
shell()->cd($this->source_dir)->initializeEnv($this)
->appendEnv(['LDFLAGS' => $ldflags, 'LIBS' => $required_libs, 'PKG_CONFIG' => '$PKG_CONFIG --static'])
->exec(
'./configure ' .
'--enable-static --disable-shared ' .
$extra .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
// special: macOS needs -iconv
$libs = $this instanceof MacOSLibraryBase ? '-liconv' : '';
$ac->appendEnv([
'LDFLAGS' => $ldflags,
'LIBS' => $libs,
'PKG_CONFIG' => '$PKG_CONFIG --static',
]);
$ac->configure()->make();
$filelist = [
'ImageMagick.pc',
'ImageMagick-7.Q16HDRI.pc',
@ -75,5 +70,6 @@ trait imagemagick
'includearchdir=${prefix}/include/ImageMagick-7'
);
}
$this->patchLaDependencyPrefix();
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait ldap
{
@ -17,33 +18,25 @@ trait ldap
protected function build(): void
{
$alt = '';
// openssl support
$alt .= $this->builder->getLib('openssl') ? '--with-tls=openssl ' : '';
// gmp support
$alt .= $this->builder->getLib('gmp') ? '--with-mp=gmp ' : '';
// libsodium support
$alt .= $this->builder->getLib('libsodium') ? '--with-argon2=libsodium ' : '--enable-argon2=no ';
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
shell()->cd($this->source_dir)->initializeEnv($this)
->appendEnv(['LDFLAGS' => "-L{$this->getLibDir()}"])
->exec(
$this->builder->makeAutoconfFlags(AUTOCONF_CPPFLAGS) .
' ./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--disable-slapd ' .
'--without-systemd ' .
'--without-cyrus-sasl ' .
$alt .
'--prefix='
UnixAutoconfExecutor::create($this)
->optionalLib('openssl', '--with-tls=openssl')
->optionalLib('gmp', '--with-mp=gmp')
->optionalLib('libsodium', '--with-argon2=libsodium', '--enable-argon2=no')
->addConfigureArgs(
'--disable-slapd',
'--without-systemd',
'--without-cyrus-sasl',
)
->exec('make clean')
// remove tests and doc to prevent compile failed with error: soelim not found
->appendEnv([
'LDFLAGS' => "-L{$this->getLibDir()}",
'CPPFLAGS' => "-I{$this->getIncludeDir()}",
])
->configure()
->exec('sed -i -e "s/SUBDIRS= include libraries clients servers tests doc/SUBDIRS= include libraries clients servers/g" Makefile')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
->make();
FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/ldap.pc', 'Libs: -L${libdir} -lldap', 'Libs: -L${libdir} -lldap -llber');
$this->patchPkgconfPrefix(['ldap.pc', 'lber.pc']);
$this->patchLaDependencyPrefix();
}
}

View File

@ -7,6 +7,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait libacl
{
@ -29,14 +30,11 @@ trait libacl
*/
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->appendEnv(['CFLAGS' => "-I{$this->getIncludeDir()}", 'LDFLAGS' => "-L{$this->getLibDir()}"])
UnixAutoconfExecutor::create($this)
->exec('libtoolize --force --copy')
->exec('./autogen.sh || autoreconf -if')
->exec('./configure --prefix= --enable-static --disable-shared --disable-tests --disable-nls')
->exec("make -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
->configure('--disable-nls', '--disable-tests')
->make();
$this->patchPkgconfPrefix(['libacl.pc'], PKGCONF_PATCH_PREFIX);
}
}

View File

@ -23,6 +23,5 @@ trait libavif
->build();
// patch pkgconfig
$this->patchPkgconfPrefix(['libavif.pc']);
$this->cleanLaFiles();
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait libcares
{
@ -24,11 +25,7 @@ trait libcares
*/
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->exec('./configure --prefix= --enable-static --disable-shared --disable-tests --with-pic')
->exec("make -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
UnixAutoconfExecutor::create($this)->configure('--disable-tests')->make();
$this->patchPkgconfPrefix(['libcares.pc'], PKGCONF_PATCH_PREFIX);
}
}

View File

@ -40,15 +40,19 @@ trait libevent
*/
protected function build(): void
{
UnixCMakeExecutor::create($this)
$cmake = UnixCMakeExecutor::create($this)
->addConfigureArgs(
'-DEVENT__LIBRARY_TYPE=STATIC',
'-DEVENT__DISABLE_BENCHMARK=ON',
'-DEVENT__DISABLE_THREAD_SUPPORT=ON',
'-DEVENT__DISABLE_TESTS=ON',
'-DEVENT__DISABLE_SAMPLES=ON',
)
->build();
'-DEVENT__DISABLE_MBEDTLS=ON ',
);
if (version_compare(get_cmake_version(), '4.0.0', '>=')) {
$cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.10');
}
$cmake->build();
$this->patchPkgconfPrefix(['libevent.pc', 'libevent_core.pc', 'libevent_extra.pc', 'libevent_openssl.pc']);

View File

@ -6,10 +6,24 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixCMakeExecutor;
trait libheif
{
public function patchBeforeBuild(): bool
{
if (!str_contains(file_get_contents($this->source_dir . '/CMakeLists.txt'), 'libbrotlienc')) {
FileSystem::replaceFileStr(
$this->source_dir . '/CMakeLists.txt',
'list(APPEND REQUIRES_PRIVATE "libbrotlidec")',
'list(APPEND REQUIRES_PRIVATE "libbrotlidec")' . "\n" . ' list(APPEND REQUIRES_PRIVATE "libbrotlienc")'
);
return true;
}
return false;
}
/**
* @throws RuntimeException
* @throws FileSystemException

View File

@ -4,26 +4,13 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait libiconv
{
protected function build(): void
{
[,,$destdir] = SEPARATED_PATH;
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--enable-extra-encodings ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . $destdir);
if (file_exists(BUILD_BIN_PATH . '/iconv')) {
unlink(BUILD_BIN_PATH . '/iconv');
}
UnixAutoconfExecutor::create($this)->configure('--enable-extra-encodings')->make();
$this->patchLaDependencyPrefix();
}
}

View File

@ -26,6 +26,5 @@ trait libjpeg
->build();
// patch pkgconfig
$this->patchPkgconfPrefix(['libjpeg.pc', 'libturbojpeg.pc']);
$this->cleanLaFiles();
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait librdkafka
{
@ -15,25 +16,33 @@ trait librdkafka
*/
protected function build(): void
{
$builddir = BUILD_ROOT_PATH;
$zstd_option = $this->builder->getLib('zstd') ? ("STATIC_LIB_libzstd={$builddir}/lib/libzstd.a ") : '';
shell()->cd($this->source_dir)
->exec(
$zstd_option .
'./configure ' .
'--enable-static --disable-shared --disable-curl --disable-sasl --disable-valgrind --disable-zlib --disable-ssl ' .
($zstd_option == '' ? '--disable-zstd ' : '') .
'--prefix='
UnixAutoconfExecutor::create($this)
->optionalLib(
'zstd',
function ($lib) {
putenv("STATIC_LIB_libzstd={$lib->getLibDir()}/libzstd.a");
return '';
},
'--disable-zstd'
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$builddir}");
->removeConfigureArgs(
'--with-pic',
'--enable-pic',
)
->configure(
'--disable-curl',
'--disable-sasl',
'--disable-valgrind',
'--disable-zlib',
'--disable-ssl',
)
->make();
$this->patchPkgconfPrefix(['rdkafka.pc', 'rdkafka-static.pc', 'rdkafka++.pc', 'rdkafka++-static.pc']);
// remove dynamic libs
shell()
->exec("rm -rf {$builddir}/lib/*.so.*")
->exec("rm -rf {$builddir}/lib/*.so")
->exec("rm -rf {$builddir}/lib/*.dylib");
->exec("rm -rf {$this->getLibDir()}/*.so.*")
->exec("rm -rf {$this->getLibDir()}/*.so")
->exec("rm -rf {$this->getLibDir()}/*.dylib");
}
}

View File

@ -4,16 +4,13 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait libsodium
{
protected function build(): void
{
shell()->cd($this->source_dir)
->exec('./configure --enable-static --disable-shared --prefix=')
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
UnixAutoconfExecutor::create($this)->configure()->make();
$this->patchPkgconfPrefix(['libsodium.pc'], PKGCONF_PATCH_PREFIX);
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait libtiff
{
@ -15,30 +16,26 @@ trait libtiff
*/
protected function build(): void
{
// zlib
$extra_libs = '--enable-zlib --with-zlib-include-dir=' . BUILD_ROOT_PATH . '/include --with-zlib-lib-dir=' . BUILD_ROOT_PATH . '/lib';
// libjpeg
$extra_libs .= ' --enable-jpeg --disable-old-jpeg --disable-jpeg12 --with-jpeg-include-dir=' . BUILD_ROOT_PATH . '/include --with-jpeg-lib-dir=' . BUILD_ROOT_PATH . '/lib';
// We disabled lzma, zstd, webp, libdeflate by default to reduce the size of the binary
$extra_libs .= ' --disable-lzma --disable-zstd --disable-webp --disable-libdeflate';
$shell = shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static --disable-shared ' .
"{$extra_libs} " .
'--disable-cxx ' .
'--prefix='
);
// TODO: Remove this check when https://gitlab.com/libtiff/libtiff/-/merge_requests/635 will be merged and released
if (file_exists($this->source_dir . '/html')) {
$shell->exec('make clean');
}
$shell
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
UnixAutoconfExecutor::create($this)
->configure(
// zlib deps
'--enable-zlib',
"--with-zlib-include-dir={$this->getIncludeDir()}",
"--with-zlib-lib-dir={$this->getLibDir()}",
// libjpeg deps
'--enable-jpeg',
'--disable-old-jpeg',
'--disable-jpeg12',
"--with-jpeg-include-dir={$this->getIncludeDir()}",
"--with-jpeg-lib-dir={$this->getLibDir()}",
// We disabled lzma, zstd, webp, libdeflate by default to reduce the size of the binary
'--disable-lzma',
'--disable-zstd',
'--disable-webp',
'--disable-libdeflate',
'--disable-cxx',
)
->make();
$this->patchPkgconfPrefix(['libtiff-4.pc']);
}
}

View File

@ -24,8 +24,6 @@ trait libwebp
// patch pkgconfig
$this->patchPkgconfPrefix(['libsharpyuv.pc', 'libwebp.pc', 'libwebpdecoder.pc', 'libwebpdemux.pc', 'libwebpmux.pc'], PKGCONF_PATCH_PREFIX | PKGCONF_PATCH_LIBDIR);
$this->patchPkgconfPrefix(['libsharpyuv.pc'], PKGCONF_PATCH_CUSTOM, ['/^includedir=.*$/m', 'includedir=${prefix}/include/webp']);
$this->cleanLaFiles();
// fix imagemagick binary linking issue
$this->patchPkgconfPrefix(['libwebp.pc'], PKGCONF_PATCH_CUSTOM, ['/-lwebp$/m', '-lwebp -lsharpyuv']);
}
}

View File

@ -17,7 +17,13 @@ trait libxml2
public function build(): void
{
$cmake = UnixCMakeExecutor::create($this)
->optionalLib('zlib', "-DLIBXML2_WITH_ZLIB=ON -DZLIB_LIBRARY={$this->getLibDir()}/libz.a -DZLIB_INCLUDE_DIR={$this->getIncludeDir()}", '-DLIBXML2_WITH_ZLIB=OFF')
->optionalLib(
'zlib',
'-DLIBXML2_WITH_ZLIB=ON ' .
"-DZLIB_LIBRARY={$this->getLibDir()}/libz.a " .
"-DZLIB_INCLUDE_DIR={$this->getIncludeDir()}",
'-DLIBXML2_WITH_ZLIB=OFF',
)
->optionalLib('icu', ...cmake_boolean_args('LIBXML2_WITH_ICU'))
->optionalLib('xz', ...cmake_boolean_args('LIBXML2_WITH_LZMA'))
->addConfigureArgs(
@ -35,8 +41,13 @@ trait libxml2
FileSystem::replaceFileStr(
BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc',
'-licudata -licui18n -licuuc',
'-licui18n -licuuc -licudata'
'-lxml2 -liconv',
'-lxml2'
);
FileSystem::replaceFileStr(
BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc',
'-lxml2',
'-lxml2 -liconv'
);
}
}

View File

@ -8,6 +8,7 @@ use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
trait libxslt
{
@ -18,34 +19,26 @@ trait libxslt
*/
protected function build(): void
{
$required_libs = '';
foreach ($this->getDependencies() as $dep) {
if ($dep instanceof LinuxLibraryBase) {
$required_libs .= ' ' . $dep->getStaticLibFiles();
}
}
shell()->cd($this->source_dir)->initializeEnv($this)
$static_libs = $this instanceof LinuxLibraryBase ? $this->getStaticLibFiles(include_self: false) : '';
$ac = UnixAutoconfExecutor::create($this)
->appendEnv([
'CFLAGS' => "-I{$this->getIncludeDir()}",
'LDFLAGS' => "-L{$this->getLibDir()}",
'LIBS' => "{$required_libs} -lstdc++",
'LIBS' => "{$static_libs} -lstdc++",
])
->exec(
"{$this->builder->getOption('library_path')} " .
"{$this->builder->getOption('ld_library_path')} " .
'./configure ' .
'--enable-static --disable-shared ' .
'--without-python ' .
'--without-mem-debug ' .
'--without-crypto ' .
'--without-debug ' .
'--without-debugger ' .
'--with-libxml-prefix=' . escapeshellarg(BUILD_ROOT_PATH) . ' ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . escapeshellarg(BUILD_ROOT_PATH));
->addConfigureArgs(
'--without-python',
'--without-crypto',
'--without-debug',
'--without-debugger',
"--with-libxml-prefix={$this->getBuildRootPath()}",
);
$ac->exec("{$this->builder->getOption('library_path')} {$this->builder->getOption('ld_library_path')} ./configure {$ac->getConfigureArgsString()}")->make();
$this->patchPkgconfPrefix(['libexslt.pc']);
$this->patchLaDependencyPrefix();
shell()->cd(BUILD_LIB_PATH)
->exec("ar -t libxslt.a | grep '\\.a$' | xargs -n1 ar d libxslt.a")
->exec("ar -t libexslt.a | grep '\\.a$' | xargs -n1 ar d libexslt.a");
}
}

View File

@ -26,6 +26,10 @@ trait libyaml
protected function build(): void
{
UnixCMakeExecutor::create($this)->addConfigureArgs('-DBUILD_TESTING=OFF')->build();
$cmake = UnixCMakeExecutor::create($this)->addConfigureArgs('-DBUILD_TESTING=OFF');
if (version_compare(get_cmake_version(), '4.0.0', '>=')) {
$cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.5');
}
$cmake->build();
}
}

View File

@ -24,7 +24,6 @@ trait libzip
->addConfigureArgs(
'-DENABLE_GNUTLS=OFF',
'-DENABLE_MBEDTLS=OFF',
'-DBUILD_SHARED_LIBS=OFF',
'-DBUILD_DOC=OFF',
'-DBUILD_EXAMPLES=OFF',
'-DBUILD_REGRESS=OFF',

View File

@ -5,37 +5,33 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait ncurses
{
protected function build(): void
{
$filelist = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true);
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--enable-overwrite ' .
'--with-curses-h ' .
'--enable-pc-files ' .
'--enable-echo ' .
'--disable-widec ' .
'--with-normal ' .
'--with-ticlib ' .
'--without-tests ' .
'--without-dlsym ' .
'--without-debug ' .
'-enable-symlinks ' .
'--bindir=' . BUILD_ROOT_PATH . '/bin ' .
'--includedir=' . BUILD_ROOT_PATH . '/include ' .
'--libdir=' . BUILD_ROOT_PATH . '/lib ' .
'--prefix=' . BUILD_ROOT_PATH
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install');
UnixAutoconfExecutor::create($this)
->configure(
'--enable-overwrite',
'--with-curses-h',
'--enable-pc-files',
'--enable-echo',
'--disable-widec',
'--with-normal',
'--with-ticlib',
'--without-tests',
'--without-dlsym',
'--without-debug',
'-enable-symlinks',
"--bindir={$this->getBinDir()}",
"--includedir={$this->getIncludeDir()}",
"--libdir={$this->getLibDir()}",
"--prefix={$this->getBuildRootPath()}",
)
->make();
$final = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true);
// Remove the new files
$new_files = array_diff($final, $filelist);

View File

@ -7,6 +7,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
trait nghttp2
{
@ -17,42 +18,33 @@ trait nghttp2
*/
protected function build(): void
{
$args = $this->builder->makeAutoconfArgs(static::NAME, [
'zlib' => null,
'openssl' => null,
'libxml2' => null,
'libev' => null,
'libcares' => null,
'libngtcp2' => null,
'libnghttp3' => null,
'libbpf' => null,
'libevent-openssl' => null,
'jansson' => null,
'jemalloc' => null,
'systemd' => null,
]);
if ($brotli = $this->builder->getLib('brotli')) {
/* @phpstan-ignore-next-line */
$args .= ' --with-libbrotlidec=yes LIBBROTLIDEC_CFLAGS="-I' . BUILD_ROOT_PATH . '/include" LIBBROTLIDEC_LIBS="' . $brotli->getStaticLibFiles() . '"';
/* @phpstan-ignore-next-line */
$args .= ' --with-libbrotlienc=yes LIBBROTLIENC_CFLAGS="-I' . BUILD_ROOT_PATH . '/include" LIBBROTLIENC_LIBS="' . $brotli->getStaticLibFiles() . '"';
}
[,,$destdir] = SEPARATED_PATH;
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--with-pic ' .
'--enable-lib-only ' .
$args . ' ' .
'--prefix='
UnixAutoconfExecutor::create($this)
->optionalLib('zlib', ...ac_with_args('zlib', true))
->optionalLib('openssl', ...ac_with_args('openssl', true))
->optionalLib('libxml2', ...ac_with_args('libxml2', true))
->optionalLib('libev', ...ac_with_args('libev', true))
->optionalLib('libcares', ...ac_with_args('libcares', true))
->optionalLib('ngtcp2', ...ac_with_args('libngtcp2', true))
->optionalLib('nghttp3', ...ac_with_args('libnghttp3', true))
// ->optionalLib('libbpf', ...ac_with_args('libbpf', true))
// ->optionalLib('libevent-openssl', ...ac_with_args('libevent-openssl', true))
// ->optionalLib('jansson', ...ac_with_args('jansson', true))
// ->optionalLib('jemalloc', ...ac_with_args('jemalloc', true))
// ->optionalLib('systemd', ...ac_with_args('systemd', true))
->optionalLib(
'brotli',
fn ($lib) => implode(' ', [
'--with-brotlidec=yes',
"LIBBROTLIDEC_CFLAGS=\"-I{$lib->getIncludeDir()}\"",
"LIBBROTLIDEC_LIBS=\"{$lib->getStaticLibFiles()}\"",
'--with-libbrotlienc=yes',
"LIBBROTLIENC_CFLAGS=\"-I{$lib->getIncludeDir()}\"",
"LIBBROTLIENC_LIBS=\"{$lib->getStaticLibFiles()}\"",
])
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
->configure('--enable-lib-only')
->make();
$this->patchPkgconfPrefix(['libnghttp2.pc']);
$this->patchLaDependencyPrefix();
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait nghttp3
{
@ -15,18 +16,8 @@ trait nghttp3
*/
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--with-pic ' .
'--enable-lib-only ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
UnixAutoconfExecutor::create($this)->configure('--enable-lib-only')->make();
$this->patchPkgconfPrefix(['libnghttp3.pc']);
$this->patchLaDependencyPrefix();
}
}

View File

@ -7,6 +7,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
trait ngtcp2
{
@ -17,37 +18,34 @@ trait ngtcp2
*/
protected function build(): void
{
$args = $this->builder->makeAutoconfArgs(static::NAME, [
'openssl' => null,
'libev' => null,
'jemalloc' => null,
'libnghttp3' => null,
]);
if ($brotli = $this->builder->getLib('brotli')) {
/* @phpstan-ignore-next-line */
$args .= ' --with-libbrotlidec=yes LIBBROTLIDEC_CFLAGS="-I' . BUILD_ROOT_PATH . '/include" LIBBROTLIDEC_LIBS="' . $brotli->getStaticLibFiles() . '"';
/* @phpstan-ignore-next-line */
$args .= ' --with-libbrotlienc=yes LIBBROTLIENC_CFLAGS="-I' . BUILD_ROOT_PATH . '/include" LIBBROTLIENC_LIBS="' . $brotli->getStaticLibFiles() . '"';
}
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--with-pic ' .
'--enable-lib-only ' .
$args . ' ' .
'--prefix='
UnixAutoconfExecutor::create($this)
->optionalLib('openssl', fn ($lib) => implode(' ', [
'--with-openssl=yes',
"OPENSSL_LIBS=\"{$lib->getStaticLibFiles()}\"",
"OPENSSL_CFLAGS=\"-I{$lib->getIncludeDir()}\"",
]), '--with-openssl=no')
->optionalLib('libev', ...ac_with_args('libev', true))
->optionalLib('nghttp3', ...ac_with_args('libnghttp3', true))
->optionalLib('jemalloc', ...ac_with_args('jemalloc', true))
->optionalLib(
'brotli',
fn ($lib) => implode(' ', [
'--with-brotlidec=yes',
"LIBBROTLIDEC_CFLAGS=\"-I{$lib->getIncludeDir()}\"",
"LIBBROTLIDEC_LIBS=\"{$lib->getStaticLibFiles()}\"",
'--with-libbrotlienc=yes',
"LIBBROTLIENC_CFLAGS=\"-I{$lib->getIncludeDir()}\"",
"LIBBROTLIENC_LIBS=\"{$lib->getStaticLibFiles()}\"",
])
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
->appendEnv(['PKG_CONFIG' => '$PKG_CONFIG --static'])
->configure('--enable-lib-only')
->make();
$this->patchPkgconfPrefix(['libngtcp2.pc', 'libngtcp2_crypto_ossl.pc']);
$this->patchLaDependencyPrefix();
// on macOS, the static library may contain other static libraries?
// ld: archive member 'libssl.a' not a mach-o file in libngtcp2_crypto_ossl.a
shell()->cd(BUILD_LIB_PATH)
->exec("ar -t libngtcp2_crypto_ossl.a | grep '\\.a$' | xargs -n1 ar d libngtcp2_crypto_ossl.a");
shell()->cd(BUILD_LIB_PATH)->exec("ar -t libngtcp2_crypto_ossl.a | grep '\\.a$' | xargs -n1 ar d libngtcp2_crypto_ossl.a");
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait onig
{
@ -15,13 +16,7 @@ trait onig
*/
protected function build(): void
{
[,,$destdir] = SEPARATED_PATH;
shell()->cd($this->source_dir)->initializeEnv($this)
->exec('./configure --enable-static --disable-shared --prefix=')
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
UnixAutoconfExecutor::create($this)->configure()->make();
$this->patchPkgconfPrefix(['oniguruma.pc']);
}
}

View File

@ -5,32 +5,27 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\util\executor\UnixAutoconfExecutor;
trait pkgconfig
{
protected function build(): void
{
$cflags = PHP_OS_FAMILY !== 'Linux' ? "{$this->builder->arch_c_flags} -Wimplicit-function-declaration -Wno-int-conversion" : '';
$ldflags = !($this instanceof LinuxLibraryBase) || getenv('SPC_LIBC') === 'glibc' ? '' : '--static';
shell()->cd($this->source_dir)->initializeEnv($this)
->appendEnv(['CFLAGS' => $cflags, 'LDFLAGS' => $ldflags])
->exec(
'./configure ' .
'--disable-shared ' .
'--enable-static ' .
'--with-internal-glib ' .
'--disable-host-tool ' .
'--with-pic ' .
'--prefix=' . BUILD_ROOT_PATH . ' ' .
'--without-sysroot ' .
'--without-system-include-path ' .
'--without-system-library-path ' .
'--without-pc-path'
UnixAutoconfExecutor::create($this)
->appendEnv([
'CFLAGS' => PHP_OS_FAMILY !== 'Linux' ? '-Wimplicit-function-declaration -Wno-int-conversion' : '',
'LDFLAGS' => !($this instanceof LinuxLibraryBase) || getenv('SPC_LIBC') === 'glibc' ? '' : '--static',
])
->configure(
'--with-internal-glib',
'--disable-host-tool',
'--without-sysroot',
'--without-system-include-path',
'--without-system-library-path',
'--without-pc-path',
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install-exec');
->make(with_install: 'install-exec');
shell()->exec('strip ' . BUILD_ROOT_PATH . '/bin/pkg-config');
}
}

View File

@ -22,7 +22,7 @@ trait postgresql
$packages = 'zlib openssl readline libxml-2.0';
$optional_packages = [
'zstd' => 'libzstd',
// 'ldap' => 'ldap',
'ldap' => 'ldap',
'libxslt' => 'libxslt',
'icu' => 'icu-i18n',
];
@ -39,10 +39,12 @@ trait postgresql
$output = shell()->execWithResult("pkg-config --cflags-only-I --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
$macos_15_bug_cflags = PHP_OS_FAMILY === 'Darwin' ? ' -Wno-unguarded-availability-new' : '';
$cflags = '';
if (!empty($output[1][0])) {
$cppflags = $output[1][0];
$macos_15_bug_cflags = PHP_OS_FAMILY === 'Darwin' ? ' -Wno-unguarded-availability-new' : '';
$envs .= " CPPFLAGS=\"{$cppflags} -fPIC -fPIE -fno-ident{$macos_15_bug_cflags}\"";
$cflags = $output[1][0];
$envs .= ' CPPFLAGS="-DPIC"';
$cflags = "{$cflags} -fno-ident{$macos_15_bug_cflags}";
}
$output = shell()->execWithResult("pkg-config --libs-only-L --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
@ -79,17 +81,19 @@ trait postgresql
}
// configure
shell()->cd($this->source_dir . '/build')
shell()->cd($this->source_dir . '/build')->initializeEnv($this)
->appendEnv(['CFLAGS' => $cflags])
->exec(
"{$envs} ../configure " .
"--prefix={$builddir} " .
'--disable-thread-safety ' .
($this->builder->getOption('enable-zts') ? '--enable-thread-safety ' : '--disable-thread-safety ') .
'--enable-coverage=no ' .
'--with-ssl=openssl ' .
'--with-readline ' .
'--with-libxml ' .
($this->builder->getLib('icu') ? '--with-icu ' : '--without-icu ') .
'--without-ldap ' .
($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') .
// '--without-ldap ' .
($this->builder->getLib('libxslt') ? '--with-libxslt ' : '--without-libxslt ') .
($this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ') .
'--without-lz4 ' .
@ -98,11 +102,7 @@ trait postgresql
'--without-pam ' .
'--without-bonjour ' .
'--without-tcl '
);
// ($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') .
// build
shell()->cd($this->source_dir . '/build')
)
->exec($envs . ' make -C src/bin/pg_config install')
->exec($envs . ' make -C src/include install')
->exec($envs . ' make -C src/common install')
@ -114,6 +114,8 @@ trait postgresql
->exec("rm -rf {$builddir}/lib/*.so.*")
->exec("rm -rf {$builddir}/lib/*.so")
->exec("rm -rf {$builddir}/lib/*.dylib");
FileSystem::replaceFileStr(BUILD_LIB_PATH . '/pkgconfig/libpq.pc', '-lldap', '-lldap -llber');
}
private function getVersion(): string

View File

@ -8,6 +8,7 @@ use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait qdbm
{
@ -17,17 +18,9 @@ trait qdbm
*/
protected function build(): void
{
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static --disable-shared ' .
'--prefix='
)
->exec('make clean');
$ac = UnixAutoconfExecutor::create($this)->configure();
FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/MYLIBS = libqdbm.a.*/m', 'MYLIBS = libqdbm.a');
shell()->cd($this->source_dir)
->exec("make -j{$this->builder->concurrency}" . ($this instanceof MacOSLibraryBase ? ' mac' : ''))
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$ac->make($this instanceof MacOSLibraryBase ? 'mac' : '');
$this->patchPkgconfPrefix(['qdbm.pc']);
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait readline
{
@ -15,18 +16,12 @@ trait readline
*/
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->exec(
'./configure ' .
'--enable-static=yes ' .
'--enable-shared=no ' .
'--prefix= ' .
'--with-curses ' .
'--enable-multibyte=yes'
UnixAutoconfExecutor::create($this)
->configure(
'--with-curses',
'--enable-multibyte=yes',
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
->make();
$this->patchPkgconfPrefix(['readline.pc']);
}
}

View File

@ -4,15 +4,13 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait sqlite
{
protected function build(): void
{
shell()->cd($this->source_dir)->initializeEnv($this)
->exec('./configure --enable-static --disable-shared --prefix=')
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
UnixAutoconfExecutor::create($this)->configure()->make();
$this->patchPkgconfPrefix(['sqlite3.pc']);
}
}

View File

@ -16,13 +16,16 @@ trait tidy
*/
protected function build(): void
{
UnixCMakeExecutor::create($this)
$cmake = UnixCMakeExecutor::create($this)
->setBuildDir("{$this->source_dir}/build-dir")
->addConfigureArgs(
'-DSUPPORT_CONSOLE_APP=OFF',
'-DBUILD_SHARED_LIB=OFF'
)
->build();
);
if (version_compare(get_cmake_version(), '4.0.0', '>=')) {
$cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.5');
}
$cmake->build();
$this->patchPkgconfPrefix(['tidy.pc']);
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait unixodbc
{
@ -15,21 +16,16 @@ trait unixodbc
*/
protected function build(): void
{
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static --disable-shared ' .
'--disable-debug ' .
'--disable-dependency-tracking ' .
'--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' .
'--with-included-ltdl ' .
'--enable-gui=no ' .
'--prefix='
UnixAutoconfExecutor::create($this)
->configure(
'--disable-debug',
'--disable-dependency-tracking',
"--with-libiconv-prefix={$this->getBuildRootPath()}",
'--with-included-ltdl',
'--enable-gui=no',
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
->make();
$this->patchPkgconfPrefix(['odbc.pc', 'odbccr.pc', 'odbcinst.pc']);
$this->cleanLaFiles();
$this->patchLaDependencyPrefix();
}
}

Some files were not shown because too many files have changed in this diff Show More