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
125 changed files with 2365 additions and 1473 deletions

3
.gitignore vendored
View File

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

View File

@@ -72,6 +72,7 @@ RUN yum update -y && \
yum install -y devtoolset-10-gcc-* yum install -y devtoolset-10-gcc-*
RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc
RUN source /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 && \ 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 && \ mkdir /cmake && \

View File

@@ -68,8 +68,8 @@ CXX=${SPC_LINUX_DEFAULT_CXX}
AR=${SPC_LINUX_DEFAULT_AR} AR=${SPC_LINUX_DEFAULT_AR}
LD=ld.gold LD=ld.gold
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build ; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="-fPIC" SPC_DEFAULT_C_FLAGS="-fpic -Os"
SPC_DEFAULT_CXX_FLAGS= 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) ; 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= SPC_EXTRA_LIBS=
; upx executable path ; upx executable path
@@ -81,7 +81,7 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime
; buildconf command ; buildconf command
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force" SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
; configure command ; 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 ; make command
SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}" SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}"
; embed type for php, static (libphp.a) or shared (libphp.so) ; 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 *** ; *** default build vars for building php ***
; CFLAGS for configuring 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 ; CPPFLAGS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}" SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}"
; LDFLAGS for configuring php ; LDFLAGS for configuring php
@@ -97,9 +97,11 @@ SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}"
; LIBS for configuring php ; LIBS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_LIBS="-ldl -lpthread -lm" SPC_CMD_VAR_PHP_CONFIGURE_LIBS="-ldl -lpthread -lm"
; EXTRA_CFLAGS for `make` php ; 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 ; EXTRA_LIBS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm" 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 ; EXTRA_LDFLAGS_PROGRAM for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie" 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 CC=clang
CXX=clang++ CXX=clang++
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build ; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_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" 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) ; 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= SPC_EXTRA_LIBS=
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches ; 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 ; LDFLAGS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}" SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}"
; EXTRA_CFLAGS for `make` php ; 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 ; EXTRA_LIBS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-lresolv" SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-lresolv"
; embed type for php, static (libphp.a) or shared (libphp.dylib) ; embed type for php, static (libphp.a) or shared (libphp.dylib)

View File

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

View File

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

View File

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

View File

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

View File

@@ -151,8 +151,7 @@ Parallel is only supported on PHP 8.0 ZTS and above.
## spx ## spx
1. The [SPX extension](https://github.com/NoiseByNorthwest/php-spx) only supports NTS mode. 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).
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).
## mimalloc ## mimalloc

View File

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

