Compare commits

...

269 Commits

Author SHA1 Message Date
Marc
79ab6490fd fix CustomPackage handling (#897) 2025-09-18 13:37:26 +02:00
henderkes
191d345250 update paths to only install once 2025-09-18 12:41:36 +02:00
henderkes
311ee40ae4 update LinuxToolCheckList.php to install perl-Time-Piece to make openssl work 2025-09-18 11:58:58 +02:00
henderkes
808d224b08 build frankenphp before shared extensions again 2025-09-18 09:07:18 +02:00
Marc
4247883664 Merge branch 'main' into fix-zig 2025-09-18 08:06:23 +02:00
Marc
3198cc40c1 Remove icu backend from libxml2 (#903) 2025-09-17 10:46:05 +02:00
Marc Henderkes
8680e83af3 fix dba building shared 2025-09-16 14:43:49 +02:00
Marc
0156f33a20 Merge branch 'main' into remove-icu-backend 2025-09-16 13:35:46 +02:00
Marc Henderkes
df8b2dbf16 better patching for libstdc++ when extensions forget they need it 2025-09-16 13:10:10 +02:00
Marc Henderkes
30e174ac95 use any available english locale instead of requiring en_US.utf-8 2025-09-16 13:10:09 +02:00
Marc Henderkes
b9f8f02d98 don't use libicu backend for libxml2
(it's discouraged from being used, the first path always goes through iconv, icu is only the fallback)
2025-09-16 13:10:09 +02:00
henderkes
0b0ae270da we lost a v somehow 2025-09-10 23:35:17 +07:00
henderkes
893ce31b17 only install pkgs for crafting when necessary 2025-09-10 23:28:20 +07:00
crazywhalecc
e35d6c2651 Oh, we also support windows here 2025-09-09 19:43:08 +08:00
crazywhalecc
8dd0512335 Fix macOS lib-depends 2025-09-09 19:43:08 +08:00
henderkes
5c1194ea92 fix custompackage handling 2025-09-09 12:10:06 +07:00
Marc
953ed83df5 Merge pull request #896 from crazywhalecc/fix-zig
Fix zig -isystem overriding
2025-09-08 11:00:03 +02:00
henderkes
c330d02e78 update pkg paths to not double the $arch-$os 2025-09-08 14:18:03 +07:00
henderkes
af6a23011c fix zig relative directory 2025-09-08 13:33:44 +07:00
Abi أب
882ae07deb libxml2 arg typo 2025-09-07 22:56:41 +08:00
crazywhalecc
4bc30b0b6f Add php-src/config.log for SPCException 2025-09-07 11:50:51 +08:00
Marc
8d303348d9 Merge pull request #883 from crazywhalecc/sapi/cgi
Add cgi support for macOS and Linux
2025-09-05 11:52:26 +02:00
Marc
2a2f4120b9 Merge pull request #889 from crazywhalecc/franken
use our toolchain for go mod
2025-09-05 11:47:15 +02:00
Marc
15f8887f14 Update config/lib.json 2025-09-05 16:25:15 +07:00
crazywhalecc
fe945ab3ea Merge branch 'main' into sapi/cgi
# Conflicts:
#	composer.lock
2025-09-05 17:15:28 +08:00
crazywhalecc
e2b6f4cedd Merge branch 'main' into sapi/cgi 2025-09-05 17:14:27 +08:00
Jerry Ma
d82c86cf62 Fix docker doctor fix pkgroot volume overwrite bug (#882)
* Fix docker doctor fix pkgroot volume overwrite bug

* cs fix

* Remove pkgroot-private

* Use arch-specified pkgroot

* Update setup-runtime php version

* Add docker-entrypoint.sh

* Update dependencies

* cs fix

* test
2025-09-05 17:13:40 +08:00
henderkes
9df2867175 just always require libxml2 until we rework sapis to require their own stuff 2025-09-05 15:52:07 +07:00
henderkes
5c803d1553 fix cs 2025-09-05 15:31:30 +07:00
henderkes
d45b1853f8 fix cs 2025-09-05 15:28:51 +07:00
henderkes
1ac621fb9c use our toolchain for go mod 2025-09-05 15:20:24 +07:00
crazywhalecc
4e74ac1937 test 2025-09-05 15:02:45 +08:00
crazywhalecc
959734ac31 cs fix 2025-09-05 11:17:45 +08:00
crazywhalecc
166f3de52f Merge branch 'main' into feat/cgi 2025-09-05 11:17:34 +08:00
crazywhalecc
e3adfff16f Update dependencies 2025-09-05 11:14:56 +08:00
crazywhalecc
7cbc374278 Add docker-entrypoint.sh 2025-09-05 11:04:42 +08:00
crazywhalecc
129041402d Update setup-runtime php version 2025-09-05 11:00:57 +08:00
crazywhalecc
9ac578dfd6 Use arch-specified pkgroot 2025-09-05 11:00:46 +08:00
crazywhalecc
ef709a169b Remove pkgroot-private 2025-09-05 11:00:25 +08:00
Marc
2eeba33f94 Merge pull request #885 from crazywhalecc/dumb_github
switch getting frankenphp version to go mod (bypass rate limits)
2025-09-04 18:15:40 +02:00
henderkes
f4b2b9ae7d fix cs 2025-09-04 17:45:13 +07:00
henderkes
e44efb2a54 use go mod to bypass github rate limiting 2025-09-04 17:42:17 +07:00
henderkes
598f6d55c5 keep retrying more 2025-09-04 16:28:17 +07:00
crazywhalecc
a2c5c7e6e6 Add cgi SAPI 2025-09-04 14:05:00 +08:00
crazywhalecc
4f6e646812 cs fix 2025-09-04 12:13:57 +08:00
crazywhalecc
a79564f685 Fix docker doctor fix pkgroot volume overwrite bug 2025-09-04 12:03:13 +08:00
crazywhalecc
a77e49cbc9 Stubborn phpstan 2025-09-02 00:17:44 +08:00
crazywhalecc
cefb737fd2 Update version to 2.7.3 2025-09-02 00:17:44 +08:00
crazywhalecc
8c8aba2dd5 Fix unixodbc driver config searching path 2025-09-02 00:17:44 +08:00
Marc
97b18e9121 Merge pull request #877 from crazywhalecc/franken-retries
retry fetching frankenphp release info
2025-09-01 15:29:21 +02:00
gemini
ddc9cc2237 Fix cli generator: prefer-pre-built belongs to download-options rather than build-options 2025-09-01 20:44:37 +08:00
DubbleClick
aff803f334 retry fetching frankenphp release info 2025-09-01 19:07:29 +07:00
Marc
38ec03fe30 Merge pull request #871 from crazywhalecc/fix/frankenphp-dynamic-exports
build frankenphp and embed after shared extensions
2025-08-31 15:06:11 +02:00
Marc
55836771c9 Merge pull request #869 from crazywhalecc/pkg-config-pkg
turn pkg-config into a package
2025-08-31 15:04:41 +02:00
crazywhalecc
08a68796bf Call export in dynamic symbol getter 2025-08-31 18:05:09 +08:00
crazywhalecc
3b9efcb2d4 Put it into toolchain manager to skip in unit test 2025-08-31 15:24:29 +08:00
crazywhalecc
022ba3dce4 Merge branch 'main' into pkg-config-pkg
# Conflicts:
#	src/globals/test-extensions.php
2025-08-31 15:20:50 +08:00
crazywhalecc
86973e622d sort config 2025-08-31 15:06:59 +08:00
crazywhalecc
0fa38bad6d Use existing pkg-config builds and pre-built contents for packages 2025-08-31 15:04:34 +08:00
crazywhalecc
465bd3ce85 Use separated functions for exporting symbols 2025-08-31 14:24:28 +08:00
Jerry Ma
0c9130ab6c Update node version in vitepress-deploy.yml 2025-08-31 13:44:37 +08:00
crazywhalecc
6c75ecf0c4 Add docs search 2025-08-31 11:47:41 +08:00
DubbleClick
d533a0591b skip line before preg_replacing 2025-08-30 19:31:22 +07:00
DubbleClick
3f74d58503 fix macos, for real this time 2025-08-30 14:12:13 +07:00
DubbleClick
1ba92ccc99 fix patch version stripping (.\d -> .\d+) 2025-08-30 12:02:15 +07:00
DubbleClick
75db184077 fix macos command to print defined symbols? 2025-08-29 17:50:47 +07:00
DubbleClick
66902d74c4 cs fix 2025-08-29 16:38:48 +07:00
DubbleClick
f6cc6af39c macos? 3 2025-08-29 16:36:43 +07:00
DubbleClick
0da8dcf04a macos? 2 2025-08-29 15:14:54 +07:00
DubbleClick
190be6c7b9 macos? 2025-08-29 14:12:00 +07:00
DubbleClick
2972ab31d7 don't add empty dynamic list x) 2025-08-29 12:15:56 +07:00
DubbleClick
4b4ae9b014 write to a --dynamic-list file
see https://sourceware.org/binutils/docs-2.36/ld/Options.html
2025-08-29 10:53:38 +07:00
DubbleClick
20db00afcc no need to test all static targets, nothing changes for them 2025-08-29 10:26:46 +07:00
DubbleClick
56c90ca4a3 use all symbols from libphp.a, so we don't need to build shared extensions 2025-08-29 10:24:51 +07:00
DubbleClick
fad2314539 found ENABLE_SHARED option in liburing! 2025-08-29 09:25:32 +07:00
DubbleClick
460eb02086 build frankenphp and embed after shared extensions, make sure the linker doesn't drop libphp.a symbols that extensions need 2025-08-29 08:52:55 +07:00
Marc
5a30d509e7 Merge pull request #864 from crazywhalecc/swoolehooks
swoole hooks can be compiled if pgsql/sqlite are not compiled in statically
2025-08-29 03:46:30 +02:00
crazywhalecc
0f0050115c Update cli generator, add frankenphp SAPI, add copy-to-clipboard func 2025-08-28 22:35:51 +08:00
crazywhalecc
bf55db959e Add swoole-hook-odbc notes 2025-08-28 22:35:23 +08:00
DubbleClick
39a9840d49 why is phpstan so stupid about this constant? 2025-08-28 12:14:26 +07:00
DubbleClick
866ca264d9 only disable it for x86_64 2025-08-28 11:35:46 +07:00
DubbleClick
f18725083a disable opcache jit automatically on alpine target (only required for php < 8.5) 2025-08-28 11:32:33 +07:00
crazywhalecc
20fbbb1dbe test 2025-08-28 11:01:58 +08:00
crazywhalecc
1a7bf2d070 test 2025-08-28 10:49:02 +08:00
crazywhalecc
fc7e8ebc53 extension test 2025-08-28 10:29:22 +08:00
crazywhalecc
532360886e Merge branch 'main' into swoolehooks 2025-08-28 10:29:07 +08:00
crazywhalecc
117a54d077 extension test 2025-08-28 10:14:47 +08:00
DubbleClick
f2c131a2cc wno-int-conversion 2025-08-27 17:01:07 +07:00
DubbleClick
6f0310e8f7 cs fix 2025-08-27 16:46:58 +07:00
DubbleClick
c7141003db oops 2025-08-27 16:46:09 +07:00
DubbleClick
d32bdb2825 all env vars 2025-08-27 16:45:47 +07:00
DubbleClick
a66abfa583 test all OS 2025-08-27 16:35:24 +07:00
DubbleClick
2551772de4 use system cc 2025-08-27 16:34:29 +07:00
DubbleClick
25fe794acc trim all items 2025-08-27 14:36:05 +07:00
DubbleClick
694fd2f1e0 turn pkg-config into a package instead of a library 2025-08-27 14:33:39 +07:00
DubbleClick
5a4b920ae2 pkg-config patch 2025-08-27 13:04:08 +07:00
DubbleClick
95f1b65bca fix perl installation by checking for FindBin 2025-08-27 13:03:57 +07:00
DubbleClick
25401e5959 cs fix 2025-08-27 12:43:48 +07:00
DubbleClick
3da58d5c24 filter micro patches to not be '' 2025-08-27 11:48:59 +07:00
DubbleClick
08ab3c17d6 fix perl-IPC-Cmd check so it doesn't try installing it every time 2025-08-27 11:40:06 +07:00
DubbleClick
ecdb94b429 suggestions 2025-08-27 08:31:48 +07:00
DubbleClick
00892c20fa fix odbc libs when iconv is built too 2025-08-26 20:44:30 +07:00
DubbleClick
c433aed521 fix macos? 2025-08-26 19:35:10 +07:00
DubbleClick
1243fb9678 don't test macos as it just fails either way, add odbc test 2025-08-26 18:55:22 +07:00
DubbleClick
d9c2247f99 fix alpine realpath -s issue 2025-08-26 18:16:44 +07:00
DubbleClick
0d4d4283d1 only install library for liburing 2025-08-26 18:04:43 +07:00
DubbleClick
effefd4844 string 2025-08-26 14:51:07 +07:00
DubbleClick
2d409db2f9 we don't need a min glibc version, just don't use --use-libc! 2025-08-26 14:42:34 +07:00
DubbleClick
00f262571c cs fix 2025-08-26 14:08:09 +07:00
DubbleClick
4eac953c71 ensure liburing is only pulled in by suggested libs when glibc >= 2.30 (or musl) 2025-08-26 14:07:49 +07:00
DubbleClick
43352ab986 don't print repeated --ri swoole check 2025-08-26 01:01:45 +07:00
DubbleClick
9803bf6c3f prevent warning message from addons 2025-08-26 00:59:54 +07:00
DubbleClick
ba326973e5 prevent infinite recursion if ext suggests addons that depend on the extension 2025-08-26 00:56:57 +07:00
DubbleClick
a1f2126c00 update comments 2025-08-26 00:38:35 +07:00
DubbleClick
b1da64d46b add swoole-hook-odbc to work the same way as the other hooks 2025-08-26 00:24:40 +07:00
DubbleClick
2694dd9e21 add liburing for swoole 2025-08-25 22:57:04 +07:00
Marc
37e0f1d3f3 Update src/SPC/command/BuildPHPCommand.php 2025-08-25 19:50:41 +07:00
DubbleClick
f80aee5133 get rid of $rt 2025-08-25 19:31:15 +07:00
DubbleClick
65ee7479ac suggestion and clean up frankenphp build 2025-08-25 19:29:10 +07:00
DubbleClick
868f6d408b only feed -lgcov to the go driver 2025-08-25 18:44:03 +07:00
DubbleClick
efdfbf437a use format string 2025-08-25 18:23:04 +07:00
DubbleClick
2b57bca55c remove useless import 2025-08-25 15:30:04 +07:00
DubbleClick
99ccbf8a40 @crazywhalecc please look what's wrong with macos 2025-08-25 15:28:53 +07:00
DubbleClick
9fe322375f use 8.4 for tests only 2025-08-25 14:55:30 +07:00
DubbleClick
d13e369994 test swoole 2025-08-25 13:11:40 +07:00
DubbleClick
a46ad7b81e cs fix 2025-08-25 12:58:12 +07:00
DubbleClick
324ba0d3dc use type=addon and arg-type=none 2025-08-25 12:57:49 +07:00
DubbleClick
1c7fa0132d remove space 2025-08-25 12:44:34 +07:00
DubbleClick
93223a9d44 too much pgo, too little pdo 2025-08-25 12:43:21 +07:00
DubbleClick
b6d4af218b zts -> --enable-swoole-thread 2025-08-25 12:42:36 +07:00
DubbleClick
448941f741 don't request configurearg if it's not used (ease debugging) 2025-08-25 12:36:10 +07:00
DubbleClick
7e0e9091be explicitly enable swoole-mysql too 2025-08-25 12:11:56 +07:00
DubbleClick
8104ff7236 update checks for shared swoole-hook extensions 2025-08-25 12:08:53 +07:00
DubbleClick
75f734daa8 cs fix 2025-08-25 11:22:35 +07:00
DubbleClick
779a724875 go's gcc driver is the dumbest shit to ever exist 2025-08-25 11:21:08 +07:00
DubbleClick
e975e151f9 swoole hooks can be compiled if pgsql/sqlite are not compiled in statically 2025-08-25 11:09:02 +07:00
Marc
a5351e1546 Merge pull request #863 from crazywhalecc/brotli-watcher
fix gcc version detection
2025-08-25 05:32:46 +02:00
DubbleClick
af90b840ee format string 2025-08-25 09:59:27 +07:00
DubbleClick
2558c02470 oopsie 2025-08-25 09:59:06 +07:00
DubbleClick
df60ccff0e also make sure clang version uses dots 2025-08-25 09:52:03 +07:00
DubbleClick
2ed8bbf391 add cflags and ldflags to frankenphp build 2025-08-25 09:29:19 +07:00
DubbleClick
ef3025798d fix gcc compiler version 2025-08-25 09:29:06 +07:00
Marc
bea3bd8392 Merge pull request #861 from crazywhalecc/fix/macos-ar
Add macOS AR and LD
2025-08-22 07:23:49 +02:00
crazywhalecc
99e8900aba Add macOS AR and LD 2025-08-22 13:19:42 +08:00
Marc
1c4a6ca02e Merge pull request #860 from crazywhalecc/brotli-watcher
add brotli and watcher to lib-suggests
2025-08-21 15:31:35 +02:00
DubbleClick
b5fa7be53f add brotli and watcher to lib-suggests 2025-08-20 13:40:54 +07:00
Marc
3804e842bb Merge pull request #858 from crazywhalecc/fix/imagick
imagick needs static libstdc++ on gcc-toolset (successor of devtoolse) too
2025-08-20 07:56:08 +02:00
DubbleClick
e6832ecf61 add msgpack suggestion 2025-08-19 20:15:41 +07:00
DubbleClick
ed3e29bade devtoolset any version 2025-08-19 20:03:16 +07:00
DubbleClick
811aeb58ea imagick needs static libstdc++ on gcc-toolset (successor of devtoolset) too 2025-08-19 20:01:10 +07:00
Marc
6b5aaa38ae Merge pull request #857 from crazywhalecc/fix/lstdcpp
move -lstdc++ to the end of the libraries
2025-08-19 10:51:28 +02:00
DubbleClick
4e9545262d finish the redis thingy from the year long open PR 2025-08-19 10:42:30 +07:00
DubbleClick
d48c84d81b move -lstdc++ to the end of the libraries 2025-08-19 10:27:52 +07:00
Jerry Ma
cbddb2652d Merge pull request #856 from crazywhalecc/fix/windows-cmd
Fix WindowsCmd execution, use popen instead of proc_open
2025-08-18 12:07:09 +08:00
Jerry Ma
5f629253ac Merge pull request #853 from crazywhalecc/fix/exception-reflection
Enhance exception handling by binding builder and extra info to exception handler
2025-08-16 19:33:13 +08:00
crazywhalecc
8d84a95c01 Fix WindowsCmd execution, use popen instead of proc_open 2025-08-16 17:54:24 +08:00
crazywhalecc
2cabaf6402 8.5 extension test 2025-08-15 13:19:14 +08:00
crazywhalecc
ad25ac49b8 Update to beta1, extension test 2025-08-15 12:28:26 +08:00
crazywhalecc
d0412a88df Use PatchException instead of ExecutionException for patchFile 2025-08-15 12:04:06 +08:00
crazywhalecc
a3ae1eb2f0 Remove redundant builer options 2025-08-15 11:54:34 +08:00
crazywhalecc
2e616af836 PHPStan fix 2025-08-11 13:32:59 +08:00
Jerry Ma
4fd8afcee4 Update src/SPC/exception/ExceptionHandler.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-11 13:30:10 +08:00
Jerry Ma
e96b4f5541 Update src/SPC/exception/ExceptionHandler.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-11 13:30:04 +08:00
Jerry Ma
9978a56b1e Update src/SPC/exception/ExceptionHandler.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-11 13:29:59 +08:00
Jerry Ma
d3a5be13ea Update src/SPC/exception/ExceptionHandler.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-11 13:29:54 +08:00
Jerry Ma
5ba0de12eb Update src/SPC/exception/ExceptionHandler.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-11 13:29:48 +08:00
Jerry Ma
a73c097c94 Update src/SPC/command/BuildPHPCommand.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-11 13:29:42 +08:00
Jerry Ma
d3840b19fa Update src/SPC/builder/BuilderProvider.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-11 13:29:36 +08:00
crazywhalecc
b34b6594de Suggestions 2025-08-11 12:05:41 +08:00
crazywhalecc
2fba61e9bd Enhance exception handling by binding builder and extra info to ExceptionHandler 2025-08-11 10:48:48 +08:00
crazywhalecc
1e9434221b Remove spc.env.log due to potential secret leaks 2025-08-07 16:25:01 +08:00
crazywhalecc
afd6791075 Fix phpunit 2025-08-07 13:09:18 +08:00
crazywhalecc
b3b53b6b4d Use latest version of logger 2025-08-07 13:09:18 +08:00
crazywhalecc
b8b8cf6ea9 Update version to 2.7.2 2025-08-07 13:09:18 +08:00
crazywhalecc
9a340e1ad8 Update docs, GitHub issue templates, workflows 2025-08-07 13:09:18 +08:00
crazywhalecc
29dc5e4ea7 Chore 2025-08-07 13:09:18 +08:00
crazywhalecc
08fa49b791 Remove craft.log 2025-08-07 13:09:18 +08:00
crazywhalecc
333b776e77 Refactor all command class exception handling 2025-08-07 13:09:18 +08:00
crazywhalecc
f68f060be2 Refactor all (except command) modules using new exceptions 2025-08-07 13:09:18 +08:00
crazywhalecc
722bb31815 Introduce AttributeMapper for managing extensions and doctor attributes 2025-08-07 13:09:18 +08:00
crazywhalecc
e28580de00 Refactor shell utilities: reorganize namespaces and introduce Shell base class 2025-08-07 13:09:18 +08:00
crazywhalecc
cc447a089a Refactor all exception classes, remove unclear RuntimeException, InvalidArgumentException 2025-08-07 13:09:18 +08:00
crazywhalecc
0c9a30256e Remove all @throws PHPDoc, it's almost useless for SPC anymore 2025-08-07 13:09:18 +08:00
Jerry Ma
fa10142f13 Merge pull request #847 from crazywhalecc/fix/spc-exe
Fix spc build actions version, add spc validation
2025-08-06 01:03:38 +08:00
Jerry Ma
c342741670 Update version to 2.7.1 2025-08-05 23:13:19 +08:00
Jerry Ma
64d49003e0 Update release-build.yml 2025-08-05 21:26:35 +08:00
crazywhalecc
b0c93c7418 Fix spc build actions version, add spc validation 2025-08-05 18:59:30 +08:00
Jerry Ma
085abd635e Merge pull request #819 from crazywhalecc/php-85
Add PHP 8.5 initial support
2025-08-05 12:01:47 +08:00
DubbleClick
3789c7c335 only enable one of password-argon2 or openssl-argon2 2025-08-04 10:14:48 +07:00
crazywhalecc
4fb4e42896 Revert 2025-08-04 01:10:08 +08:00
crazywhalecc
81e7a0c554 Add without argon2 option 2025-08-03 23:01:24 +08:00
crazywhalecc
4cbe4ea82d Revert corrupted revert 2025-08-03 23:01:09 +08:00
crazywhalecc
ea4905cd0d Add argon2 support for PHP-NTS < 8.5 2025-08-03 22:59:40 +08:00
crazywhalecc
3c09ba59d7 Merge remote-tracking branch 'origin/php-85' into php-85 2025-08-03 22:55:17 +08:00
Jerry Ma
430f436b79 Update src/SPC/builder/macos/MacOSBuilder.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-03 22:48:09 +08:00
Jerry Ma
93001dce88 Update src/SPC/builder/macos/MacOSBuilder.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-03 22:47:02 +08:00
Jerry Ma
2d6d25cadf Update src/SPC/builder/linux/LinuxBuilder.php
Co-authored-by: Marc <m@pyc.ac>
2025-08-03 22:46:47 +08:00
crazywhalecc
b644da8210 Remove redundant patches for openssl 2025-08-03 22:45:24 +08:00
crazywhalecc
f1a9a28ed7 Use backup file function to avoid multiple build conflict 2025-08-03 02:06:08 +08:00
crazywhalecc
643926886c Test original 2025-08-03 02:00:19 +08:00
crazywhalecc
9a5a59d876 Test 2025-08-03 01:49:15 +08:00
crazywhalecc
e7fe91faef Fix patch, use pure socket client directly 2025-08-03 01:23:47 +08:00
crazywhalecc
e6cf05ddff Test 2025-08-03 01:12:28 +08:00
crazywhalecc
c3e9a2816b Test 2025-08-03 00:29:13 +08:00
Marc
0bb8e83d68 Merge pull request #844 from crazywhalecc/swoole-v6
change swoole to version 6.x because 5.x is not compatible with php 8.4+
2025-08-02 23:06:35 +07:00
crazywhalecc
d0053534ab tmate 2025-08-02 23:06:16 +08:00
crazywhalecc
38725c2bb4 Update ca certificates 2025-08-02 22:22:09 +08:00
DubbleClick
b8fe70e5ee change swoole to version 6.x because 5.x is not compatible with php 8.4+ 2025-08-02 20:23:26 +07:00
crazywhalecc
3960a21e05 Use full domain test list 2025-08-02 18:40:55 +08:00
crazywhalecc
e14301d991 Symbol workaround for cross toolchain 2025-08-02 18:07:32 +08:00
Jerry Ma
65f74044d8 Update tests.yml 2025-08-02 03:03:20 +08:00
Jerry Ma
f6eba32be5 Update tests.yml 2025-08-02 02:38:24 +08:00
crazywhalecc
af62e55da8 Add missing space 2025-08-02 01:38:32 +08:00
crazywhalecc
22a8191b97 Fix opcache jit option parsing in builder 2025-08-02 01:29:20 +08:00
Jerry Ma
17ff5f63bf Update tests.yml 2025-08-02 00:58:36 +08:00
crazywhalecc
48a7d814f8 Test jit 2025-08-01 17:00:35 +08:00
crazywhalecc
2c5cf07e9c cs fix, fix file name 2025-08-01 15:45:33 +08:00
crazywhalecc
cace504a63 Workaround for windows openssl temporarily 2025-08-01 15:42:34 +08:00
crazywhalecc
efa47af347 Add git source test 2025-08-01 15:17:13 +08:00
crazywhalecc
1c9fbdb032 Use none base combination 2025-08-01 15:01:55 +08:00
crazywhalecc
ac2eb3adae Remove redis test 2025-08-01 14:21:38 +08:00
crazywhalecc
d6081ee10f Support alpha4 2025-08-01 13:00:12 +08:00
crazywhalecc
8b9b72958e Add PHP_BUILD_COMPILER for different toolchain 2025-08-01 12:48:48 +08:00
crazywhalecc
34edb6e329 Add PHP_BUILD_PROVIDER to env.ini 2025-08-01 10:58:31 +08:00
crazywhalecc
9487051796 Add PHP_BUILD_PROVIDER for PHP >= 8.4 2025-08-01 02:25:12 +08:00
crazywhalecc
7d0577460f cs-fix 2025-08-01 02:05:46 +08:00
crazywhalecc
6b23f4b34a Fix PHPUnit test on Windows, ignore calling linux system util for other OS 2025-08-01 01:53:38 +08:00
crazywhalecc
451de4a6f6 Fix ConfigValidator and sort config 2025-08-01 01:50:32 +08:00
crazywhalecc
33d587ee9e Remove redis test (https://github.com/phpredis/phpredis/pull/2676) 2025-08-01 01:32:37 +08:00
crazywhalecc
6b381238fe Remove collision, it's useless at all 2025-08-01 01:29:35 +08:00
crazywhalecc
07d66ade85 Add separated patchedBeforeWindowsConfigure 2025-08-01 01:28:56 +08:00
crazywhalecc
e1c9240698 README update 2025-08-01 00:51:04 +08:00
crazywhalecc
d3e8af23bc Whoops 2025-08-01 00:50:51 +08:00
crazywhalecc
5f9fe2948c Fix missing SPC_EXTRA_LIBS with type error bug 2025-08-01 00:09:05 +08:00
crazywhalecc
4c54d99621 Remove pcntl 2025-07-31 23:49:53 +08:00
crazywhalecc
72beba76c3 Merge remote-tracking branch 'origin/php-85' into php-85 2025-07-31 23:46:43 +08:00
crazywhalecc
1047d471ed Merge branch 'main' into php-85
# Conflicts:
#	src/SPC/builder/linux/LinuxBuilder.php
#	src/SPC/store/source/PhpSource.php
#	src/globals/test-extensions.php
2025-07-31 23:46:34 +08:00
crazywhalecc
0496af47df Fix windows PHP 8.5 build 2025-07-31 23:43:44 +08:00
crazywhalecc
96a7aabda0 Don't show shell log 2025-07-31 21:31:48 +08:00
crazywhalecc
be857913cd Add alt for re2c 2025-07-31 01:54:28 +08:00
crazywhalecc
601444d0a5 Add re2c build for spc-gnu-docker 2025-07-31 01:44:44 +08:00
crazywhalecc
3c972ac905 Add re2c build 2025-07-31 00:55:25 +08:00
crazywhalecc
6984c29a3a suggestion 2025-07-31 00:11:49 +08:00
crazywhalecc
cb0ea67a28 Fix x86_64 macOS bison finder path 2025-07-31 00:09:13 +08:00
crazywhalecc
fcdb029b10 Install re2c manually in gnu docker 2025-07-31 00:07:23 +08:00
crazywhalecc
5f33a07f4c Fix windows builds when unix configure does not exist 2025-07-30 23:57:52 +08:00
crazywhalecc
357c04def0 Merge branch 'main' into php-85
# Conflicts:
#	src/SPC/util/PkgConfigUtil.php
2025-07-30 23:25:49 +08:00
crazywhalecc
0dfa6e63bd Fix dev:lib-version command with dependencies 2025-07-30 23:23:27 +08:00
crazywhalecc
af10cacdff Add openssl version getter for Windows, test openssl 2025-07-30 23:23:12 +08:00
crazywhalecc
5f5d934d58 Add openssl argon2 password hash support for PHP 8.5 2025-07-30 23:02:28 +08:00
crazywhalecc
9ed3c8b498 phpstan 2025-07-29 11:25:06 +08:00
crazywhalecc
ed67393d33 Move opcache JIT handling from Linux and MacOS builders to Extension 2025-07-29 11:22:58 +08:00
crazywhalecc
e9dbeb1e34 Refactor opcache JIT handling and version checks in Linux and MacOS builders 2025-07-29 10:59:36 +08:00
crazywhalecc
4efb3dfc9a Add check for Bison version in MacOS tool checklist, trigger extension test 2025-07-28 16:47:04 +08:00
crazywhalecc
b9bec5b526 Whoops, extension test 2025-07-28 16:00:32 +08:00
crazywhalecc
1ae0752933 Trigger full extension test 2025-07-28 15:58:07 +08:00
crazywhalecc
0696acb9c5 Add support for re2c in tool checklists and environment setup 2025-07-28 15:54:55 +08:00
crazywhalecc
973c8f082f Add php-src git version support 2025-07-28 15:36:53 +08:00
crazywhalecc
85e89e4326 alpha2 2025-07-28 10:17:14 +08:00
crazywhalecc
fb106a3d41 Merge branch 'refs/heads/main' into php-85
# Conflicts:
#	src/globals/test-extensions.php
2025-07-28 10:12:13 +08:00
crazywhalecc
f0612591be Test bulk (without amqp, swoole) and spc-max 2025-07-15 23:31:26 +08:00
crazywhalecc
5838c87140 Merge remote-tracking branch 'origin/php-85' into php-85 2025-07-15 22:08:16 +08:00
crazywhalecc
1ce3ba0f30 Update docs and READMEs 2025-07-15 22:08:10 +08:00
Jerry Ma
dc8f7de75a Merge branch 'main' into php-85 2025-07-15 21:59:48 +08:00
crazywhalecc
d3f8e94fe9 Use new branch of micro, extension test 2025-07-15 21:57:49 +08:00
crazywhalecc
88cf0184cc extension test 2025-07-15 21:57:06 +08:00
crazywhalecc
b9e096abfa Download alpha version for 8.5 2025-07-15 21:14:15 +08:00
crazywhalecc
ec959f6239 Add 8.5 patch support for phpmicro 2025-07-15 21:14:02 +08:00
crazywhalecc
5f2459ae43 Avoid useless exception on startup version mismatch 2025-07-15 21:11:38 +08:00
244 changed files with 5398 additions and 4444 deletions

View File

@@ -10,6 +10,7 @@ trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
indent_size = 2
[*.{yml,yaml, vue}]
[*.{yml,yaml,vue,ts}]
indent_size = 2

View File

@@ -3,6 +3,15 @@ name: Bug report
about: Build PHP or library failed, download failed, doesn't seem to work...
title: ''
labels: bug
assignees: crazywhalecc
body:
- type: textarea
id: what-happened
attributes:
label: What happened?
description: |
Please tell us what you do, what you get and what you expected.
Provide with some step-by-step instructions to reproduce the issue.
If possible, attach a screenshot or log files in ./log directory.
validations:
required: true
---

View File

@@ -3,6 +3,6 @@ name: Feature request
about: Suggest an idea for this project
title: ''
labels: new feature
assignees: ''
assignees: crazywhalecc
---

View File

@@ -65,7 +65,7 @@ jobs:
- sqlsrv
- ssh2
- swoole
- swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite
- swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite,swoole-hook-odbc
- swow
- sysvmsg,sysvsem,sysvshm
- tidy

View File

@@ -3,6 +3,10 @@ name: Build SPC Binary
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
paths:
- '.github/workflows/release-build.yml'
release:
types:
- published
@@ -10,7 +14,7 @@ on:
env:
PHP_VERSION: 8.4
MICRO_VERSION: 8.4.10
MICRO_VERSION: 8.4.11
jobs:
build-release-artifacts:
@@ -117,7 +121,8 @@ jobs:
files: dist/${{ matrix.operating-system.filename }}
- name: "Deploy to self-hosted OSS"
if: github.repository == 'crazywhalecc/static-php-cli'
# only run this step if the repository is static-php-cli and the branch is main
if: github.repository == 'crazywhalecc/static-php-cli' && github.ref == 'refs/heads/main'
uses: static-php/upload-s3-action@v1.0.0
with:
aws_key_id: ${{ secrets.AWS_KEY_ID }}
@@ -132,3 +137,39 @@ jobs:
with:
path: spc${{ env.SUFFIX }}
name: spc-${{ matrix.operating-system.name }}${{ env.SUFFIX }}
test-spc:
name: "Test SPC Binary for ${{ matrix.operating-system.name }}"
runs-on: ${{ matrix.operating-system.os }}
needs: [build-release-artifacts]
strategy:
matrix:
operating-system:
- name: "linux-x86_64"
os: "ubuntu-latest"
- name: "macos-x86_64"
os: "macos-13"
- name: "linux-aarch64"
os: "ubuntu-24.04-arm"
- name: "macos-aarch64"
os: "macos-latest"
- name: "windows-x64"
os: "windows-latest"
steps:
- name: "Checkout"
uses: actions/checkout@v4
- name: "Download Artifact"
uses: actions/download-artifact@v4
env:
SUFFIX: ${{ matrix.operating-system.name == 'windows-x64' && '.exe' || '' }}
with:
name: spc-${{ matrix.operating-system.name }}${{ env.SUFFIX }}
- name: "Chmod"
if: matrix.operating-system.name != 'windows-x64'
run: chmod +x spc
- name: "Run SPC Tests"
env:
SUFFIX: ${{ matrix.operating-system.name == 'windows-x64' && '.exe' || '' }}
run: ./spc${{ env.SUFFIX }} dev:extensions

View File

@@ -145,6 +145,10 @@ jobs:
os: ${{ fromJSON(needs.define-matrix.outputs.os) }}
fail-fast: false
steps:
- name: "Update runner packages"
if: ${{ startsWith(matrix.os, 'ubuntu-') }}
run: sudo apt-get update && sudo apt-get install -y ca-certificates
- name: "Checkout"
uses: actions/checkout@v4
@@ -202,6 +206,13 @@ jobs:
if: ${{ !startsWith(matrix.os, 'windows-') }}
run: php src/globals/test-extensions.php build_embed_cmd ${{ matrix.os }} ${{ matrix.php }}
- name: "Upload logs"
if: ${{ always() && hashFiles('log/**') != '' }}
uses: actions/upload-artifact@v4
with:
name: build-logs-${{ matrix.os }}-${{ matrix.php }}
path: log
# - name: Setup tmate session
# if: ${{ failure() }}
# uses: mxschmitt/action-tmate@v3

View File

@@ -21,7 +21,6 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 18
cache: yarn
- run: yarn install --frozen-lockfile

11
.gitignore vendored
View File

@@ -34,6 +34,7 @@ packlib_files.txt
/bin/*
!/bin/spc*
!/bin/setup-runtime*
!/bin/docker-entrypoint.sh
# exclude windows build tools
/php-sdk-binary-tools/
@@ -48,6 +49,12 @@ packlib_files.txt
package-lock.json
pnpm-lock.yaml
# craft.log
craft.log
# craft
craft.yml
# SPC logs
log/
# spc.phar
spc.phar
spc.exe

View File

@@ -76,22 +76,23 @@ static-php-cli简称 `spc`)有许多特性:
当前支持编译的 PHP 版本:
> :warning: 支持,但 static-php-cli 作者可能不再提供补丁修复
> :warning: 部分支持,对于新的测试版和旧版本可能存在问题。
>
> :heavy_check_mark: 支持
>
> :x: 不支持
| PHP Version | Status | Comment |
|-------------|--------------------|----------------------------------------------|
| 7.2 | :x: | |
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
| 8.1 | :heavy_check_mark: | PHP 官方仅对 8.1 提供安全更新 |
| 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | |
| PHP Version | Status | Comment |
|-------------|--------------------|---------------------------------------------------------|
| 7.2 | :x: | |
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
| 8.1 | :heavy_check_mark: | PHP 官方仅对 8.1 提供安全更新,在 8.5 发布后我们不再处理 8.1 相关的 backport 支持 |
| 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | |
| 8.5 (alpha) | :warning: | PHP 8.5 目前处于 alpha 阶段 |
> 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。
@@ -206,6 +207,7 @@ bin/spc --version
- `--build-micro`:构建 phpmicro 自执行二进制
- `--build-fpm`:构建 fpm
- `--build-embed`:构建 embedlibphp
- `--build-cgi`: 构建 cgi不推荐
- `--build-all`:构建所有
如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误:

View File

@@ -83,7 +83,7 @@ Here is the supported OS and arch, where :octocat: represents support for GitHub
Currently supported PHP versions for compilation:
> :warning: supported but not maintained by static-php-cli authors
> :warning: Partial support, there may be issues with newer test versions or older versions.
>
> :heavy_check_mark: supported
>
@@ -95,10 +95,11 @@ Currently supported PHP versions for compilation:
| 7.3 | :x: | phpmicro and some extensions not supported on 7.x |
| 7.4 | :x: | phpmicro and some extensions not supported on 7.x |
| 8.0 | :warning: | PHP official has stopped maintenance of 8.0, we no longer provide backport support for version 8.0 |
| 8.1 | :heavy_check_mark: | PHP official has security fixes only |
| 8.1 | :heavy_check_mark: | PHP official has security fixes only, we no longer provide backport support when 8.5 released |
| 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | |
| 8.5 (alpha) | :warning: | PHP 8.5 is in alpha |
> This table shows the support status for static-php-cli in building the corresponding version,
> not the official PHP support status for that version.
@@ -217,6 +218,7 @@ Now we support `cli`, `micro`, `fpm` and `embed` SAPI. You can use one or more o
- `--build-micro`: build static phpmicro self-extracted executable
- `--build-fpm`: build static fpm binary
- `--build-embed`: build embed (libphp)
- `--build-cgi`: build cgi binary (not recommended)
- `--build-all`: build all
If anything goes wrong, use `--debug` option to display full terminal output:

11
bin/docker-entrypoint.sh Normal file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -e
TARGET_DIR="/app/pkgroot/$(uname -m)-linux"
BACKUP_DIR="/app/pkgroot-private"
# copy private pkgroot to pkgroot if pkgroot is empty
if [ ! -d "$TARGET_DIR" ] || [ -z "$(ls -A "$TARGET_DIR")" ]; then
echo "* Copying private pkgroot to pkgroot ..."
rm -rf "$TARGET_DIR"
cp -r "$BACKUP_DIR" "$TARGET_DIR"
fi
exec "$@"

View File

@@ -25,7 +25,7 @@ __DIR__=$(cd "$(dirname "$0")" && pwd)
__PROJECT__=$(cd "${__DIR__}"/../ && pwd)
# set download dir
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.4.4-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.4.12-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__COMPOSER_URL__="https://getcomposer.org/download/latest-stable/composer.phar"
# use china mirror
@@ -45,7 +45,7 @@ done
case "$mirror" in
china)
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.4.4-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.4.12-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__COMPOSER_URL__="https://mirrors.tencent.com/composer/composer.phar"
;;

View File

@@ -3,7 +3,7 @@
set -e
# This file is using docker to run commands
SPC_DOCKER_VERSION=v5
SPC_DOCKER_VERSION=v6
# Detect docker can run
if ! which docker >/dev/null; then
@@ -104,6 +104,7 @@ RUN apk update; \
m4 \
make \
pkgconfig \
re2c \
wget \
xz \
gettext-dev \
@@ -121,6 +122,14 @@ ADD ./src /app/src
COPY ./composer.* /app/
ADD ./bin /app/bin
RUN composer install --no-dev
ADD ./config /app/config
RUN bin/spc doctor --auto-fix
RUN bin/spc install-pkg upx
RUN mv /app/pkgroot/\$(uname -m)-linux /app/pkgroot-private
ADD bin/docker-entrypoint.sh /bin/docker-entrypoint.sh
RUN chmod +x /bin/docker-entrypoint.sh
ENTRYPOINT ["/bin/docker-entrypoint.sh"]
EOF
fi

View File

@@ -3,7 +3,7 @@
set -e
# This file is using docker to run commands
SPC_DOCKER_VERSION=v4
SPC_DOCKER_VERSION=v6
# Detect docker can run
if ! which docker >/dev/null; then
@@ -102,17 +102,21 @@ RUN curl -o cmake.tgz -#fSL https://github.com/Kitware/CMake/releases/download/v
tar -xzf cmake.tgz -C /cmake --strip-components 1
WORKDIR /app
ADD ./src /app/src
COPY ./composer.* /app/
ADD ./bin/setup-runtime /app/bin/setup-runtime
ADD ./bin/spc /app/bin/spc
RUN /app/bin/setup-runtime
ADD ./src /app/src
RUN /app/bin/php /app/bin/composer install --no-dev
ENV SPC_LIBC=glibc
ENV PATH="/app/bin:/cmake/bin:/opt/rh/devtoolset-10/root/usr/bin:\$PATH"
ADD ./config/env.ini /app/config/env.ini
ADD ./config /app/config
RUN CC=gcc bin/spc doctor --auto-fix --debug
RUN bin/spc install-pkg upx
RUN if [ -f /app/buildroot/bin/re2c ]; then \
cp /app/buildroot/bin/re2c /usr/local/bin/re2c ;\
fi
RUN curl -o make.tgz -fsSL https://ftp.gnu.org/gnu/make/make-4.4.tar.gz && \
tar -zxvf make.tgz && \
@@ -129,6 +133,11 @@ RUN curl -o automake.tgz -fsSL https://ftp.gnu.org/gnu/automake/automake-1.17.ta
make && \
make install && \
ln -sf /usr/local/bin/automake /usr/bin/automake
RUN mv /app/pkgroot/\$(uname -m)-linux /app/pkgroot-private
ADD bin/docker-entrypoint.sh /bin/docker-entrypoint.sh
RUN chmod +x /bin/docker-entrypoint.sh
ENTRYPOINT ["/bin/docker-entrypoint.sh"]
EOF
fi

View File

@@ -16,14 +16,13 @@
"symfony/console": "^5.4 || ^6 || ^7",
"symfony/process": "^7.2",
"symfony/yaml": "^7.2",
"zhamao/logger": "^1.0"
"zhamao/logger": "^1.1.3"
},
"require-dev": {
"captainhook/captainhook-phar": "^5.23",
"captainhook/hook-installer": "^1.0",
"friendsofphp/php-cs-fixer": "^3.60",
"humbug/box": "^4.5.0 || ^4.6.0",
"nunomaduro/collision": "^7.8",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.3 || ^9.5"
},

741
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@
;
; Here's a list of env vars, these value cannot be changed anywhere:
;
; SPC_VERSION: the version of static-php-cli.
; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`)
; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`)
; BUILD_ROOT_PATH: the root path of the build process. (default: `$(pwd)/buildroot`)
@@ -43,6 +44,8 @@ SPC_SKIP_PHP_VERSION_CHECK="no"
SPC_SKIP_DOCTOR_CHECK_ITEMS=""
; extra modules that xcaddy will include in the FrankenPHP build
SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/frankenphp/caddy --with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli"
; The display message for php version output (PHP >= 8.4 available)
PHP_BUILD_PROVIDER="static-php-cli ${SPC_VERSION}"
; EXTENSION_DIR where the built php will look for extension when a .ini instructs to load them
; only useful for builds targeting not pure-static linking
@@ -100,7 +103,7 @@ SPC_MICRO_PATCHES=cli_checks,disable_huge_page
; buildconf command
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
; configure command
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --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-phpdbg --with-pic"
; make command
SPC_CMD_PREFIX_PHP_MAKE="make -j${SPC_CONCURRENCY}"
@@ -121,6 +124,8 @@ SPC_TARGET=native-macos
; compiler environments
CC=clang
CXX=clang++
AR=ar
LD=ld
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
@@ -132,7 +137,7 @@ SPC_MICRO_PATCHES=cli_checks,macos_iconv
; buildconf command
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
; configure command
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg"
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-phpdbg"
; make command
SPC_CMD_PREFIX_PHP_MAKE="make -j${SPC_CONCURRENCY}"

View File

@@ -414,9 +414,17 @@
"libmemcached",
"fastlz"
],
"lib-suggests": [
"zstd"
],
"ext-depends": [
"session",
"zlib"
],
"ext-suggests": [
"igbinary",
"msgpack",
"session"
]
},
"mongodb": {
@@ -488,6 +496,7 @@
"opcache": {
"type": "builtin",
"arg-type-unix": "custom",
"arg-type-windows": "enable",
"zend-extension": true
},
"openssl": {
@@ -530,9 +539,10 @@
},
"notes": true,
"type": "builtin",
"arg-type": "with-path",
"arg-type": "custom",
"lib-depends": [
"libargon2"
"libargon2",
"openssl"
]
},
"pcntl": {
@@ -692,7 +702,8 @@
"arg-type": "custom",
"ext-suggests": [
"session",
"igbinary"
"igbinary",
"msgpack"
],
"lib-suggests-unix": [
"zstd",
@@ -839,14 +850,23 @@
"nghttp2",
"zlib"
],
"lib-suggests": [
"zstd"
],
"lib-suggests-linux": [
"zstd",
"liburing"
],
"ext-depends": [
"openssl",
"curl"
],
"ext-suggests": [
"sockets",
"swoole-hook-pgsql",
"swoole-hook-mysql",
"swoole-hook-sqlite"
"swoole-hook-sqlite",
"swoole-hook-odbc"
]
},
"swoole-hook-mysql": {
@@ -856,11 +876,12 @@
},
"notes": true,
"type": "addon",
"arg-type": "custom",
"arg-type": "none",
"ext-depends": [
"mysqlnd",
"pdo",
"pdo_mysql"
"pdo_mysql",
"swoole"
],
"ext-suggests": [
"mysqli"
@@ -874,10 +895,11 @@
},
"notes": true,
"type": "addon",
"arg-type": "custom",
"arg-type": "none",
"ext-depends": [
"pgsql",
"pdo"
"pdo",
"swoole"
]
},
"swoole-hook-sqlite": {
@@ -887,10 +909,27 @@
},
"notes": true,
"type": "addon",
"arg-type": "custom",
"arg-type": "none",
"ext-depends": [
"sqlite3",
"pdo"
"pdo",
"swoole"
]
},
"swoole-hook-odbc": {
"support": {
"Windows": "no",
"BSD": "wip"
},
"notes": true,
"type": "addon",
"arg-type": "none",
"ext-depends": [
"pdo",
"swoole"
],
"lib-depends": [
"unixodbc"
]
},
"swow": {

View File

@@ -1,9 +1,6 @@
{
"lib-base": {
"type": "root",
"lib-depends-unix": [
"pkg-config"
]
"type": "root"
},
"php": {
"type": "root",
@@ -12,8 +9,19 @@
"lib-base",
"micro"
],
"lib-depends-macos": [
"lib-base",
"micro",
"libxml2"
],
"lib-suggests-linux": [
"libacl"
"libacl",
"brotli",
"watcher"
],
"lib-suggests-macos": [
"brotli",
"watcher"
]
},
"micro": {
@@ -444,6 +452,7 @@
},
"libmemcached": {
"source": "libmemcached",
"cpp-library": true,
"static-libs-unix": [
"libmemcached.a",
"libmemcachedprotocol.a",
@@ -588,7 +597,6 @@
],
"lib-suggests-unix": [
"xz",
"icu",
"zlib"
],
"lib-depends-windows": [
@@ -797,6 +805,12 @@
"depot.h"
]
},
"re2c": {
"source": "re2c",
"bin-unix": [
"re2c"
]
},
"readline": {
"source": "readline",
"static-libs-unix": [
@@ -913,5 +927,20 @@
"zstd.h",
"zstd_errors.h"
]
},
"liburing": {
"source": "liburing",
"pkg-configs": [
"liburing",
"liburing-ffi"
],
"static-libs-linux": [
"liburing.a",
"liburing-ffi.a"
],
"headers-linux": [
"liburing/",
"liburing.h"
]
}
}

View File

@@ -1,4 +1,16 @@
{
"go-xcaddy-aarch64-linux": {
"type": "custom"
},
"go-xcaddy-aarch64-macos": {
"type": "custom"
},
"go-xcaddy-x86_64-linux": {
"type": "custom"
},
"go-xcaddy-x86_64-macos": {
"type": "custom"
},
"musl-toolchain-aarch64-linux": {
"type": "url",
"url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/aarch64-musl-toolchain.tgz"
@@ -15,6 +27,38 @@
"nasm-2.16.01/ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe"
}
},
"pkg-config-aarch64-linux": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-aarch64-linux-musl-1.2.5.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"pkg-config-aarch64-macos": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-aarch64-darwin.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"pkg-config-x86_64-linux": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-x86_64-linux-musl-1.2.5.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"pkg-config-x86_64-macos": {
"type": "ghrel",
"repo": "static-php/static-php-cli-hosted",
"match": "pkg-config-x86_64-darwin.txz",
"extract-files": {
"bin/pkg-config": "{pkg_root_path}/bin/pkg-config"
}
},
"strawberry-perl-x86_64-win": {
"type": "url",
"url": "https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip"
@@ -43,30 +87,18 @@
"upx-*-win64/upx.exe": "{pkg_root_path}/bin/upx.exe"
}
},
"go-xcaddy-x86_64-linux": {
"zig-aarch64-linux": {
"type": "custom"
},
"go-xcaddy-aarch64-linux": {
"type": "custom"
},
"go-xcaddy-x86_64-macos": {
"type": "custom"
},
"go-xcaddy-aarch64-macos": {
"zig-aarch64-macos": {
"type": "custom"
},
"zig-x86_64-linux": {
"type": "custom"
},
"zig-aarch64-linux": {
"type": "custom"
},
"zig-x86_64-macos": {
"type": "custom"
},
"zig-aarch64-macos": {
"type": "custom"
},
"zig-x86_64-win": {
"type": "custom"
}

View File

@@ -733,7 +733,7 @@
"micro": {
"type": "git",
"path": "php-src/sapi/micro",
"rev": "84beta",
"rev": "php-85-win",
"url": "https://github.com/static-php/phpmicro",
"license": {
"type": "file",
@@ -932,6 +932,20 @@
"path": "LICENSE"
}
},
"re2c": {
"type": "ghrel",
"repo": "skvadrik/re2c",
"match": "re2c.+\\.tar\\.xz",
"prefer-stable": true,
"alt": {
"type": "url",
"url": "https://dl.static-php.dev/static-php-cli/deps/re2c/re2c-4.3.tar.xz"
},
"license": {
"type": "file",
"path": "LICENSE"
}
},
"readline": {
"type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/readline/",
@@ -998,6 +1012,7 @@
"path": "php-src/ext/swoole",
"type": "ghtar",
"repo": "swoole/swoole-src",
"match": "v6\\.+",
"prefer-stable": true,
"license": {
"type": "file",
@@ -1121,5 +1136,14 @@
"type": "file",
"path": "LICENSE"
}
},
"liburing": {
"type": "ghtar",
"repo": "axboe/liburing",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -51,6 +51,14 @@ export default {
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2023-present crazywhalecc'
}
},
search: {
provider: 'algolia',
options: {
appId: 'IHJHUB1SF1',
apiKey: '8266d31cc2ffbd0e059f1c6e5bdaf8fc',
indexName: 'static-php docs',
},
},
}
}

View File

@@ -46,6 +46,14 @@ If you use `swoole,swoole-hook-sqlite`, you will enable the coroutine mode of Sw
swoole-hook-sqlite conflicts with the `pdo_sqlite` extension. If you want to use Swoole and `pdo_sqlite`, please delete the pdo_sqlite extension and enable `swoole` and `swoole-hook-sqlite`.
This extension contains an implementation of the coroutine environment for `pdo_sqlite`.
## swoole-hook-odbc
swoole-hook-odbc is not an extension, it's a Hook feature of Swoole.
If you use `swoole,swoole-hook-odbc`, you will enable the coroutine mode of Swoole's `odbc` extension.
swoole-hook-odbc conflicts with the `pdo_odbc` extension. If you want to use Swoole and `pdo_odbc`, please delete the `pdo_odbc` extension and enable `swoole` and `swoole-hook-odbc`.
This extension contains an implementation of the coroutine environment for `pdo_odbc`.
## swow
1. Only PHP 8.0+ is supported.

View File

@@ -32,7 +32,7 @@ Windows currently only supports the x86_64 architecture, and does not support 32
## Supported PHP Version
Currently, static php cli supports PHP versions 8.1 to 8.4, and theoretically supports PHP 8.0 and earlier versions.
Currently, static php cli supports PHP versions 8.1 to 8.5, and theoretically supports PHP 8.0 and earlier versions.
Simply select the earlier version when downloading.
However, due to some extensions and special components that have stopped supporting earlier versions of PHP,
static-php-cli will not explicitly support earlier versions.

View File

@@ -172,7 +172,7 @@ If the build is successful, you will see the `buildroot/bin` directory in the cu
If the build fails, you can use the `--debug` parameter to view detailed error information,
or use the `--with-clean` to clear the old compilation results and recompile.
If the build still fails to use the above method, please submit an issue and attach your `craft.yml` and `craft.log`.
If the build still fails to use the above method, please submit an issue and attach your `craft.yml` and `./log` archive.
## Step-by-step build command
@@ -242,8 +242,8 @@ Also, it is available when downloading with the `--for-extensions` option.
```bash
# Specifying to download a beta version of PHP8.3
bin/spc download --all -U "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"
# Specifying to download a alpha version of PHP 8.5
bin/spc download --all -U "php-src:https://downloads.php.net/~edorian/php-8.5.0alpha2.tar.xz"
# Specifying to download an older version of the curl library
bin/spc download --all -U "curl:https://curl.se/download/curl-7.88.1.tar.gz"
@@ -289,6 +289,7 @@ You need to specify a compilation target, choose from the following parameters:
- `--build-cli`: Build a cli sapi (command line interface, which can execute PHP code on the command line)
- `--build-fpm`: Build a fpm sapi (php-fpm, used in conjunction with other traditional fpm architecture software such as nginx)
- `--build-cgi`: Build a cgi sapi (cgi, rarely used)
- `--build-micro`: Build a micro sapi (used to build a standalone executable binary containing PHP code)
- `--build-embed`: Build an embed sapi (used to embed into other C language programs)
- `--build-frankenphp`: Build a [FrankenPHP](https://github.com/php/frankenphp) executable

View File

@@ -43,6 +43,14 @@ swoole-hook-sqlite 不是一个扩展,而是 Swoole 的 Hook 特性。
swoole-hook-sqlite 与 `pdo_sqlite` 扩展冲突。如需使用 Swoole 和 `pdo_sqlite`,请删除 pdo_sqlite 扩展,启用 `swoole``swoole-hook-sqlite` 即可。
该扩展包含了 `pdo_sqlite` 的协程环境的实现。
## swoole-hook-odbc
swoole-hook-odbc 不是一个扩展,而是 Swoole 的 Hook 特性。
如果你在编译时添加了 `swoole,swoole-hook-odbc`,你将启用 Swoole 的 `odbc` 扩展的协程模式。
swoole-hook-odbc 与 `pdo_odbc` 扩展冲突。如需使用 Swoole 和 `pdo_odbc`,请删除 `pdo_odbc` 扩展,启用 `swoole``swoole-hook-odbc` 即可。
该扩展包含了 `pdo_odbc` 的协程环境的实现。
## swow
1. swow 仅支持 PHP 8.0+ 版本。

View File

@@ -29,6 +29,6 @@ Windows 目前只支持 x86_64 架构,不支持 32 位 x86、不支持 arm64
## PHP 支持版本
目前static-php-cli 对 PHP 8.1 ~ 8.4 版本是支持的,对于 PHP 8.0 及更早版本理论上支持,只需下载时选择早期版本即可。
目前static-php-cli 对 PHP 8.1 ~ 8.5 版本是支持的,对于 PHP 8.0 及更早版本理论上支持,只需下载时选择早期版本即可。
但由于部分扩展和特殊组件已对早期版本的 PHP 停止了支持,所以 static-php-cli 不会明确支持早期版本。
我们推荐你编译尽可能新的 PHP 版本,以获得更好的体验。

View File

@@ -149,7 +149,7 @@ bin/spc craft --debug
如果中途构建出错,你可以使用 `--debug` 参数查看详细的错误信息,或者使用 `--with-clean` 参数清除旧的编译结果,重新编译。
如使用以上方式仍构建失败,请提交一个 issue附上你的 `craft.yml``craft.log`
如使用以上方式仍构建失败,请提交一个 issue附上你的 `craft.yml` 文件`log/` 目录的压缩包
## 分步构建命令
@@ -209,8 +209,8 @@ bin/spc download --from-zip=/path/to/your/download.zip
让下载器强制使用你指定的链接下载此 source 的包。使用方法为 `{source-name}:{url}` 即可,可同时重写多个库的下载地址。在使用 `--for-extensions` 选项下载时同样可用。
```bash
# 例如:指定下载测试版的 PHP8.3
bin/spc download --all -U "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"
# 例如:指定下载 Alpha 版的 PHP8.5
bin/spc download --all -U "php-src:https://downloads.php.net/~edorian/php-8.5.0alpha2.tar.xz"
# 指定下载旧版本的 curl 库
bin/spc download --all -U "curl:https://curl.se/download/curl-7.88.1.tar.gz"
@@ -249,6 +249,7 @@ bin/spc doctor --auto-fix
- `--build-cli`: 构建一个 cli sapi命令行界面可在命令行执行 PHP 代码)
- `--build-fpm`: 构建一个 fpm sapiphp-fpm用于和其他传统的 fpm 架构的软件如 nginx 配合使用)
- `--build-cgi`: 构建一个 cgi sapicgi可用于传统的 cgi 架构的软件如 apache 配合使用)
- `--build-micro`: 构建一个 micro sapi用于构建一个包含 PHP 代码的独立可执行二进制)
- `--build-embed`: 构建一个 embed sapi用于嵌入到其他 C 语言程序中)
- `--build-frankenphp`: 构建一个 [frankenphp](https://github.com/php/frankenphp) 二进制

View File

@@ -8,6 +8,8 @@ parameters:
- '#class Fiber#'
- '#Attribute class JetBrains\\PhpStorm\\ArrayShape does not exist#'
- '#Function Swoole\\Coroutine\\run not found.#'
- '#Static call to instance method ZM\\Logger\\ConsoleColor#'
- '#Constant GNU_ARCH not found#'
dynamicConstantNames:
- PHP_OS_FAMILY
excludePaths:

View File

@@ -34,7 +34,7 @@ use Symfony\Component\Console\Application;
*/
final class ConsoleApplication extends Application
{
public const VERSION = '2.7.0';
public const string VERSION = '2.7.4';
public function __construct()
{

View File

@@ -4,18 +4,16 @@ declare(strict_types=1);
namespace SPC\builder;
use PharIo\FileSystem\File;
use SPC\exception\ExceptionHandler;
use SPC\exception\FileSystemException;
use SPC\exception\BuildFailureException;
use SPC\exception\InterruptException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\store\LockFile;
use SPC\store\pkg\GoXcaddy;
use SPC\store\SourceManager;
use SPC\store\SourcePatcher;
use SPC\util\CustomExt;
use SPC\util\AttributeMapper;
abstract class BuilderBase
{
@@ -46,20 +44,14 @@ abstract class BuilderBase
/**
* Convert libraries to class
*
* @param array<string> $sorted_libraries Libraries to build (if not empty, must sort first)
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
* @param array<string> $sorted_libraries Libraries to build (if not empty, must sort first)
*
* @internal
*/
abstract public function proveLibs(array $sorted_libraries);
/**
* Set-Up libraries
*
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function setupLibs(): void
{
@@ -70,12 +62,11 @@ abstract class BuilderBase
match ($status) {
LIB_STATUS_OK => logger()->info('lib [' . $lib::NAME . '] setup success, took ' . round(microtime(true) - $starttime, 2) . ' s'),
LIB_STATUS_ALREADY => logger()->notice('lib [' . $lib::NAME . '] already built'),
LIB_STATUS_BUILD_FAILED => logger()->error('lib [' . $lib::NAME . '] build failed'),
LIB_STATUS_INSTALL_FAILED => logger()->error('lib [' . $lib::NAME . '] install failed'),
default => logger()->warning('lib [' . $lib::NAME . '] build status unknown'),
};
if (in_array($status, [LIB_STATUS_BUILD_FAILED, LIB_STATUS_INSTALL_FAILED])) {
throw new RuntimeException('Library [' . $lib::NAME . '] setup failed.');
throw new BuildFailureException('Library [' . $lib::NAME . '] setup failed.');
}
}
}
@@ -139,9 +130,6 @@ abstract class BuilderBase
/**
* Check if there is a cpp extensions or libraries.
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function hasCpp(): bool
{
@@ -174,15 +162,10 @@ abstract class BuilderBase
/**
* Verify the list of "ext" extensions for validity and declare an Extension object to check the dependencies of the extensions.
*
* @throws FileSystemException
* @throws RuntimeException
* @throws \ReflectionException
* @throws \Throwable|WrongUsageException
* @internal
*/
public function proveExts(array $static_extensions, array $shared_extensions = [], bool $skip_check_deps = false, bool $skip_extract = false): void
{
CustomExt::loadCustomExt();
// judge ext
foreach ($static_extensions as $ext) {
// if extension does not support static build, throw exception
@@ -213,7 +196,7 @@ abstract class BuilderBase
}
foreach ([...$static_extensions, ...$shared_extensions] as $extension) {
$class = CustomExt::getExtClass($extension);
$class = AttributeMapper::getExtensionClassByName($extension) ?? Extension::class;
/** @var Extension $ext */
$ext = new $class($extension, $this);
if (in_array($extension, $static_extensions)) {
@@ -248,9 +231,7 @@ abstract class BuilderBase
abstract public function testPHP(int $build_target = BUILD_TARGET_NONE);
/**
* @throws WrongUsageException
* @throws RuntimeException
* @throws FileSystemException
* Build shared extensions.
*/
public function buildSharedExts(): void
{
@@ -273,9 +254,8 @@ abstract class BuilderBase
}
$ext->buildShared();
}
} catch (RuntimeException $e) {
} finally {
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);
FileSystem::replaceFileStr(BUILD_LIB_PATH . '/php/build/phpize.m4', '# test "[$]$1" = "no" && $1=yes', 'test "[$]$1" = "no" && $1=yes');
@@ -284,19 +264,16 @@ abstract class BuilderBase
/**
* Generate extension enable arguments for configure.
* e.g. --enable-mbstring
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function makeStaticExtensionArgs(): string
{
$ret = [];
foreach ($this->getExts() as $ext) {
$arg = $ext->getConfigureArg();
$arg = null;
if ($ext->isBuildShared() && !$ext->isBuildStatic()) {
if (
(Config::getExt($ext->getName(), 'type') === 'builtin' &&
!file_exists(SOURCE_PATH . '/php-src/ext/' . $ext->getName() . '/config.m4')) ||
!file_exists(SOURCE_PATH . '/php-src/ext/' . $ext->getName() . '/config.m4')) ||
Config::getExt($ext->getName(), 'build-with-php') === true
) {
$arg = $ext->getConfigureArg(true);
@@ -304,6 +281,7 @@ abstract class BuilderBase
continue;
}
}
$arg ??= $ext->getConfigureArg();
logger()->info($ext->getName() . ' is using ' . $arg);
$ret[] = trim($arg);
}
@@ -321,9 +299,6 @@ abstract class BuilderBase
/**
* Get PHP Version ID from php-src/main/php_version.h
*
* @throws RuntimeException
* @throws WrongUsageException
*/
public function getPHPVersionID(): int
{
@@ -336,20 +311,25 @@ abstract class BuilderBase
return intval($match[1]);
}
throw new RuntimeException('PHP version file format is malformed, please remove it and download again');
throw new WrongUsageException('PHP version file format is malformed, please remove "./source/php-src" dir and download/extract again');
}
public function getPHPVersion(): string
public function getPHPVersion(bool $exception_on_failure = true): string
{
if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) {
if (!$exception_on_failure) {
return 'unknown';
}
throw new WrongUsageException('PHP source files are not available, you need to download them first');
}
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
if (preg_match('/PHP_VERSION "(.*)"/', $file, $match) !== 0) {
return $match[1];
}
throw new RuntimeException('PHP version file format is malformed, please remove it and download again');
if (!$exception_on_failure) {
return 'unknown';
}
throw new WrongUsageException('PHP version file format is malformed, please remove it and download again');
}
/**
@@ -366,7 +346,7 @@ abstract class BuilderBase
}
$file = LockFile::getLockFullPath($lock);
}
if (preg_match('/php-(\d+\.\d+\.\d+(?:RC\d+)?)\.tar\.(?:gz|bz2|xz)/', $file, $match)) {
if (preg_match('/php-(\d+\.\d+\.\d+(?:RC\d+|alpha\d+|beta\d+)?)\.tar\.(?:gz|bz2|xz)/', $file, $match)) {
return $match[1];
}
return false;
@@ -413,6 +393,9 @@ abstract class BuilderBase
if (($type & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP) {
$ls[] = 'frankenphp';
}
if (($type & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) {
$ls[] = 'cgi';
}
return implode(', ', $ls);
}
@@ -496,7 +479,7 @@ abstract class BuilderBase
foreach ($patches as $patch) {
try {
if (!file_exists($patch)) {
throw new RuntimeException("Additional patch script file {$patch} not found!");
throw new WrongUsageException("Additional patch script file {$patch} not found!");
}
logger()->debug('Running additional patch script: ' . $patch);
require $patch;
@@ -509,11 +492,6 @@ abstract class BuilderBase
exit($e->getCode());
} catch (\Throwable $e) {
logger()->critical('Patch script ' . $patch . ' failed to run.');
if ($this->getOption('debug')) {
ExceptionHandler::getInstance()->handle($e);
} else {
logger()->critical('Please check with --debug option to see more details.');
}
throw $e;
}
}
@@ -530,8 +508,7 @@ abstract class BuilderBase
throw new WrongUsageException('FrankenPHP SAPI is only available on Linux and macOS!');
}
// frankenphp needs package go-xcaddy installed
$pkg_dir = PKG_ROOT_PATH . '/go-xcaddy-' . arch2gnu(php_uname('m')) . '-' . osfamily2shortname();
if (!file_exists("{$pkg_dir}/bin/go") || !file_exists("{$pkg_dir}/bin/xcaddy")) {
if (!GoXcaddy::isInstalled()) {
global $argv;
throw new WrongUsageException("FrankenPHP SAPI requires the go-xcaddy package, please install it first: {$argv[0]} install-pkg go-xcaddy");
}

View File

@@ -8,8 +8,7 @@ use SPC\builder\freebsd\BSDBuilder;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\macos\MacOSBuilder;
use SPC\builder\windows\WindowsBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\ExceptionHandler;
use SPC\exception\WrongUsageException;
use Symfony\Component\Console\Input\InputInterface;
@@ -20,11 +19,6 @@ class BuilderProvider
{
private static ?BuilderBase $builder = null;
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public static function makeBuilderByInput(InputInterface $input): BuilderBase
{
ini_set('memory_limit', '4G');
@@ -36,12 +30,13 @@ class BuilderProvider
'BSD' => new BSDBuilder($input->getOptions()),
default => throw new WrongUsageException('Current OS "' . PHP_OS_FAMILY . '" is not supported yet'),
};
// bind the builder to ExceptionHandler
ExceptionHandler::bindBuilder(self::$builder);
return self::$builder;
}
/**
* @throws WrongUsageException
*/
public static function getBuilder(): BuilderBase
{
if (self::$builder === null) {

View File

@@ -4,11 +4,15 @@ declare(strict_types=1);
namespace SPC\builder;
use SPC\exception\EnvironmentException;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\SPCException;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\toolchain\ClangNativeToolchain;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\SPCConfigUtil;
@@ -24,21 +28,16 @@ class Extension
protected string $source_dir;
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function __construct(protected string $name, protected BuilderBase $builder)
{
$ext_type = Config::getExt($this->name, 'type');
$unix_only = Config::getExt($this->name, 'unix-only', false);
$windows_only = Config::getExt($this->name, 'windows-only', false);
if (PHP_OS_FAMILY !== 'Windows' && $windows_only) {
throw new RuntimeException("{$ext_type} extension {$name} is not supported on Linux and macOS platform");
throw new EnvironmentException("{$ext_type} extension {$name} is not supported on Linux and macOS platform");
}
if (PHP_OS_FAMILY === 'Windows' && $unix_only) {
throw new RuntimeException("{$ext_type} extension {$name} is not supported on Windows platform");
throw new EnvironmentException("{$ext_type} extension {$name} is not supported on Windows platform");
}
// set source_dir for builtin
if ($ext_type === 'builtin') {
@@ -46,7 +45,7 @@ class Extension
} elseif ($ext_type === 'external') {
$source = Config::getExt($this->name, 'source');
if ($source === null) {
throw new RuntimeException("{$ext_type} extension {$name} source not found");
throw new ValidationException("{$ext_type} extension {$name} source not found", validation_module: "Extension [{$name}] loader");
}
$source_path = Config::getSource($source)['path'] ?? null;
$source_path = $source_path === null ? SOURCE_PATH . '/' . $source : SOURCE_PATH . '/' . $source_path;
@@ -63,9 +62,6 @@ class Extension
/**
* 获取开启该扩展的 PHP 编译添加的参数
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getConfigureArg(bool $shared = false): string
{
@@ -80,9 +76,6 @@ class Extension
/**
* 根据 ext 的 arg-type 获取对应开启的参数,一般都是 --enable-xxx 和 --with-xxx
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getEnableArg(bool $shared = false): string
{
@@ -112,10 +105,6 @@ class Extension
/**
* 检查下依赖就行了,作用是导入依赖给 Extension 对象,今后可以对库依赖进行选择性处理
*
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
*/
public function checkDependency(): static
{
@@ -183,6 +172,14 @@ class Extension
return false;
}
/**
* Patch code before ./configure.bat for Windows
*/
public function patchBeforeWindowsConfigure(): bool
{
return false;
}
/**
* Patch code before make
* If you need to patch some code, overwrite this
@@ -251,8 +248,6 @@ class Extension
* i.e.; pdo_pgsql would return:
*
* `-d "extension=pgsql" -d "extension=pdo_pgsql"`
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getSharedExtensionLoadString(): string
{
@@ -260,12 +255,15 @@ class Extension
$order = [];
$resolve = function ($extension) use (&$resolve, &$loaded, &$order) {
if (!$extension instanceof Extension) {
return;
}
if (isset($loaded[$extension->getName()])) {
return;
}
$loaded[$extension->getName()] = true;
foreach ($this->dependencies as $dependency) {
foreach ($extension->dependencies as $dependency) {
$resolve($dependency);
}
@@ -277,6 +275,9 @@ class Extension
$ret = '';
foreach ($order as $ext) {
if ($ext instanceof self && $ext->isBuildShared()) {
if (Config::getExt($ext->getName(), 'type', false) === 'addon') {
continue;
}
if (Config::getExt($ext->getName(), 'zend-extension', false) === true) {
$ret .= " -d \"zend_extension={$ext->getName()}\"";
} else {
@@ -292,20 +293,16 @@ class Extension
return $ret;
}
/**
* @throws RuntimeException
*/
public function runCliCheckUnix(): void
{
// Run compile check if build target is cli
// If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php
// If check failed, throw RuntimeException
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
if ($ret !== 0) {
throw new RuntimeException(
'extension ' . $this->getName() . ' failed runtime check: php-cli returned ' . $ret . "\n" .
join("\n", $out)
throw new ValidationException(
"extension {$this->getName()} failed compile check: php-cli returned {$ret}",
validation_module: 'Extension ' . $this->getName() . ' sanity check'
);
}
@@ -319,23 +316,21 @@ class Extension
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' -r "' . trim($test) . '"');
if ($ret !== 0) {
var_dump($out);
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
throw new ValidationException(
"extension {$this->getName()} failed sanity check. Code: {$ret}, output: " . implode("\n", $out),
validation_module: 'Extension ' . $this->getName() . ' function check'
);
}
}
}
/**
* @throws RuntimeException
*/
public function runCliCheckWindows(): void
{
// Run compile check if build target is cli
// If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php
// If check failed, throw RuntimeException
[$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n --ri "' . $this->getDistName() . '"', false);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");
}
if (file_exists(FileSystem::convertPath(ROOT_DIR . '/src/globals/ext-tests/' . $this->getName() . '.php'))) {
@@ -348,7 +343,10 @@ class Extension
[$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n -r "' . trim($test) . '"');
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
throw new ValidationException(
"extension {$this->getName()} failed function check",
validation_module: "Extension {$this->getName()} function check"
);
}
}
}
@@ -360,50 +358,50 @@ class Extension
/**
* Build shared extension
*
* @throws WrongUsageException
* @throws RuntimeException
*/
public function buildShared(): void
public function buildShared(array $visited = []): void
{
if (Config::getExt($this->getName(), 'type') === 'builtin' || Config::getExt($this->getName(), 'build-with-php') === true) {
try {
if (Config::getExt($this->getName(), 'type') === 'builtin' || Config::getExt($this->getName(), 'build-with-php') === true) {
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
logger()->info('Shared extension [' . $this->getName() . '] was already built by php-src/configure (' . $this->getName() . '.so)');
return;
}
if (Config::getExt($this->getName(), 'build-with-php') === true) {
logger()->warning('Shared extension [' . $this->getName() . '] did not build with php-src/configure (' . $this->getName() . '.so)');
logger()->warning('Try deleting your build and source folders and running `spc build`` again.');
return;
}
}
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
logger()->info('Shared extension [' . $this->getName() . '] was already built by php-src/configure (' . $this->getName() . '.so)');
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
return;
}
if (Config::getExt($this->getName(), 'build-with-php') === true) {
logger()->warning('Shared extension [' . $this->getName() . '] did not build with php-src/configure (' . $this->getName() . '.so)');
logger()->warning('Try deleting your build and source folders and running `spc build`` again.');
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
foreach ($this->dependencies as $dependency) {
if (!$dependency instanceof Extension) {
continue;
}
if (!$dependency->isBuildStatic() && !in_array($dependency->getName(), $visited)) {
logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName());
$dependency->buildShared([...$visited, $this->getName()]);
}
}
if (Config::getExt($this->getName(), 'type') === 'addon') {
return;
}
match (PHP_OS_FAMILY) {
'Darwin', 'Linux' => $this->buildUnixShared(),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
};
} catch (SPCException $e) {
$e->bindExtensionInfo(['extension_name' => $this->getName()]);
throw $e;
}
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
}
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
foreach ($this->dependencies as $dependency) {
if (!$dependency instanceof Extension) {
continue;
}
if (!$dependency->isBuildStatic()) {
logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName());
$dependency->buildShared();
}
}
match (PHP_OS_FAMILY) {
'Darwin', 'Linux' => $this->buildUnixShared(),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
};
}
/**
* Build shared extension for Unix
*
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
* @throws \ReflectionException
* @throws \Throwable
*/
public function buildUnixShared(): void
{
@@ -423,8 +421,24 @@ class Extension
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
if (ToolchainManager::getToolchainClass() === ZigToolchain::class && SPCTarget::getTargetOS() === 'Linux') {
$env['SPC_COMPILER_EXTRA'] = '-lstdc++';
if (str_contains($env['LIBS'], '-lstdc++') && SPCTarget::getTargetOS() === 'Linux') {
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$env['SPC_COMPILER_EXTRA'] = '-lstdc++';
} elseif (ToolchainManager::getToolchainClass() === GccNativeToolchain::class || ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) {
try {
$content = FileSystem::readFile($this->source_dir . '/config.m4');
if ($content && !str_contains($content, 'PHP_ADD_LIBRARY(stdc++')) {
$pattern = '/(PHP_NEW_EXTENSION\(' . $this->name . ',.*\))/m';
$replacement = "$1\nPHP_ADD_LIBRARY(stdc++, 1, " . strtoupper($this->name) . '_SHARED_LIBADD)';
FileSystem::replaceFileRegex(
$this->source_dir . '/config.m4',
$pattern,
$replacement
);
}
} catch (FileSystemException) {
}
}
}
if ($this->patchBeforeSharedPhpize()) {
@@ -498,15 +512,12 @@ class Extension
return $this->build_static;
}
/**
* @throws RuntimeException
*/
protected function addLibraryDependency(string $name, bool $optional = false): void
{
$depLib = $this->builder->getLib($name);
if (!$depLib) {
if (!$optional) {
throw new RuntimeException("extension {$this->name} requires library {$name}");
throw new WrongUsageException("extension {$this->name} requires library {$name}");
}
logger()->info("enabling {$this->name} without library {$name}");
} else {
@@ -514,15 +525,12 @@ class Extension
}
}
/**
* @throws RuntimeException
*/
protected function addExtensionDependency(string $name, bool $optional = false): void
{
$depExt = $this->builder->getExt($name);
if (!$depExt) {
if (!$optional) {
throw new RuntimeException("{$this->name} requires extension {$name}");
throw new WrongUsageException("{$this->name} requires extension {$name} which is not included");
}
logger()->info("enabling {$this->name} without extension {$name}");
} else {

View File

@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace SPC\builder;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\SPCException;
use SPC\exception\SPCInternalException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\Downloader;
@@ -27,23 +27,17 @@ abstract class LibraryBase
protected bool $patched = false;
/**
* @throws RuntimeException
*/
public function __construct(?string $source_dir = null)
{
if (static::NAME === 'unknown') {
throw new RuntimeException('no unknown!!!!!');
throw new SPCInternalException('Please set the NAME constant in ' . static::class);
}
$this->source_dir = $source_dir ?? (SOURCE_PATH . '/' . Config::getLib(static::NAME, 'source'));
$this->source_dir = $source_dir ?? (SOURCE_PATH . DIRECTORY_SEPARATOR . Config::getLib(static::NAME, 'source'));
}
/**
* Try to install or build this library.
* @param bool $force If true, force install or build
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
* @param bool $force If true, force install or build
*/
public function setup(bool $force = false): int
{
@@ -107,10 +101,6 @@ abstract class LibraryBase
/**
* Calculate dependencies for current library.
*
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
*/
public function calcDependency(): void
{
@@ -131,9 +121,6 @@ abstract class LibraryBase
/**
* Get config static libs.
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getStaticLibs(): array
{
@@ -142,9 +129,6 @@ abstract class LibraryBase
/**
* Get config headers.
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getHeaders(): array
{
@@ -153,19 +137,12 @@ abstract class LibraryBase
/**
* Get binary files.
*
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getBinaryFiles(): array
{
return Config::getLib(static::NAME, 'bin', []);
}
/**
* @throws WrongUsageException
* @throws FileSystemException
*/
public function tryInstall(array $lock, bool $force_install = false): int
{
$install_file = $lock['filename'];
@@ -177,7 +154,7 @@ abstract class LibraryBase
FileSystem::extractPackage($install_file, $lock['source_type'], DOWNLOAD_PATH . '/' . $install_file, BUILD_ROOT_PATH);
$this->install();
return LIB_STATUS_OK;
} catch (FileSystemException|RuntimeException $e) {
} catch (SPCException $e) {
logger()->error('Failed to extract pre-built library [' . static::NAME . ']: ' . $e->getMessage());
return LIB_STATUS_INSTALL_FAILED;
}
@@ -194,10 +171,6 @@ abstract class LibraryBase
* BUILD_STATUS_OK if build success
* BUILD_STATUS_ALREADY if already built
* BUILD_STATUS_FAILED if build failed
*
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
*/
public function tryBuild(bool $force_build = false): int
{
@@ -288,6 +261,16 @@ abstract class LibraryBase
return false;
}
/**
* Patch code before windows configure.bat
* If you need to patch some code, overwrite this
* return true if you patched something, false if not
*/
public function patchBeforeWindowsConfigure(): bool
{
return false;
}
/**
* Patch code before make
* If you need to patch some code, overwrite this
@@ -309,8 +292,6 @@ abstract class LibraryBase
/**
* Build this library.
*
* @throws RuntimeException
*/
abstract protected function build();
@@ -323,7 +304,7 @@ abstract class LibraryBase
}
$replace_items = json_decode(file_get_contents($replace_item_file), true);
if (!is_array($replace_items)) {
throw new RuntimeException('Invalid placeholder file: ' . $replace_item_file);
throw new SPCInternalException("Invalid placeholder file: {$replace_item_file}");
}
$placeholders = get_pack_replace();
// replace placeholders in BUILD_ROOT_PATH
@@ -341,8 +322,6 @@ abstract class LibraryBase
/**
* Add lib dependency
*
* @throws RuntimeException
*/
protected function addLibraryDependency(string $name, bool $optional = false): void
{
@@ -352,7 +331,7 @@ abstract class LibraryBase
return;
}
if (!$optional) {
throw new RuntimeException(static::NAME . " requires library {$name}");
throw new WrongUsageException(static::NAME . " requires library {$name} but it is not included");
}
logger()->debug('enabling ' . static::NAME . " without {$name}");
}

View File

@@ -6,18 +6,12 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('bz2')]
class bz2 extends Extension
{
/**
* @throws FileSystemException
* @throws WrongUsageException
*/
public function patchBeforeConfigure(): bool
{
$frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : '';

View File

@@ -8,17 +8,13 @@ use SPC\builder\Extension;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\macos\MacOSBuilder;
use SPC\builder\windows\WindowsBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException;
use SPC\exception\PatchException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('curl')]
class curl extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeBuildconf(): bool
{
logger()->info('patching before-configure for curl checks');
@@ -46,10 +42,6 @@ class curl extends Extension
return true;
}
/**
* @throws FileSystemException
* @throws WrongUsageException
*/
public function patchBeforeConfigure(): bool
{
$frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : '';
@@ -61,7 +53,7 @@ class curl extends Extension
public function patchBeforeMake(): bool
{
$patched = parent::patchBeforeMake();
$extra_libs = getenv('SPC_EXTRA_LIBS');
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
if ($this->builder instanceof WindowsBuilder && !str_contains($extra_libs, 'secur32.lib')) {
$extra_libs .= ' secur32.lib';
putenv('SPC_EXTRA_LIBS=' . trim($extra_libs));
@@ -105,7 +97,7 @@ class curl extends Extension
);
if ($patched === null) {
throw new \RuntimeException('Failed to patch config.m4 due to a regex error');
throw new PatchException('shared extension curl patcher', 'Failed to patch config.m4 due to a regex error');
}
FileSystem::writeFile($file, $patched);

View File

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

View File

@@ -5,16 +5,12 @@ 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' : '');

View File

@@ -5,16 +5,12 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('ev')]
class ev extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeBuildconf(): bool
{
/*

View File

@@ -6,7 +6,6 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
@@ -27,18 +26,12 @@ class event extends Extension
return $arg;
}
/**
* @throws FileSystemException
*/
public function patchBeforeConfigure(): bool
{
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-levent_openssl/', $this->getLibFilesString());
return true;
}
/**
* @throws FileSystemException
*/
public function patchBeforeMake(): bool
{
$patched = parent::patchBeforeMake();

View File

@@ -6,17 +6,12 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('gettext')]
class gettext extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeBuildconf(): bool
{
if ($this->builder instanceof MacOSBuilder) {
@@ -25,10 +20,6 @@ class gettext extends Extension
return true;
}
/**
* @throws WrongUsageException
* @throws FileSystemException
*/
public function patchBeforeConfigure(): bool
{
if ($this->builder instanceof MacOSBuilder) {

View File

@@ -5,16 +5,12 @@ 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('glfw')]
class glfw extends Extension
{
/**
* @throws RuntimeException
*/
public function patchBeforeBuildconf(): bool
{
if (file_exists(SOURCE_PATH . '/php-src/ext/glfw')) {

View File

@@ -6,6 +6,7 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\windows\WindowsBuilder;
use SPC\exception\ValidationException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
use SPC\util\GlobalEnvManager;
@@ -18,7 +19,7 @@ class grpc extends Extension
public function patchBeforeBuildconf(): bool
{
if ($this->builder instanceof WindowsBuilder) {
throw new \RuntimeException('grpc extension does not support windows yet');
throw new ValidationException('grpc extension does not support windows yet');
}
if (file_exists(SOURCE_PATH . '/php-src/ext/grpc')) {
return false;
@@ -27,7 +28,7 @@ class grpc extends Extension
if (is_dir($this->source_dir . '/src/php/ext/grpc')) {
shell()->exec('ln -s ' . $this->source_dir . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc');
} else {
throw new \RuntimeException('Cannot find grpc source code');
throw new ValidationException('Cannot find grpc source code in ' . $this->source_dir . '/src/php/ext/grpc');
}
if (SPCTarget::getTargetOS() === 'Darwin') {
FileSystem::replaceFileRegex(

View File

@@ -19,7 +19,7 @@ class imagick extends Extension
protected function splitLibsIntoStaticAndShared(string $allLibs): array
{
[$static, $shared] = parent::splitLibsIntoStaticAndShared($allLibs);
if (str_contains(getenv('PATH'), 'rh/devtoolset-10')) {
if (str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset')) {
$static .= ' -l:libstdc++.a';
$shared = str_replace('-lstdc++', '', $shared);
}

View File

@@ -24,9 +24,6 @@ class imap extends Extension
return false;
}
/**
* @throws WrongUsageException
*/
public function validate(): void
{
if ($this->builder->getOption('enable-zts')) {
@@ -49,7 +46,7 @@ class imap extends Extension
if (PHP_OS_FAMILY !== 'Linux' || SystemUtil::isMuslDist()) {
return $patched;
}
$extra_libs = trim(getenv('SPC_EXTRA_LIBS') . ' -lcrypt');
$extra_libs = trim((getenv('SPC_EXTRA_LIBS') ?: '') . ' -lcrypt');
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
return true;
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\ValidationException;
use SPC\util\CustomExt;
#[CustomExt('mbregex')]
@@ -16,11 +16,6 @@ class mbregex extends Extension
return 'mbstring';
}
public function getConfigureArg(bool $shared = false): string
{
return '';
}
/**
* mbregex is not an extension, we need to overwrite the default check.
*/
@@ -29,7 +24,7 @@ class mbregex extends Extension
$sharedext = $this->builder->getExt('mbstring')->isBuildShared() ? '-d "extension_dir=' . BUILD_MODULES_PATH . '" -d "extension=mbstring"' : '';
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $sharedext . ' --ri "mbstring" | grep regex', false);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !');
throw new ValidationException("Extension {$this->getName()} failed compile check: compiled php-cli mbstring extension does not contain regex !");
}
}
@@ -37,11 +32,11 @@ class mbregex extends Extension
{
[$ret, $out] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n --ri "mbstring"', false);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli does not contain mbstring !');
throw new ValidationException("extension {$this->getName()} failed compile check: compiled php-cli does not contain mbstring !");
}
$out = implode("\n", $out);
if (!str_contains($out, 'regex')) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !');
throw new ValidationException("extension {$this->getName()} failed compile check: compiled php-cli mbstring extension does not contain regex !");
}
}
}

View File

@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
@@ -17,9 +16,6 @@ class memcache extends Extension
return '--enable-memcache' . ($shared ? '=shared' : '') . ' --with-zlib-dir=' . BUILD_ROOT_PATH;
}
/**
* @throws FileSystemException
*/
public function patchBeforeBuildconf(): bool
{
FileSystem::replaceFileStr(

View File

@@ -17,6 +17,10 @@ class memcached extends Extension
'--with-libmemcached-dir=' . BUILD_ROOT_PATH . ' ' .
'--disable-memcached-sasl ' .
'--enable-memcached-json ' .
($this->builder->getLib('zstd') ? '--with-zstd ' : '') .
($this->builder->getExt('igbinary') ? '--enable-memcached-igbinary ' : '') .
($this->builder->getExt('session') ? '--enable-memcached-session ' : '') .
($this->builder->getExt('msgpack') ? '--enable-memcached-msgpack ' : '') .
'--with-system-fastlz';
}
}

View File

@@ -12,9 +12,9 @@ class mongodb extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
$arg = ' --enable-mongodb ';
$arg = ' --enable-mongodb' . ($shared ? '=shared' : '') . ' ';
$arg .= ' --with-mongodb-system-libs=no --with-mongodb-client-side-encryption=no ';
$arg .= ' --with-mongodb-sasl=no ';
$arg .= ' --with-mongodb-sasl=no ';
if ($this->builder->getLib('openssl')) {
$arg .= '--with-mongodb-ssl=openssl';
}
@@ -22,6 +22,6 @@ class mongodb extends Extension
$arg .= $this->builder->getLib('zstd') ? ' --with-mongodb-zstd=yes ' : ' --with-mongodb-zstd=no ';
// $arg .= $this->builder->getLib('snappy') ? ' --with-mongodb-snappy=yes ' : ' --with-mongodb-snappy=no ';
$arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled ';
return $arg;
return clean_spaces($arg);
}
}

View File

@@ -5,18 +5,14 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\SourcePatcher;
use SPC\util\CustomExt;
use SPC\util\SPCTarget;
#[CustomExt('opcache')]
class opcache extends Extension
{
/**
* @throws WrongUsageException
* @throws RuntimeException
*/
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
@@ -26,25 +22,43 @@ class opcache extends Extension
public function patchBeforeBuildconf(): bool
{
$version = $this->builder->getPHPVersion();
if (file_exists(SOURCE_PATH . '/php-src/.opcache_patched')) {
return false;
}
// if 8.2.0 <= PHP_VERSION < 8.2.23, we need to patch from legacy patch file
if (version_compare($this->builder->getPHPVersion(), '8.2.0', '>=') && version_compare($this->builder->getPHPVersion(), '8.2.23', '<')) {
if (version_compare($version, '8.2.0', '>=') && version_compare($version, '8.2.23', '<')) {
SourcePatcher::patchFile('spc_fix_static_opcache_before_80222.patch', SOURCE_PATH . '/php-src');
}
// if 8.3.0 <= PHP_VERSION < 8.3.11, we need to patch from legacy patch file
elseif (version_compare($this->builder->getPHPVersion(), '8.3.0', '>=') && version_compare($this->builder->getPHPVersion(), '8.3.11', '<')) {
elseif (version_compare($version, '8.3.0', '>=') && version_compare($version, '8.3.11', '<')) {
SourcePatcher::patchFile('spc_fix_static_opcache_before_80310.patch', SOURCE_PATH . '/php-src');
} else {
}
// if 8.3.12 <= PHP_VERSION < 8.5.0-dev, we need to patch from legacy patch file
elseif (version_compare($version, '8.5.0-dev', '<')) {
SourcePatcher::patchMicro(items: ['static_opcache']);
}
// PHP 8.5.0-dev and later supports static opcache without patching
else {
return false;
}
return file_put_contents(SOURCE_PATH . '/php-src/.opcache_patched', '1') !== false;
}
public function getUnixConfigureArg(bool $shared = false): string
{
return '--enable-opcache';
$phpVersionID = $this->builder->getPHPVersionID();
$opcache_jit = ' --enable-opcache-jit';
if ((SPCTarget::getTargetOS() === 'Linux' &&
SPCTarget::getLibc() === 'musl' &&
$this->builder->getOption('enable-zts') &&
arch2gnu(php_uname('m')) === 'x86_64' &&
$phpVersionID < 80500) ||
$this->builder->getOption('disable-opcache-jit')
) {
$opcache_jit = ' --disable-opcache-jit';
}
return '--enable-opcache' . ($shared ? '=shared' : '') . $opcache_jit;
}
public function getDistName(): string

View File

@@ -27,6 +27,19 @@ class openssl extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
$openssl_dir = $this->builder->getPHPVersionID() >= 80400 ? '' : ' --with-openssl-dir=' . BUILD_ROOT_PATH;
return '--with-openssl=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $openssl_dir;
$args = '--with-openssl=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $openssl_dir;
if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) {
$args .= ' --with-openssl-argon2 OPENSSL_LIBS="-lz"';
}
return $args;
}
public function getWindowsConfigureArg(bool $shared = false): string
{
$args = '--with-openssl';
if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) {
$args .= ' --with-openssl-argon2';
}
return $args;
}
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\ValidationException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
use SPC\util\GlobalEnvManager;
@@ -15,7 +16,7 @@ class opentelemetry extends Extension
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
throw new \RuntimeException('The opentelemetry extension requires PHP 8.0 or later');
throw new ValidationException('The opentelemetry extension requires PHP 8.0 or later');
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\ValidationException;
use SPC\util\CustomExt;
#[CustomExt('password-argon2')]
@@ -20,7 +20,7 @@ class password_argon2 extends Extension
{
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n -r "assert(defined(\'PASSWORD_ARGON2I\'));"');
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
throw new ValidationException('extension ' . $this->getName() . ' failed sanity check', validation_module: 'password_argon2 function check');
}
}
@@ -42,4 +42,14 @@ class password_argon2 extends Extension
}
return $patched;
}
public function getConfigureArg(bool $shared = false): string
{
if ($this->builder->getLib('openssl') !== null) {
if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) {
return '--without-password-argon2'; // use --with-openssl-argon2 in openssl extension instead
}
}
return '--with-password-argon2';
}
}

View File

@@ -5,16 +5,12 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('pdo_sqlite')]
class pdo_sqlite extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeConfigure(): bool
{
FileSystem::replaceFileRegex(

View File

@@ -5,20 +5,12 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('pgsql')]
class pgsql extends Extension
{
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function patchBeforeConfigure(): bool
{
FileSystem::replaceFileRegex(
@@ -29,10 +21,6 @@ class pgsql extends Extension
return true;
}
/**
* @throws WrongUsageException
* @throws RuntimeException
*/
public function getUnixConfigureArg(bool $shared = false): string
{
if ($this->builder->getPHPVersionID() >= 80400) {
@@ -46,10 +34,6 @@ class pgsql extends Extension
return '--with-pgsql=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH;
}
/**
* @throws WrongUsageException
* @throws RuntimeException
*/
public function getWindowsConfigureArg(bool $shared = false): string
{
if ($this->builder->getPHPVersionID() >= 80400) {

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\ValidationException;
use SPC\util\CustomExt;
#[CustomExt('protobuf')]
@@ -13,12 +14,12 @@ class protobuf extends Extension
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
throw new \RuntimeException('The latest protobuf extension requires PHP 8.0 or later');
throw new ValidationException('The latest protobuf extension requires PHP 8.0 or later');
}
$grpc = $this->builder->getExt('grpc');
// protobuf conflicts with grpc
if ($grpc?->isBuildStatic()) {
throw new \RuntimeException('protobuf conflicts with grpc, please remove grpc or protobuf extension');
throw new ValidationException('protobuf conflicts with grpc, please remove grpc or protobuf extension');
}
}
}

View File

@@ -6,16 +6,12 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('rar')]
class rar extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeBuildconf(): bool
{
// workaround for newer Xcode clang (>= 15.0)

View File

@@ -5,16 +5,12 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('readline')]
class readline extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeConfigure(): bool
{
FileSystem::replaceFileRegex(

View File

@@ -16,9 +16,11 @@ class redis extends Extension
if ($this->isBuildStatic()) {
$arg .= $this->builder->getExt('session')?->isBuildStatic() ? ' --enable-redis-session' : ' --disable-redis-session';
$arg .= $this->builder->getExt('igbinary')?->isBuildStatic() ? ' --enable-redis-igbinary' : ' --disable-redis-igbinary';
$arg .= $this->builder->getExt('msgpack')?->isBuildStatic() ? ' --enable-redis-msgpack' : ' --disable-redis-msgpack';
} else {
$arg .= $this->builder->getExt('session') ? ' --enable-redis-session' : ' --disable-redis-session';
$arg .= $this->builder->getExt('igbinary') ? ' --enable-redis-igbinary' : ' --disable-redis-igbinary';
$arg .= $this->builder->getExt('msgpack') ? ' --enable-redis-msgpack' : ' --disable-redis-msgpack';
}
if ($this->builder->getLib('zstd')) {
$arg .= ' --enable-redis-zstd --with-libzstd="' . BUILD_ROOT_PATH . '"';

View File

@@ -6,16 +6,12 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('snappy')]
class snappy extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeConfigure(): bool
{
FileSystem::replaceFileRegex(

View File

@@ -24,7 +24,7 @@ class sqlsrv extends Extension
return false;
}
public function patchBeforeConfigure(): bool
public function patchBeforeWindowsConfigure(): bool
{
if ($this->pdo_sqlsrv_patched) {
// revert pdo_sqlsrv patch

View File

@@ -5,16 +5,12 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('ssh2')]
class ssh2 extends Extension
{
/**
* @throws FileSystemException
*/
public function patchBeforeConfigure(): bool
{
FileSystem::replaceFileRegex(

View File

@@ -8,6 +8,8 @@ use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget;
#[CustomExt('swoole')]
class swoole extends Extension
@@ -43,32 +45,40 @@ class swoole extends Extension
public function getUnixConfigureArg(bool $shared = false): string
{
// enable swoole
$arg = '--enable-swoole';
$arg = '--enable-swoole' . ($shared ? '=shared' : '');
// commonly-used feature: coroutine-time, disable-thread-context
$arg .= ' --enable-swoole-coro-time --disable-thread-context';
// commonly used feature: coroutine-time
$arg .= ' --enable-swoole-coro-time --with-pic';
// required feature: curl, openssl (but curl hook is buggy for php 8.0)
$arg .= $this->builder->getOption('enable-zts') ? ' --enable-swoole-thread --disable-thread-context' : ' --disable-swoole-thread --enable-thread-context';
// required features: curl, openssl (but curl hook is buggy for php 8.0)
$arg .= $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl';
$arg .= ' --enable-openssl';
// additional feature: c-ares, brotli, nghttp2 (can be disabled, but we enable it by default in config to support full network feature)
// additional features that only require libraries
$arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : '';
if (!$shared) {
$arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
}
$arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
$arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : '';
$arg .= $this->builder->getLib('zstd') ? ' --enable-zstd' : '';
$arg .= $this->builder->getLib('liburing') ? ' --enable-iouring' : '';
$arg .= $this->builder->getExt('sockets') ? ' --enable-sockets' : '';
// additional feature: swoole-pgsql, it should depend on lib [postgresql], but it will lack of CFLAGS etc.
// so this is a tricky way (enable ext [pgsql,pdo] to add postgresql hook and pdo_pgsql support)
$arg .= $this->builder->getExt('swoole-hook-pgsql') ? '' : ' --disable-swoole-pgsql';
// enable additional features that require the pdo extension, but conflict with pdo_* extensions
// to make sure everything works as it should, this is done in fake addon extensions
$arg .= $this->builder->getExt('swoole-hook-pgsql') ? ' --enable-swoole-pgsql' : ' --disable-swoole-pgsql';
$arg .= $this->builder->getExt('swoole-hook-mysql') ? ' --enable-mysqlnd' : ' --disable-mysqlnd';
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? ' --enable-swoole-sqlite' : ' --disable-swoole-sqlite';
// enable this feature , need remove pdo_sqlite
// more info : https://wenda.swoole.com/detail/109023
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? '' : ' --disable-swoole-sqlite';
if ($this->builder->getExt('swoole-hook-odbc')) {
$config = (new SPCConfigUtil($this->builder, ['libs_only_deps' => true]))->config([], ['unixodbc']);
$arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"';
}
if (SPCTarget::getTargetOS() === 'Darwin') {
$arg .= ' ac_cv_lib_pthread_pthread_barrier_init=no';
}
// enable this feature , need stop pdo_*
// $arg .= $this->builder->getLib('unixodbc') ? ' --with-swoole-odbc=unixODBC,' : ' ';
return $arg;
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\ValidationException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-mysql')]
@@ -16,26 +16,15 @@ class swoole_hook_mysql extends Extension
return 'swoole';
}
public function getUnixConfigureArg(bool $shared = false): string
{
// pdo_mysql doesn't need to be disabled
// enable swoole-hook-mysql will enable mysqli, pdo, pdo_mysql, we don't need to add any additional options
return '';
}
public function runCliCheckUnix(): void
{
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $this->getSharedExtensionLoadString() . ' --ri "swoole"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: 'extension swoole_hook_mysql sanity check');
}
if (!str_contains($out, 'mysqlnd')) {
throw new RuntimeException('swoole mysql hook is not enabled correctly.');
throw new ValidationException('swoole mysql hook is not enabled correctly.', validation_module: 'Extension swoole mysql hook availability check');
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-odbc')]
class swoole_hook_odbc extends Extension
{
public function getDistName(): string
{
return 'swoole';
}
public function validate(): void
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_odbc')?->isBuildStatic()) {
throw new WrongUsageException('swoole-hook-odbc provides pdo_odbc, if you enable odbc hook for swoole, you must remove pdo_odbc extension.');
}
}
public function runCliCheckUnix(): void
{
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");
}
if (!str_contains($out, 'coroutine_odbc')) {
throw new ValidationException('swoole odbc hook is not enabled correctly.', validation_module: 'Extension swoole odbc hook availability check');
}
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
@@ -20,31 +20,27 @@ class swoole_hook_pgsql extends Extension
public function validate(): void
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_pgsql') !== null) {
if ($this->builder->getExt('pdo_pgsql')?->isBuildStatic()) {
throw new WrongUsageException('swoole-hook-pgsql provides pdo_pgsql, if you enable pgsql hook for swoole, you must remove pdo_pgsql extension.');
}
}
public function getUnixConfigureArg(bool $shared = false): string
{
// enable swoole pgsql hook
return '--enable-swoole-pgsql';
}
public function runCliCheckUnix(): void
{
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
throw new ValidationException(
"extension {$this->getName()} failed sanity check: php-cli returned {$ret}",
validation_module: 'Extension swoole-hook-pgsql sanity check'
);
}
if (!str_contains($out, 'coroutine_pgsql')) {
throw new RuntimeException('swoole pgsql hook is not enabled correctly.');
throw new ValidationException(
'swoole pgsql hook is not enabled correctly.',
validation_module: 'Extension swoole pgsql hook availability check'
);
}
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
@@ -20,31 +20,21 @@ class swoole_hook_sqlite extends Extension
public function validate(): void
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_sqlite') !== null) {
if ($this->builder->getExt('pdo_sqlite')?->isBuildStatic()) {
throw new WrongUsageException('swoole-hook-sqlite provides pdo_sqlite, if you enable sqlite hook for swoole, you must remove pdo_sqlite extension.');
}
}
public function getUnixConfigureArg(bool $shared = false): string
{
// enable swoole pgsql hook
return '--enable-swoole-sqlite';
}
public function runCliCheckUnix(): void
{
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");
}
if (!str_contains($out, 'coroutine_sqlite')) {
throw new RuntimeException('swoole sqlite hook is not enabled correctly.');
throw new ValidationException('swoole sqlite hook is not enabled correctly.', validation_module: 'Extension swoole sqlite hook availability check');
}
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\ValidationException;
use SPC\util\CustomExt;
#[CustomExt('swow')]
@@ -14,7 +14,7 @@ class swow extends Extension
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
throw new RuntimeException('The latest swow extension requires PHP 8.0 or later');
throw new ValidationException('The latest swow extension requires PHP 8.0 or later');
}
}
@@ -26,9 +26,6 @@ class swow extends Extension
return $arg;
}
/**
* @throws RuntimeException
*/
public function patchBeforeBuildconf(): bool
{
if ($this->builder->getPHPVersionID() >= 80000 && !is_link(SOURCE_PATH . '/php-src/ext/swow')) {

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\ValidationException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
@@ -14,7 +15,7 @@ class uv extends Extension
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
throw new \RuntimeException('The latest uv extension requires PHP 8.0 or later');
throw new ValidationException('The latest uv extension requires PHP 8.0 or later');
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\SPCInternalException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
@@ -16,9 +16,6 @@ use SPC\util\CustomExt;
#[CustomExt('simplexml')]
class xml extends Extension
{
/**
* @throws RuntimeException
*/
public function getUnixConfigureArg(bool $shared = false): string
{
$arg = match ($this->name) {
@@ -27,7 +24,7 @@ class xml extends Extension
'xmlreader' => '--enable-xmlreader',
'xmlwriter' => '--enable-xmlwriter',
'simplexml' => '--enable-simplexml',
default => throw new RuntimeException('Not accept non-xml extension'),
default => throw new SPCInternalException('Not accept non-xml extension'),
};
$arg .= ($shared ? '=shared' : '') . ' --with-libxml="' . BUILD_ROOT_PATH . '"';
return $arg;
@@ -47,7 +44,7 @@ class xml extends Extension
'xmlreader' => '--enable-xmlreader',
'xmlwriter' => '--enable-xmlwriter',
'simplexml' => '--with-simplexml',
default => throw new RuntimeException('Not accept non-xml extension'),
default => throw new SPCInternalException('Not accept non-xml extension'),
};
$arg .= ' --with-libxml';
return $arg;

View File

@@ -5,8 +5,6 @@ declare(strict_types=1);
namespace SPC\builder\freebsd;
use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
@@ -16,11 +14,6 @@ class BSDBuilder extends UnixBuilderBase
/** @var bool Micro patch phar flag */
private bool $phar_patched = false;
/**
* @throws RuntimeException
* @throws WrongUsageException
* @throws FileSystemException
*/
public function __construct(array $options = [])
{
$this->options = $options;
@@ -32,10 +25,6 @@ class BSDBuilder extends UnixBuilderBase
f_putenv('CXX=' . $this->getOption('cxx', 'clang++'));
// set PATH
f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
// set PKG_CONFIG
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
// set PKG_CONFIG_PATH
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig/');
// set arch (default: current)
$this->setOptionIfNotExist('arch', php_uname('m'));
@@ -56,10 +45,7 @@ class BSDBuilder extends UnixBuilderBase
/**
* Just start to build statically linked php binary
*
* @param int $build_target build target
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
* @param int $build_target build target
*/
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
{
@@ -132,6 +118,11 @@ class BSDBuilder extends UnixBuilderBase
}
$this->buildEmbed();
}
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...');
$this->buildSharedExts();
}
if ($enableFrankenphp) {
logger()->info('building frankenphp');
$this->buildFrankenphp();
@@ -148,9 +139,6 @@ class BSDBuilder extends UnixBuilderBase
/**
* Build cli sapi
*
* @throws RuntimeException
* @throws FileSystemException
*/
protected function buildCli(): void
{
@@ -170,10 +158,6 @@ class BSDBuilder extends UnixBuilderBase
/**
* Build phpmicro sapi
*
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function buildMicro(): void
{
@@ -209,9 +193,6 @@ class BSDBuilder extends UnixBuilderBase
/**
* Build fpm sapi
*
* @throws RuntimeException
* @throws FileSystemException
*/
protected function buildFpm(): void
{
@@ -230,8 +211,6 @@ class BSDBuilder extends UnixBuilderBase
/**
* Build embed sapi
*
* @throws RuntimeException
*/
protected function buildEmbed(): void
{

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\freebsd;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\exception\RuntimeException;
use SPC\exception\EnvironmentException;
use SPC\exception\WrongUsageException;
class SystemUtil
@@ -15,14 +15,15 @@ class SystemUtil
/**
* Get Logic CPU Count for macOS
*
* @throws RuntimeException
*/
public static function getCpuCount(): int
{
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu');
if ($ret !== 0) {
throw new RuntimeException('Failed to get cpu count');
throw new EnvironmentException(
'Failed to get cpu count from FreeBSD sysctl',
'Please ensure you are running this command on a FreeBSD system and have the sysctl command available.'
);
}
return (int) $output[0];
@@ -31,9 +32,8 @@ class SystemUtil
/**
* Get Target Arch CFlags
*
* @param string $arch Arch Name
* @return string return Arch CFlags string
* @throws WrongUsageException
* @param string $arch Arch Name
* @return string return Arch CFlags string
*/
public static function getArchCFlags(string $arch): string
{

View File

@@ -22,19 +22,11 @@ declare(strict_types=1);
namespace SPC\builder\freebsd\library;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
class openssl extends BSDLibraryBase
{
public const NAME = 'openssl';
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function build(): void
{
[$lib,,$destdir] = SEPARATED_PATH;

View File

@@ -5,8 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\linux;
use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\PatchException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
@@ -19,10 +18,6 @@ class LinuxBuilder extends UnixBuilderBase
/** @var bool Micro patch phar flag */
private bool $phar_patched = false;
/**
* @throws FileSystemException
* @throws WrongUsageException
*/
public function __construct(array $options = [])
{
$this->options = $options;
@@ -45,10 +40,7 @@ class LinuxBuilder extends UnixBuilderBase
/**
* Build PHP from source.
*
* @param int $build_target Build target, use `BUILD_TARGET_*` constants
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
* @param int $build_target Build target, use `BUILD_TARGET_*` constants
*/
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
{
@@ -66,6 +58,14 @@ class LinuxBuilder extends UnixBuilderBase
$phpVersionID = $this->getPHPVersionID();
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
$opcache_jit = !$this->getOption('disable-opcache-jit', false);
if ($opcache_jit && ($phpVersionID >= 80500 || $this->getExt('opcache'))) {
// php 8.5 contains opcache extension by default,
// if opcache_jit is enabled for 8.5 or opcache enabled,
// we need to disable undefined behavior sanitizer.
f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined');
}
if ($this->getOption('enable-zts', false)) {
$maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : '';
$zts = '--enable-zts --disable-zend-signals ';
@@ -73,10 +73,7 @@ class LinuxBuilder extends UnixBuilderBase
$maxExecutionTimers = '';
$zts = '';
}
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
if (!$disable_jit && $this->getExt('opcache')) {
f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined');
}
$config_file_path = $this->getOption('with-config-file-path', false) ?
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
@@ -87,11 +84,13 @@ class LinuxBuilder extends UnixBuilderBase
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
$enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP;
$enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI;
// prepare build php envs
// $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__';
$php_configure_env = SystemUtil::makeEnvVarString([
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'),
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag,
'LDFLAGS' => '-L' . BUILD_LIB_PATH,
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
]);
@@ -104,22 +103,21 @@ class LinuxBuilder extends UnixBuilderBase
);
}
shell()->cd(SOURCE_PATH . '/php-src')
->exec(
$php_configure_env . ' ' .
$this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec(
$php_configure_env . ' ' .
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
($enableCli ? '--enable-cli ' : '--disable-cli ') .
($enableFpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') .
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
($enableCgi ? '--enable-cgi ' : '--disable-cgi ') .
$config_file_path .
$config_file_scan_dir .
$disable_jit .
$json_74 .
$zts .
$maxExecutionTimers .
$this->makeStaticExtensionArgs() . ' '
);
));
$this->emitPatchPoint('before-php-make');
SourcePatcher::patchBeforeMake($this);
@@ -134,6 +132,10 @@ class LinuxBuilder extends UnixBuilderBase
logger()->info('building fpm');
$this->buildFpm();
}
if ($enableCgi) {
logger()->info('building cgi');
$this->buildCgi();
}
if ($enableMicro) {
logger()->info('building micro');
$this->buildMicro();
@@ -149,6 +151,11 @@ class LinuxBuilder extends UnixBuilderBase
logger()->info('building frankenphp');
$this->buildFrankenphp();
}
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...');
$this->buildSharedExts();
}
}
public function testPHP(int $build_target = BUILD_TARGET_NONE)
@@ -159,9 +166,6 @@ class LinuxBuilder extends UnixBuilderBase
/**
* Build cli sapi
*
* @throws RuntimeException
* @throws FileSystemException
*/
protected function buildCli(): void
{
@@ -182,12 +186,27 @@ class LinuxBuilder extends UnixBuilderBase
$this->deployBinary(BUILD_TARGET_CLI);
}
protected function buildCgi(): void
{
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cgi");
if (!$this->getOption('no-strip', false)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')->exec('strip --strip-unneeded php-cgi');
}
if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')
->exec(getenv('UPX_EXEC') . ' --best php-cgi');
}
$this->deployBinary(BUILD_TARGET_CGI);
}
/**
* Build phpmicro sapi
*
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function buildMicro(): void
{
@@ -222,9 +241,6 @@ class LinuxBuilder extends UnixBuilderBase
/**
* Build fpm sapi
*
* @throws FileSystemException
* @throws RuntimeException
*/
protected function buildFpm(): void
{
@@ -246,8 +262,6 @@ class LinuxBuilder extends UnixBuilderBase
/**
* Build embed sapi
*
* @throws RuntimeException
*/
protected function buildEmbed(): void
{
@@ -311,7 +325,7 @@ class LinuxBuilder extends UnixBuilderBase
$target = "{$libDir}/{$realLibName}";
if (file_exists($target)) {
[, $output] = shell()->execWithResult('readelf -d ' . escapeshellarg($target));
$output = join("\n", $output);
$output = implode("\n", $output);
if (preg_match('/SONAME.*\[(.+)]/', $output, $sonameMatch)) {
$currentSoname = $sonameMatch[1];
if ($currentSoname !== basename($target)) {
@@ -327,6 +341,8 @@ class LinuxBuilder extends UnixBuilderBase
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar';
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');
// export dynamic symbols
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
}
if (!$this->getOption('no-strip', false) && file_exists(BUILD_LIB_PATH . '/' . $realLibName)) {
@@ -335,6 +351,9 @@ class LinuxBuilder extends UnixBuilderBase
$this->patchPhpScripts();
}
/**
* Return extra variables for php make command.
*/
private function getMakeExtraVars(): array
{
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
@@ -352,8 +371,6 @@ class LinuxBuilder extends UnixBuilderBase
* Strip micro.sfx for Linux.
* The micro.sfx does not support UPX directly, but we can remove UPX-info segment to adapt.
* This will also make micro.sfx with upx-packed more like a malware fore antivirus :(
*
* @throws RuntimeException
*/
private function processMicroUPX(): void
{
@@ -368,7 +385,7 @@ class LinuxBuilder extends UnixBuilderBase
$out[1] = explode(' ', $out[1]);
$offset = $out[1][0];
if ($ret !== 0 || !str_starts_with($offset, '0x')) {
throw new RuntimeException('Cannot find offset in readelf output');
throw new PatchException('phpmicro UPX patcher', 'Cannot find offset in readelf output');
}
$offset = hexdec($offset);
// remove upx extra wastes

View File

@@ -4,8 +4,6 @@ declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\SPCTarget;
@@ -13,9 +11,6 @@ class imap extends LinuxLibraryBase
{
public const NAME = 'imap';
/**
* @throws FileSystemException
*/
public function patchBeforeBuild(): bool
{
$cc = getenv('CC') ?: 'gcc';
@@ -44,9 +39,6 @@ class imap extends LinuxLibraryBase
return false;
}
/**
* @throws RuntimeException
*/
protected function build(): void
{
if ($this->builder->getLib('openssl')) {

View File

@@ -4,18 +4,12 @@ declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
class libffi extends LinuxLibraryBase
{
public const NAME = 'libffi';
/**
* @throws RuntimeException
* @throws FileSystemException
*/
public function build(): void
{
UnixAutoconfExecutor::create($this)

View File

@@ -21,20 +21,12 @@ declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
class libpng extends LinuxLibraryBase
{
public const NAME = 'libpng';
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function build(): void
{
UnixAutoconfExecutor::create($this)

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\builder\linux\SystemUtil;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
use SPC\util\SPCTarget;
class liburing extends LinuxLibraryBase
{
public const NAME = 'liburing';
public function patchBeforeBuild(): bool
{
if (!SystemUtil::isMuslDist()) {
return false;
}
FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath');
return true;
}
protected function build(): void
{
$use_libc = SPCTarget::getLibc() !== 'glibc' || version_compare(SPCTarget::getLibcVersion(), '2.30', '>=');
$make = UnixAutoconfExecutor::create($this);
if (!$use_libc) {
$make->appendEnv([
'CC' => 'gcc', // libc-less version fails to compile with clang or zig
'CXX' => 'g++',
'AR' => 'ar',
'LD' => 'ld',
]);
} else {
$make->appendEnv([
'CFLAGS' => '-D_GNU_SOURCE',
]);
}
$make
->removeConfigureArgs(
'--disable-shared',
'--enable-static',
'--with-pic',
'--enable-pic',
)
->addConfigureArgs(
$use_libc ? '--use-libc' : '',
)
->configure()
->make('library', 'install ENABLE_SHARED=0', with_clean: false);
$this->patchPkgconfPrefix();
}
}

View File

@@ -21,24 +21,16 @@ declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
class openssl extends LinuxLibraryBase
{
use \SPC\builder\traits\openssl;
public const NAME = 'openssl';
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function build(): void
{
[,,$destdir] = SEPARATED_PATH;
$extra = '';
$ex_lib = '-ldl -pthread';
$arch = getenv('SPC_ARCH');

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
/**
* a template library class for unix
*/
class re2c extends LinuxLibraryBase
{
use \SPC\builder\unix\library\re2c;
public const NAME = 're2c';
}

View File

@@ -6,8 +6,6 @@ namespace SPC\builder\macos;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
@@ -19,11 +17,6 @@ class MacOSBuilder extends UnixBuilderBase
/** @var bool Micro patch phar flag */
private bool $phar_patched = false;
/**
* @throws RuntimeException
* @throws WrongUsageException
* @throws FileSystemException
*/
public function __construct(array $options = [])
{
$this->options = $options;
@@ -48,9 +41,7 @@ class MacOSBuilder extends UnixBuilderBase
/**
* Get dynamically linked macOS frameworks
*
* @param bool $asString If true, return as string
* @throws FileSystemException
* @throws WrongUsageException
* @param bool $asString If true, return as string
*/
public function getFrameworks(bool $asString = false): array|string
{
@@ -83,10 +74,7 @@ class MacOSBuilder extends UnixBuilderBase
/**
* Just start to build statically linked php binary
*
* @param int $build_target build target
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
* @param int $build_target build target
*/
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
{
@@ -98,7 +86,8 @@ class MacOSBuilder extends UnixBuilderBase
$this->emitPatchPoint('before-php-configure');
SourcePatcher::patchBeforeConfigure($this);
$json_74 = $this->getPHPVersionID() < 80000 ? '--enable-json ' : '';
$phpVersionID = $this->getPHPVersionID();
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
$config_file_path = $this->getOption('with-config-file-path', false) ?
@@ -111,6 +100,7 @@ class MacOSBuilder extends UnixBuilderBase
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
$enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP;
$enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI;
// prepare build php envs
$envs_build_php = SystemUtil::makeEnvVarString([
@@ -128,20 +118,20 @@ class MacOSBuilder extends UnixBuilderBase
}
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
shell()->cd(SOURCE_PATH . '/php-src')
->exec(
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
$this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec(
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
($enableCli ? '--enable-cli ' : '--disable-cli ') .
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
($enableCgi ? '--enable-cgi ' : '--disable-cgi ') .
$config_file_path .
$config_file_scan_dir .
$json_74 .
$zts .
$this->makeStaticExtensionArgs() . ' ' .
$envs_build_php
);
));
$this->emitPatchPoint('before-php-make');
SourcePatcher::patchBeforeMake($this);
@@ -156,6 +146,10 @@ class MacOSBuilder extends UnixBuilderBase
logger()->info('building fpm');
$this->buildFpm();
}
if ($enableCgi) {
logger()->info('building cgi');
$this->buildCgi();
}
if ($enableMicro) {
logger()->info('building micro');
$this->buildMicro();
@@ -171,6 +165,11 @@ class MacOSBuilder extends UnixBuilderBase
logger()->info('building frankenphp');
$this->buildFrankenphp();
}
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...');
$this->buildSharedExts();
}
}
public function testPHP(int $build_target = BUILD_TARGET_NONE)
@@ -181,9 +180,6 @@ class MacOSBuilder extends UnixBuilderBase
/**
* Build cli sapi
*
* @throws RuntimeException
* @throws FileSystemException
*/
protected function buildCli(): void
{
@@ -198,12 +194,21 @@ class MacOSBuilder extends UnixBuilderBase
$this->deployBinary(BUILD_TARGET_CLI);
}
protected function buildCgi(): void
{
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$shell = shell()->cd(SOURCE_PATH . '/php-src');
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
$shell->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cgi");
if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/cgi/php-cgi')->exec('strip -S sapi/cgi/php-cgi');
}
$this->deployBinary(BUILD_TARGET_CGI);
}
/**
* Build phpmicro sapi
*
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function buildMicro(): void
{
@@ -239,9 +244,6 @@ class MacOSBuilder extends UnixBuilderBase
/**
* Build fpm sapi
*
* @throws RuntimeException
* @throws FileSystemException
*/
protected function buildFpm(): void
{
@@ -257,8 +259,6 @@ class MacOSBuilder extends UnixBuilderBase
/**
* Build embed sapi
*
* @throws RuntimeException
*/
protected function buildEmbed(): void
{
@@ -270,6 +270,8 @@ class MacOSBuilder extends UnixBuilderBase
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar';
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');
// export dynamic symbols
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
}
$this->patchPhpScripts();
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\macos;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\exception\RuntimeException;
use SPC\exception\EnvironmentException;
use SPC\exception\WrongUsageException;
class SystemUtil
@@ -15,25 +15,25 @@ class SystemUtil
/**
* Get Logic CPU Count for macOS
*
* @throws RuntimeException
*/
public static function getCpuCount(): int
{
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu', false);
$cpu = exec('sysctl -n hw.ncpu', $output, $ret);
if ($ret !== 0) {
throw new RuntimeException('Failed to get cpu count');
throw new EnvironmentException(
'Failed to get cpu count from macOS sysctl',
'Please ensure you are running this command on a macOS system and have the sysctl command available.'
);
}
return (int) $output[0];
return (int) $cpu;
}
/**
* Get Target Arch CFlags
*
* @param string $arch Arch Name
* @return string return Arch CFlags string
* @throws WrongUsageException
* @param string $arch Arch Name
* @return string return Arch CFlags string
*/
public static function getArchCFlags(string $arch): string
{

View File

@@ -8,8 +8,6 @@ use SPC\builder\BuilderBase;
use SPC\builder\LibraryBase;
use SPC\builder\macos\MacOSBuilder;
use SPC\builder\traits\UnixLibraryTrait;
use SPC\exception\FileSystemException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
abstract class MacOSLibraryBase extends LibraryBase
@@ -28,10 +26,6 @@ abstract class MacOSLibraryBase extends LibraryBase
return $this->builder;
}
/**
* @throws WrongUsageException
* @throws FileSystemException
*/
public function getFrameworks(): array
{
return Config::getLib(static::NAME, 'frameworks', []);

View File

@@ -21,7 +21,6 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem;
class curl extends MacOSLibraryBase
@@ -30,9 +29,6 @@ class curl extends MacOSLibraryBase
public const NAME = 'curl';
/**
* @throws FileSystemException
*/
public function patchBeforeBuild(): bool
{
FileSystem::replaceFileRegex(

View File

@@ -4,18 +4,12 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixCMakeExecutor;
class glfw extends MacOSLibraryBase
{
public const NAME = 'glfw';
/**
* @throws FileSystemException
* @throws RuntimeException
*/
protected function build(): void
{
UnixCMakeExecutor::create($this)

View File

@@ -4,8 +4,6 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\store\SourcePatcher;
@@ -13,10 +11,6 @@ class imap extends MacOSLibraryBase
{
public const NAME = 'imap';
/**
* @throws FileSystemException
* @throws RuntimeException
*/
public function patchBeforeBuild(): bool
{
$cc = getenv('CC') ?: 'clang';
@@ -37,9 +31,6 @@ class imap extends MacOSLibraryBase
return true;
}
/**
* @throws RuntimeException
*/
protected function build(): void
{
if ($this->builder->getLib('openssl')) {

View File

@@ -4,18 +4,12 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
class libffi extends MacOSLibraryBase
{
public const NAME = 'libffi';
/**
* @throws RuntimeException
* @throws FileSystemException
*/
protected function build(): void
{
$arch = getenv('SPC_ARCH');

View File

@@ -21,20 +21,12 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\executor\UnixAutoconfExecutor;
class libpng extends MacOSLibraryBase
{
public const NAME = 'libpng';
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function build(): void
{
$arch = arch2gnu(php_uname('m'));

View File

@@ -21,20 +21,14 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
class openssl extends MacOSLibraryBase
{
use \SPC\builder\traits\openssl;
public const NAME = 'openssl';
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function build(): void
{
// lib:zlib

View File

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

View File

@@ -4,20 +4,13 @@ declare(strict_types=1);
namespace SPC\builder\traits;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\exception\PatchException;
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\util\SPCConfigUtil;
trait UnixLibraryTrait
{
/**
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
*/
public function getStaticLibFiles(bool $include_self = true): string
{
$libs = $include_self ? [$this] : [];
@@ -28,11 +21,11 @@ trait UnixLibraryTrait
}
/**
* Patch pkgconfig file prefix
* Patch pkgconfig file prefix, exec_prefix, libdir, includedir for correct build.
*
* @param array $files file list
* @throws FileSystemException
* @throws RuntimeException
* @param array $files File list to patch, if empty, will use pkg-configs from config (e.g. ['zlib.pc', 'openssl.pc'])
* @param int $patch_option Patch options
* @param null|array $custom_replace Custom replace rules, if provided, will be used to replace in the format [regex, replacement]
*/
public function patchPkgconfPrefix(array $files = [], int $patch_option = PKGCONF_PATCH_ALL, ?array $custom_replace = null): void
{
@@ -43,7 +36,7 @@ trait UnixLibraryTrait
foreach ($files as $name) {
$realpath = realpath(BUILD_ROOT_PATH . '/lib/pkgconfig/' . $name);
if ($realpath === false) {
throw new RuntimeException('Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] !');
throw new PatchException('pkg-config prefix patcher', 'Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] in ' . BUILD_LIB_PATH . '/pkgconfig/ !');
}
logger()->debug('Patching ' . $realpath);
// replace prefix
@@ -70,7 +63,7 @@ trait UnixLibraryTrait
$realpath = realpath(BUILD_LIB_PATH . '/' . $name);
if ($realpath === false) {
if ($throwOnMissing) {
throw new RuntimeException('Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
throw new PatchException('la dependency patcher', 'Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
}
logger()->warning('Cannot find library [' . static::NAME . '] la file [' . $name . '] !');
continue;

View File

@@ -4,21 +4,101 @@ declare(strict_types=1);
namespace SPC\builder\traits;
/**
* Unix 系统的工具函数 Trait适用于 Linux、macOS
*/
use SPC\exception\ExecutionException;
use SPC\exception\SPCInternalException;
use SPC\exception\WrongUsageException;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\SPCTarget;
trait UnixSystemUtilTrait
{
/**
* @param string $name 命令名称
* @param array $paths 寻找的目标路径(如果不传入,则使用环境变量 PATH
* @return null|string 找到了返回命令路径,找不到返回 null
* Export static library dynamic symbols to a .dynsym file.
* It will export to "/path/to/libxxx.a.dynsym".
*
* @param string $lib_file Static library file path (e.g. /path/to/libxxx.a)
*/
public static function exportDynamicSymbols(string $lib_file): void
{
// check
if (!is_file($lib_file)) {
throw new WrongUsageException("The lib archive file {$lib_file} does not exist, please build it first.");
}
// shell out
$cmd = 'nm -g --defined-only -P ' . escapeshellarg($lib_file);
$result = shell()->execWithResult($cmd);
if ($result[0] !== 0) {
throw new ExecutionException($cmd, 'Failed to get defined symbols from ' . $lib_file);
}
// parse shell output and filter
$defined = [];
foreach ($result[1] as $line) {
$line = trim($line);
if ($line === '' || str_ends_with($line, '.o:') || str_ends_with($line, '.o]:')) {
continue;
}
$name = strtok($line, " \t");
if (!$name) {
continue;
}
$name = preg_replace('/@.*$/', '', $name);
if ($name !== '' && $name !== false) {
$defined[] = $name;
}
}
$defined = array_unique($defined);
sort($defined);
// export
if (SPCTarget::getTargetOS() === 'Linux') {
file_put_contents("{$lib_file}.dynsym", "{\n" . implode("\n", array_map(fn ($x) => " {$x};", $defined)) . "};\n");
} else {
file_put_contents("{$lib_file}.dynsym", implode("\n", $defined) . "\n");
}
}
/**
* Get linker flag to export dynamic symbols from a static library.
*
* @param string $lib_file Static library file path (e.g. /path/to/libxxx.a)
* @return null|string Linker flag to export dynamic symbols, null if no .dynsym file found
*/
public static function getDynamicExportedSymbols(string $lib_file): ?string
{
$symbol_file = "{$lib_file}.dynsym";
if (!is_file($symbol_file)) {
self::exportDynamicSymbols($lib_file);
}
if (!is_file($symbol_file)) {
throw new SPCInternalException("The symbol file {$symbol_file} does not exist, please check if nm command is available.");
}
// https://github.com/ziglang/zig/issues/24662
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
return '-Wl,--export-dynamic';
}
// macOS
if (SPCTarget::getTargetOS() !== 'Linux') {
return "-Wl,-exported_symbols_list,{$symbol_file}";
}
return "-Wl,--dynamic-list={$symbol_file}";
}
/**
* Find a command in given paths or system PATH.
* If $name is an absolute path, check if it exists.
*
* @param string $name Command name or absolute path
* @param array $paths Paths to search, if empty, use system PATH
* @return null|string Absolute path of the command if found, null otherwise
*/
public static function findCommand(string $name, array $paths = []): ?string
{
if (!$paths) {
$paths = explode(PATH_SEPARATOR, getenv('PATH'));
}
if (str_starts_with($name, '/')) {
return file_exists($name) ? $name : null;
}
foreach ($paths as $path) {
if (file_exists($path . DIRECTORY_SEPARATOR . $name)) {
return $path . DIRECTORY_SEPARATOR . $name;
@@ -28,6 +108,8 @@ trait UnixSystemUtilTrait
}
/**
* Make environment variable string for shell command.
*
* @param array $vars Variables, like: ["CFLAGS" => "-Ixxx"]
* @return string like: CFLAGS="-Ixxx"
*/

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace SPC\builder\traits;
use SPC\exception\SPCException;
use SPC\store\FileSystem;
use SPC\util\PkgConfigUtil;
trait openssl
{
public function getLibVersion(): ?string
{
// get openssl version from source directory
if (file_exists("{$this->source_dir}/VERSION.dat")) {
// parse as INI
$version = parse_ini_file("{$this->source_dir}/VERSION.dat");
if ($version !== false) {
return "{$version['MAJOR']}.{$version['MINOR']}.{$version['PATCH']}";
}
}
// get openssl version from pkg-config
if (PHP_OS_FAMILY !== 'Windows') {
try {
return PkgConfigUtil::getModuleVersion('openssl');
} catch (SPCException) {
}
}
// get openssl version from header openssl/opensslv.h
if (file_exists(BUILD_INCLUDE_PATH . '/openssl/opensslv.h')) {
if (preg_match('/OPENSSL_VERSION_STR "(.*)"/', FileSystem::readFile(BUILD_INCLUDE_PATH . '/openssl/opensslv.h'), $match)) {
return $match[1];
}
}
return null;
}
}

View File

@@ -5,14 +5,16 @@ declare(strict_types=1);
namespace SPC\builder\unix;
use SPC\builder\BuilderBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
use SPC\exception\SPCException;
use SPC\exception\SPCInternalException;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\CurlHook;
use SPC\store\Downloader;
use SPC\store\FileSystem;
use SPC\store\pkg\GoXcaddy;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\util\DependencyUtil;
use SPC\util\GlobalEnvManager;
use SPC\util\SPCConfigUtil;
@@ -56,7 +58,14 @@ abstract class UnixBuilderBase extends BuilderBase
}
// if some libs are not supported (but in config "lib.json", throw exception)
if (!isset($support_lib_list[$library])) {
throw new WrongUsageException('library [' . $library . '] is in the lib.json list but not supported to compile, but in the future I will support it!');
$os = match (PHP_OS_FAMILY) {
'Linux' => 'Linux',
'Darwin' => 'macOS',
'Windows' => 'Windows',
'BSD' => 'FreeBSD',
default => PHP_OS_FAMILY,
};
throw new WrongUsageException("library [{$library}] is in the lib.json list but not supported to build on {$os}.");
}
$lib = new ($support_lib_list[$library])($this);
$this->addLib($lib);
@@ -70,9 +79,7 @@ abstract class UnixBuilderBase extends BuilderBase
}
/**
* Sanity check after build complete
*
* @throws RuntimeException
* Sanity check after build complete.
*/
protected function sanityCheck(int $build_target): void
{
@@ -82,7 +89,7 @@ abstract class UnixBuilderBase extends BuilderBase
[$ret, $output] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n -r "echo \"hello\";"');
$raw_output = implode('', $output);
if ($ret !== 0 || trim($raw_output) !== 'hello') {
throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]");
throw new ValidationException("cli failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cli sanity check');
}
foreach ($this->getExts() as $ext) {
@@ -105,12 +112,25 @@ abstract class UnixBuilderBase extends BuilderBase
foreach ($task['conditions'] as $condition => $closure) {
if (!$closure($ret, $out)) {
$raw_out = trim(implode('', $out));
throw new RuntimeException("micro failed sanity check: {$task_name}, condition [{$condition}], ret[{$ret}], out[{$raw_out}]");
throw new ValidationException(
"failure info: {$condition}, code: {$ret}, output: {$raw_out}",
validation_module: "phpmicro sanity check item [{$task_name}]"
);
}
}
}
}
// sanity check for php-cgi
if (($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) {
logger()->info('running cgi sanity check');
[$ret, $output] = shell()->execWithResult("echo '<?php echo \"<h1>Hello, World!</h1>\";' | " . BUILD_BIN_PATH . '/php-cgi -n');
$raw_output = implode('', $output);
if ($ret !== 0 || !str_contains($raw_output, 'Hello, World!') || !str_contains($raw_output, 'text/html')) {
throw new ValidationException("cgi failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cgi sanity check');
}
}
// sanity check for embed
if (($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) {
logger()->info('running embed sanity check');
@@ -127,6 +147,7 @@ abstract class UnixBuilderBase extends BuilderBase
if (SPCTarget::isStatic()) {
$lens .= ' -static';
}
$dynamic_exports = '';
// if someone changed to EMBED_TYPE=shared, we need to add LD_LIBRARY_PATH
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
if (PHP_OS_FAMILY === 'Darwin') {
@@ -141,14 +162,25 @@ abstract class UnixBuilderBase extends BuilderBase
foreach (glob(BUILD_LIB_PATH . "/libphp*.{$suffix}") as $file) {
unlink($file);
}
// calling linux system util in other unix OS is okay
if ($dynamic_exports = LinuxSystemUtil::getDynamicExportedSymbols(BUILD_LIB_PATH . '/libphp.a')) {
$dynamic_exports = ' ' . $dynamic_exports;
}
}
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
$cc = getenv('CC');
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult("{$cc} -o embed embed.c {$lens} {$dynamic_exports}");
if ($ret !== 0) {
throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out));
throw new ValidationException(
'embed failed sanity check: build failed. Error message: ' . implode("\n", $out),
validation_module: 'static libphp.a sanity check'
);
}
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed');
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output));
throw new ValidationException(
'embed failed sanity check: run failed. Error message: ' . implode("\n", $output),
validation_module: 'static libphp.a sanity check'
);
}
}
@@ -157,24 +189,28 @@ abstract class UnixBuilderBase extends BuilderBase
logger()->info('running frankenphp sanity check');
$frankenphp = BUILD_BIN_PATH . '/frankenphp';
if (!file_exists($frankenphp)) {
throw new RuntimeException('FrankenPHP binary not found: ' . $frankenphp);
throw new ValidationException(
"FrankenPHP binary not found: {$frankenphp}",
validation_module: 'FrankenPHP sanity check'
);
}
$prefix = PHP_OS_FAMILY === 'Darwin' ? 'DYLD_' : 'LD_';
[$ret, $output] = shell()
->setEnv(["{$prefix}LIBRARY_PATH" => BUILD_LIB_PATH])
->execWithResult("{$frankenphp} version");
if ($ret !== 0 || !str_contains(implode('', $output), 'FrankenPHP')) {
throw new RuntimeException('FrankenPHP failed sanity check: ret[' . $ret . ']. out[' . implode('', $output) . ']');
throw new ValidationException(
'FrankenPHP failed sanity check: ret[' . $ret . ']. out[' . implode('', $output) . ']',
validation_module: 'FrankenPHP sanity check'
);
}
}
}
/**
* 将编译好的二进制文件发布到 buildroot
* Deploy the binary file to the build bin path.
*
* @param int $type 发布类型
* @throws RuntimeException
* @throws FileSystemException
* @param int $type Type integer, one of BUILD_TARGET_CLI, BUILD_TARGET_MICRO, BUILD_TARGET_FPM
*/
protected function deployBinary(int $type): bool
{
@@ -182,7 +218,8 @@ abstract class UnixBuilderBase extends BuilderBase
BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
default => throw new RuntimeException('Deployment does not accept type ' . $type),
BUILD_TARGET_CGI => SOURCE_PATH . '/php-src/sapi/cgi/php-cgi',
default => throw new SPCInternalException("Deployment does not accept type {$type}"),
};
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
FileSystem::createDir(BUILD_BIN_PATH);
@@ -192,18 +229,15 @@ abstract class UnixBuilderBase extends BuilderBase
/**
* Run php clean
*
* @throws RuntimeException
*/
protected function cleanMake(): void
{
logger()->info('cleaning up');
logger()->info('cleaning up php-src build files');
shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean');
}
/**
* Patch phpize and php-config if needed
* @throws FileSystemException
*/
protected function patchPhpScripts(): void
{
@@ -231,12 +265,9 @@ abstract class UnixBuilderBase extends BuilderBase
}
}
/**
* @throws WrongUsageException
* @throws RuntimeException
*/
protected function buildFrankenphp(): void
{
GlobalEnvManager::addPathIfNotExists(GoXcaddy::getPath());
$nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : '';
$nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : '';
$xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES');
@@ -248,45 +279,49 @@ abstract class UnixBuilderBase extends BuilderBase
logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.');
$xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules);
}
$lrt = PHP_OS_FAMILY === 'Linux' ? '-lrt' : '';
$releaseInfo = json_decode(Downloader::curlExec(
'https://api.github.com/repos/php/frankenphp/releases/latest',
hooks: [[CurlHook::class, 'setupGithubToken']],
), true);
$frankenPhpVersion = $releaseInfo['tag_name'];
[, $out] = shell()->execWithResult('go list -m github.com/dunglas/frankenphp@latest');
$frankenPhpVersion = str_replace('github.com/dunglas/frankenphp v', '', $out[0]);
$libphpVersion = $this->getPHPVersion();
$dynamic_exports = '';
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
$libphpVersion = preg_replace('/\.\d$/', '', $libphpVersion);
$libphpVersion = preg_replace('/\.\d+$/', '', $libphpVersion);
} else {
if ($dynamicSymbolsArgument = LinuxSystemUtil::getDynamicExportedSymbols(BUILD_LIB_PATH . '/libphp.a')) {
$dynamic_exports = ' ' . $dynamicSymbolsArgument;
}
}
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
$extLdFlags = "-extldflags '-pie'";
$extLdFlags = "-extldflags '-pie{$dynamic_exports}'";
$muslTags = '';
$staticFlags = '';
if (SPCTarget::isStatic()) {
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000'";
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports}'";
$muslTags = 'static_build,';
$staticFlags = '-static-pie';
}
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
$env = [
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
$libs = $config['libs'];
$libs .= PHP_OS_FAMILY === 'Linux' ? ' -lrt' : '';
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&
ToolchainManager::getToolchainClass() === GccNativeToolchain::class) {
$cflags .= ' -Wno-error=missing-profile';
$libs .= ' -lgcov';
}
$env = [...[
'CGO_ENABLED' => '1',
'CGO_CFLAGS' => $config['cflags'],
'CGO_LDFLAGS' => "{$staticFlags} {$config['ldflags']} {$config['libs']} {$lrt}",
'CGO_CFLAGS' => clean_spaces($cflags),
'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}",
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags .
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
"{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
"v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
"-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
foreach (GoXcaddy::getEnvironment() as $key => $value) {
if ($key === 'PATH') {
GlobalEnvManager::addPathIfNotExists($value);
} else {
$env[$key] = $value;
}
}
], ...GoXcaddy::getEnvironment()];
shell()->cd(BUILD_BIN_PATH)
->setEnv($env)
->exec("xcaddy build --output frankenphp {$xcaddyModules}");
@@ -299,4 +334,20 @@ abstract class UnixBuilderBase extends BuilderBase
}
}
}
/**
* Seek php-src/config.log when building PHP, add it to exception.
*/
protected function seekPhpSrcLogFileOnException(callable $callback): void
{
try {
$callback();
} catch (SPCException $e) {
if (file_exists(SOURCE_PATH . '/php-src/config.log')) {
$e->addExtraLogFile('php-src config.log', 'php-src.config.log');
copy(SOURCE_PATH . '/php-src/config.log', SPC_LOGS_DIR . '/php-src.config.log');
}
throw $e;
}
}
}

View File

@@ -4,14 +4,10 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixAutoconfExecutor;
trait attr
{
/**
* @throws RuntimeException
*/
protected function build(): void
{
UnixAutoconfExecutor::create($this)

View File

@@ -4,17 +4,11 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixCMakeExecutor;
trait brotli
{
/**
* @throws FileSystemException
* @throws RuntimeException
*/
protected function build(): void
{
UnixCMakeExecutor::create($this)

View File

@@ -4,16 +4,10 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\util\executor\UnixCMakeExecutor;
trait curl
{
/**
* @throws RuntimeException
* @throws FileSystemException
*/
protected function build(): void
{
shell()->cd($this->source_dir)->exec('sed -i.save s@\${CMAKE_C_IMPLICIT_LINK_LIBRARIES}@@ ./CMakeLists.txt');

View File

@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\BuildFailureException;
trait fastlz
{
protected function build(): void
@@ -13,10 +15,10 @@ trait fastlz
->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');
throw new BuildFailureException('Failed to copy fastlz.h, file does not exist');
}
if (!copy($this->source_dir . '/libfastlz.a', BUILD_LIB_PATH . '/libfastlz.a')) {
throw new \RuntimeException('Failed to copy libfastlz.a');
throw new BuildFailureException('Failed to copy libfastlz.a, file does not exist');
}
}
}

View File

@@ -4,19 +4,11 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixCMakeExecutor;
trait freetype
{
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function build(): void
{
$cmake = UnixCMakeExecutor::create($this)

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