View File

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

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\builder; namespace SPC\builder;
use PharIo\FileSystem\File;
use SPC\exception\ExceptionHandler; use SPC\exception\ExceptionHandler;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\InterruptException; use SPC\exception\InterruptException;
@@ -127,7 +128,7 @@ abstract class BuilderBase
if ($including_shared) { if ($including_shared) {
return $this->exts; 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); 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 public function buildSharedExts(): void
{ {
foreach ($this->getExts() as $ext) { $lines = file(BUILD_BIN_PATH . '/php-config');
if (!$ext->isBuildShared()) { $extension_dir_line = null;
continue; 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 public function makeStaticExtensionArgs(): string
{ {
$ret = []; $ret = [];
foreach ($this->getExts(false) as $ext) { foreach ($this->getExts() as $ext) {
logger()->info($ext->getName() . ' is using ' . $ext->getConfigureArg()); $arg = $ext->getConfigureArg();
$ret[] = trim($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)); logger()->debug('Using configure: ' . implode(' ', $ret));
return implode(' ', $ret); return implode(' ', $ret);

View File

@@ -53,26 +53,26 @@ class Extension
} }
} }
public function getFrameworks(): array
{
return Config::getExt($this->getName(), 'frameworks', []);
}
/** /**
* 获取开启该扩展的 PHP 编译添加的参数 * 获取开启该扩展的 PHP 编译添加的参数
* *
* @throws FileSystemException * @throws FileSystemException
* @throws WrongUsageException * @throws WrongUsageException
*/ */
public function getConfigureArg(): string public function getConfigureArg(bool $shared = false): string
{ {
$arg = $this->getEnableArg(); return match (PHP_OS_FAMILY) {
switch (PHP_OS_FAMILY) { 'Windows' => $this->getWindowsConfigureArg($shared),
case 'Windows': 'Darwin',
$arg .= $this->getWindowsConfigureArg(); 'Linux',
break; 'BSD' => $this->getUnixConfigureArg($shared),
case 'Darwin': default => throw new WrongUsageException(PHP_OS_FAMILY . ' build is not supported yet'),
case 'Linux': };
case 'BSD':
$arg .= $this->getUnixConfigureArg();
break;
}
return $arg;
} }
/** /**
@@ -81,13 +81,13 @@ class Extension
* @throws FileSystemException * @throws FileSystemException
* @throws WrongUsageException * @throws WrongUsageException
*/ */
public function getEnableArg(): string public function getEnableArg(bool $shared = false): string
{ {
$_name = str_replace('_', '-', $this->name); $_name = str_replace('_', '-', $this->name);
return match ($arg_type = Config::getExt($this->name, 'arg-type', 'enable')) { return match ($arg_type = Config::getExt($this->name, 'arg-type', 'enable')) {
'enable' => '--enable-' . $_name . ' ', 'enable' => '--enable-' . $_name . ($shared ? '=shared' : '') . ' ',
'with' => '--with-' . $_name . ' ', 'with' => '--with-' . $_name . ($shared ? '=shared' : '') . ' ',
'with-prefix' => '--with-' . $_name . '="' . BUILD_ROOT_PATH . '" ', 'with-prefix' => '--with-' . $_name . '=' . ($shared ? 'shared,' : '') . '"' . BUILD_ROOT_PATH . '" ',
'none', 'custom' => '', 'none', 'custom' => '',
default => throw new WrongUsageException("argType does not accept {$arg_type}, use [enable/with/with-prefix] ."), default => throw new WrongUsageException("argType does not accept {$arg_type}, use [enable/with/with-prefix] ."),
}; };
@@ -147,15 +147,15 @@ class Extension
return $this->name; return $this->name;
} }
public function getWindowsConfigureArg(): string public function getWindowsConfigureArg(bool $shared = false): string
{ {
return ''; return $this->getEnableArg();
// Windows is not supported yet // Windows is not supported yet
} }
public function getUnixConfigureArg(bool $shared = false): string 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 * Patch code before shared extension phpize
* @throws RuntimeException * 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()); return false;
if ($ret !== 0) { }
throw new RuntimeException($this->getName() . '.so failed to load');
/**
* 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 // 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 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 // 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) { if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret); 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') 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 ($ret !== 0) {
if ($this->builder->getOption('debug')) { if ($this->builder->getOption('debug')) {
var_dump($out); var_dump($out);
@@ -275,6 +328,20 @@ class Extension
*/ */
public function buildShared(): void 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) { match (PHP_OS_FAMILY) {
'Darwin', 'Linux' => $this->buildUnixShared(), 'Darwin', 'Linux' => $this->buildUnixShared(),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'), default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
@@ -292,26 +359,44 @@ class Extension
*/ */
public function buildUnixShared(): void 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 = [ $env = [
'CFLAGS' => $config['cflags'], 'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'], '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 // prepare configure args
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->setEnv($env) ->setEnv($env)
->exec(BUILD_BIN_PATH . '/phpize') ->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);
// copy shared library if ($this->patchBeforeSharedConfigure()) {
copy($this->source_dir . '/modules/' . $this->getDistName() . '.so', BUILD_LIB_PATH . '/' . $this->getDistName() . '.so'); logger()->info('ext [ . ' . $this->getName() . '] patching before shared configure');
// check shared extension with php-cli
if (file_exists(BUILD_BIN_PATH . '/php')) {
$this->runSharedExtensionCheckUnix();
} }
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 private function getLibraryDependencies(bool $recursive = false): array
{ {
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase); $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; return $deps;
} }
} }

View File

@@ -11,9 +11,12 @@ use SPC\store\Config;
use SPC\store\Downloader; use SPC\store\Downloader;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\store\SourceManager; use SPC\store\SourceManager;
use SPC\util\GlobalValueTrait;
abstract class LibraryBase abstract class LibraryBase
{ {
use GlobalValueTrait;
/** @var string */ /** @var string */
public const NAME = 'unknown'; public const NAME = 'unknown';
@@ -31,7 +34,7 @@ abstract class LibraryBase
if (static::NAME === 'unknown') { if (static::NAME === 'unknown') {
throw new RuntimeException('no 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; 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. * Build this library.
* *

View File

@@ -25,10 +25,10 @@ class amqp extends Extension
public function getUnixConfigureArg(bool $shared = false): string 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'; return '--with-amqp';
} }

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension; namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\macos\MacOSBuilder; use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
@@ -21,7 +22,7 @@ class curl extends Extension
{ {
logger()->info('patching before-configure for curl checks'); logger()->info('patching before-configure for curl checks');
$file1 = "AC_DEFUN([PHP_CHECK_LIBRARY], [\n $3\n])"; $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], [ $file2 = 'AC_DEFUN([PHP_CHECK_LIBRARY], [
save_old_LDFLAGS=$LDFLAGS save_old_LDFLAGS=$LDFLAGS
ac_stuff="$5" ac_stuff="$5"
@@ -40,7 +41,7 @@ class curl extends Extension
$4 $4
])dnl ])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; return true;
} }
@@ -52,6 +53,72 @@ class curl extends Extension
{ {
$frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : ''; $frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : '';
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-lcurl/', $this->getLibFilesString() . $frameworks); FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-lcurl/', $this->getLibFilesString() . $frameworks);
$this->patchBeforeSharedConfigure();
return true; 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 public function getUnixConfigureArg(bool $shared = false): string
{ {
$qdbm = $this->builder->getLib('qdbm') ? (' --with-qdbm=' . BUILD_ROOT_PATH) : ''; $qdbm = $this->builder->getLib('qdbm') ? (' --with-qdbm=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH) : '';
return '--enable-dba' . $qdbm; return '--enable-dba' . ($shared ? '=shared' : '') . $qdbm;
} }
public function getWindowsConfigureArg(): string public function getWindowsConfigureArg(bool $shared = false): string
{ {
$qdbm = $this->builder->getLib('qdbm') ? ' --with-qdbm' : ''; $qdbm = $this->builder->getLib('qdbm') ? ' --with-qdbm' : '';
return '--with-dba' . $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 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'; return '--with-ffi';
} }

View File

@@ -12,7 +12,7 @@ class gd extends Extension
{ {
public function getUnixConfigureArg(bool $shared = false): string 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('freetype') ? ' --with-freetype' : '';
$arg .= $this->builder->getLib('libjpeg') ? ' --with-jpeg' : ''; $arg .= $this->builder->getLib('libjpeg') ? ' --with-jpeg' : '';
$arg .= $this->builder->getLib('libwebp') ? ' --with-webp' : ''; $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; return '--enable-glfw --with-glfw-dir=' . BUILD_ROOT_PATH;
} }
public function getWindowsConfigureArg(): string public function getWindowsConfigureArg(bool $shared = false): string
{ {
return '--enable-glfw=static'; return '--enable-glfw=static';
} }

View File

@@ -12,10 +12,13 @@ class imagick extends Extension
{ {
public function patchBeforeMake(): bool public function patchBeforeMake(): bool
{ {
if (getenv('SPC_LIBC') !== 'musl') { if (PHP_OS_FAMILY !== 'Linux') {
return false; 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'); $extra_libs = trim(getenv('SPC_EXTRA_LIBS') . ' -lgomp');
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs); f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
return true; return true;
@@ -23,7 +26,7 @@ class imagick extends Extension
public function getUnixConfigureArg(bool $shared = false): string public function getUnixConfigureArg(bool $shared = false): string
{ {
$disable_omp = getenv('SPC_LIBC') === 'musl' ? '' : ' ac_cv_func_omp_pause_resource_all=no'; $disable_omp = !(getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) ? '' : ' ac_cv_func_omp_pause_resource_all=no';
return '--with-imagick=' . BUILD_ROOT_PATH . $disable_omp; 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 // 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')) { if (is_string($env = getenv('CXX')) && !str_contains($env, 'std=c++17')) {
f_putenv('CXX=' . $env . ' -std=c++17'); f_putenv('CXX=' . $env . ' -std=c++17');
} else {
f_putenv('CXX=clang++ -std=c++17');
} }
return true; 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; 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'; return '--enable-lz4';
} }

View File

@@ -16,7 +16,7 @@ class mbregex extends Extension
return 'mbstring'; return 'mbstring';
} }
public function getConfigureArg(): string public function getConfigureArg(bool $shared = false): string
{ {
return ''; return '';
} }
@@ -26,7 +26,8 @@ class mbregex extends Extension
*/ */
public function runCliCheckUnix(): void 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) { if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !'); 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')] #[CustomExt('mbstring')]
class mbstring extends Extension 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) { if ($this->builder->getExt('mbregex') === null) {
$arg .= ' --disable-mbregex'; $arg .= ' --disable-mbregex';
} else { } else {

View File

@@ -14,7 +14,7 @@ class memcache extends Extension
{ {
public function getUnixConfigureArg(bool $shared = false): string 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 public function getUnixConfigureArg(bool $shared = false): string
{ {
$rootdir = BUILD_ROOT_PATH; return '--enable-memcached' . ($shared ? '=shared' : '') . ' ' .
$zlib_dir = $this->builder->getPHPVersionID() >= 80400 ? '' : "--with-zlib-dir={$rootdir}"; '--with-zlib-dir=' . BUILD_ROOT_PATH . ' ' .
return "--enable-memcached {$zlib_dir} --with-libmemcached-dir={$rootdir} --disable-memcached-sasl --enable-memcached-json"; '--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 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 public function getUnixConfigureArg(bool $shared = false): string
{ {
$openssl_dir = $this->builder->getPHPVersionID() >= 80400 ? '' : ' --with-openssl-dir=' . BUILD_ROOT_PATH; $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 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'; return '--with-pdo-odbc';
} }

View File

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

View File

@@ -36,16 +36,21 @@ class pgsql extends Extension
public function getUnixConfigureArg(bool $shared = false): string public function getUnixConfigureArg(bool $shared = false): string
{ {
if ($this->builder->getPHPVersionID() >= 80400) { 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 WrongUsageException
* @throws RuntimeException * @throws RuntimeException
*/ */
public function getWindowsConfigureArg(): string public function getWindowsConfigureArg(bool $shared = false): string
{ {
if ($this->builder->getPHPVersionID() >= 80400) { if ($this->builder->getPHPVersionID() >= 80400) {
return '--with-pgsql'; 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')] #[CustomExt('rdkafka')]
class rdkafka extends Extension 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 public function patchBeforeMake(): bool
{ {
// when compiling rdkafka with inline builds, it shows some errors, I don't know why. // 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; 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 = shell()->execWithResult('pkg-config --libs --static rdkafka')[1];
$pkgconf_libs = trim(implode('', $pkgconf_libs)); $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; 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; return $arg;
} }
public function getWindowsConfigureArg(): string public function getWindowsConfigureArg(bool $shared = false): string
{ {
$arg = '--enable-redis'; $arg = '--enable-redis';
$arg .= $this->builder->getExt('session') ? ' --enable-redis-session' : ' --disable-redis-session'; $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; namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\exception\WrongUsageException; use SPC\store\FileSystem;
use SPC\util\CustomExt; use SPC\util\CustomExt;
#[CustomExt('spx')] #[CustomExt('spx')]
class spx extends Extension 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 public function getUnixConfigureArg(bool $shared = false): string
{ {
$arg = '--enable-spx'; $arg = '--enable-spx' . ($shared ? '=shared' : '');
if ($this->builder->getExt('zlib') === null) { if ($this->builder->getLib('zlib') !== null) {
$arg .= ' --with-zlib-dir=' . BUILD_ROOT_PATH; $arg .= ' --with-zlib-dir=' . BUILD_ROOT_PATH;
} }
return $arg; 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) { if ($this->builder->getExt('swoole') === null) {
return; 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); $out = implode('', $out);
if ($ret !== 0) { if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret); 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) { if ($this->builder->getExt('swoole') === null) {
return; 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); $out = implode('', $out);
if ($ret !== 0) { if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret); 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) { if ($this->builder->getExt('swoole') === null) {
return; 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); $out = implode('', $out);
if ($ret !== 0) { if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret); 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 = '--enable-swow';
$arg .= $this->builder->getLib('openssl') ? ' --enable-swow-ssl' : ' --disable-swow-ssl'; $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; return $arg;
} }
public function getWindowsConfigureArg(): string public function getWindowsConfigureArg(bool $shared = false): string
{ {
return '--with-xlswriter'; return '--with-xlswriter';
} }

View File

@@ -13,7 +13,6 @@ use SPC\util\CustomExt;
#[CustomExt('soap')] #[CustomExt('soap')]
#[CustomExt('xmlreader')] #[CustomExt('xmlreader')]
#[CustomExt('xmlwriter')] #[CustomExt('xmlwriter')]
#[CustomExt('dom')]
#[CustomExt('simplexml')] #[CustomExt('simplexml')]
class xml extends Extension class xml extends Extension
{ {
@@ -27,11 +26,10 @@ class xml extends Extension
'soap' => '--enable-soap', 'soap' => '--enable-soap',
'xmlreader' => '--enable-xmlreader', 'xmlreader' => '--enable-xmlreader',
'xmlwriter' => '--enable-xmlwriter', 'xmlwriter' => '--enable-xmlwriter',
'dom' => '--enable-dom',
'simplexml' => '--enable-simplexml', 'simplexml' => '--enable-simplexml',
default => throw new RuntimeException('Not accept non-xml extension'), 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; return $arg;
} }
@@ -41,14 +39,13 @@ class xml extends Extension
return true; return true;
} }
public function getWindowsConfigureArg(): string public function getWindowsConfigureArg(bool $shared = false): string
{ {
$arg = match ($this->name) { $arg = match ($this->name) {
'xml' => '--with-xml', 'xml' => '--with-xml',
'soap' => '--enable-soap', 'soap' => '--enable-soap',
'xmlreader' => '--enable-xmlreader', 'xmlreader' => '--enable-xmlreader',
'xmlwriter' => '--enable-xmlwriter', 'xmlwriter' => '--enable-xmlwriter',
'dom' => '--with-dom',
'simplexml' => '--with-simplexml', 'simplexml' => '--with-simplexml',
default => throw new RuntimeException('Not accept non-xml extension'), 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 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(); $this->buildEmbed();
} }
}
public function testPHP(int $build_target = BUILD_TARGET_NONE)
{
if (php_uname('m') === $this->getOption('arch')) { if (php_uname('m') === $this->getOption('arch')) {
$this->emitPatchPoint('before-sanity-check'); $this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target); $this->sanityCheck($build_target);

View File

@@ -10,9 +10,9 @@ class curl extends BSDLibraryBase
public const NAME = 'curl'; 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')) { if ($this->builder->getLib('openssl')) {
$this->builder->setOption('extra-libs', $this->builder->getOption('extra-libs') . ' /usr/lib/libpthread.a /usr/lib/libdl.a'); $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); $ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib);
} }
shell()->cd($this->source_dir) shell()->cd($this->source_dir)->initializeEnv($this)
->exec( ->exec(
"./Configure no-shared {$extra} " . "./Configure no-shared {$extra} " .
'--prefix=/ ' . // use prefix=/ '--prefix=/ ' . // use prefix=/

View File

@@ -175,7 +175,10 @@ class LinuxBuilder extends UnixBuilderBase
} }
$this->buildEmbed(); $this->buildEmbed();
} }
}
public function testPHP(int $build_target = BUILD_TARGET_NONE)
{
$this->emitPatchPoint('before-sanity-check'); $this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target); $this->sanityCheck($build_target);
} }
@@ -189,9 +192,10 @@ class LinuxBuilder extends UnixBuilderBase
protected function buildCli(): void protected function buildCli(): void
{ {
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("\$SPC_CMD_PREFIX_PHP_MAKE {$vars} cli"); ->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli");
if ($this->getOption('with-upx-pack')) { if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli') shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')
@@ -227,10 +231,11 @@ class LinuxBuilder extends UnixBuilderBase
// patch fake cli for micro // patch fake cli for micro
$vars['EXTRA_CFLAGS'] .= $enable_fake_cli; $vars['EXTRA_CFLAGS'] .= $enable_fake_cli;
$vars = SystemUtil::makeEnvVarString($vars); $vars = SystemUtil::makeEnvVarString($vars);
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("\$SPC_CMD_PREFIX_PHP_MAKE {$vars} micro"); ->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} micro");
$this->processMicroUPX(); $this->processMicroUPX();
@@ -250,9 +255,10 @@ class LinuxBuilder extends UnixBuilderBase
protected function buildFpm(): void protected function buildFpm(): void
{ {
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("\$SPC_CMD_PREFIX_PHP_MAKE {$vars} fpm"); ->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} fpm");
if ($this->getOption('with-upx-pack')) { if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm') shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')
@@ -275,7 +281,20 @@ class LinuxBuilder extends UnixBuilderBase
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec('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"); ->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(); $this->patchPhpScripts();
} }
@@ -284,6 +303,7 @@ class LinuxBuilder extends UnixBuilderBase
return [ return [
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '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_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'), 'EXTRA_LDFLAGS_PROGRAM' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM'),
]; ];
} }

View File

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

View File

@@ -10,9 +10,9 @@ class curl extends LinuxLibraryBase
public const NAME = 'curl'; 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')) { if ($this->builder->getLib('openssl')) {
$libs .= ' -ldl -lpthread'; $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 protected function build(): void
{ {
$cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1 -fPIC -fPIE -fno-ident"'; $cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1 -DPIC -fPIC"';
$cxxflags = 'CXXFLAGS="-std=c++17"'; $cxxflags = 'CXXFLAGS="-std=c++17 -DPIC -fPIC -fno-ident"';
$ldflags = getenv('SPC_LIBC') !== 'glibc' ? 'LDFLAGS="-static"' : ''; $ldflags = getenv('SPC_LIBC') !== 'glibc' ? 'LDFLAGS="-static"' : '';
shell()->cd($this->source_dir . '/source') shell()->cd($this->source_dir . '/source')->initializeEnv($this)
->exec( ->exec(
"{$cppflags} {$cxxflags} {$ldflags} " . "{$cppflags} {$cxxflags} {$ldflags} " .
'./runConfigureICU Linux ' . './runConfigureICU Linux ' .

View File

@@ -6,6 +6,7 @@ namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
class libffi extends LinuxLibraryBase class libffi extends LinuxLibraryBase
{ {
@@ -17,23 +18,14 @@ class libffi extends LinuxLibraryBase
*/ */
public function build(): void public function build(): void
{ {
[$lib, , $destdir] = SEPARATED_PATH;
$arch = getenv('SPC_ARCH'); $arch = getenv('SPC_ARCH');
UnixAutoconfExecutor::create($this)
shell()->cd($this->source_dir) ->configure(
->initializeEnv($this) "--host={$arch}-unknown-linux",
->exec( "--target={$arch}-unknown-linux",
'./configure ' . "--libdir={$this->getLibDir()}"
'--enable-static ' .
'--disable-shared ' .
"--host={$arch}-unknown-linux " .
"--target={$arch}-unknown-linux " .
'--prefix= ' .
"--libdir={$lib}"
) )
->exec('make clean') ->make();
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
if (is_file(BUILD_ROOT_PATH . '/lib64/libffi.a')) { if (is_file(BUILD_ROOT_PATH . '/lib64/libffi.a')) {
copy(BUILD_ROOT_PATH . '/lib64/libffi.a', BUILD_ROOT_PATH . '/lib/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; 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 class libmemcached extends LinuxLibraryBase
{ {
public const NAME = 'libmemcached'; 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\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
class libpng extends LinuxLibraryBase class libpng extends LinuxLibraryBase
{ {
@@ -36,28 +37,22 @@ class libpng extends LinuxLibraryBase
*/ */
public function build(): void public function build(): void
{ {
$optimizations = match (getenv('SPC_ARCH')) { UnixAutoconfExecutor::create($this)
'x86_64' => '--enable-intel-sse ',
'aarch64' => '--enable-arm-neon ',
default => '',
};
shell()->cd($this->source_dir)->initializeEnv($this)
->exec('chmod +x ./configure') ->exec('chmod +x ./configure')
->exec('chmod +x ./install-sh') ->exec('chmod +x ./install-sh')
->exec( ->appendEnv(['LDFLAGS' => "-L{$this->getLibDir()}"])
'LDFLAGS="-L' . BUILD_LIB_PATH . '" ' . ->configure(
'./configure ' . '--enable-hardware-optimizations',
'--disable-shared ' . "--with-zlib-prefix={$this->getBuildRootPath()}",
'--enable-static ' . match (getenv('SPC_ARCH')) {
'--enable-hardware-optimizations ' . 'x86_64' => '--enable-intel-sse',
'--with-zlib-prefix="' . BUILD_ROOT_PATH . '" ' . 'aarch64' => '--enable-arm-neon',
$optimizations . default => '',
'--prefix=' }
) )
->exec('make clean') ->make('libpng16.la', 'install-libLTLIBRARIES install-data-am', after_env_vars: ['DEFAULT_INCLUDES' => "-I{$this->source_dir} -I{$this->getIncludeDir()}"]);
->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);
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX); $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")'); 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)) { if (!str_contains('-ldl -lpthread', $libFiles)) {
$libFiles .= ' -ldl -lpthread'; $libFiles .= ' -ldl -lpthread';
} }

View File

@@ -67,6 +67,10 @@ class MacOSBuilder extends UnixBuilderBase
array_push($frameworks, ...$lib->getFrameworks()); array_push($frameworks, ...$lib->getFrameworks());
} }
foreach ($this->exts as $ext) {
array_push($frameworks, ...$ext->getFrameworks());
}
if ($asString) { if ($asString) {
return implode(' ', array_map(fn ($x) => "-framework {$x}", $frameworks)); return implode(' ', array_map(fn ($x) => "-framework {$x}", $frameworks));
} }
@@ -181,6 +185,12 @@ class MacOSBuilder extends UnixBuilderBase
$this->sanityCheck($build_target); $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 * Build cli sapi
* *
@@ -192,7 +202,8 @@ class MacOSBuilder extends UnixBuilderBase
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$shell = shell()->cd(SOURCE_PATH . '/php-src'); $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)) { if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/cli/php')->exec('strip sapi/cli/php'); $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()); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install") ->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
// Workaround for https://github.com/php/php-src/issues/12082
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o') if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
->exec('mkdir ' . BUILD_ROOT_PATH . '/lib/php-o') shell()->cd(SOURCE_PATH . '/php-src')
->cd(BUILD_ROOT_PATH . '/lib/php-o') ->exec('ar -t ' . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 ar d " . BUILD_LIB_PATH . '/libphp.a');
->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');
$this->patchPhpScripts(); $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\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
class libffi extends MacOSLibraryBase class libffi extends MacOSLibraryBase
{ {
@@ -17,20 +18,13 @@ class libffi extends MacOSLibraryBase
*/ */
protected function build(): void protected function build(): void
{ {
[, , $destdir] = SEPARATED_PATH;
$arch = getenv('SPC_ARCH'); $arch = getenv('SPC_ARCH');
shell()->cd($this->source_dir) UnixAutoconfExecutor::create($this)
->exec( ->configure(
'./configure ' . "--host={$arch}-apple-darwin",
'--enable-static ' . "--target={$arch}-apple-darwin",
'--disable-shared ' .
"--host={$arch}-apple-darwin " .
"--target={$arch}-apple-darwin " .
'--prefix= ' // use prefix=/
) )
->exec('make clean') ->make();
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
$this->patchPkgconfPrefix(['libffi.pc']); $this->patchPkgconfPrefix(['libffi.pc']);
} }
} }

View File

@@ -4,24 +4,9 @@ declare(strict_types=1);
namespace SPC\builder\macos\library; namespace SPC\builder\macos\library;
use SPC\store\FileSystem;
class libheif extends MacOSLibraryBase class libheif extends MacOSLibraryBase
{ {
use \SPC\builder\unix\library\libheif; use \SPC\builder\unix\library\libheif;
public const NAME = '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; namespace SPC\builder\macos\library;
/** use SPC\util\executor\UnixCMakeExecutor;
* gmp is a template library class for unix
*/
class libmemcached extends MacOSLibraryBase class libmemcached extends MacOSLibraryBase
{ {
public const NAME = 'libmemcached'; public const NAME = 'libmemcached';
public function build(): void public function build(): void
{ {
$rootdir = BUILD_ROOT_PATH; UnixCMakeExecutor::create($this)->build();
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');
} }
} }

View File

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

View File

@@ -17,9 +17,9 @@ trait UnixLibraryTrait
* @throws FileSystemException * @throws FileSystemException
* @throws WrongUsageException * @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) { if ($recursive) {
array_unshift($libs, ...array_values($this->getDependencies(recursive: true))); array_unshift($libs, ...array_values($this->getDependencies(recursive: true)));
} }
@@ -84,19 +84,34 @@ trait UnixLibraryTrait
} }
} }
/** public function patchLaDependencyPrefix(?array $files = null): void
* remove libtool archive files
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function cleanLaFiles(): void
{ {
foreach ($this->getStaticLibs() as $lib) { logger()->info('Patching library [' . static::NAME . '] la files');
$filename = pathinfo($lib, PATHINFO_FILENAME) . '.la'; $throwOnMissing = true;
if (file_exists(BUILD_LIB_PATH . '/' . $filename)) { if ($files === null) {
unlink(BUILD_LIB_PATH . '/' . $filename); $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 // sanity check for php-cli
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) { if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
logger()->info('running cli sanity check'); 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); $raw_output = implode('', $output);
if ($ret !== 0 || trim($raw_output) !== 'hello') { if ($ret !== 0 || trim($raw_output) !== 'hello') {
throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]"); throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]");
} }
foreach ($this->getExts(false) as $ext) { foreach ($this->getExts() as $ext) {
logger()->debug('testing ext: ' . $ext->getName()); logger()->debug('testing ext: ' . $ext->getName());
$ext->runCliCheckUnix(); $ext->runCliCheckUnix();
} }
@@ -236,8 +236,8 @@ abstract class UnixBuilderBase extends BuilderBase
default => throw new RuntimeException('Deployment does not accept type ' . $type), default => throw new RuntimeException('Deployment does not accept type ' . $type),
}; };
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file'); logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
FileSystem::createDir(BUILD_ROOT_PATH . '/bin'); FileSystem::createDir(BUILD_BIN_PATH);
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_ROOT_PATH . '/bin/')); shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_BIN_PATH));
return true; return true;
} }
@@ -263,6 +263,7 @@ abstract class UnixBuilderBase extends BuilderBase
logger()->debug('Patching phpize prefix'); logger()->debug('Patching phpize prefix');
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'"); FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'");
FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#'); 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 // patch php-config
if (file_exists(BUILD_BIN_PATH . '/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; namespace SPC\builder\unix\library;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait attr trait attr
{ {
@@ -13,14 +14,11 @@ trait attr
*/ */
protected function build(): void protected function build(): void
{ {
shell()->cd($this->source_dir)->initializeEnv($this) UnixAutoconfExecutor::create($this)
->appendEnv(['CFLAGS' => "-I{$this->getIncludeDir()}", 'LDFLAGS' => "-L{$this->getLibDir()}"])
->exec('libtoolize --force --copy') ->exec('libtoolize --force --copy')
->exec('./autogen.sh || autoreconf -if') ->exec('./autogen.sh || autoreconf -if')
->exec('./configure --prefix= --enable-static --disable-shared --with-pic --disable-nls') ->configure('--disable-nls')
->exec("make -j {$this->builder->concurrency}") ->make();
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['libattr.pc'], PKGCONF_PATCH_PREFIX); $this->patchPkgconfPrefix(['libattr.pc'], PKGCONF_PATCH_PREFIX);
} }
} }

View File

@@ -23,6 +23,8 @@ trait brotli
->build(); ->build();
$this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']); $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'); shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a');
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { 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'))) { 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/lib ',
' -L' . BUILD_ROOT_PATH . '/lib ' ' -L' . BUILD_ROOT_PATH . '/lib '
); );
$this->cleanLaFiles();
} }
} }

View File

@@ -4,34 +4,34 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait gettext trait gettext
{ {
protected function build(): void protected function build(): void
{ {
$extra = $this->builder->getLib('ncurses') ? ('--with-libncurses-prefix=' . BUILD_ROOT_PATH . ' ') : ''; $autoconf = UnixAutoconfExecutor::create($this)
$extra .= $this->builder->getLib('libxml2') ? ('--with-libxml2-prefix=' . BUILD_ROOT_PATH . ' ') : ''; ->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' : ''; $autoconf->configure()->make(with_clean: true);
$ldflags = $this->builder->getOption('enable-zts') ? '-lpthread' : ''; $this->patchLaDependencyPrefix();
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');
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -40,15 +40,19 @@ trait libevent
*/ */
protected function build(): void protected function build(): void
{ {
UnixCMakeExecutor::create($this) $cmake = UnixCMakeExecutor::create($this)
->addConfigureArgs( ->addConfigureArgs(
'-DEVENT__LIBRARY_TYPE=STATIC', '-DEVENT__LIBRARY_TYPE=STATIC',
'-DEVENT__DISABLE_BENCHMARK=ON', '-DEVENT__DISABLE_BENCHMARK=ON',
'-DEVENT__DISABLE_THREAD_SUPPORT=ON', '-DEVENT__DISABLE_THREAD_SUPPORT=ON',
'-DEVENT__DISABLE_TESTS=ON', '-DEVENT__DISABLE_TESTS=ON',
'-DEVENT__DISABLE_SAMPLES=ON', '-DEVENT__DISABLE_SAMPLES=ON',
) '-DEVENT__DISABLE_MBEDTLS=ON ',
->build(); );
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']); $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\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixCMakeExecutor; use SPC\util\executor\UnixCMakeExecutor;
trait libheif 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 RuntimeException
* @throws FileSystemException * @throws FileSystemException

View File

@@ -4,26 +4,13 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait libiconv trait libiconv
{ {
protected function build(): void protected function build(): void
{ {
[,,$destdir] = SEPARATED_PATH; UnixAutoconfExecutor::create($this)->configure('--enable-extra-encodings')->make();
$this->patchLaDependencyPrefix();
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');
}
} }
} }

View File

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

View File

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

View File

@@ -24,8 +24,6 @@ trait libwebp
// patch pkgconfig // patch pkgconfig
$this->patchPkgconfPrefix(['libsharpyuv.pc', 'libwebp.pc', 'libwebpdecoder.pc', 'libwebpdemux.pc', 'libwebpmux.pc'], PKGCONF_PATCH_PREFIX | PKGCONF_PATCH_LIBDIR); $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->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']); $this->patchPkgconfPrefix(['libwebp.pc'], PKGCONF_PATCH_CUSTOM, ['/-lwebp$/m', '-lwebp -lsharpyuv']);
} }
} }

View File

@@ -17,7 +17,13 @@ trait libxml2
public function build(): void public function build(): void
{ {
$cmake = UnixCMakeExecutor::create($this) $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('icu', ...cmake_boolean_args('LIBXML2_WITH_ICU'))
->optionalLib('xz', ...cmake_boolean_args('LIBXML2_WITH_LZMA')) ->optionalLib('xz', ...cmake_boolean_args('LIBXML2_WITH_LZMA'))
->addConfigureArgs( ->addConfigureArgs(
@@ -35,8 +41,13 @@ trait libxml2
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc', BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc',
'-licudata -licui18n -licuuc', '-lxml2 -liconv',
'-licui18n -licuuc -licudata' '-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\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
trait libxslt trait libxslt
{ {
@@ -18,34 +19,26 @@ trait libxslt
*/ */
protected function build(): void protected function build(): void
{ {
$required_libs = ''; $static_libs = $this instanceof LinuxLibraryBase ? $this->getStaticLibFiles(include_self: false) : '';
foreach ($this->getDependencies() as $dep) { $ac = UnixAutoconfExecutor::create($this)
if ($dep instanceof LinuxLibraryBase) {
$required_libs .= ' ' . $dep->getStaticLibFiles();
}
}
shell()->cd($this->source_dir)->initializeEnv($this)
->appendEnv([ ->appendEnv([
'CFLAGS' => "-I{$this->getIncludeDir()}", 'CFLAGS' => "-I{$this->getIncludeDir()}",
'LDFLAGS' => "-L{$this->getLibDir()}", 'LDFLAGS' => "-L{$this->getLibDir()}",
'LIBS' => "{$required_libs} -lstdc++", 'LIBS' => "{$static_libs} -lstdc++",
]) ])
->exec( ->addConfigureArgs(
"{$this->builder->getOption('library_path')} " . '--without-python',
"{$this->builder->getOption('ld_library_path')} " . '--without-crypto',
'./configure ' . '--without-debug',
'--enable-static --disable-shared ' . '--without-debugger',
'--without-python ' . "--with-libxml-prefix={$this->getBuildRootPath()}",
'--without-mem-debug ' . );
'--without-crypto ' . $ac->exec("{$this->builder->getOption('library_path')} {$this->builder->getOption('ld_library_path')} ./configure {$ac->getConfigureArgsString()}")->make();
'--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));
$this->patchPkgconfPrefix(['libexslt.pc']); $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 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( ->addConfigureArgs(
'-DENABLE_GNUTLS=OFF', '-DENABLE_GNUTLS=OFF',
'-DENABLE_MBEDTLS=OFF', '-DENABLE_MBEDTLS=OFF',
'-DBUILD_SHARED_LIBS=OFF',
'-DBUILD_DOC=OFF', '-DBUILD_DOC=OFF',
'-DBUILD_EXAMPLES=OFF', '-DBUILD_EXAMPLES=OFF',
'-DBUILD_REGRESS=OFF', '-DBUILD_REGRESS=OFF',

View File

@@ -5,37 +5,33 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
trait ncurses trait ncurses
{ {
protected function build(): void protected function build(): void
{ {
$filelist = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true); $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); $final = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true);
// Remove the new files // Remove the new files
$new_files = array_diff($final, $filelist); $new_files = array_diff($final, $filelist);

View File

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

View File

@@ -6,6 +6,7 @@ namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait nghttp3 trait nghttp3
{ {
@@ -15,18 +16,8 @@ trait nghttp3
*/ */
protected function build(): void protected function build(): void
{ {
shell()->cd($this->source_dir)->initializeEnv($this) UnixAutoconfExecutor::create($this)->configure('--enable-lib-only')->make();
->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);
$this->patchPkgconfPrefix(['libnghttp3.pc']); $this->patchPkgconfPrefix(['libnghttp3.pc']);
$this->patchLaDependencyPrefix();
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,13 +16,16 @@ trait tidy
*/ */
protected function build(): void protected function build(): void
{ {
UnixCMakeExecutor::create($this) $cmake = UnixCMakeExecutor::create($this)
->setBuildDir("{$this->source_dir}/build-dir") ->setBuildDir("{$this->source_dir}/build-dir")
->addConfigureArgs( ->addConfigureArgs(
'-DSUPPORT_CONSOLE_APP=OFF', '-DSUPPORT_CONSOLE_APP=OFF',
'-DBUILD_SHARED_LIB=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']); $this->patchPkgconfPrefix(['tidy.pc']);
} }
} }

View File

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