Compare commits

...

222 Commits

Author SHA1 Message Date
crazywhalecc
71d20a8322 fix(docs): update Windows SAPI warning and download links in CliGenerator.vue 2026-07-14 23:27:46 +08:00
crazywhalecc
01a0b26a2a feat(docs): update package model documentation to include new package types and clarify definitions 2026-07-14 23:03:15 +08:00
crazywhalecc
abc6e3695f feat(docs): add staticphp-documentation-sync skill for bilingual documentation synchronization 2026-07-14 23:02:33 +08:00
crazywhalecc
a1ccaaca36 fix(docs): update build scripts and dependencies for VitePress 2026-07-14 23:00:56 +08:00
Jerry Ma
c1eefb8399 feat(manifest): implement BuildManifestDumper for generating build manifest (#1210) 2026-07-13 18:53:54 +08:00
crazywhalecc
4d00e338af feat(manifest): implement BuildManifestDumper for generating build manifest 2026-07-13 16:59:19 +08:00
Marc
422323a41d Fable v3 windows (#1207) 2026-07-10 23:25:39 +07:00
Jerry Ma
6144f7affb fix(windows): survive cmd.exe's 8191 character command line limit (#1209) 2026-07-10 21:02:19 +08:00
m-this
6d58d53f7d fix(imagemagick): build the VisualMagick tree under source/ on windows
- C:\im was outside the project so bin/spc reset could not clean it
- with the command line limit fixed a short base path is no longer
  needed; keep SPC_IMAGEMAGICK_BUILD_DIR as an override
2026-07-10 10:52:14 +02:00
m-this
c54fa78ad1 fix(windows): survive cmd.exe's 8191 character command line limit
- with big extension stacks (imagick) the link command lines exceed what
  cmd.exe allows and fail with 'The command line is too long'
- pass the collected LIBS_CLI/LIBS_CGI/LIBS_MICRO lib lists to link.exe
  through @response files, like php-src already does for its object lists
- compile the frankenphp -mthreads shim instead of generating a .bat:
  batch files run through cmd.exe and cap cgo link lines at 8191 chars,
  a real executable gets the full 32K and past that go writes a response
  file by itself; still probe-gated, still a stopgap for golang/go#80290
2026-07-10 08:04:10 +02:00
crazywhalecc
4d6f334cbb Refactor UPX patching logic for phpmicro binary 2026-07-09 16:52:39 +08:00
crazywhalecc
e99423c7d1 Unify GOPATH with go-win custom binary extraction method 2026-07-09 16:20:52 +09:00
crazywhalecc
44daaad548 Resolve xlswriter dllimport issue 2026-07-09 16:20:29 +09:00
crazywhalecc
4dac0d18b4 Fix windows file delete permissions 2026-07-09 16:20:10 +09:00
Jerry Ma
79db27da04 Merge branch 'v3' into fable-v3-windows 2026-07-09 12:31:39 +09:00
crazywhalecc
d04d82a1f1 Fix strawberry-perl detect time 2026-07-09 12:27:41 +09:00
crazywhalecc
dca24585d4 Add frankenphp test label 2026-07-09 11:56:29 +09:00
crazywhalecc
7edd8359d5 Enhance artifact extraction logic to check for existing files and handle hash storage for both file and directory targets 2026-07-09 11:55:54 +09:00
crazywhalecc
be8f239259 Merge remote-tracking branch 'origin/fable-v3-windows' into fable-v3-windows 2026-07-09 11:24:41 +09:00
crazywhalecc
6c7a47c9b5 Trigger full test when containing 'need-full-test' tag 2026-07-09 11:17:10 +09:00
Jerry Ma
859c06a470 Fix the Windows extension test failures on fable-v3-windows (#1208) 2026-07-09 11:09:33 +09:00
crazywhalecc
274706084a Fix frankenphp package path bug 2026-07-09 11:04:00 +09:00
crazywhalecc
0bd94b0ebd Lint 2026-07-09 11:03:39 +09:00
crazywhalecc
150998723d Fix windows captainhook 2026-07-09 11:03:32 +09:00
crazywhalecc
303dca5f59 Remove doctor item 2026-07-09 11:03:15 +09:00
m-this
d7902b9931 feat(tool): bundle python for the meson build
- add a python-win tool package that unzips the official python.org
  nuget package into the pkgroot (venv and ensurepip included)
- meson uses it to build its venv and only falls back to a system
  python, so no manual environment setup is needed
2026-07-08 14:17:36 +02:00
m-this
43b2da0511 fix(libiconv): only put the static lib on the windows link line
- static-libs@windows listed both libiconv.lib (the dll import lib) and
  libiconv_a.lib; the import lib came first, so php.exe ended up
  importing libiconv.dll and the cli smoke test died with
  STATUS_DLL_NOT_FOUND on machines without it
2026-07-08 11:15:11 +02:00
m-this
6dc5c5b770 fix(pgsql): link secur32 and crypt32 on windows
- libpq authenticates through SSPI and the static libcrypto behind it
  reads the system cert store; php.exe failed to link with unresolved
  Cert* and SSPI symbols when the openssl extension is not in the build
2026-07-08 11:15:11 +02:00
m-this
f3afd81c81 fix(php): pass /FORCE:MULTIPLE when linking php-cgi.exe and micro.sfx
- php.exe already links with /FORCE:MULTIPLE for extension-bundled
  duplicate symbols, cgi and micro did not
- imagick's MagickCore defines gettimeofday, also defined in php's
  time.obj, and both links failed with LNK2005
2026-07-08 11:15:11 +02:00
m-this
1dce506222 fix(postgresql): provision meson, ninja and winflexbison on windows
- the meson build assumed meson/ninja/win_flex/win_bison/perl on PATH,
  which only held on machines that had them installed
- add meson, ninja and winflexbison tool packages and declare them via
  tools@windows on postgresql, together with the existing strawberry-perl
- meson no longer ships a Windows MSI, so the wheel is installed offline
  into a venv: postgres re-invokes meson through find_program, which
  needs the real meson.exe launcher pip generates
2026-07-08 11:15:11 +02:00
crazywhalecc
323f21a6f2 Add gdi32.lib 2026-07-08 17:02:32 +09:00
crazywhalecc
ab30c9dc49 fix: update Visual Studio version handling in imagemagick configuration 2026-07-08 16:27:52 +09:00
Jerry Ma
996cca12c0 [v3] - fix(windows): resolve doctor-installed perl and quote perl path (#1174) 2026-07-08 13:59:05 +08:00
crazywhalecc
5451945972 Use escapeshellarg instead 2026-07-08 13:21:52 +08:00
crazywhalecc
fc1673e37f Merge branch 'refs/heads/v3' into pr/win-openssl-perl-path
# Conflicts:
#	src/Package/Library/openssl.php
2026-07-08 13:19:36 +08:00
Marc
f1722a0f3e Merge branch 'v3' into fable-v3-windows 2026-07-08 11:45:02 +07:00
Marc
8034ae37ea v3 weekly build fix (#1203) 2026-07-08 11:40:37 +07:00
Marc
c9f24b980d [v3] Enable SQLite column metadata (#1205) 2026-07-08 11:39:22 +07:00
Jerry Ma
5ffbf2d5fe fix(frankenphp): strip Go's -mthreads so the Windows build survives Clang >= 20 (#1201) 2026-07-08 11:47:02 +08:00
crazywhalecc
facc7bc5a7 test swoole 2026-07-08 11:43:35 +08:00
crazywhalecc
160d7f5537 fix: disable undefined behavior sanitizer in build flags 2026-07-08 11:41:41 +08:00
Jerry Ma
afa5f535e9 Merge branch 'v3' into v3c/fix-builds 2026-07-08 10:06:19 +08:00
Jerry Ma
0dde151632 Merge branch 'v3' into fix/v3-sqlite-column-metadata 2026-07-08 10:00:57 +08:00
Jerry Ma
e906edb332 Test bot separate (#1206) 2026-07-08 10:00:41 +08:00
mathis
83ce54b62b docs(frankenphp): link golang/go#80290 so the -mthreads workaround can be removed later 2026-07-08 03:59:20 +02:00
crazywhalecc
7d6c082c86 random test 2026-07-07 22:38:39 +08:00
crazywhalecc
db4f7c6a0c feat: separate workflow for posting test bot comments 2026-07-07 22:37:23 +08:00
Jan Jakeš
ca0167c83e Enable SQLite column metadata
Build Unix SQLite with SQLITE_ENABLE_COLUMN_METADATA so the metadata APIs are available on macOS and Linux.

Remove the pdo_sqlite configure override that forced PHP to treat sqlite3_column_table_name() as unavailable, and add sanity checks for both SQLite compile options and PDO column metadata.
2026-07-07 16:25:00 +02:00
m-this
5a5c784c4f fix(frankenphp): strip Go's -mthreads so the Windows build survives Clang >= 20
Go passes the MinGW-only -mthreads flag to the C compiler for cgo builds
(golang/go#16932); Clang >= 20 rejects it for the MSVC target, so the final
frankenphp go build fails on current windows-latest (VS 18 / LLVM 20+).

Wrap Clang with a generated .bat that drops the -mthreads token and forwards
the rest, used only when the detected Clang refuses the flag.
2026-07-07 15:30:52 +02:00
crazywhalecc
331da67049 Fix gen-ext-test-matrix AND bug (should be OR) 2026-07-07 15:48:35 +08:00
crazywhalecc
cc448d463b simdjson test 2026-07-07 15:42:34 +08:00
crazywhalecc
dc55881b78 libde265 fix build 2026-07-07 15:21:19 +08:00
crazywhalecc
a59473e4ab ext-test-matrix generation fix 2026-07-07 15:03:31 +08:00
crazywhalecc
c6a227f4de libde265 test 2026-07-07 14:50:32 +08:00
Jerry Ma
392733b7c3 feat(v3): Tool package refactor (#1200) 2026-07-06 21:59:44 +08:00
Jerry Ma
3870269330 feat(docs): add agent guide, build class patterns, log triage, and AI instructions (#1202) 2026-07-06 21:59:26 +08:00
crazywhalecc
03f1313eec chore 2026-07-06 21:20:38 +08:00
crazywhalecc
b9def51f86 Simplify redundant github instruction 2026-07-06 21:20:20 +08:00
crazywhalecc
8533702cf6 oops 2026-07-06 21:19:55 +08:00
crazywhalecc
fe3cd15f81 feat(docs): add agent guide, build class patterns, log triage, and AI instructions 2026-07-06 20:39:44 +08:00
crazywhalecc
dc33b55fd0 Use binary 2026-07-06 20:12:10 +08:00
crazywhalecc
c9401a0b7a Use redirect instead 2026-07-06 19:35:48 +08:00
crazywhalecc
fa040bc346 Fix mingw patch paths 2026-07-06 19:10:10 +08:00
crazywhalecc
ab37b34fb5 fix: improve Windows patching logic and update file paths for xlsxwriter 2026-07-06 16:46:29 +08:00
crazywhalecc
0b02f62b7e feat: add pkg-config tool package config 2026-07-06 15:36:36 +08:00
crazywhalecc
924fac137c docs: fix hosted repo URL in READMEs
- Update static-php-cli-hosted → static-php/hosted in both README.md and README-zh.md
2026-07-06 15:11:07 +08:00
crazywhalecc
d9c41a73da feat: add --installed flag to check-update, improve CLI and InteractiveTerm
- Add --installed option to check-update command to compare against on-disk version (tool packages)
- Support use_installed parameter in ArtifactDownloader::checkUpdate/checkUpdates
- Add -y shorthand for --auto-fix in doctor command
- Hook InteractiveTerm::init() in ConsoleApplication::doRun() to properly inject Symfony input/output
2026-07-06 15:10:52 +08:00
crazywhalecc
dd1e70a394 feat: declare tool dependencies in package configs via tools field
- Add 'tools' field to ConfigValidator for build-time tool declarations
- Move jom and strawberry-perl from depends@windows to tools@windows in openssl.yml
- Move go-xcaddy/go-win from depends to tools in frankenphp.yml
- Register config/pkg/tool/ path in spc.registry.yml
- Use addInstallPackage for upx tool in php.php (ToolPackage instead of library dep)
- Include 'tool' type in DumpCapabilitiesCommand and InstallPackageCommand package lists
2026-07-06 15:10:22 +08:00
crazywhalecc
1bdbdfc08c refactor: move getLibExtra* to Package base, add ToolPackage support to executors and builders
- Move getLibExtraCFlags/getLibExtraCxxFlags/getLibExtraLdFlags/getLibExtraLibs from LibraryPackage to Package base class so ToolPackage can also use them
- Full ToolPackage implementation: getBuildRootPath, getIncludeDir, getLibDir, getBinDir, getToolField with platform suffix support
- Update PackageBuilder to support building ToolPackage (not just LibraryPackage)
- Update PackageInstaller: support ToolPackage in download/extract/install pipeline, auto-install build-time tools, record installed versions
- Allow LibraryPackage|ToolPackage union type in all Executor classes and UnixShell::initializeEnv
2026-07-06 15:10:08 +08:00
crazywhalecc
90846ab149 refactor: restructure tool target configs into tool package system
- Move tool configs from config/pkg/target/ to config/pkg/tool/
- Add ToolVersionRegistry for tracking installed tool versions
- Delete old Target/pkgconfig.php, move to tool config
- Rename: 7za-win, go-win, go-xcaddy, jom, nasm, protoc, strawberry-perl, upx, vswhere, zig, pkg-config
2026-07-06 15:08:43 +08:00
Jerry Ma
8dd7882869 CRLF to LF (#1199) 2026-07-06 14:14:57 +08:00
crazywhalecc
7f6be12bf1 CRLF to LF 2026-07-06 14:02:38 +08:00
Jerry Ma
45b97581d8 feat(zip): add additional dependencies for Windows zip build (#1198) 2026-07-04 15:42:31 +08:00
crazywhalecc
12a5217f17 feat(zip): add additional dependencies for Windows zip build 2026-07-04 14:10:59 +08:00
Jerry Ma
5913cb07fd [v3] implement tool package support with validation and config (#1196) 2026-06-27 20:17:53 +08:00
crazywhalecc
dd69155539 feat(tool): remove deprecated tool package directory from registry configuration 2026-06-27 15:47:46 +08:00
crazywhalecc
a81dd6d5c9 feat(tool): implement tool package support with validation and configuration 2026-06-27 15:39:30 +08:00
Jerry Ma
b4ed673261 feat(windows): replace php-sdk-binary-tools with MSYS2 + 7za-win (#1193) 2026-06-23 14:36:28 +08:00
crazywhalecc
db2d9a909f feat(gmssl): add patch for pbkdf2_hmac_sm3_genkey rename and update build process 2026-06-22 16:44:44 +08:00
crazywhalecc
38e01a9b88 feat(tests): enhance label information for triggering extension build tests 2026-06-22 13:33:25 +08:00
crazywhalecc
2b210f9403 feat(logging): synchronize logger level and debug mode with output verbosity 2026-06-22 13:33:02 +08:00
crazywhalecc
be329c1d56 feat(build): add patch to Makefile for include order to resolve zip.h conflict 2026-06-22 11:14:14 +08:00
Jerry Ma
227b8f0b0a fix(test): fix redundant terminal output during phpunit (#1194) 2026-06-22 08:08:47 +08:00
crazywhalecc
c88041b7e0 feat(build): add UPX as an optional package for compression 2026-06-21 20:08:27 +08:00
crazywhalecc
3bb84f3b94 feat(build): add zlib as a dependency for Windows 2026-06-21 19:35:07 +08:00
crazywhalecc
c31bf73685 feat(build): add bison and re2c to required packages; bypass phpsdk_version check for MSVC + msys2 2026-06-21 19:28:15 +08:00
crazywhalecc
c4d7ca819b fix(openssl): update perl path for Windows compatibility 2026-06-21 19:27:47 +08:00
crazywhalecc
fd8ab71d80 feat(build): use WinCNG as crypto backend for libssh2 windows 2026-06-21 19:27:32 +08:00
crazywhalecc
2a7966aa4b Fix curl zstd build bug 2026-06-21 19:26:55 +08:00
crazywhalecc
ef83ff074e fix(source): use ftp.gnu.org as primary, ftpmirror.gnu.org as fallback
All GNU packages now use ftp.gnu.org (stable canonical server) as the
primary filelist source, with ftpmirror.gnu.org configured as
source-mirror fallback. ftpmirror uses DNS round-robin across many
mirrors of varying reliability; this setup eliminates random CI failures
caused by unreachable mirror nodes while preserving a fallback path.
2026-06-21 17:33:48 +08:00
crazywhalecc
06864fc3f6 feat(windows): replace php-sdk-binary-tools with MSYS2 + 7za-win
- Add msys2-build-essentials target: downloads the MSYS2 nightly sfx,
  extracts it, disables PGP keyring (CI-safe), runs two-pass pacman
  update, and installs autotools build essentials (make, autoconf,
  automake, libtool, pkgconf, perl).
- Add 7za-win target: downloads 7za.exe to PKG_ROOT_PATH\bin.
- Remove php-sdk-binary-tools target and all PHP_SDK_PATH references;
  replace with SPC_MSYS2_PATH throughout Artifact, ArtifactExtractor,
  FileSystem, DefaultShell and MSVCToolchain.
- Replace {php_sdk_path} path placeholder with {spc_msys2_path}.
- WindowsToolCheck: replace checkSDK/installSDK with checkMsys2,
  installMsys2 and check7zaWin/install7zaWin fix items.
- nasm.yml: extract nasm.exe/ndisasm.exe to {pkg_root_path}/bin.
- env.ini: rename PHP_SDK_PATH to SPC_MSYS2_PATH.
- Docs: update Windows migration guide and package-model placeholder docs.
2026-06-21 16:56:40 +08:00
Marc
408d8f755c Remove laravel/prompts from box.json (#1190) 2026-06-16 19:05:39 +07:00
Marc
1f291a9036 Add Visual Studio 2026 support (#1191) 2026-06-16 19:05:09 +07:00
crazywhalecc
127fb1989f Add vs 18 support 2026-06-16 19:21:18 +08:00
Jerry Ma
af771cf2b5 feat: enhance type hints and improve verbosity handling in commands (#1186) 2026-06-16 18:50:18 +08:00
crazywhalecc
5df65d926c Remove laravel/prompts from box.json 2026-06-16 18:49:22 +08:00
Jerry Ma
bdc7bbe1f1 v3: Fix gmssl build (#1188) 2026-06-16 18:45:43 +08:00
Jerry Ma
89dca1f0fb refactor: remove unused symfony/process and unnecessary laravel/prompts (#1187) 2026-06-16 18:15:03 +08:00
crazywhalecc
064a1f05ae Fix phpstan 2026-06-16 15:17:51 +08:00
crazywhalecc
88cb6749b8 Remove laravel/prompts and symfony/process 2026-06-16 15:11:48 +08:00
Jerry Ma
0010e35882 ext: add ext-fastchart and ext-fastjson registry entries (#1165) 2026-06-16 13:57:33 +08:00
crazywhalecc
728c8dd598 Make gmssl standalone 2026-06-16 13:19:03 +08:00
Marc
bf6216e59f Merge branch 'v3' into v3c/ext-fastchart-fastjson 2026-06-14 17:14:37 +07:00
DubbleClick
f66e68754e fable output 2026-06-14 11:51:07 +07:00
Marc
411ad7cc0f Add macports support (#1179) 2026-06-06 21:06:13 +07:00
Kevin Boyd
0761267eb3 Combine the macos tool checks into a single checkBrewOrPorts method 2026-06-04 21:40:01 -07:00
Jerry Ma
072a3b5505 feat: add permissions for id-token and attestations in release build (#1181) 2026-06-04 10:35:38 +08:00
Marc
0e5738b710 toolchain: add SPC_DEFAULT_RANLIB and pin cmake AR/RANLIB (#1163) 2026-06-04 09:25:42 +07:00
crazywhalecc
3ff9426e50 feat: add permissions for id-token and attestations in release build 2026-06-04 09:51:06 +08:00
Kevin Boyd
6057394641 Simplify macports checks 2026-05-31 22:04:44 -07:00
Kevin Boyd
2f4fb9d28f Add a check for macports alongside Brew in toolchainmanager 2026-05-28 22:40:33 -07:00
Kevin Boyd
96ab2de4b1 Add preliminary MacPorts support 2026-05-28 22:38:56 -07:00
Luther Monson
6c59456c02 fix(windows): consolidate to single canonical strawberry-perl path
Per review: spc's pkg config, doctor, and MSVCToolchain all use
PKG_ROOT_PATH\strawberry-perl. The arch-suffixed strawberry-perl-{arch}-win
path was stale and shouldn't be juggled alongside it. Validate against the
one canonical pkg-root path, falling back to WindowsUtil::findCommand.
2026-05-27 22:30:04 -07:00
Luther Monson
0e8a806640 fix(windows): resolve doctor-installed perl and quote perl path
Two related fixes for OpenSSL builds on Windows:

1. spc doctor installs Strawberry Perl under `pkgroot/strawberry-perl/`,
   but the validate() check only looks at the arch-specific native path
   (`strawberry-perl-x86_64-win`). When a user runs `spc doctor` to
   install perl, the subsequent build fails because the doctor's install
   layout isn't on the lookup list. Add it as a fallback before falling
   through to WindowsUtil::findCommand.

2. Wrap the resolved perl path in quote() when building the Configure
   command. WindowsUtil::findCommand can return a path containing spaces
   (e.g. `C:\Program Files\...`), which then splits the cmd.exe
   invocation. Quoting matches how every other interpolated path in this
   command is handled.
2026-05-27 22:07:57 -07:00
crazywhalecc
c641c3b8db Make mongodb standalone 2026-05-25 10:25:47 +08:00
Jerry Ma
48d6e9ebc2 LinuxMuslCheck: pass tool env via setEnv instead of command prefixes (#1170) 2026-05-24 22:59:47 +08:00
Jerry Ma
6cab47db67 deduplicate_flags: keep paired flag+value tokens together (#1168) 2026-05-24 22:57:23 +08:00
Jerry Ma
ec3fd0f4b0 patch: strip trailing U+200E from spc_fix_avx512_cache_before_80400.p… (#1167) 2026-05-24 22:57:01 +08:00
henderkes
e72f9aa623 LinuxMuslCheck: pass tool env via setEnv instead of command prefixes
Build the CC/CXX/AR/LD/RANLIB map once and hand it to shell()->setEnv()
so the configure/make invocations don't have to repeat the same prefix
on every line. For the sudo make-install path the env still needs to
be on the command line (sudo strips the parent env), so the same map
is rendered into $envFlags and prepended there. Also adds RANLIB,
which the upstream Makefile honours.
2026-05-24 21:40:26 +07:00
henderkes
c666cd6cd0 deduplicate_flags: keep paired flag+value tokens together
deduplicate_flags() split flags on whitespace then ran a per-token
unique. For paired flags like `-Xclang -mllvm` or `-framework Cocoa`,
where the value is a separate token, the value token could collide
with an unrelated flag or value and get dropped, corrupting the
command line.

Group known paired flags (-Xclang, -Xpreprocessor, -Xlinker,
-Xassembler, -framework, -arch, -target, -include, -imacros, -isystem,
-isysroot, -iquote, -idirafter, -MT, -MF, -MQ) with their following
token into a single atom before the unique pass.
2026-05-24 21:38:22 +07:00
henderkes
b8dd508148 patch: strip trailing U+200E from spc_fix_avx512_cache_before_80400.patch
The filename had a Left-To-Right Mark (U+200E) appended invisibly, so
the file is unreachable by code that constructs the path from a plain
ASCII string literal. Rename to the visible name.
2026-05-24 21:38:00 +07:00
henderkes
37d8b87c3b oops 2026-05-24 21:11:49 +07:00
Jerry Ma
582a88ef60 artifact: use {pkg_root_path} template in rust and go_win extract (#1164) 2026-05-24 22:04:39 +08:00
Jerry Ma
153003b75c imagemagick: --without-gcc-arch (#1162) 2026-05-24 22:04:02 +08:00
Jerry Ma
899555a964 watcher: drop ldflags from compile-only invocation (#1161) 2026-05-24 22:03:38 +08:00
Jerry Ma
891a222c39 revert useless patch (#1160) 2026-05-24 22:03:11 +08:00
henderkes
39beb68024 artifact: use {pkg_root_path} template in rust and go_win extract
Switch the rust and go_win downloaders from baking PKG_ROOT_PATH into
the extract path at download time to the {pkg_root_path} template,
which ArtifactExtractor resolves at extract time. This keeps the path
stable across runs where pkg_root_path differs between download and
extract (e.g. containerised vs host builds).
2026-05-24 20:56:08 +07:00
henderkes
5172580294 toolchain: add SPC_DEFAULT_RANLIB and pin cmake AR/RANLIB
ClangBrew, ClangNative and GccNative now export SPC_DEFAULT_RANLIB
alongside SPC_DEFAULT_AR. UnixCMakeExecutor honours both when
generating the Linux toolchain file, so cmake uses the toolchain's
ar/ranlib (e.g. zig-ar/zig-ranlib for archives that the system
ranlib does not understand) instead of /usr/bin/ranlib.
2026-05-24 20:55:35 +07:00
henderkes
99e05aa22b ext: add ext-fastchart and ext-fastjson registry entries
Register two iliaal/fastchart and iliaal/fastjson PHP extensions
sourced from ghtar, extracted into php-src/ext/{fastchart,fastjson}.
Both target Linux and Darwin. fastchart depends on freetype and
suggests libpng, libjpeg, libwebp.
2026-05-24 20:55:11 +07:00
henderkes
0807e9e253 watcher: drop ldflags from compile-only invocation
The shell invocation runs `$CXX -c` to compile watcher-c.cpp to a .o,
which never links. Passing linker flags to a compile-only step is
either ignored or, with some flags, an error. Drop them.
2026-05-24 20:54:44 +07:00
henderkes
1a779be028 imagemagick: --without-gcc-arch
ax_gcc_archflag has no Zen cpuid pattern and falls back to
-mtune=amdfam10, which under LLVM+LTO emits SSE4a extrq and SIGILLs on
Intel hosts. Disable the implicit --with-gcc-arch so host CPU features
do not bleed into the built binaries.
2026-05-24 20:54:21 +07:00
henderkes
bdfd3eb269 also revert #1122 2026-05-24 20:41:18 +07:00
Marc
7ae5d742c2 V3 check/4 (#1159) 2026-05-24 20:24:11 +07:00
Marc
95be291a84 Merge branch 'v3' into v3-check/4 2026-05-24 20:24:03 +07:00
Marc
d89add106a V3 check/3 (#1158) 2026-05-24 20:23:44 +07:00
Marc
a36129c6cd V3 check/2 (#1157) 2026-05-24 20:23:32 +07:00
Marc
3f3edd62a1 Update src/Package/Extension/password_argon2.php 2026-05-24 17:57:02 +07:00
crazywhalecc
82b77af317 Chore: extension fixes
clickhouse, mongodb, opcache, password-argon2, pgsql, spx
2026-05-24 18:16:47 +08:00
crazywhalecc
df26b93e58 Remove redundant suffix for getClassesPsr4 function 2026-05-24 18:12:04 +08:00
crazywhalecc
d1b4c05381 Fix curl exe build on windows 2026-05-24 18:11:41 +08:00
crazywhalecc
e1658bc0e6 Chore: gettext-win version, password-argon2 deps 2026-05-24 18:09:51 +08:00
crazywhalecc
5053620b61 feat: auto-load local working directory registry in vendor mode 2026-05-24 18:07:06 +08:00
crazywhalecc
9366cbacd9 Update discord invite link 2026-05-24 18:06:30 +08:00
Jerry Ma
b8ce9f7787 [v3] fix(windows): static builds vswhere.exe -product * (#1149) 2026-05-22 10:20:18 +08:00
Jerry Ma
6772403d81 [v3] fix: use ftpmirror.gnu.org instead of ftp.gnu.org (#1151) 2026-05-21 15:26:58 +08:00
Marc
60a91a82e1 [v3] fix(macos): static build remove -fno-plt from macOS CFLAGS (#1150) 2026-05-21 12:06:18 +07:00
Luther Monson
4a274b69ac fix: use ftpmirror.gnu.org instead of ftp.gnu.org
ftp.gnu.org is unreliable and frequently times out during CI builds.
ftpmirror.gnu.org is GNU's own CDN that auto-redirects to the nearest
mirror. This is the recommended download method per
https://www.gnu.org/prep/ftp.en.html

Also normalizes /pub/gnu/ paths to /gnu/ since ftpmirror only serves
the latter.

Affects: libiconv, gettext, gmp, idn2, libunistring, ncurses, readline
2026-05-20 21:09:34 -07:00
Luther Monson
e4edd0a00f Merge branch 'v3' into fix/macos-fno-plt 2026-05-20 21:05:54 -07:00
Luther Monson
ae26ef3bdb fix(macos): remove -fno-plt from macOS CFLAGS
-fno-plt is an ELF-only flag that has no effect on macOS Mach-O
targets — clang emits "argument unused" when it encounters it.
Libraries like xz that run -Werror sanity checks during configure
promote that warning to a fatal error, breaking the build.
2026-05-20 20:57:12 -07:00
Luther Monson
049ecfe0a5 Merge branch 'v3' into fix/vswhere-products 2026-05-20 20:54:26 -07:00
Jerry Ma
01a4d872ad fix windows test failures: path separators and arch normalization (#1148) 2026-05-21 10:50:33 +08:00
Luther Monson
a9e54bb725 fix(windows): add -products * to vswhere so Build Tools are found
vswhere.exe defaults to searching Community, Professional, and
Enterprise editions only. CI environments typically install the
lightweight Build Tools product which is a separate product type
(Microsoft.VisualStudio.Product.BuildTools). Without -products *
the tool returns no results and the build fails with "Visual Studio
with C++ tools not found".

See: https://github.com/microsoft/vswhere/wiki/Find-MSBuild
2026-05-20 18:36:58 -07:00
Luther Monson
ad9b9ec69f Merge branch 'v3' into v3-fix-windows-test-paths 2026-05-19 23:19:39 -07:00
Marc
8a37303925 Add a Log Filter to Strip Github Tokens (#1147) 2026-05-20 13:19:03 +07:00
Luther Monson
52d234f1f4 fix windows test failures: path separators and arch normalization 2026-05-19 21:59:18 -07:00
Luther Monson
a3c39576df filter secrets at logger callback; register basic-auth encoded blob 2026-05-19 21:23:43 -07:00
Marc
3f7bad75ec Feat/clickhouse (#1137) 2026-05-11 13:28:16 +07:00
crazywhalecc
a3f135d26c Simplify pull request template 2026-05-11 13:59:32 +08:00
Jerry Ma
0732c1f0b0 Merge branch 'v3' into feat/clickhouse 2026-05-11 13:18:16 +08:00
Jerry Ma
9b64ad8299 Add dev:gen-ext-test-matrix command (#1133) 2026-05-11 13:17:57 +08:00
crazywhalecc
4d1ae0093d Bypass curl test on swow loaded time 2026-05-11 11:02:31 +08:00
Jerry Ma
db11d5a420 Update config/pkg/ext/ext-swow.yml 2026-05-11 11:01:43 +08:00
Marc
b20c1fa5c2 Update config/pkg/ext/ext-swow.yml 2026-05-11 09:49:19 +07:00
crazywhalecc
bf38212814 Add isolated extension mark 2026-05-11 10:07:02 +08:00
crazywhalecc
42fdc4eb87 Use PHP 8.5 by default 2026-05-11 09:48:31 +08:00
crazywhalecc
685f5c565f Use PHP 8.5 by default 2026-05-11 09:47:10 +08:00
crazywhalecc
b8ee484e81 Comment upterm session 2026-05-10 16:38:45 +08:00
crazywhalecc
c186038dca Use system cc instead 2026-05-10 16:27:25 +08:00
crazywhalecc
36e738f849 strange there 2026-05-10 16:06:20 +08:00
crazywhalecc
2cc3c8c9af Revert 2026-05-10 15:55:12 +08:00
crazywhalecc
0469b658bf Revert 2026-05-10 15:55:03 +08:00
crazywhalecc
7107566da7 Fix wrongly constructed class 2026-05-10 15:50:21 +08:00
crazywhalecc
02d8f51bb2 Enhance Unix Makefile patch to disable auto-vectorization for zig-cc to prevent minilua segfault 2026-05-10 15:17:51 +08:00
Jerry Ma
21c868463a Update tests.yml 2026-05-10 14:26:38 +08:00
Jerry Ma
079a30c5b1 Add tmate session setup for debugging on failure 2026-05-10 14:12:47 +08:00
crazywhalecc
64d9650f88 Fix compiler extra appending 2026-05-09 17:23:01 +08:00
crazywhalecc
e63d49ec13 Disable pdo pgsql hook for swow temporarily 2026-05-09 16:30:57 +08:00
Jerry Ma
9dbb178bf3 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-09 16:11:26 +08:00
henderkes
3f48413281 add clickhouse extension by ilia 2026-05-09 15:10:30 +07:00
henderkes
dc6e63e1ba fix logic errors in shared ext patching 2026-05-09 15:09:59 +07:00
crazywhalecc
6ad4b6a4af Add concurrency settings to GitHub Actions workflow 2026-05-09 16:07:22 +08:00
crazywhalecc
270f131f54 Add label event 2026-05-09 16:01:44 +08:00
crazywhalecc
ceade306b8 phpstan fix 2026-05-09 15:55:55 +08:00
crazywhalecc
629b5b6b2d Add test-bot 2026-05-09 15:54:01 +08:00
crazywhalecc
7b79767355 Add retry mechanism to Git clone and GitHub release fetching methods 2026-05-09 14:13:47 +08:00
crazywhalecc
2ed4b10260 Make brotli and zstd as dep 2026-05-09 14:13:09 +08:00
crazywhalecc
184a091fd9 Implicitly define swow dependencies (due to extension generating and windows swow curl bug) 2026-05-09 14:12:50 +08:00
crazywhalecc
e6642459b8 Fix opentelemetry strict flag 2026-05-09 12:16:48 +08:00
crazywhalecc
af3c6a6d08 Move build command here 2026-05-09 11:05:28 +08:00
crazywhalecc
e930873e60 Add tier 2 support for actions runner test 2026-05-09 11:00:26 +08:00
crazywhalecc
cd803c75c5 Add filtering options for extensions, libs, and OS in test matrix generation 2026-05-09 10:44:04 +08:00
crazywhalecc
ad7475246f Merge remote-tracking branch 'origin/v3-docs/readme' into v3-docs/readme 2026-05-09 10:33:10 +08:00
crazywhalecc
b09cc968e6 Add curl execute output log 2026-05-09 10:19:16 +08:00
crazywhalecc
bf308e89a5 Remove duplicate phar patch for micro 2026-05-09 09:49:53 +08:00
crazywhalecc
bf326de985 Fix extracting hosted type for zip archive caused overwriting 2026-05-09 08:17:03 +08:00
crazywhalecc
4f9a555bf3 ds use git (pecl have buggy config.w32) 2026-05-09 08:16:11 +08:00
crazywhalecc
04df87cd5f Make intl use c++17 2026-05-09 08:15:45 +08:00
crazywhalecc
e4201a28ca Add 'imagick' and 'intl' to standalone array 2026-05-08 23:11:48 +08:00
crazywhalecc
1b30c98fbd Make glfw standalone though 2026-05-08 22:51:49 +08:00
crazywhalecc
61747f6f4e Add frameworks for glfw 2026-05-08 22:51:17 +08:00
crazywhalecc
c374163a05 Fix windows mpir build 2026-05-08 22:37:05 +08:00
crazywhalecc
ee21199ebb Remove hosted binary temporarily 2026-05-08 22:33:06 +08:00
crazywhalecc
01607a06c9 Add spx compatible command arg 2026-05-08 22:32:50 +08:00
crazywhalecc
fd4bf90a70 Add standalone list 2026-05-08 22:23:14 +08:00
crazywhalecc
73bf9ff93f Add libzstd.lib for windows builds 2026-05-08 22:13:50 +08:00
crazywhalecc
dcf1c5942c Add macOS test, conflicts 2026-05-08 22:12:06 +08:00
crazywhalecc
4695f846f5 Add macOS test 2026-05-08 21:23:29 +08:00
crazywhalecc
37b5f89ee1 Add extra build flags for specific extensions 2026-05-08 21:07:49 +08:00
crazywhalecc
5e40982e85 Use windows-latest 2026-05-08 20:58:33 +08:00
crazywhalecc
1d1f58f3a1 Disable parallel downloading 2026-05-08 20:55:23 +08:00
crazywhalecc
be039802c0 Add exclude for gen-ext-test-matrix 2026-05-08 20:54:41 +08:00
crazywhalecc
5529e66a61 Add dom deps for xmlreader 2026-05-08 19:33:19 +08:00
crazywhalecc
641ad8becf Add patch for PHP 8.2 compatibility in imap extension 2026-05-08 19:27:11 +08:00
crazywhalecc
a19c4470bb Fix frameworks in unix cmake executor wrongly used by linux 2026-05-08 19:11:31 +08:00
crazywhalecc
143ae4b8c4 Use -i instead of -I (-I used by hardcoded INI) 2026-05-08 19:08:00 +08:00
crazywhalecc
a980b0a1df Use -i instead of -I (-I used by hardcoded INI) 2026-05-08 19:07:39 +08:00
crazywhalecc
a8a851659f Fix memcache build on PHP 8.5 2026-05-08 19:07:06 +08:00
crazywhalecc
6b6025d3f0 Add parallel download 2026-05-08 17:41:12 +08:00
crazywhalecc
4507c8feb4 Fix zig check on fresh installed spc 2026-05-08 16:47:34 +08:00
crazywhalecc
9f80d6b2a8 Add dev:gen-ext-test-matrix command 2026-05-08 15:57:15 +08:00
crazywhalecc
ca8a28a364 Group shell command 2026-05-08 10:06:30 +08:00
crazywhalecc
8e3e790cc3 Add migration guide 2026-05-08 10:06:21 +08:00
240 changed files with 8793 additions and 2215 deletions

24
.gitattributes vendored Normal file
View File

@@ -0,0 +1,24 @@
# Force LF line endings for all text files.
# Prevents git from auto-converting LF -> CRLF on Windows checkouts.
* text=auto eol=lf
# Explicit binary files — git won't touch line endings for these
*.phar binary
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.zip binary
*.gz binary
*.tgz binary
*.txz binary
*.xz binary
*.bz2 binary
*.7z binary
*.exe binary
*.dll binary
*.sfx binary
*.so binary
*.a binary
*.o binary

24
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,24 @@
# StaticPHP v3 Copilot Instructions
> The canonical agent instructions live in [AGENTS.md](./AGENTS.md). This file provides the essential summary for GitHub Copilot; read `AGENTS.md` for the complete project map, working rules, and validation steps.
StaticPHP is a PHP CLI application for building static PHP binaries, PHP SAPIs, extensions, libraries, and helper tools. Prefer the v3 architecture under `src/StaticPHP`, `src/Package`, `config/pkg`, and `config/artifact`.
## Skills
Use the repository skills when the task matches them:
- `.github/skills/staticphp-package-maintenance`: add, modify, review, or validate package, artifact, extension, library, target, or tool definitions.
- `.github/skills/staticphp-build-troubleshooting`: diagnose build, download, doctor, shell, terminal, CI, smoke-test, or log failures.
- `.github/skills/staticphp-documentation-sync`: synchronize bilingual documentation (`docs/en/` and `docs/zh/`) when features, commands, configuration, APIs, or behavior change.
## Quick Reference
- **Entrypoint**: `php bin/spc`
- **Config lint**: `php bin/spc dev:lint-config`
- **CS fix**: `composer cs-fix`
- **Tests**: `composer test`
- **Static analysis**: `composer analyse`
- **Extension packages**: `config/pkg/ext/ext-*.yml`, prefix with `ext-` in dependencies
- **Platform suffixes**: `@unix`, `@linux`, `@macos`, `@windows` — prefer these over runtime conditionals
- **Do NOT edit generated dirs**: `buildroot/`, `source/`, `downloads/`, `pkgroot/`

View File

@@ -1,17 +1,12 @@
## What does this PR do?
<!-- Please describe the changes made in this PR here. -->
## Checklist before merging
> If your PR involves the changes mentioned below and completed the action, please tick the corresponding option.
> If a modification is not involved, please skip it directly.
- If you modified `*.php` or `*.json`, run them locally to ensure your changes are valid:
- If you modified `*.php` or `*.yml`, run them locally to ensure your changes are valid:
- [ ] `composer cs-fix`
- [ ] `composer analyse`
- [ ] `composer test`
- [ ] `bin/spc dev:sort-config`
- If it's an extension or dependency update, please ensure the following:
- [ ] Add your test combination to `src/globals/test-extensions.php`.
- [ ] If adding new or fixing bugs, add commit message containing `extension test` or `test extensions` to trigger full test suite.
- [ ] `bin/spc dev:lint-config`

View File

@@ -0,0 +1,56 @@
---
name: staticphp-build-troubleshooting
description: Diagnose StaticPHP v3 failures. Use when investigating build, compile, linker, download, doctor, environment, CI, smoke-test, terminal output, spc.output.log, spc.shell.log, config.log, CMake logs, or user-provided error snippets from StaticPHP commands.
---
# StaticPHP Build Troubleshooting
## Overview
Use this skill to triage StaticPHP failures from the outside in: command and environment first, SPC module/stage metadata next, shell/config logs last. The goal is to isolate the failing package, stage, command, and root cause before editing code.
## First Pass
1. Capture the exact command, OS, architecture, PHP version, extensions/libs/targets, and whether the run used `-v`, `-vv`, or `-vvv`.
2. Read the final terminal error first. StaticPHP prints module error info, failed package, failed stage, failed command, log paths, and extra log files when available.
3. If log files exist, inspect them in this order:
- `log/spc.output.log`: user-facing SPC messages and exception summary.
- `log/spc.shell.log`: executed commands, working directories, env, stdout/stderr.
- Extra logs named in the exception output: `php-src.config.log`, `lib.<pkg>.console.log`, `lib.<pkg>.cmake-error.log`, `lib.<pkg>.cmake-configure.log`, `lib.<pkg>.cmake-output.log`.
4. Read `references/log-triage.md` for pattern matching, likely causes, and next checks.
## Diagnosis Rules
- Do not start by changing shared core code. Most failures are package metadata, environment, upstream source, dependency order, or platform flags.
- Prefer evidence from the last failing command over earlier warnings.
- When logs are long, search backward for `Command exited`, `error:`, `undefined reference`, `not found`, `No package`, `CMake Error`, `configure: error`, `fatal error`, `Failed module`, and `Failed stage`.
- Use `config.log` and CMake logs for configure detection failures; use `spc.shell.log` for the actual command and env.
- Be careful with rebuild suggestions. `spc reset --with-download --yes` is destructive to caches; ask before clearing caches unless the user explicitly asked.
## Repro Commands
Use focused commands when reproducing:
```bash
php bin/spc doctor -vvv
php bin/spc download --for-extensions="curl,openssl" --with-php=8.5 --parallel=4 --retry=3 -vvv
php bin/spc build:libs "openssl" -vvv
php bin/spc build:php "bcmath,openssl,curl" --build-cli -vvv
php bin/spc dev:lint-config
```
Choose the smallest command that still reaches the failing package.
## Fix Direction
After finding the failing package/stage:
- Package YAML issue: use `$staticphp-package-maintenance`, then edit `config/pkg/*` or `config/artifact/*`.
- Build command or patch issue: inspect the package class under `src/Package/*`.
- Environment issue: check `doctor`, toolchain classes, and `config/pkg/tool/*`.
- Upstream download issue: check artifact type, regex, GitHub rate limiting, mirror behavior, and `GITHUB_TOKEN`.
- Core exception/logging issue: inspect `src/StaticPHP/Exception`, `src/StaticPHP/Runtime/Shell`, or executor classes only after package-level causes are ruled out.
## Resources
- `references/log-triage.md`: log files, failure categories, search patterns, and likely fixes.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "StaticPHP Build Troubleshooting"
short_description: "Diagnose StaticPHP build and log failures."
default_prompt: "Use $staticphp-build-troubleshooting to investigate a StaticPHP build, download, doctor, or log failure."

View File

@@ -0,0 +1,209 @@
# StaticPHP Log Triage
## Contents
- Log files
- Terminal summary
- Search strategy
- Failure categories
- Rebuild hygiene
- Reporting checklist
## Log Files
Default log directory is `log/`, controlled by `SPC_LOGS_DIR`. The important files are:
- `spc.output.log`: StaticPHP console/logger output and exception summaries.
- `spc.shell.log`: command execution log with command, caller, inline env, working directory, stdout, stderr, and exit code.
- `php-src.config.log`: copied when PHP source configure fails.
- `lib.<pkg>.console.log`: copied Autoconf `config.log` for a library when available.
- `lib.<pkg>.cmake-configure.log`: copied CMake 3.26+ configure log.
- `lib.<pkg>.cmake-error.log`: copied CMake error log.
- `lib.<pkg>.cmake-output.log`: copied CMake output log.
Logs are created when `SPC_ENABLE_LOG_FILE` is true. Old `*.log` files are cleaned unless `SPC_PRESERVE_LOG` is set to a truthy value. The code in `src/bootstrap.php` reads `SPC_PRESERVE_LOG` (no trailing S).
## Terminal Summary
StaticPHP exceptions often print:
- Exception category: build, download, environment, execution, file system, patch, validation, wrong usage, registry, internal.
- Failed module: package name, type, and sometimes class/file/line.
- Failed stage: call chain such as `build` or `build -> configure`.
- Failed command: the command that returned non-zero.
- Command working directory and inline env.
- Paths to `spc.output.log`, `spc.shell.log`, and extra logs.
Use this summary to choose the first files to read. If a package and stage are present, start with that package's YAML and class after reading the relevant log tail.
## Search Strategy
For long logs, search from the end first.
Useful patterns:
```text
Failed module:
Failed stage:
Failed command:
Command exited with non-zero code
configure: error
CMake Error
undefined reference
cannot find -l
fatal error:
No package
Package .* not found
Could NOT find
is not a valid
permission denied
curl: (
HTTP/2 403
rate limit
```
In `spc.shell.log`, each command block begins with `>>>>>>>>>>>>>>>>>>>>>>>>>>`, then prints the command, caller, env, and working dir. The last failed block is usually the highest-value evidence.
## Failure Categories
### Download Failure
Signs:
- `Download failed`
- `curl: (56)`, `curl: (22)`, HTTP 403/404/429
- GitHub API calls in verbose logs
- Asset regex did not match a release asset
Likely checks:
- If GitHub rate limited, ask user to set `GITHUB_TOKEN`.
- Verify artifact source type and regex in `config/pkg/*` or `config/artifact/*`.
- Use `--dl-retry`, `--dl-parallel`, `--ignore-cache`, `--no-alt`, or custom source options only as repro aids.
- Prefer fixing stale URLs/regexes over adding workarounds.
### Doctor or Environment Failure
Signs:
- `Environment check failed`
- missing `make`, `cmake`, `autoconf`, `pkg-config`, compiler, Perl, Visual Studio, MSYS2, Zig, etc.
- `Some check items can not be fixed`
Likely checks:
- Run `php bin/spc doctor -vvv`.
- Inspect `src/StaticPHP/Doctor/Item/*` for the check and fix behavior.
- Inspect `config/pkg/tool/*` for installable helper tools.
- On Windows, some dependencies cannot be auto-installed.
### Configure Failure
Signs:
- `configure: error`
- Autoconf failure before compilation
- extra `config.log` listed
Likely checks:
- Read copied `php-src.config.log` or `lib.<pkg>.console.log`.
- Look for the first compiler/linker probe that failed.
- Check `headers`, `static-libs`, `pkg-configs`, dependency order, and `initializeEnv($pkg)` behavior.
- For extensions, check `php-extension.arg-type` and `#[CustomPhpConfigureArg]`.
### CMake Failure
Signs:
- `CMake Error`
- `Could NOT find`
- missing target, package config, or static library
Likely checks:
- Read `lib.<pkg>.cmake-error.log` and `lib.<pkg>.cmake-configure.log`.
- Inspect `UnixCMakeExecutor`/`WindowsCMakeExecutor` usage in the package class.
- Check CMake options, toolchain root path, `pkg-configs`, and transitive dependency libraries.
### Compile Failure
Signs:
- compiler `fatal error: header.h: No such file or directory`
- syntax/type errors from upstream source
- incompatible PHP API or platform macros
Likely checks:
- Identify the source file and include path from `spc.shell.log`.
- Verify dependency headers are installed in `buildroot/include`.
- Check PHP version compatibility and existing patches in `src/globals/patch`.
- Prefer targeted patches or compile flags in the package class over broad toolchain changes.
### Link Failure
Signs:
- `undefined reference`
- `cannot find -lfoo`
- duplicate symbols
- Windows unresolved external symbol or missing `.lib`
Likely checks:
- Verify `static-libs`, dependency order, and `getStaticLibFiles()` usage.
- Inspect `SPC_EXTRA_LIBS`, `Libs.private` in `.pc` files, and package-specific pkg-config patching.
- On Windows, confirm `.lib` names and required system libraries.
- For OpenSSL/curl-like packages, search existing linker flag hooks before adding a new one.
### Smoke Test or Validation Failure
Signs:
- `Validation failed`
- `php --ri` failure
- extension not loaded after build
- micro/embed runtime smoke test fails
Likely checks:
- Check extension `display-name`; empty string skips `php --ri`.
- Confirm static vs shared build settings.
- Confirm the extension is included in the final SAPI target and not only built as a dependency.
- Inspect `src/globals/ext-tests/*` and common tests for expected runtime behavior.
### Registry or Config Failure
Signs:
- `Registry error`
- unknown package, invalid field, invalid platform suffix, type mismatch
- package referenced by attribute but missing config
Likely checks:
- Run `php bin/spc dev:lint-config`.
- Inspect `ConfigValidator` tests for accepted fields and error expectations.
- Confirm attribute type matches YAML `type`.
- Confirm hooks reference existing package names and stages for the current platform.
## Rebuild Hygiene
Use the smallest cleanup that can invalidate the suspected stale state:
- Redownload one artifact: `--ignore-cache="artifact-name"`.
- Skip downloads to test local source/build logic: `--no-download`.
- Prefer source when debugging build logic: `--dl-prefer-source`.
- Clear build products only when necessary. `spc reset --with-download --yes` removes caches and should not be suggested casually.
## Reporting Checklist
When preparing an issue or PR explanation, include:
- Exact `php bin/spc ...` command.
- OS, architecture, PHP version option, and relevant env vars.
- Failed package and stage.
- Last failed command and exit code.
- Tail of `spc.output.log`, relevant command block from `spc.shell.log`, and any extra config/CMake log.
- Whether the failure reproduces after a focused clean or cache refresh.

View File

@@ -0,0 +1,160 @@
---
name: staticphp-documentation-sync
description: Synchronize bilingual documentation when StaticPHP v3 user-facing or developer-facing documentation must change. Use when adding, modifying, deprecating, or removing documented features, CLI commands/options, environment variables, configuration formats, public APIs/extension points, workflows, installation requirements, migration guidance, or user-visible behavior. Do not use solely for internal implementation changes, package/library additions, or build bug fixes unless they change documented behavior or require updating existing docs.
---
# StaticPHP Documentation Sync
## Overview
StaticPHP maintains bilingual documentation under `docs/en/` (English) and `docs/zh/` (Chinese). User-facing or developer-facing documentation changes must be reflected in both languages. Use this skill to identify affected docs, update them in sync, and validate sidebar/config consistency.
## When to Use This Skill
Invoke this skill when the change involves:
- New or modified CLI commands, options, or arguments
- New or changed environment variables
- Package (extension/library/target/tool) additions, removals, or behavioral changes that affect documented support, dependencies, commands, or workflows
- Configuration format changes (YAML fields, artifact definitions, registry)
- Build lifecycle, doctor, or toolchain changes
- API or extension point changes (attributes, hooks, DI, custom artifacts)
- Workflow changes (installation, first build, migration)
- Deprecation or removal of any documented feature
Do not update docs just because code changed. Internal refactors, new libraries used only as dependencies, package build fixes, CI-only changes, and bug fixes that preserve documented behavior usually do not need documentation changes. If existing docs mention the changed behavior, command, package support, dependency, caveat, or workaround, update them.
## Documentation Map
```
docs/
├── en/ # English docs (canonical source)
│ ├── index.md # Home page hero/features
│ ├── guide/ # User-facing guides
│ │ ├── index.md # Overview
│ │ ├── installation.md # Installation instructions
│ │ ├── first-build.md # First build walkthrough
│ │ ├── sapi-reference.md # PHP SAPI options
│ │ ├── cli-reference.md # CLI commands and options
│ │ ├── cli-generator.md # Build command generator
│ │ ├── migrate-from-v2.md # v2 → v3 migration
│ │ ├── extensions.md # Supported extensions list
│ │ ├── extension-notes.md # Per-extension notes
│ │ ├── env-vars.md # Environment variables
│ │ ├── deps-map.md # Dependency map
│ │ └── troubleshooting.md # Troubleshooting guide
│ ├── develop/ # Developer docs
│ │ ├── index.md # Dev overview
│ │ ├── structure.md # Project structure
│ │ ├── registry.md # Registry model
│ │ ├── package-model.md # Package YAML model
│ │ ├── artifact-model.md # Artifact YAML model
│ │ ├── craft-yml.md # craft.yml reference
│ │ ├── build-lifecycle.md # Build stages/lifecycle
│ │ ├── system-build-tools.md # System tool requirements
│ │ ├── doctor-module.md # Doctor module
│ │ ├── php-src-changes.md # PHP source patches
│ │ └── extending/ # Extension authoring
│ │ ├── index.md
│ │ ├── package-classes.md
│ │ ├── annotations.md
│ │ ├── lifecycle-hooks.md
│ │ ├── dependency-injection.md
│ │ └── custom-artifact.md
│ ├── contributing/
│ │ └── index.md
│ └── faq/
│ └── index.md
├── zh/ # Chinese docs (mirrors en/ structure)
│ └── (same structure as en/)
├── .vitepress/
│ ├── sidebar.en.ts # English sidebar config
│ ├── sidebar.zh.ts # Chinese sidebar config
│ └── config.ts # VitePress site config
└── deps-craft-yml.md # Shared craft.yml include used by both languages
```
Other documentation files outside this tree may also matter, especially root-level `ext-support.md`.
**Key rule**: `docs/en/` and `docs/zh/` have identical file trees. Every `.md` file under `en/` must have a corresponding file under `zh/`.
## Workflow
### Step 1: Identify Impact Scope
Map the change to affected documentation:
| Change Type | Likely Affected Docs |
|---|---|
| New/removed CLI command | `guide/cli-reference.md`, `guide/cli-generator.md` |
| New/removed CLI option | `guide/cli-reference.md`, `guide/first-build.md` |
| New env var | `guide/env-vars.md` |
| New/removed documented extension package | `guide/extensions.md`, `guide/extension-notes.md`, `guide/deps-map.md`, root `ext-support.md` |
| Package config field change | `develop/package-model.md`, `develop/artifact-model.md` |
| Build lifecycle change | `develop/build-lifecycle.md` |
| Doctor change | `develop/doctor-module.md`, `develop/system-build-tools.md` |
| New attribute/hook/DI | `develop/extending/annotations.md`, `develop/extending/lifecycle-hooks.md`, `develop/extending/dependency-injection.md` |
| PHP source patch | `develop/php-src-changes.md` |
| Registry change | `develop/registry.md` |
| Install/setup change | `guide/installation.md`, `guide/first-build.md` |
| Deprecation/removal | All docs referencing the feature |
| New doc page | `sidebar.en.ts`, `sidebar.zh.ts` |
### Step 2: Read Current Docs
Before editing, read BOTH the English and Chinese versions of each affected file to understand the current content and existing translation patterns.
```bash
# Example: check both language versions of the CLI reference
cat docs/en/guide/cli-reference.md
cat docs/zh/guide/cli-reference.md
```
### Step 3: Update English Docs First
1. Update `docs/en/` files with accurate, complete English content.
2. Follow existing formatting conventions (headings, code blocks, tables, admonitions).
3. If adding a new page:
- Create the file under `docs/en/<category>/<name>.md`
- Add the corresponding entry in `docs/.vitepress/sidebar.en.ts`
- Ensure the file has proper VitePress frontmatter if needed
### Step 4: Sync Chinese Docs
1. Update `docs/zh/` files to match the English changes.
2. Translate all changed or added prose. Do not leave placeholder text or untranslated English in Chinese docs.
3. Match the structure and formatting of the English version exactly.
4. If a new page was added in English, create the corresponding `docs/zh/` file and update `docs/.vitepress/sidebar.zh.ts`.
5. Treat `docs/deps-craft-yml.md` as a special shared include for both languages. If it needs prose changes, either keep the shared content acceptable for both languages or split the included content before adding language-specific prose.
### Step 5: Validate
Run these checks before considering the task complete:
```bash
# Check that en/ and zh/ have matching file trees
diff <(find docs/en -name '*.md' | sed 's|docs/en/||' | sort) \
<(find docs/zh -name '*.md' | sed 's|docs/zh/||' | sort)
# Check that all sidebar links point to existing files
# (manual check: every 'link' in sidebar.*.ts must resolve to an actual .md file)
# Build docs when Node dependencies are available; this catches many broken links/config issues
npm run docs:build
```
## Translation Guidelines
- **Chinese docs must be complete**: Every section, paragraph, and table in the English docs must have a Chinese equivalent. Never skip sections.
- **Code blocks and command examples**: Keep executable code and commands identical in both languages. Translate surrounding prose; translate comments inside examples only when they are explanatory docs rather than copy-pasteable source/config.
- **Technical terms**: Use consistent translations. Refer to existing Chinese docs for established term translations. When in doubt, prefer the term used elsewhere in `docs/zh/`.
- **Links**: Internal links in Chinese docs should point to `/zh/...` paths (not `/en/...`).
- **YAML frontmatter**: Keep frontmatter identical between languages (layout, etc.) unless the title/tagline field is translated.
## Common Pitfalls
- **Don't update only one language**: This is the most common mistake. Always update both `en/` and `zh/` in the same change.
- **Don't forget sidebar configs**: When adding, renaming, or removing doc pages, update both `sidebar.en.ts` and `sidebar.zh.ts`.
- **Don't forget shared/root docs**: root `ext-support.md` and `docs/deps-craft-yml.md` are also documentation. Update them if relevant.
- **Don't leave TODO markers**: Do not commit TODO translation placeholders unless the user explicitly allows it or the task is blocked; if that happens, call it out in the final response.
- **Don't translate file paths or URLs**: Only translate human-readable content, not paths, URLs, command names, or code identifiers.

View File

@@ -0,0 +1,55 @@
---
name: staticphp-package-maintenance
description: Maintain StaticPHP v3 packages and artifacts. Use when adding, modifying, reviewing, or validating config under config/pkg or config/artifact; package classes under src/Package; extension/library/target/tool dependencies; PHP configure args; build hooks; package metadata; or related tests and docs.
---
# StaticPHP Package Maintenance
## Overview
Use this skill to make focused package changes without re-reading the entire repository. StaticPHP v3 separates declarative package/artifact YAML from package-specific PHP build logic; prefer config-only edits unless current patterns require a class.
## Quick Workflow
1. Identify the package kind and exact name.
- Extension: `config/pkg/ext/ext-name.yml`, class `src/Package/Extension/name.php`.
- Library: `config/pkg/lib/name.yml`, class `src/Package/Library/name.php`.
- Target or virtual target: `config/pkg/target/name.yml`, class `src/Package/Target/name.php`.
- Tool: `config/pkg/tool/name.yml`, class `src/Package/Tool/name.php`.
- Shared/custom artifact: `config/artifact/name.yml`, class `src/Package/Artifact/name.php`.
2. Search for the closest existing package before designing anything new.
- Similar build system: `rg "#\\[BuildFor|UnixCMakeExecutor|UnixAutoconfExecutor|WindowsCMakeExecutor" src/Package`.
- Similar config fields: `rg "static-libs|pkg-configs|arg-type|depends@" config/pkg`.
- Similar download type: `rg "type: ghrel|type: pecl|type: pie|type: git|binary: hosted" config`.
3. Read `references/package-reference.md` when changing YAML fields, artifact definitions, package naming, dependencies, platform suffixes, or validation expectations.
4. Read `references/build-class-patterns.md` when PHP build logic, attributes, lifecycle hooks, custom configure args, source patching, or executor usage is needed.
5. Validate narrowly, then broadly if risk warrants it.
- Config lint: `php bin/spc dev:lint-config`
- Focused tests: `vendor/bin/phpunit tests/StaticPHP/Config tests/StaticPHP/Registry tests/StaticPHP/Util/DependencyResolverTest.php --no-coverage`
- Full project checks: `composer test`, `composer analyse`
## Editing Rules
- Treat `config/pkg/*` and `config/artifact/*` as the source of package truth; package classes augment behavior.
- Use platform suffix fields for declarative OS differences: `@unix`, `@linux`, `@macos`, `@windows`.
- Add a PHP class only for custom build stages, validation, hook behavior, patches, or custom configure arguments.
- Keep extension dependencies prefixed with `ext-`; libraries, tools, and targets use their package names.
- Prefer existing helpers such as `UnixAutoconfExecutor`, `UnixCMakeExecutor`, `WindowsCMakeExecutor`, `shell()`, `cmd()`, and `FileSystem`.
- Do not modify build outputs (`buildroot/`, `source/`, `downloads/`, `pkgroot/`) to fix package definitions.
- If upstream metadata changes, update license metadata and smoke-test/display names when relevant.
## Common Task Paths
- Add a new PECL extension: define `config/pkg/ext/ext-name.yml` with `type: php-extension`, `artifact.source.type: pecl`, dependencies, and `php-extension.arg-type`; add a class only if configure args, patches, or hooks are non-standard.
- Add a library: define `config/pkg/lib/name.yml` with artifact, dependencies, and install verification fields (`headers`, `static-libs`, `pkg-configs`, `static-bins`); add build class methods by OS.
- Fix an existing package build: start from the failing package config/class, then inspect dependencies and hooks targeting that package before changing shared core code.
- Update a version source: prefer artifact fields that support update checking (`ghrel`, `ghtar`, `ghtagtar`, `git` with regex, `filelist`, `pecl`, `pie`) over hard-coded URLs when upstream supports it.
## Resources
- `references/package-reference.md`: YAML package/artifact model, naming, fields, validation, and commands.
- `references/build-class-patterns.md`: PHP package attributes, stages, hooks, executors, and class patterns.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "StaticPHP Package Maintenance"
short_description: "Add, update, and validate StaticPHP v3 package definitions."
default_prompt: "Use $staticphp-package-maintenance to add, modify, or review StaticPHP package and artifact definitions."

View File

@@ -0,0 +1,143 @@
# StaticPHP Build Class Patterns
## Contents
- When a class is needed
- Package attributes
- Stage and hook behavior
- Executor choices
- Common patterns
- Failure-safe edits
## When a Class Is Needed
Do not add a PHP package class for simple metadata. Use YAML alone when StaticPHP can infer the configure args, dependencies, and verification.
Add or update a class when the package needs:
- OS-specific build commands.
- Custom validation before building.
- Custom PHP configure arguments.
- Patches or file edits before build.
- Hooks into another package's stage.
- Custom source/binary download or extraction logic.
- Package info shown by dev tooling.
Package classes live in `src/Package/*` and are discovered through PSR-4 plus attributes. Config must exist first; `PackageLoader` throws if an attribute references an undefined package.
## Package Attributes
Class-level package attributes:
- `#[Extension('curl')]` maps to package `ext-curl` if the prefix is omitted.
- `#[Library('openssl')]`
- `#[Target('php')]`
- `#[Tool('zig')]`
Method-level attributes:
- `#[BuildFor('Linux'|'Darwin'|'Windows')]`: registers the `build` stage for that OS.
- `#[Stage('name')]`: registers a named stage; defaults to the method name when omitted.
- `#[BeforeStage('package', 'stage', 'only-when-package-resolved')]`: hook before a target package stage.
- `#[AfterStage('package', 'stage', 'only-when-package-resolved')]`: hook after a target package stage.
- `#[PatchBeforeBuild]`: runs once before package build unless `.spc-patched` exists; return `true` to write that marker.
- `#[CustomPhpConfigureArg('Linux')]`: supplies custom extension configure args.
- `#[Validate]`: validates environment/source assumptions.
- `#[Info]`: returns package information for tooling.
- `#[InitPackage]`: runs while loading a package class.
- `#[ResolveBuild]`: target package callback for resolving build dependencies.
- `#[ConditionalOn(SomeClass::class)]`: conditionally enables before/after hooks only when DI has the class.
## Stage and Hook Behavior
`PackageBuilder::buildPackage()` does:
1. Ensure build directories exist.
2. Skip if already installed unless forced.
3. Ensure source exists for non-virtual packages.
4. Emit `PatchBeforeBuild` callbacks.
5. Run the `build` stage.
6. Install license data.
7. Record tool package versions where relevant.
`Package::runStage()` wraps a stage with:
1. `BeforeStage` callbacks.
2. The stage method itself.
3. `AfterStage` callbacks.
SPC exceptions bind package and stage metadata. Preserve that behavior by throwing existing `SPCException` subclasses instead of raw exceptions when adding new failure paths.
## Executor Choices
Use existing executors where possible:
- `UnixAutoconfExecutor`: for Unix packages using `./configure && make && make install`. It injects default static flags and copies `config.log` into SPC logs on failure.
- `UnixCMakeExecutor`: for Unix CMake packages. It writes toolchain settings and copies CMake configure/error/output logs on failure.
- `WindowsCMakeExecutor`: for Windows CMake packages.
- `shell()->cd(...)->initializeEnv($pkg)`: for custom Unix command chains.
- `cmd()->cd(...)`: for Windows command chains.
Prefer `FileSystem` helpers for file edits and copies so behavior stays consistent.
## Common Patterns
Minimal library class:
```php
#[Library('example')]
class example
{
#[BuildFor('Linux')]
public function build(LibraryPackage $pkg): void
{
(new UnixAutoconfExecutor($pkg))
->configure()
->make();
}
}
```
Extension hook into PHP build:
```php
#[Extension('curl')]
class curl
{
#[BeforeStage('php', [php::class, 'makeForWindows'], 'ext-curl')]
public function patchBeforePhpBuild(): void
{
// Adjust env, generated build files, or linker flags.
}
}
```
Validation:
```php
#[Validate]
public function validate(): void
{
if (SystemTarget::getTargetOS() === 'Windows' && WindowsUtil::findCommand('perl.exe') === null) {
throw new EnvironmentException('You need to install perl first!');
}
}
```
Custom configure args should be used when YAML `arg-type` is `custom` or when args need package/install context:
```php
#[CustomPhpConfigureArg('Linux')]
public function configureArg(PhpExtensionPackage $ext): string
{
return '--with-example=' . $ext->getBuildRootPath();
}
```
## Failure-Safe Edits
- Make hooks conditional with the third `BeforeStage`/`AfterStage` argument when a dependency must be resolved before the hook should run.
- Keep platform-specific code under matching `#[BuildFor]` methods rather than branching heavily inside one method.
- If a patch changes upstream source, place patch files in `src/globals/patch/` and describe them with `#[PatchDescription]` where appropriate.
- If a class only mutates environment variables for another package, search for existing hooks first to avoid duplicate linker flags.
- After adding attributes, run registry/config tests because invalid stages and unknown packages are caught during loading.

View File

@@ -0,0 +1,157 @@
# StaticPHP Package Reference
## Contents
- Package locations
- Package types
- Artifact model
- Common YAML fields
- PHP extension fields
- Platform suffixes
- Validation and tests
## Package Locations
StaticPHP v3 keeps package metadata in YAML and behavior in PHP classes.
| Kind | YAML | PHP class namespace | Typical attribute |
|---|---|---|---|
| PHP extension | `config/pkg/ext/ext-name.yml` | `Package\Extension` | `#[Extension('name')]` |
| Library | `config/pkg/lib/name.yml` | `Package\Library` | `#[Library('name')]` |
| Target | `config/pkg/target/name.yml` | `Package\Target` | `#[Target('name')]` |
| Virtual target | `config/pkg/target/name.yml` | `Package\Target` | `#[Target('name')]` |
| Tool | `config/pkg/tool/name.yml` | `Package\Tool` | `#[Tool('name')]` |
| Custom artifact | `config/artifact/name.yml` | `Package\Artifact` | artifact attributes |
Prefer one package per YAML file unless an existing file groups related definitions. Match nearby naming and ordering.
## Package Types
`php-extension` packages describe PHP extensions. Config package names must use the `ext-` prefix. Dependencies on extensions also use `ext-`.
`library` packages describe buildable dependency libraries. They usually define source artifacts plus verification fields such as headers, static libraries, pkg-config files, or binaries.
`target` packages represent final build outputs and inherit the library-style fields. StaticPHP automatically exposes build commands for targets.
`virtual-target` packages are abstract dependency/build scheduling nodes. They may omit `artifact`.
`tool` packages are helper programs or toolchains installed into `pkgroot/` or used by builds.
## Artifact Model
Artifacts define downloadable source archives or prebuilt binaries. Use inline artifacts for simple one-package sources and `config/artifact/*.yml` for shared, complex, or custom artifacts.
Top-level artifact sections:
- `source`: source archive, git checkout, PECL/PIE package, local directory, or custom source.
- `binary`: prebuilt binary by platform, or aliases such as `hosted`/`custom`.
- `metadata`: `license`, `license-files`, and `source-root`.
Common source types:
- `url`: fixed URL; supports `filename`, `version`, and `extract`.
- `git`: repository source; use `rev` for a fixed branch/tag/commit or `regex` with named `version` capture for update checks.
- `ghrel`: GitHub release asset by regex filename match.
- `ghtar`: generated GitHub release tarball.
- `ghtagtar`: generated GitHub tag tarball.
- `filelist`: scrape a download index and extract version/filename with regex.
- `pecl`: PECL extension by name.
- `pie`: Packagist PIE extension by `vendor/package`.
- `php-release`: official PHP source selected by build PHP version.
- `local`: local source directory for development/offline use.
- `custom`: PHP artifact class handles source or binary logic.
Use `metadata.source-root` when the actual build directory is inside an extracted subdirectory.
Use `metadata.license-files` for source licenses. `@/file.txt` points to bundled license files in `src/globals/licenses/`.
## Common YAML Fields
Shared fields:
- `type`: required package type.
- `description`: optional human-readable package description.
- `license`: package-level license annotation where applicable.
- `lang`: implementation language such as `c` or `c++`.
- `frameworks`: macOS framework tags.
- `artifact`: string reference or inline artifact object. Required for `library` and `target`; optional for built-in extensions and virtual targets.
- `depends`: hard dependencies.
- `suggests`: optional dependencies.
Library, target, and tool verification/installation fields:
- `headers`: expected files/directories under `buildroot/include`.
- `static-libs`: expected static libraries under `buildroot/lib`.
- `pkg-configs`: expected `.pc` files under `buildroot/lib/pkgconfig`.
- `static-bins`: expected executables under `buildroot/bin`.
- `path`: directories appended to PATH after install.
- `env`: environment variables set after install.
- `append-env`: values appended to existing environment variables.
Path placeholders in `path`, `env`, and `append-env`:
- `{build_root_path}`: `buildroot/`
- `{pkg_root_path}`: `pkgroot/`
- `{working_dir}`: repository or working directory
- `{download_path}`: `downloads/`
- `{source_path}`: `source/`
- `{spc_msys2_path}`: MSYS2 root on Windows
## PHP Extension Fields
Extension-specific fields live under `php-extension`.
- `arg-type`: configure argument behavior. Built-ins include `enable`, `enable-path`, `with`, `with-path`, `custom`, and `none`. Full strings are allowed.
- `zend-extension`: true for Zend extensions such as opcache/xdebug.
- `build-shared`: whether shared builds are allowed.
- `build-static`: whether static builds are allowed.
- `build-with-php`: true when built inside the PHP source tree.
- `display-name`: value used for `php --ri` smoke tests and license display; empty string skips the `--ri` check.
- `os`: allowed OS families: `Linux`, `Darwin`, `Windows`.
Configure string placeholders:
- `@build_root_path@`: absolute buildroot path.
- `@shared_suffix@`: `=shared` in shared builds, empty in static builds.
- `@shared_path_suffix@`: `=shared,{buildroot}` in shared builds, `={buildroot}` in static builds.
## Platform Suffixes
Many fields support platform suffixes:
- `@unix`: Linux and macOS.
- `@linux`: Linux only.
- `@macos`: macOS only.
- `@windows`: Windows only.
For Linux, specific fields override generic fields in this order: `field@linux`, then `field@unix`, then `field`.
Use suffixes for declarative differences in dependencies, headers, libraries, pkg-configs, extension args, and suggestions.
## Validation and Tests
Run config validation for most package edits:
```bash
php bin/spc dev:lint-config
```
Run focused tests after config or registry changes:
```bash
vendor/bin/phpunit tests/StaticPHP/Config tests/StaticPHP/Registry tests/StaticPHP/Util/DependencyResolverTest.php --no-coverage
```
Run broader checks for framework or class changes:
```bash
composer test
composer analyse
```
Build commands are expensive. Use them for user-provided repros, package-specific fixes, or when validation cannot prove the behavior:
```bash
php bin/spc build:libs "openssl,curl" -vvv
php bin/spc build:php "bcmath,openssl,curl" --build-cli -vvv
```

View File

@@ -331,5 +331,4 @@ jobs:
with:
name: build-meta-${{ inputs.php-version }}-${{ inputs.os }}
path: |
buildroot/build-extensions.json
buildroot/build-libraries.json
buildroot/build-manifest.json

View File

@@ -115,5 +115,4 @@ jobs:
with:
name: build-meta
path: |
buildroot/build-extensions.json
buildroot/build-libraries.json
buildroot/build-manifest.json

View File

@@ -2,13 +2,14 @@ name: "Extension Matrix Tests"
on:
workflow_dispatch:
push:
pull_request:
types: [opened, synchronize, labeled]
jobs:
test:
name: "${{ matrix.extension }} (PHP ${{ matrix.php-version }} on ${{ matrix.operating-system }})"
runs-on: ${{ matrix.operating-system }}
if: contains(github.event.head_commit.message, 'extension test') || contains(github.event.head_commit.message, 'test extensions')
if: contains(github.event.pull_request.labels.*.name, 'need-full-test')
strategy:
fail-fast: false
matrix:

View File

@@ -0,0 +1,48 @@
name: Post Test Bot Comment
on:
workflow_run:
workflows: ["v3 Tests"]
types: [completed]
permissions:
pull-requests: write
actions: read
jobs:
post-comment:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Download bot output
id: download
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: bot-output
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Post/Update comment
if: steps.download.outcome == 'success'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
COMMENT_BODY=$(jq -r '.comment_body' bot-output.json)
PR_NUMBER=$(jq -r '.pr_number' bot-output.json)
MARKER="<!-- spc-test-bot -->"
# Find existing bot comment id
EXISTING_ID=$(gh api \
"repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
--jq "[.[] | select(.body | startswith(\"${MARKER}\")) | .id] | first // empty")
if [ -n "$EXISTING_ID" ]; then
gh api --method PATCH \
"repos/${{ github.repository }}/issues/comments/${EXISTING_ID}" \
-f body="$COMMENT_BODY"
else
gh pr comment "$PR_NUMBER" \
--repo "${{ github.repository }}" \
--body "$COMMENT_BODY"
fi

View File

@@ -38,6 +38,9 @@ jobs:
- name: "windows-x64"
os: "ubuntu-latest"
filename: "spc-windows-x64.exe"
permissions:
id-token: write
attestations: write
steps:
- name: "Checkout"
uses: "actions/checkout@v5"
@@ -105,6 +108,12 @@ jobs:
fi
fi
- name: "Generate build provenance attestation"
if: github.event_name != 'pull_request'
uses: actions/attest-build-provenance@v4
with:
subject-path: "${{ github.workspace }}/${{ matrix.operating-system.name == 'windows-x64' && 'spc.exe' || 'spc' }}"
- name: "Copy file"
run: |
if [ "${{ matrix.operating-system.name }}" != "windows-x64" ]; then

View File

@@ -1,9 +1,9 @@
name: Tests
name: v3 Tests
on:
pull_request:
branches: [ "main", "v3" ]
types: [ opened, synchronize, reopened ]
branches: [ "v3" ]
types: [ opened, synchronize, reopened, labeled, unlabeled ]
paths:
- 'src/**'
- 'config/**'
@@ -15,6 +15,10 @@ on:
permissions: read-all
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -103,114 +107,164 @@ jobs:
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: "Run PHPUnit Tests"
run: SPC_LIBC=glibc vendor/bin/phpunit tests/ --no-coverage
run: vendor/bin/phpunit tests/ --no-coverage
define-matrix:
if: false # TODO: enable when refactoring workflows
name: "Define Matrix"
check-gate:
name: "Check: need-test label"
runs-on: ubuntu-latest
outputs:
php: ${{ steps.gendef.outputs.php }}
os: ${{ steps.gendef.outputs.os }}
enabled: ${{ steps.gate.outputs.enabled }}
steps:
- name: "Checkout"
uses: actions/checkout@v4
- name: "Setup PHP"
uses: shivammathur/setup-php@v2
with:
php-version: 8.4
extensions: curl, openssl, mbstring
- name: Define
id: gendef
- name: Check label
id: gate
run: |
PHP_VERSIONS=$(php src/globals/test-extensions.php php)
OS_VERSIONS=$(php src/globals/test-extensions.php os)
echo 'php='"$PHP_VERSIONS" >> "$GITHUB_OUTPUT"
echo 'os='"$OS_VERSIONS" >> "$GITHUB_OUTPUT"
LABELS='${{ toJSON(github.event.pull_request.labels.*.name) }}'
if echo "$LABELS" | grep -q '"need-test"'; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
else
echo "enabled=false" >> "$GITHUB_OUTPUT"
fi
build:
if: false
name: "Build PHP Test (PHP ${{ matrix.php }} ${{ matrix.os }})"
runs-on: ${{ matrix.os }}
needs: [define-matrix, php-cs-fixer, phpstan, phpunit]
timeout-minutes: 120
strategy:
matrix:
php: ${{ fromJSON(needs.define-matrix.outputs.php) }}
os: ${{ fromJSON(needs.define-matrix.outputs.os) }}
fail-fast: false
test-bot:
name: "Test Bot: analyze PR"
needs: check-gate
if: needs.check-gate.outputs.enabled == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
need_test: ${{ steps.bot.outputs.need_test }}
gen_matrix_args: ${{ steps.bot.outputs.gen_matrix_args }}
gen_matrix_args_tier2: ${{ steps.bot.outputs.gen_matrix_args_tier2 }}
php_versions: ${{ steps.bot.outputs.php_versions }}
tier2: ${{ steps.bot.outputs.tier2 }}
steps:
- name: "Update runner packages"
if: ${{ startsWith(matrix.os, 'ubuntu-') }}
run: sudo apt-get update && sudo apt-get install -y ca-certificates
- uses: actions/checkout@v4
- name: "Checkout"
uses: actions/checkout@v4
- name: "Setup PHP"
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.4
tools: pecl, composer
php-version: '8.4'
extensions: curl, openssl, mbstring
ini-values: memory_limit=-1
tools: composer
- name: Install dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-dev
- name: Run dev:test-bot
id: bot
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
BOT_JSON=$(php -d opcache.enable_cli=0 bin/spc dev:test-bot \
--pr=${{ github.event.pull_request.number }} \
--repo=${{ github.repository }} 2>/dev/null)
echo "need_test=$(echo "$BOT_JSON" | jq -r '.need_test')" >> "$GITHUB_OUTPUT"
echo "gen_matrix_args=$(echo "$BOT_JSON" | jq -r '.gen_matrix_args')" >> "$GITHUB_OUTPUT"
echo "gen_matrix_args_tier2=$(echo "$BOT_JSON" | jq -r '.gen_matrix_args_tier2')" >> "$GITHUB_OUTPUT"
echo "php_versions=$(echo "$BOT_JSON" | jq -c '.php_versions')" >> "$GITHUB_OUTPUT"
echo "tier2=$(echo "$BOT_JSON" | jq -r '.tier2')" >> "$GITHUB_OUTPUT"
# Save JSON for the comment-posting workflow
jq -n --argjson bot "$BOT_JSON" \
--arg pr '${{ github.event.pull_request.number }}' \
'$bot + {pr_number: $pr}' > bot-output.json
- name: Upload bot output
uses: actions/upload-artifact@v4
with:
name: bot-output
path: bot-output.json
retention-days: 1
gen-matrix:
name: "Generate test matrix"
needs: test-bot
if: needs.test-bot.outputs.need_test == 'true'
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.build.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: curl, openssl, mbstring
ini-values: memory_limit=-1
tools: composer
- name: Install dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-dev
- name: Build matrix
id: build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GEN_MATRIX_ARGS: ${{ needs.test-bot.outputs.gen_matrix_args }}
GEN_MATRIX_ARGS_TIER2: ${{ needs.test-bot.outputs.gen_matrix_args_tier2 }}
PHP_VERSIONS: ${{ needs.test-bot.outputs.php_versions }}
TIER2: ${{ needs.test-bot.outputs.tier2 }}
run: |
# Tier1 matrix
MATRIX1=$(bin/spc dev:gen-ext-test-matrix $GEN_MATRIX_ARGS 2>/dev/null)
# Merge Tier2 if requested
if [ "$TIER2" = "true" ] && [ -n "$GEN_MATRIX_ARGS_TIER2" ]; then
MATRIX2=$(bin/spc dev:gen-ext-test-matrix $GEN_MATRIX_ARGS_TIER2 2>/dev/null)
COMBINED=$(jq -n --argjson m1 "$MATRIX1" --argjson m2 "$MATRIX2" '$m1 + $m2')
else
COMBINED=$MATRIX1
fi
# Expand PHP versions: cartesian product of entries × php_versions
FINAL=$(echo "$COMBINED" | jq --argjson versions "$PHP_VERSIONS" \
'[.[] | . as $entry | $versions[] | $entry + {"php-version": .}]')
echo "matrix=$(echo "$FINAL" | jq -c '{"combo": .}')" >> "$GITHUB_OUTPUT"
ext-test:
name: "Ext test: ${{ matrix.combo.extension }} [${{ matrix.combo.sapi }}] (PHP ${{ matrix.combo.php-version }} - ${{ matrix.combo.os }}-${{ matrix.combo.arch }})"
needs: gen-matrix
runs-on: ${{ matrix.combo.runner }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.gen-matrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.4
extensions: curl, openssl, mbstring
ini-values: memory_limit=-1
tools: composer
env:
phpts: nts
- name: "Cache composer packages"
id: composer-cache
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-
- name: Install dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-dev
# Cache downloaded source
- id: cache-download
uses: actions/cache@v4
with:
path: downloads
key: php-dependencies-${{ matrix.os }}
- name: "Install Dependencies"
run: composer update -vvv --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-plugins
- name: "Run Build Tests (doctor)"
run: php src/globals/test-extensions.php doctor_cmd ${{ matrix.os }} ${{ matrix.php }}
- name: "Prepare UPX for Windows"
if: ${{ startsWith(matrix.os, 'windows-') }}
- name: Build
env:
SPC_USE_SUDO: "yes"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
php src/globals/test-extensions.php install_upx_cmd ${{ matrix.os }} ${{ matrix.php }}
echo "UPX_CMD=$(php src/globals/test-extensions.php upx)" >> $env:GITHUB_ENV
./bin/spc doctor --auto-fix
${{ matrix.combo.build-args }} --dl-with-php=${{ matrix.combo.php-version }}
- name: "Prepare UPX for Linux"
if: ${{ startsWith(matrix.os, 'ubuntu-') }}
run: |
php src/globals/test-extensions.php install_upx_cmd ${{ matrix.os }} ${{ matrix.php }}
echo "UPX_CMD=$(php src/globals/test-extensions.php upx)" >> $GITHUB_ENV
- name: "Run Build Tests (download)"
run: php src/globals/test-extensions.php download_cmd ${{ matrix.os }} ${{ matrix.php }}
- name: "Run Build Tests (build)"
run: php src/globals/test-extensions.php build_cmd ${{ matrix.os }} ${{ matrix.php }}
- name: "Run Build Tests (build - embed for non-windows)"
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@v7
with:
name: build-logs-${{ matrix.os }}-${{ matrix.php }}
path: log
# - name: Setup tmate session
# - name: Setup upterm session
# if: ${{ failure() }}
# uses: mxschmitt/action-tmate@v3
# uses: owenthereal/action-upterm@v1
- name: Upload logs
if: always() && hashFiles('log/**') != ''
uses: actions/upload-artifact@v4
with:
name: logs-${{ matrix.combo.os }}-${{ matrix.combo.arch }}-${{ matrix.combo.sapi }}-${{ matrix.combo.extension }}-php${{ matrix.combo.php-version }}
path: log

View File

@@ -1,68 +1,73 @@
name: Docs build test and auto deploy
on:
pull_request:
branches: [ "v3" ]
types: [ opened, synchronize, reopened ]
paths:
- 'config/**.yml'
- 'docs/**'
- 'package.json'
- 'yarn.lock'
- '.github/workflows/vitepress-deploy.yml'
push:
branches: [ "v3" ]
paths:
- 'config/**.yml'
- 'docs/**'
- 'package.json'
- 'yarn.lock'
- '.github/workflows/vitepress-deploy.yml'
jobs:
build:
name: Deploy docs
runs-on: ubuntu-latest
if: github.repository == 'crazywhalecc/static-php-cli'
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/setup-node@v3
- run: npm install
- name: "Install PHP for official runners"
uses: shivammathur/setup-php@v2
with:
coverage: none
tools: composer:v2
php-version: 8.4
ini-values: memory_limit=-1
extensions: curl, openssl, mbstring
- name: "Get Composer Cache Directory"
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: "Cache Composer dependencies"
uses: "actions/cache@v4"
with:
path: "${{ steps.composer-cache.outputs.dir }}"
key: "php-8.2-locked-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: |
php-8.2-locked-composer
- name: "Install Locked Dependencies"
run: "composer install --no-interaction --no-progress"
- name: Build
run: npm run docs:build
# Deploy to GitHub Pages only when the workflow is triggered by a push to the v3 branch
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
if: github.event_name == 'push' && github.ref == 'refs/heads/v3'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/.vitepress/dist
name: Docs build test and auto deploy
on:
pull_request:
branches: [ "v3" ]
types: [ opened, synchronize, reopened ]
paths:
- 'config/**.yml'
- 'docs/**'
- 'package.json'
- 'yarn.lock'
- '.github/workflows/vitepress-deploy.yml'
push:
branches: [ "v3" ]
paths:
- 'config/**.yml'
- 'docs/**'
- 'package.json'
- 'yarn.lock'
- '.github/workflows/vitepress-deploy.yml'
jobs:
build:
name: Deploy docs
runs-on: ubuntu-latest
if: github.repository == 'crazywhalecc/static-php-cli'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: yarn
- name: Install documentation dependencies
run: yarn install --frozen-lockfile
- name: "Install PHP for official runners"
uses: shivammathur/setup-php@v2
with:
coverage: none
tools: composer:v2
php-version: 8.4
ini-values: memory_limit=-1
extensions: curl, openssl, mbstring
- name: "Get Composer Cache Directory"
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: "Cache Composer dependencies"
uses: "actions/cache@v4"
with:
path: "${{ steps.composer-cache.outputs.dir }}"
key: "php-8.2-locked-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: |
php-8.2-locked-composer
- name: "Install Locked Dependencies"
run: "composer install --no-interaction --no-progress"
- name: Build
run: yarn docs:build
# Deploy to GitHub Pages only when the workflow is triggered by a push to the v3 branch
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
if: github.event_name == 'push' && github.ref == 'refs/heads/v3'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/.vitepress/dist

1
.gitignore vendored
View File

@@ -52,6 +52,7 @@ packlib_files.txt
/node_modules/
/docs/.vitepress/dist/
/docs/.vitepress/cache/
/docs/.vitepress/.temp/
/docs/.vitepress/ext-data.json
/docs/.vitepress/deps-data.json
package-lock.json

60
AGENTS.md Normal file
View File

@@ -0,0 +1,60 @@
# StaticPHP v3 Agent Guide
StaticPHP is a PHP CLI application for building static PHP binaries, PHP SAPIs, extensions, libraries, helper tools, and project bundles. Prefer the v3 architecture under `src/StaticPHP`, `src/Package`, `config/pkg`, and `config/artifact`.
This file is the shared entry point for coding agents such as Codex, OpenCode, Claude-compatible agents, and GitHub Copilot agents. GitHub Copilot also has `.github/copilot-instructions.md`.
## Skills
Detailed task workflows live in `.github/skills`. Use them when the task matches:
- `.github/skills/staticphp-package-maintenance`: add, modify, review, or validate package, artifact, extension, library, target, or tool definitions.
- `.github/skills/staticphp-build-troubleshooting`: diagnose build, download, doctor, shell, terminal, CI, smoke-test, or log failures.
- `.github/skills/staticphp-documentation-sync`: synchronize bilingual documentation (`docs/en/` and `docs/zh/`) when features, commands, configuration, APIs, or behavior change.
If your agent does not automatically discover skills from `.github/skills`, read the matching `SKILL.md` manually before working on that task.
## Project Map
- `bin/spc`: primary CLI entrypoint.
- `composer.json`: PHP 8.4+, Symfony Console, DI, YAML, logger; useful scripts are `composer test`, `composer analyse`, `composer lint-config`, and `composer cs-fix`.
- `spc.registry.yml`: built-in `core` registry.
- `config/pkg/ext`: PHP extension package YAML, usually named `ext-*.yml`.
- `config/pkg/lib`: library package YAML.
- `config/pkg/target`: final build target and virtual target YAML.
- `config/pkg/tool`: helper tool package YAML.
- `config/artifact`: standalone artifact YAML for shared or complex sources/binaries.
- `log/`: build and shell execution logs (`spc.output.log`, `spc.shell.log`, and per-package CMake/config logs); controlled by `SPC_LOGS_DIR` and `SPC_ENABLE_LOG_FILE`.
- `src/StaticPHP`: framework core: registry loading, config validation, dependency resolution, package install/build pipeline, doctor, toolchains, runtime shell/executors, exceptions.
- `src/Package`: package-specific build logic registered by PHP attributes.
- `src/globals`: constants, helper functions, patches, smoke tests, bundled license text.
- `tests`: PHPUnit tests for config, registry, artifacts, dependency resolver, DI, commands, and utilities.
- `docs/en/develop` and `docs/zh/develop`: developer documentation. Some pages may be TODO; verify against source when behavior matters.
## Working Rules
- Keep changes scoped to the requested package, artifact, command, docs, or tests.
- Prefer existing package patterns over new abstractions. Search for a similar package first.
- Use structured YAML config; do not encode dependency logic in PHP when config fields are enough.
- Match package names exactly: extension packages use `ext-` in config and dependencies; `#[Extension('curl')]` expands to `ext-curl`.
- Use platform suffixes such as `@unix`, `@linux`, `@macos`, and `@windows` instead of runtime conditionals when the difference is declarative.
- Add or update PHP package classes only when build commands, validation, custom configure args, hooks, or source patching are required.
- Do not edit generated build directories (`buildroot/`, `source/`, `downloads/`, `pkgroot/`) as a fix.
## Validation
For config or package changes, run CS checks first:
```bash
bin/spc dev:lint-config
composer cs-fix
```
For broader PHP code changes, also run:
```bash
composer test
composer analyse
```
Use build commands only when needed for the task or when the user provided a repro, because full static builds can be slow and platform-sensitive.

View File

@@ -1,156 +1,156 @@
# StaticPHP
[![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md)
[![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md)
[![Releases](https://img.shields.io/packagist/v/crazywhalecc/static-php-cli?include_prereleases&label=Release&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/releases)
[![CI](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
[![Discord](https://img.shields.io/discord/nrSRbpMJ?label=Discord&logo=discord&style=flat-square)](https://discord.gg/nrSRbpMJ)
**StaticPHP** 是一个强大的工具,用于构建可移植的可执行文件,包括 PHP、扩展等。
> [!IMPORTANT]
> 我们正准备发布 **v3** 版本,届时项目名称将从 **static-php-cli** 更改为 **StaticPHP**。
> 此分支对应 v3 版本。v2 版本请查看 [v2 分支](https://github.com/crazywhalecc/static-php-cli/tree/main)。
> 请更新您的参考资料,并关注正式版发布。
## 特性
- :elephant: 支持多个 PHP 版本 - PHP 8.1, 8.2, 8.3, 8.4, 8.5
- :handbag: 构建零依赖的单文件 PHP 可执行程序
- :hamburger: 构建 **[phpmicro](https://github.com/static-php/phpmicro)** 自解压可执行文件(将 PHP 二进制和源码合并为单个文件)
- :pill: 自动构建环境检查器,支持自动修复
- :zap: 支持 `Linux``macOS``Windows`
- :wrench: 通过 vendor 模式和自定义注册表实现便捷扩展
- :books: 智能依赖管理
- 📦 自包含 `spc` 可执行文件,便于自安装
- :fire: 支持 100+ 热门 [PHP 扩展](https://static-php.dev/en/guide/extensions.html)
- :floppy_disk: 支持 UPX 压缩(二进制体积可缩小 30-50%
**单文件独立 php-cli**
<img width="700" alt="out1" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/01a2e60f-13b0-4242-a645-f7afa4936396">
**使用 phpmicro 将 PHP 代码与 PHP 解释器结合:**
<img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2">
## 快速开始
### 1. 下载 spc 二进制
```bash
# For Linux x86_64
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64
# For Linux aarch64
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-aarch64
# macOS x86_64 (Intel)
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-x86_64
# macOS aarch64 (Apple)
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-aarch64
# Windows (x86_64, win10 build 17063 or later, please install VS2022 first)
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x64.exe
```
对于 macOS 和 Linux请先添加可执行权限
```bash
chmod +x ./spc
```
### 2. 构建静态 PHP
首先,创建 `craft.yml` 文件,并从 [扩展列表](https://static-php.dev/en/guide/extensions.html) 或 [命令生成器](https://static-php.dev/en/guide/cli-generator.html) 指定要包含的扩展:
```yml
# PHP version support: 8.1, 8.2, 8.3, 8.4, 8.5
php-version: 8.5
# Put your extension list here
extensions: "apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib"
sapi:
- cli
- micro
download-options:
parallel: 10
```
运行命令:
```bash
./spc craft
# 输出完整控制台日志
./spc craft -vvv
```
### 3. 静态 PHP 使用
现在你可以将 StaticPHP 构建的二进制复制到另一台机器并在无依赖环境下运行:
```
# php-cli
buildroot/bin/php -v
# phpmicro
echo '<?php echo "Hello world!\n";' > a.php
./spc micro:combine a.php -O my-app
./my-app
```
## 文档
当前 README 包含基础用法。有关 StaticPHP 的完整功能集,
请访问 <https://static-php.dev>。
## 直接下载
如果你暂时不想构建,或只想先测试,可以从 [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml) 下载示例预编译产物,或从自托管服务器下载。
我们为每个 PHP 版本提供 2 种扩展集合:
- **gigantic**:尽可能包含更多扩展,二进制大小约 100-150MB。
- **base**:仅包含 StaticPHP 自身使用的少量扩展,二进制大小约 10MB。
> WIP
### 在线构建(使用 GitHub Actions
当上方直接下载的二进制无法满足你的需求时,
你可以使用 GitHub Actions 轻松构建静态编译的 PHP
并同时自定义要编译的扩展列表。
1. Fork 此仓库。
2. 进入项目的 Actions 并选择 `CI`
3. 选择 `Run workflow`,填写你要编译的 PHP 版本、目标类型和扩展列表。(扩展用逗号分隔,例如 `bcmath,curl,mbstring`
4. 等待工作流执行完成后,进入对应运行记录并下载 `Artifacts`
如果你启用 `debug`,构建时将输出所有日志,包括编译日志,便于排查问题。
> 我们也计划在未来提供可复用的 GitHub Actions 工作流,
> 这样你无需 fork 本项目,也能在自己的仓库中轻松构建 static PHP。
## 贡献
如果你需要的扩展缺失,可以创建 issue。
如果你熟悉本项目,也欢迎发起 pull request。
如果你想贡献文档,请直接编辑 `docs/`
## 赞助本项目
你可以通过 [GitHub Sponsor](https://github.com/crazywhalecc) 赞助我或我的项目。你捐赠的一部分将用于维护 **static-php.dev** 服务器。
**特别感谢以下赞助商:**
<a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a>
<a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a>
## 开源许可证
本项目本身采用 MIT 许可证。
一些新添加的扩展和依赖可能来自其他项目。
这些源码文件头部也可能包含额外的 LICENSE 和 AUTHOR 信息。
请在编译后使用 `bin/spc dump-license` 命令导出项目中使用的开源许可证,
并遵守对应项目的 LICENSE。
# StaticPHP
[![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md)
[![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md)
[![Releases](https://img.shields.io/packagist/v/crazywhalecc/static-php-cli?include_prereleases&label=Release&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/releases)
[![CI](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
[![Discord](https://img.shields.io/discord/nrSRbpMJ?label=Discord&logo=discord&style=flat-square)](https://discord.gg/xf6Rd4pEAk)
**StaticPHP** 是一个强大的工具,用于构建可移植的可执行文件,包括 PHP、扩展等。
> [!IMPORTANT]
> 我们正准备发布 **v3** 版本,届时项目名称将从 **static-php-cli** 更改为 **StaticPHP**。
> 此分支对应 v3 版本。v2 版本请查看 [v2 分支](https://github.com/crazywhalecc/static-php-cli/tree/main)。
> 请更新您的参考资料,并关注正式版发布。
## 特性
- :elephant: 支持多个 PHP 版本 - PHP 8.1, 8.2, 8.3, 8.4, 8.5
- :handbag: 构建零依赖的单文件 PHP 可执行程序
- :hamburger: 构建 **[phpmicro](https://github.com/static-php/phpmicro)** 自解压可执行文件(将 PHP 二进制和源码合并为单个文件)
- :pill: 自动构建环境检查器,支持自动修复
- :zap: 支持 `Linux``macOS``Windows`
- :wrench: 通过 vendor 模式和自定义注册表实现便捷扩展
- :books: 智能依赖管理
- 📦 自包含 `spc` 可执行文件,便于自安装
- :fire: 支持 100+ 热门 [PHP 扩展](https://static-php.dev/en/guide/extensions.html)
- :floppy_disk: 支持 UPX 压缩(二进制体积可缩小 30-50%
**单文件独立 php-cli**
<img width="700" alt="out1" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/01a2e60f-13b0-4242-a645-f7afa4936396">
**使用 phpmicro 将 PHP 代码与 PHP 解释器结合:**
<img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2">
## 快速开始
### 1. 下载 spc 二进制
```bash
# For Linux x86_64
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64
# For Linux aarch64
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-aarch64
# macOS x86_64 (Intel)
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-x86_64
# macOS aarch64 (Apple)
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-aarch64
# Windows (x86_64, win10 build 17063 or later, please install VS2022 first)
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x64.exe
```
对于 macOS 和 Linux请先添加可执行权限
```bash
chmod +x ./spc
```
### 2. 构建静态 PHP
首先,创建 `craft.yml` 文件,并从 [扩展列表](https://static-php.dev/en/guide/extensions.html) 或 [命令生成器](https://static-php.dev/en/guide/cli-generator.html) 指定要包含的扩展:
```yml
# PHP version support: 8.1, 8.2, 8.3, 8.4, 8.5
php-version: 8.5
# Put your extension list here
extensions: "apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib"
sapi:
- cli
- micro
download-options:
parallel: 10
```
运行命令:
```bash
./spc craft
# 输出完整控制台日志
./spc craft -vvv
```
### 3. 静态 PHP 使用
现在你可以将 StaticPHP 构建的二进制复制到另一台机器并在无依赖环境下运行:
```
# php-cli
buildroot/bin/php -v
# phpmicro
echo '<?php echo "Hello world!\n";' > a.php
./spc micro:combine a.php -O my-app
./my-app
```
## 文档
当前 README 包含基础用法。有关 StaticPHP 的完整功能集,
请访问 <https://static-php.dev>。
## 直接下载
如果你暂时不想构建,或只想先测试,可以从 [Actions](https://github.com/static-php/hosted/actions/workflows/build-php-bulk.yml) 下载示例预编译产物,或从自托管服务器下载。
我们为每个 PHP 版本提供 2 种扩展集合:
- **gigantic**:尽可能包含更多扩展,二进制大小约 100-150MB。
- **base**:仅包含 StaticPHP 自身使用的少量扩展,二进制大小约 10MB。
> WIP
### 在线构建(使用 GitHub Actions
当上方直接下载的二进制无法满足你的需求时,
你可以使用 GitHub Actions 轻松构建静态编译的 PHP
并同时自定义要编译的扩展列表。
1. Fork 此仓库。
2. 进入项目的 Actions 并选择 `CI`
3. 选择 `Run workflow`,填写你要编译的 PHP 版本、目标类型和扩展列表。(扩展用逗号分隔,例如 `bcmath,curl,mbstring`
4. 等待工作流执行完成后,进入对应运行记录并下载 `Artifacts`
如果你启用 `debug`,构建时将输出所有日志,包括编译日志,便于排查问题。
> 我们也计划在未来提供可复用的 GitHub Actions 工作流,
> 这样你无需 fork 本项目,也能在自己的仓库中轻松构建 static PHP。
## 贡献
如果你需要的扩展缺失,可以创建 issue。
如果你熟悉本项目,也欢迎发起 pull request。
如果你想贡献文档,请直接编辑 `docs/`
## 赞助本项目
你可以通过 [GitHub Sponsor](https://github.com/crazywhalecc) 赞助我或我的项目。你捐赠的一部分将用于维护 **static-php.dev** 服务器。
**特别感谢以下赞助商:**
<a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a>
<a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a>
## 开源许可证
本项目本身采用 MIT 许可证。
一些新添加的扩展和依赖可能来自其他项目。
这些源码文件头部也可能包含额外的 LICENSE 和 AUTHOR 信息。
请在编译后使用 `bin/spc dump-license` 命令导出项目中使用的开源许可证,
并遵守对应项目的 LICENSE。

View File

@@ -5,7 +5,7 @@
[![Releases](https://img.shields.io/packagist/v/crazywhalecc/static-php-cli?include_prereleases&label=Release&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/releases)
[![CI](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
[![Discord](https://img.shields.io/discord/nrSRbpMJ?label=Discord&logo=discord&style=flat-square)](https://discord.gg/nrSRbpMJ)
[![Discord](https://img.shields.io/discord/nrSRbpMJ?label=Discord&logo=discord&style=flat-square)](https://discord.gg/xf6Rd4pEAk)
**StaticPHP** is a powerful tool designed for building portable executables including PHP, extensions, and more.
@@ -104,7 +104,7 @@ see <https://static-php.dev>.
## Direct Download
If you do not want to build yet or just want to test first, you can download example pre-compiled artifacts from [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml) or from a self-hosted server.
If you do not want to build yet or just want to test first, you can download example pre-compiled artifacts from [Actions](https://github.com/static-php/hosted/actions/workflows/build-php-bulk.yml) or from a self-hosted server.
We offer 2 types of extension sets for each PHP version:

View File

@@ -1,116 +1,116 @@
param (
[string] ${action}
)
function AddToPath {
param (
[string]$pathToAdd
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -notlike "*$pathToAdd*") {
$newPath = $currentPath + ";$pathToAdd"
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Added '$pathToAdd' to Path."
Write-Host "To remove path, use: " -NoNewline
Write-Host "bin/setup-runtime remove-path" -ForegroundColor Cyan
} else {
Write-Host "Path already exists."
}
}
function RemoveFromPath {
param (
[string]$pathToRemove
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -like "*$pathToRemove*") {
$newPath = $currentPath -replace [regex]::Escape(';' + $pathToRemove), ''
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Removed Path '$pathToRemove'"
} else {
Write-Host "Path '$pathToRemove' not in Path"
}
}
# working dir
$WorkingDir = (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Definition))
if ($action -eq 'add-path') {
AddToPath ($WorkingDir + '\runtime')
exit 0
} elseif ($action -eq 'remove-path') {
RemoveFromPath ($WorkingDir + '\runtime')
exit 0
} elseif (-not($action -eq '')) {
Write-Host ("Invalid action: " + $action) -ForegroundColor Red
exit 1
}
# get php 8.1 specific version
# php windows download
$PHPRuntimeUrl = "https://windows.php.net/downloads/releases/archives/php-8.4.4-nts-Win32-vs17-x64.zip"
Write-Host "Downloading PHP from: " -NoNewline
Write-Host $PHPRuntimeUrl -ForegroundColor Cyan
$ComposerUrl = "https://getcomposer.org/download/latest-stable/composer.phar"
# create dir
New-Item -Path "downloads" -ItemType Directory -Force | Out-Null
# download php
if (-not(Test-Path "downloads\php.zip"))
{
Write-Host "Downloading PHP ..."
Invoke-WebRequest $PHPRuntimeUrl -OutFile "downloads\php.zip"
}
# extract php
New-Item -Path "runtime" -ItemType Directory -Force | Out-Null
Write-Host "Extracting php.zip ..."
Expand-Archive -Path "downloads/php.zip" -DestinationPath "runtime" -Force
# make php.ini
Move-Item -Path "runtime\php.ini-production" -Destination "runtime\php.ini" -Force
$OriginINI = Get-Content -Path "runtime\php.ini" -Raw
$OriginINI = $OriginINI -replace ';extension=openssl', 'extension=openssl'
$OriginINI = $OriginINI -replace ';extension=curl', 'extension=curl'
$OriginINI = $OriginINI -replace ';extension=mbstring', 'extension=mbstring'
$OriginINI = $OriginINI -replace ';extension=sodium', 'extension=sodium'
$OriginINI = $OriginINI -replace ';extension_dir = "./"', ('extension_dir = "' + (Split-Path -Parent $MyInvocation.MyCommand.Definition) + '\..\runtime\ext"')
$OriginINI | Set-Content -Path "runtime\php.ini"
# download composer
if (-not(Test-Path "runtime\composer.phar"))
{
Write-Host "Downloading composer ..."
Invoke-WebRequest $ComposerUrl -OutFile "downloads\composer.phar"
Move-Item -Path "downloads\composer.phar" -Destination "runtime\composer.phar" -Force
}
# create runtime\composer.ps1
$ComposerContent = '
$WorkingDir = (Split-Path -Parent $MyInvocation.MyCommand.Definition)
& ($WorkingDir + "\php.exe") (Join-Path $WorkingDir "\composer.phar") @args
'
$ComposerContent | Set-Content -Path 'runtime\composer.ps1' -Encoding UTF8
Write-Host "Successfully downloaded PHP and Composer !" -ForegroundColor Green
Write-Host "Use static-php-cli: " -NoNewline
Write-Host "bin/spc" -ForegroundColor Cyan
Write-Host "Use php: " -NoNewline
Write-Host "runtime/php" -ForegroundColor Cyan
Write-Host "Use composer: " -NoNewline
Write-Host "runtime/composer" -ForegroundColor Cyan
Write-Host ""
Write-Host "Don't forget installing composer dependencies '" -NoNewline
Write-Host "runtime/composer install" -ForegroundColor Cyan -NoNewline
Write-Host "' before using static-php-cli !"
Write-Host ""
Write-Host "If you want to use this PHP for quality tools (like phpstan, php-cs-fixer) or other project,"
Write-Host "or use PHP, Composer as system executable,"
Write-Host "use '" -NoNewline
Write-Host "bin/setup-runtime add-path" -ForegroundColor Cyan -NoNewline
Write-Host "' to add runtime dir in Path."
param (
[string] ${action}
)
function AddToPath {
param (
[string]$pathToAdd
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -notlike "*$pathToAdd*") {
$newPath = $currentPath + ";$pathToAdd"
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Added '$pathToAdd' to Path."
Write-Host "To remove path, use: " -NoNewline
Write-Host "bin/setup-runtime remove-path" -ForegroundColor Cyan
} else {
Write-Host "Path already exists."
}
}
function RemoveFromPath {
param (
[string]$pathToRemove
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -like "*$pathToRemove*") {
$newPath = $currentPath -replace [regex]::Escape(';' + $pathToRemove), ''
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Removed Path '$pathToRemove'"
} else {
Write-Host "Path '$pathToRemove' not in Path"
}
}
# working dir
$WorkingDir = (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Definition))
if ($action -eq 'add-path') {
AddToPath ($WorkingDir + '\runtime')
exit 0
} elseif ($action -eq 'remove-path') {
RemoveFromPath ($WorkingDir + '\runtime')
exit 0
} elseif (-not($action -eq '')) {
Write-Host ("Invalid action: " + $action) -ForegroundColor Red
exit 1
}
# get php 8.1 specific version
# php windows download
$PHPRuntimeUrl = "https://windows.php.net/downloads/releases/archives/php-8.4.4-nts-Win32-vs17-x64.zip"
Write-Host "Downloading PHP from: " -NoNewline
Write-Host $PHPRuntimeUrl -ForegroundColor Cyan
$ComposerUrl = "https://getcomposer.org/download/latest-stable/composer.phar"
# create dir
New-Item -Path "downloads" -ItemType Directory -Force | Out-Null
# download php
if (-not(Test-Path "downloads\php.zip"))
{
Write-Host "Downloading PHP ..."
Invoke-WebRequest $PHPRuntimeUrl -OutFile "downloads\php.zip"
}
# extract php
New-Item -Path "runtime" -ItemType Directory -Force | Out-Null
Write-Host "Extracting php.zip ..."
Expand-Archive -Path "downloads/php.zip" -DestinationPath "runtime" -Force
# make php.ini
Move-Item -Path "runtime\php.ini-production" -Destination "runtime\php.ini" -Force
$OriginINI = Get-Content -Path "runtime\php.ini" -Raw
$OriginINI = $OriginINI -replace ';extension=openssl', 'extension=openssl'
$OriginINI = $OriginINI -replace ';extension=curl', 'extension=curl'
$OriginINI = $OriginINI -replace ';extension=mbstring', 'extension=mbstring'
$OriginINI = $OriginINI -replace ';extension=sodium', 'extension=sodium'
$OriginINI = $OriginINI -replace ';extension_dir = "./"', ('extension_dir = "' + (Split-Path -Parent $MyInvocation.MyCommand.Definition) + '\..\runtime\ext"')
$OriginINI | Set-Content -Path "runtime\php.ini"
# download composer
if (-not(Test-Path "runtime\composer.phar"))
{
Write-Host "Downloading composer ..."
Invoke-WebRequest $ComposerUrl -OutFile "downloads\composer.phar"
Move-Item -Path "downloads\composer.phar" -Destination "runtime\composer.phar" -Force
}
# create runtime\composer.ps1
$ComposerContent = '
$WorkingDir = (Split-Path -Parent $MyInvocation.MyCommand.Definition)
& ($WorkingDir + "\php.exe") (Join-Path $WorkingDir "\composer.phar") @args
'
$ComposerContent | Set-Content -Path 'runtime\composer.ps1' -Encoding UTF8
Write-Host "Successfully downloaded PHP and Composer !" -ForegroundColor Green
Write-Host "Use static-php-cli: " -NoNewline
Write-Host "bin/spc" -ForegroundColor Cyan
Write-Host "Use php: " -NoNewline
Write-Host "runtime/php" -ForegroundColor Cyan
Write-Host "Use composer: " -NoNewline
Write-Host "runtime/composer" -ForegroundColor Cyan
Write-Host ""
Write-Host "Don't forget installing composer dependencies '" -NoNewline
Write-Host "runtime/composer install" -ForegroundColor Cyan -NoNewline
Write-Host "' before using static-php-cli !"
Write-Host ""
Write-Host "If you want to use this PHP for quality tools (like phpstan, php-cs-fixer) or other project,"
Write-Host "or use PHP, Composer as system executable,"
Write-Host "use '" -NoNewline
Write-Host "bin/setup-runtime add-path" -ForegroundColor Cyan -NoNewline
Write-Host "' to add runtime dir in Path."

View File

@@ -1,12 +1,12 @@
$PHP_Exec = ".\runtime\php.exe"
if (-not(Test-Path $PHP_Exec)) {
$PHP_Exec = Get-Command php.exe -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition
if (-not $PHP_Exec) {
Write-Host "Error: PHP not found, you need to install PHP on your system or use 'bin/setup-runtime'." -ForegroundColor Red
exit 1
}
}
& "$PHP_Exec" -d xdebug.mode=debug -d xdebug.client_host=127.0.0.1 -d xdebug.client_port=9003 -d xdebug.start_with_request=yes ("bin/spc") @args
exit $LASTEXITCODE
$PHP_Exec = ".\runtime\php.exe"
if (-not(Test-Path $PHP_Exec)) {
$PHP_Exec = Get-Command php.exe -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition
if (-not $PHP_Exec) {
Write-Host "Error: PHP not found, you need to install PHP on your system or use 'bin/setup-runtime'." -ForegroundColor Red
exit 1
}
}
& "$PHP_Exec" -d xdebug.mode=debug -d xdebug.client_host=127.0.0.1 -d xdebug.client_port=9003 -d xdebug.start_with_request=yes ("bin/spc") @args
exit $LASTEXITCODE

View File

@@ -1,12 +1,12 @@
$PHP_Exec = ".\runtime\php.exe"
if (-not(Test-Path $PHP_Exec)) {
$PHP_Exec = Get-Command php.exe -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition
if (-not $PHP_Exec) {
Write-Host "Error: PHP not found, you need to install PHP on your system or use 'bin/setup-runtime'." -ForegroundColor Red
exit 1
}
}
& "$PHP_Exec" ("bin/spc") @args
exit $LASTEXITCODE
$PHP_Exec = ".\runtime\php.exe"
if (-not(Test-Path $PHP_Exec)) {
$PHP_Exec = Get-Command php.exe -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition
if (-not $PHP_Exec) {
Write-Host "Error: PHP not found, you need to install PHP on your system or use 'bin/setup-runtime'." -ForegroundColor Red
exit 1
}
}
& "$PHP_Exec" ("bin/spc") @args
exit $LASTEXITCODE

View File

@@ -10,7 +10,6 @@
"config",
"src",
"vendor/psr",
"vendor/laravel/prompts",
"vendor/symfony",
"vendor/php-di",
"vendor/zhamao"

View File

@@ -20,7 +20,7 @@
]
},
{
"action": "bin/spc dev:lint-config --check",
"action": "php bin/spc dev:lint-config --check",
"conditions": [
{
"exec": "\\CaptainHook\\App\\Hook\\Condition\\FileStaged\\InDirectory",

View File

@@ -12,10 +12,8 @@
"php": ">=8.4",
"ext-mbstring": "*",
"ext-zlib": "*",
"laravel/prompts": "~0.1",
"php-di/php-di": "^7.1",
"symfony/console": "^5.4 || ^6 || ^7",
"symfony/process": "^7.2",
"symfony/yaml": "^7.2",
"zhamao/logger": "^1.1.4"
},

568
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,12 @@
ncurses:
binary: hosted
metadata:
license-files:
- COPYING
source:
type: filelist
url: 'https://ftp.gnu.org/pub/gnu/ncurses/'
url: 'https://ftp.gnu.org/gnu/ncurses/'
regex: '/href="(?<file>ncurses-(?<version>[^"]+)\.tar\.gz)"/'
source-mirror:
type: filelist
url: 'https://ftpmirror.gnu.org/gnu/ncurses/'
regex: '/href="(?<file>ncurses-(?<version>[^"]+)\.tar\.gz)"/'

View File

@@ -53,8 +53,8 @@ PHP_BUILD_PROVIDER="StaticPHP ${SPC_VERSION}"
SPC_ENABLE_LOG_FILE="yes"
; The LOG DIR for spc logs
SPC_LOGS_DIR="${WORKING_DIR}/log"
; Preserve old logs when running new builds
SPC_PRESERVE_LOGS="no"
; Preserve old logs when running new builds (code checks SPC_PRESERVE_LOG, not SPC_PRESERVE_LOGS)
SPC_PRESERVE_LOG="no"
; 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
@@ -68,8 +68,8 @@ SPC_PRESERVE_LOGS="no"
[windows]
; build target: win7-static
SPC_TARGET=native-windows
; php-sdk-binary-tools path
PHP_SDK_PATH="${WORKING_DIR}\php-sdk-binary-tools"
; MSYS2 root directory (msys64 subfolder), used by the Windows toolchain
SPC_MSYS2_PATH="${PKG_ROOT_PATH}\msys2-build-essentials\msys64"
; upx executable path
UPX_EXEC="${PKG_ROOT_PATH}\bin\upx.exe"
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
@@ -142,7 +142,7 @@ CXX=${SPC_DEFAULT_CXX}
AR=${SPC_DEFAULT_AR}
LD=${SPC_DEFAULT_LD}
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_CFLAGS="--target=${MAC_ARCH}-apple-darwin -O3 -fno-plt -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections"
SPC_DEFAULT_CFLAGS="--target=${MAC_ARCH}-apple-darwin -O3 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections"
SPC_DEFAULT_CXXFLAGS="${SPC_DEFAULT_CFLAGS}"
SPC_DEFAULT_LDFLAGS="-Wl,-dead_strip"
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches

View File

@@ -186,6 +186,7 @@ ext-password-argon2:
type: php-extension
depends:
- libargon2
suggests:
- ext-openssl
php-extension:
os:
@@ -348,6 +349,7 @@ ext-xmlreader:
type: php-extension
depends:
- ext-xml
- ext-dom
php-extension:
arg-type: enable
build-with-php: true

View File

@@ -0,0 +1,19 @@
ext-clickhouse:
type: php-extension
artifact:
source:
type: ghtar
repo: iliaal/php_clickhouse
extract: php-src/ext/clickhouse
prefer-stable: true
metadata:
license-files: [LICENSE]
license: PHP-3.01
suggests@unix:
- openssl
lang: cpp
php-extension:
os:
- Linux
- Darwin
arg-type@unix: custom

View File

@@ -2,8 +2,10 @@ ext-ds:
type: php-extension
artifact:
source:
type: pecl
name: ds
type: git
url: 'https://github.com/php-ds/ext-ds.git'
rev: master
extract: php-src/ext/ds
metadata:
license-files: [LICENSE]
license: MIT

View File

@@ -0,0 +1,20 @@
ext-fastchart:
type: php-extension
artifact:
source:
type: ghtar
repo: iliaal/fastchart
extract: php-src/ext/fastchart
prefer-stable: true
metadata:
license-files: [LICENSE]
depends:
- freetype
suggests:
- libpng
- libjpeg
- libwebp
php-extension:
os:
- Linux
- Darwin

View File

@@ -0,0 +1,14 @@
ext-fastjson:
type: php-extension
artifact:
source:
type: ghtar
repo: iliaal/fastjson
extract: php-src/ext/fastjson
prefer-stable: true
metadata:
license-files: [LICENSE]
php-extension:
os:
- Linux
- Darwin

View File

@@ -10,3 +10,5 @@ ext-gmssl:
license: PHP-3.01
depends:
- gmssl
php-extension:
arg-type: with-path

View File

@@ -13,4 +13,5 @@ ext-imagick:
os:
- Linux
- Darwin
- Windows
arg-type: custom

View File

@@ -14,5 +14,6 @@ ext-swow:
- curl
- ext-openssl
- ext-curl
- postgresql
php-extension:
arg-type: custom

View File

@@ -10,6 +10,11 @@ ext-zip:
license: PHP-3.01
depends:
- libzip
depends@windows:
- libzip
- zlib
- xz
- bzip2
php-extension:
arg-type: custom
arg-type@windows: enable

View File

@@ -5,7 +5,6 @@ brotli:
type: ghtagtar
repo: google/brotli
match: 'v1\.\d.*'
binary: hosted
metadata:
license-files: [LICENSE]
license: MIT

View File

@@ -8,7 +8,6 @@ bzip2:
type: filelist
url: 'https://sourceware.org/pub/bzip2/'
regex: '/href="(?<file>bzip2-(?<version>[^"]+)\.tar\.gz)"/'
binary: hosted
metadata:
license-files: ['@/bzip2.txt']
license: bzip2-1.0.6

View File

@@ -4,6 +4,6 @@ gettext-win:
source:
type: git
url: 'https://github.com/winlibs/gettext.git'
rev: master
rev: '0.18'
static-libs@windows:
- libintl_a.lib

View File

@@ -3,7 +3,11 @@ gettext:
artifact:
source:
type: filelist
url: 'https://ftp.gnu.org/pub/gnu/gettext/'
url: 'https://ftp.gnu.org/gnu/gettext/'
regex: '/href="(?<file>gettext-(?<version>[^"]+)\.tar\.xz)"/'
source-mirror:
type: filelist
url: 'https://ftpmirror.gnu.org/gnu/gettext/'
regex: '/href="(?<file>gettext-(?<version>[^"]+)\.tar\.xz)"/'
metadata:
license-files: [gettext-runtime/intl/COPYING.LIB]

View File

@@ -1,6 +1,12 @@
glfw:
type: library
artifact: glfw
frameworks:
- Cocoa
- CoreFoundation
- CoreVideo
- IOKit
- QuartzCore
headers:
- GLFW/glfw3.h
- GLFW/glfw3native.h

View File

@@ -6,8 +6,9 @@ gmp:
url: 'https://ftp.gnu.org/gnu/gmp/'
regex: '/href="(?<file>gmp-(?<version>[^"]+)\.tar\.xz)"/'
source-mirror:
type: url
url: 'https://dl.static-php.dev/static-php-cli/deps/gmp/gmp-6.3.0.tar.xz'
type: filelist
url: 'https://ftpmirror.gnu.org/gnu/gmp/'
regex: '/href="(?<file>gmp-(?<version>[^"]+)\.tar\.xz)"/'
metadata:
license-files: ['@/gmp.txt']
license: Custom

View File

@@ -5,6 +5,10 @@ idn2:
type: filelist
url: 'https://ftp.gnu.org/gnu/libidn/'
regex: '/href="(?<file>libidn2-(?<version>[^"]+)\.tar\.gz)"/'
source-mirror:
type: filelist
url: 'https://ftpmirror.gnu.org/gnu/libidn/'
regex: '/href="(?<file>libidn2-(?<version>[^"]+)\.tar\.gz)"/'
metadata:
license-files: [COPYING.LESSERv3]
license: LGPL-3.0-or-later

View File

@@ -16,13 +16,59 @@ imagemagick:
- libtiff
- libheif
- bzip2
depends@windows:
- zlib
suggests:
- zstd
- xz
- libzip
- libxml2
headers@windows:
- imagemagick/MagickWand/MagickWand.h
lang: cpp
pkg-configs:
- Magick++-7.Q16HDRI
- MagickCore-7.Q16HDRI
- MagickWand-7.Q16HDRI
static-libs@windows:
- CORE_RL_MagickWand_.lib
- CORE_RL_MagickCore_.lib
- CORE_RL_coders_.lib
- CORE_RL_filters_.lib
- CORE_RL_aom_.lib
- CORE_RL_brotli_.lib
- CORE_RL_bzip2_.lib
- CORE_RL_cairo_.lib
- CORE_RL_croco_.lib
- CORE_RL_de265_.lib
- CORE_RL_exr_.lib
- CORE_RL_ffi_.lib
- CORE_RL_freetype_.lib
- CORE_RL_fribidi_.lib
- CORE_RL_gdk-pixbuf_.lib
- CORE_RL_glib_.lib
- CORE_RL_harfbuzz_.lib
- CORE_RL_heif_.lib
- CORE_RL_highway_.lib
- CORE_RL_imath_.lib
- CORE_RL_jpeg-turbo-12_.lib
- CORE_RL_jpeg-turbo-16_.lib
- CORE_RL_jpeg-turbo_.lib
- CORE_RL_jpeg-xl_.lib
- CORE_RL_lcms_.lib
- CORE_RL_lqr_.lib
- CORE_RL_lzma_.lib
- CORE_RL_openh264_.lib
- CORE_RL_openjpeg_.lib
- CORE_RL_openjph_.lib
- CORE_RL_pango_.lib
- CORE_RL_pixman_.lib
- CORE_RL_png_.lib
- CORE_RL_raqm_.lib
- CORE_RL_raw_.lib
- CORE_RL_rsvg_.lib
- CORE_RL_tiff_.lib
- CORE_RL_webp_.lib
- CORE_RL_xml_.lib
- CORE_RL_zip_.lib
- CORE_RL_zlib_.lib

View File

@@ -10,7 +10,6 @@ libcares:
type: filelist
url: 'https://c-ares.org/download/'
regex: '/href="\/download\/(?<file>c-ares-(?<version>[^"]+)\.tar\.gz)"/'
binary: hosted
metadata:
license-files: [LICENSE.md]
headers@unix:

View File

@@ -5,7 +5,6 @@ libedit:
type: filelist
url: 'https://thrysoee.dk/editline/'
regex: '/href="(?<file>libedit-(?<version>[^"]+)\.tar\.gz)"/'
binary: hosted
metadata:
license-files: [COPYING]
license: BSD-3-Clause

View File

@@ -9,5 +9,4 @@ libiconv-win:
license-files: [source/COPYING]
license: GPL-3.0-or-later
static-libs@windows:
- libiconv.lib
- libiconv_a.lib

View File

@@ -5,7 +5,10 @@ libiconv:
type: filelist
url: 'https://ftp.gnu.org/gnu/libiconv/'
regex: '/href="(?<file>libiconv-(?<version>[^"]+)\.tar\.gz)"/'
binary: hosted
source-mirror:
type: filelist
url: 'https://ftpmirror.gnu.org/gnu/libiconv/'
regex: '/href="(?<file>libiconv-(?<version>[^"]+)\.tar\.gz)"/'
metadata:
license-files: [COPYING.LIB]
license: LGPL-2.0-or-later

View File

@@ -6,7 +6,6 @@ libpng:
repo: pnggroup/libpng
match: v1\.6\.\d+
query: '?per_page=150'
binary: hosted
metadata:
license-files: [LICENSE]
license: PNG

View File

@@ -6,7 +6,6 @@ libsodium:
repo: jedisct1/libsodium
match: 'libsodium-(?!1\.0\.21)\d+(\.\d+)*\.tar\.gz'
prefer-stable: true
binary: hosted
metadata:
license-files: [LICENSE]
pkg-configs:

View File

@@ -6,12 +6,13 @@ libssh2:
repo: libssh2/libssh2
match: libssh2.+\.tar\.gz
prefer-stable: true
binary: hosted
metadata:
license-files: [COPYING]
license: BSD-3-Clause
depends:
depends@unix:
- openssl
depends@windows:
- zlib
headers:
- libssh2.h
- libssh2_publickey.h

View File

@@ -5,7 +5,10 @@ libunistring:
type: filelist
url: 'https://ftp.gnu.org/gnu/libunistring/'
regex: '/href="(?<file>libunistring-(?<version>[^"]+)\.tar\.gz)"/'
binary: hosted
source-mirror:
type: filelist
url: 'https://ftpmirror.gnu.org/gnu/libunistring/'
regex: '/href="(?<file>libunistring-(?<version>[^"]+)\.tar\.gz)"/'
metadata:
license-files: [COPYING.LIB]
license: LGPL-3.0-or-later

View File

@@ -11,6 +11,10 @@ libzip:
license: BSD-3-Clause
depends:
- zlib
depends@windows:
- zlib
- bzip2
- xz
suggests:
- bzip2
- xz

View File

@@ -10,7 +10,6 @@ openssl:
type: filelist
url: 'https://www.openssl.org/source/'
regex: '/href="(?<file>openssl-(?<version>3\.[^"]+)\.tar\.gz)"/'
binary: hosted
metadata:
license-files: [LICENSE.txt]
license: OpenSSL
@@ -18,7 +17,6 @@ openssl:
- zlib
depends@windows:
- zlib
- jom
headers:
- openssl
static-libs@unix:
@@ -27,3 +25,7 @@ openssl:
static-libs@windows:
- libssl.lib
- libcrypto.lib
tools@windows:
- jom
- nasm
- strawberry-perl

View File

@@ -5,8 +5,6 @@ postgresql:
type: ghtagtar
repo: postgres/postgres
match: REL_18_\d+
binary:
windows-x86_64: { type: url, url: 'https://get.enterprisedb.com/postgresql/postgresql-16.8-1-windows-x64-binaries.zip', extract: { lib/libpq.lib: '{build_root_path}/lib/libpq.lib', lib/libpgport.lib: '{build_root_path}/lib/libpgport.lib', lib/libpgcommon.lib: '{build_root_path}/lib/libpgcommon.lib', include/libpq-fe.h: '{build_root_path}/include/libpq-fe.h', include/postgres_ext.h: '{build_root_path}/include/postgres_ext.h', include/pg_config_ext.h: '{build_root_path}/include/pg_config_ext.h', include/libpq/libpq-fs.h: '{build_root_path}/include/libpq/libpq-fs.h' } }
metadata:
license-files: ['@/postgresql.txt']
license: PostgreSQL
@@ -16,6 +14,9 @@ postgresql:
- openssl
- zlib
- libedit
depends@windows:
- openssl
- zlib
suggests@unix:
- icu
- libxslt
@@ -27,3 +28,9 @@ postgresql:
- libpq.lib
- libpgport.lib
- libpgcommon.lib
tools@windows:
- python-win
- meson
- ninja
- winflexbison
- strawberry-perl

View File

@@ -3,7 +3,11 @@ readline:
artifact:
source:
type: filelist
url: 'https://ftp.gnu.org/pub/gnu/readline/'
url: 'https://ftp.gnu.org/gnu/readline/'
regex: '/href="(?<file>readline-(?<version>[^"]+)\.tar\.gz)"/'
source-mirror:
type: filelist
url: 'https://ftpmirror.gnu.org/gnu/readline/'
regex: '/href="(?<file>readline-(?<version>[^"]+)\.tar\.gz)"/'
metadata:
license-files: [COPYING]

View File

@@ -6,7 +6,6 @@ xz:
repo: tukaani-project/xz
match: xz.+\.tar\.xz
prefer-stable: true
binary: hosted
metadata:
license-files: [COPYING]
license: 0BSD

View File

@@ -5,7 +5,6 @@ zlib:
type: ghrel
repo: madler/zlib
match: zlib.+\.tar\.gz
binary: hosted
metadata:
license-files: ['@/zlib.txt']
license: Zlib-Custom

View File

@@ -19,3 +19,4 @@ zstd:
- libzstd.a
static-libs@windows:
- zstd.lib
- libzstd.lib

View File

@@ -16,6 +16,8 @@ curl:
- zlib
- libssh2
- nghttp2
- brotli
- zstd
suggests@unix:
- libssh2
- brotli
@@ -27,9 +29,6 @@ curl:
- ldap
- idn2
- krb5
suggests@windows:
- brotli
- zstd
frameworks:
- CoreFoundation
- CoreServices

View File

@@ -10,10 +10,8 @@ frankenphp:
license: MIT
depends:
- php-embed
- go-xcaddy
depends@windows:
- php-embed
- go-win
- pthreads4w
suggests@unix:
- brotli
@@ -24,3 +22,7 @@ frankenphp:
- frankenphp
static-bins@windows:
- frankenphp.exe
tools:
- go-xcaddy
tools@windows:
- go-win

View File

@@ -0,0 +1,8 @@
msys2-build-essentials:
type: target
artifact:
binary: custom
env:
SPC_MSYS2_PATH: '{pkg_root_path}/msys2-build-essentials/msys64'
path@windows:
- '{pkg_root_path}/msys2-build-essentials/msys64/usr/bin'

View File

@@ -1,5 +0,0 @@
nasm:
type: target
artifact:
binary:
windows-x86_64: { type: url, url: 'https://dl.static-php.dev/static-php-cli/deps/nasm/nasm-2.16.01-win64.zip', extract: { nasm.exe: '{php_sdk_path}/bin/nasm.exe', ndisasm.exe: '{php_sdk_path}/bin/ndisasm.exe' } }

View File

@@ -1,5 +0,0 @@
php-sdk-binary-tools:
type: target
artifact:
binary:
windows-x86_64: { type: git, rev: master, url: 'https://github.com/php/php-sdk-binary-tools.git', extract: '{php_sdk_path}' }

View File

@@ -1,9 +0,0 @@
pkg-config:
type: target
artifact:
source: 'https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz'
binary:
linux-x86_64: { type: ghrel, repo: static-php/static-php-cli-hosted, match: pkg-config-x86_64-linux-musl-1.2.5.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }
linux-aarch64: { type: ghrel, repo: static-php/static-php-cli-hosted, match: pkg-config-aarch64-linux-musl-1.2.5.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }
macos-x86_64: { type: ghrel, repo: static-php/static-php-cli-hosted, match: pkg-config-x86_64-darwin.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }
macos-aarch64: { type: ghrel, repo: static-php/static-php-cli-hosted, match: pkg-config-aarch64-darwin.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }

View File

@@ -1,4 +0,0 @@
zig:
type: target
artifact:
binary: custom

View File

@@ -0,0 +1,9 @@
7za-win:
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://dl.static-php.dev/v3/tools/7zip/7za.exe', extract: '{pkg_root_path}/bin/7za.exe' }
tool:
provides:
- 7za.exe
binary-subdir: bin

View File

@@ -1,10 +1,15 @@
go-win:
type: target
type: tool
artifact:
binary: custom
env:
GOROOT: '{pkg_root_path}/go-win'
GOBIN: '{pkg_root_path}/go-win/bin'
GOPATH: '{pkg_root_path}/go-win/go'
GOPATH: '{pkg_root_path}/go-win/gopath'
path@windows:
- '{pkg_root_path}/go-win/bin'
tool:
provides:
- go.exe
- gofmt.exe
binary-subdir: go-win/bin

View File

@@ -1,5 +1,5 @@
go-xcaddy:
type: target
type: tool
artifact:
binary: custom
env:
@@ -8,5 +8,8 @@ go-xcaddy:
GOPATH: '{pkg_root_path}/go-xcaddy/go'
path@unix:
- '{pkg_root_path}/go-xcaddy/bin'
static-bins:
- xcaddy
tool:
provides:
- go
- gofmt
binary-subdir: go-xcaddy/bin

View File

@@ -1,7 +1,11 @@
jom:
type: target
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://download.qt.io/official_releases/jom/jom.zip', extract: '{pkg_root_path}/jom' }
path@windows:
- '{pkg_root_path}\jom'
tool:
provides:
- jom.exe
binary-subdir: jom

11
config/pkg/tool/meson.yml Normal file
View File

@@ -0,0 +1,11 @@
meson:
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://github.com/mesonbuild/meson/releases/download/1.11.1/meson-1.11.1-py3-none-any.whl', extract: '{pkg_root_path}/meson/meson-1.11.1-py3-none-any.whl' }
path@windows:
- '{pkg_root_path}\meson'
tool:
provides:
- meson.bat
binary-subdir: meson

10
config/pkg/tool/nasm.yml Normal file
View File

@@ -0,0 +1,10 @@
nasm:
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://dl.static-php.dev/static-php-cli/deps/nasm/nasm-2.16.01-win64.zip', extract: { nasm.exe: '{pkg_root_path}/bin/nasm.exe', ndisasm.exe: '{pkg_root_path}/bin/ndisasm.exe' } }
tool:
provides:
- nasm.exe
- ndisasm.exe
binary-subdir: bin

View File

@@ -0,0 +1,9 @@
ninja:
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://github.com/ninja-build/ninja/releases/download/v1.13.2/ninja-win.zip', extract: { ninja.exe: '{pkg_root_path}/bin/ninja.exe' } }
tool:
provides:
- ninja.exe
binary-subdir: bin

View File

@@ -0,0 +1,13 @@
pkg-config:
type: tool
artifact:
source: 'https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz'
binary:
linux-x86_64: { type: ghrel, repo: static-php/hosted, match: pkg-config-x86_64-linux-musl-1.2.5.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }
linux-aarch64: { type: ghrel, repo: static-php/hosted, match: pkg-config-aarch64-linux-musl-1.2.5.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }
macos-x86_64: { type: ghrel, repo: static-php/hosted, match: pkg-config-x86_64-darwin.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }
macos-aarch64: { type: ghrel, repo: static-php/hosted, match: pkg-config-aarch64-darwin.txz, extract: { bin/pkg-config: '{pkg_root_path}/bin/pkg-config' } }
tool:
provides:
- pkg-config
binary-subdir: bin

View File

@@ -1,8 +1,12 @@
protoc:
type: target
type: tool
artifact:
binary:
linux-x86_64: { type: ghrel, repo: protocolbuffers/protobuf, match: 'protoc-([0-9.]+)-linux-x86_64\.zip', extract: '{pkg_root_path}/protoc' }
linux-aarch64: { type: ghrel, repo: protocolbuffers/protobuf, match: 'protoc-([0-9.]+)-linux-aarch_64\.zip', extract: '{pkg_root_path}/protoc' }
path:
- '{pkg_root_path}/protoc/bin'
tool:
provides:
- protoc
binary-subdir: protoc/bin

View File

@@ -0,0 +1,8 @@
python-win:
type: tool
artifact:
binary: custom
tool:
provides:
- python.exe
binary-subdir: python-win/tools

View File

@@ -1,5 +1,9 @@
strawberry-perl:
type: target
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip', extract: '{pkg_root_path}/strawberry-perl' }
tool:
provides:
- perl.exe
binary-subdir: strawberry-perl/perl/bin

View File

@@ -1,7 +1,13 @@
upx:
type: target
type: tool
artifact:
binary:
linux-x86_64: { type: ghrel, repo: upx/upx, match: upx.+-amd64_linux\.tar\.xz, extract: { upx: '{pkg_root_path}/bin/upx' } }
linux-aarch64: { type: ghrel, repo: upx/upx, match: upx.+-arm64_linux\.tar\.xz, extract: { upx: '{pkg_root_path}/bin/upx' } }
windows-x86_64: { type: ghrel, repo: upx/upx, match: upx.+-win64\.zip, extract: { upx.exe: '{pkg_root_path}/bin/upx.exe' } }
tool:
provides:
- upx
provides@windows:
- upx.exe
binary-subdir: bin

View File

@@ -1,5 +1,9 @@
vswhere:
type: target
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://github.com/microsoft/vswhere/releases/download/3.1.7/vswhere.exe', extract: '{pkg_root_path}/bin/vswhere.exe' }
tool:
provides:
- vswhere.exe
binary-subdir: bin

View File

@@ -0,0 +1,12 @@
winflexbison:
type: tool
artifact:
binary:
windows-x86_64: { type: url, url: 'https://github.com/lexxmark/winflexbison/releases/download/v2.5.25/win_flex_bison-2.5.25.zip', extract: '{pkg_root_path}/winflexbison' }
path@windows:
- '{pkg_root_path}\winflexbison'
tool:
provides:
- win_flex.exe
- win_bison.exe
binary-subdir: winflexbison

14
config/pkg/tool/zig.yml Normal file
View File

@@ -0,0 +1,14 @@
zig:
type: tool
artifact:
binary: custom
tool:
provides:
- zig
- zig-cc
- zig-c++
- zig-ar
- zig-ld.lld
- zig-ranlib
- zig-objcopy
binary-subdir: zig

View File

@@ -45,7 +45,7 @@
<label :for="'build_' + item">{{ item }}</label>
</div>
</div>
<div v-if="selectedSystem === 'windows' && (checkedTargets.includes('fpm') || checkedTargets.includes('embed') || checkedTargets.includes('frankenphp'))" class="warning custom-block">
<div v-if="selectedSystem === 'windows' && checkedTargets.includes('fpm')" class="warning custom-block">
<p class="custom-block-title">WARNING</p>
<p>{{ I18N[lang].windowsSAPIUnavailable }}</p>
</div>
@@ -157,7 +157,7 @@
<div class="warning custom-block">
<p class="custom-block-title">WARNING</p>
<p>{{ I18N[lang].windowsDownSPCWarning }}</p>
<a href="https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe" target="_blank">https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe</a>
<a href="https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x86_64.exe" target="_blank">https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x86_64.exe</a>
</div>
</div>
</div>
@@ -278,7 +278,7 @@ const spcCommand = computed(() => {
const spcDownloadCommand = computed(() => {
const os = selectedSystem.value === 'macos' ? 'macos' : 'linux';
const arch = selectedArch.value;
return `curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-${os}-${arch} -o spc && chmod +x spc`;
return `curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-${os}-${arch} -o spc && chmod +x spc`;
});
const doctorCommandString = computed(() => `${spcCommand.value} doctor --auto-fix`);
@@ -425,7 +425,7 @@ const I18N: Record<string, Record<string, string>> = {
downloadPhpVersion: '下载 PHP 版本',
downloadSPCBinaryCommand: '下载 spc 二进制命令',
selectedSystem: '选择操作系统',
windowsSAPIUnavailable: 'Windows 目前不支持 fpm、embed、frankenphp 构建!',
windowsSAPIUnavailable: 'Windows 目前不支持 fpm 构建!',
useUPX: '是否开启 UPX 压缩(减小二进制体积)',
windowsDownSPCWarning: 'Windows 下请手动下载 spc.exe 二进制文件!',
usePreBuilt: '如果可能,使用预编译的依赖库(减少编译时间)',
@@ -459,7 +459,7 @@ const I18N: Record<string, Record<string, string>> = {
downloadPhpVersion: 'PHP version',
downloadSPCBinaryCommand: 'Download spc binary',
selectedSystem: 'Select OS',
windowsSAPIUnavailable: 'Windows does not support fpm, embed and frankenphp build!',
windowsSAPIUnavailable: 'Windows does not support fpm build!',
useUPX: 'Enable UPX compression (reduce binary size)',
windowsDownSPCWarning: 'Please download the spc.exe binary manually on Windows!',
usePreBuilt: 'Use pre-built dependencies where available (reduce compile time)',

View File

@@ -8,6 +8,7 @@ export default {
{ text: 'First Build', link: '/en/guide/first-build' },
{ text: 'PHP SAPI Reference', link: '/en/guide/sapi-reference' },
{ text: 'CLI Reference', link: '/en/guide/cli-reference' },
{ text: 'Migrating from v2', link: '/en/guide/migrate-from-v2' },
],
},
{

View File

@@ -8,6 +8,7 @@ export default {
{ text: '第一次构建', link: '/zh/guide/first-build' },
{ text: 'PHP SAPI 构建参考', link: '/zh/guide/sapi-reference' },
{ text: '命令行参考', link: '/zh/guide/cli-reference' },
{ text: '从 v2 迁移', link: '/zh/guide/migrate-from-v2' },
],
},
{

View File

@@ -4,14 +4,15 @@
A Package is the core concept in StaticPHP's build system, representing a buildable/installable unit such as a PHP extension, library, or build target.
Each Package contains build information, dependencies, and build logic, forming StaticPHP's build model. Package definitions are primarily implemented through YAML/JSON configuration files. The package configuration files for the `core` registry are located in the `config/pkg/` directory, and the corresponding build classes are in the `src/Package/` directory.
Each Package contains build information, dependencies, and build logic, forming StaticPHP's build model. Package definitions are primarily implemented through YAML/JSON configuration files. The package configuration files for the `core` registry are located in the `config/pkg/` directory, and optional recipe classes are in the corresponding subdirectories of `src/Package/`.
Packages are primarily divided into four types:
Packages are divided into five types:
- **php-extension**: A PHP extension package containing build information and logic for a PHP extension.
- **library**: A library package containing build information and logic for build tools, dependency libraries, etc.
- **library**: A dependency library package, usually installed into `buildroot/` for other packages to compile and link against.
- **target**: A build target package representing the final build artifact, such as a PHP binary or curl binary. Inherits from the `library` package type.
- **virtual-target**: A virtual build target package representing an abstract build target that doesn't directly correspond to a build artifact, primarily used for dependency management and build scheduling.
- **tool**: A host-side build tool package, installed separately under `pkgroot/` and not treated as a link-time library dependency.
```yaml
{pkg-name}:
@@ -21,7 +22,7 @@ Packages are primarily divided into four types:
## Artifact Definition
An Artifact is a definition independent of Packages. It contains the source archive file or pre-built binary for building packages. Each Artifact defines download URLs, extraction methods, and build artifact file paths. Packages can reference one or more Artifacts via the `artifact` field to obtain the source or binaries needed for building.
An Artifact is a definition independent of Packages. It contains the source archive file or pre-built binary for building packages. Each Artifact defines download URLs, extraction methods, and build artifact file paths. A Package can reference one Artifact via the `artifact` field to obtain the source or binary needed for building.
In simple terms, by default one Package corresponds to one Artifact; if multiple Packages share the same source, you can define a single Artifact for multiple Packages to reference. Artifact definitions are located in the `config/artifact/` directory, and the corresponding custom download/extract logic classes are in the `src/Package/Artifact/` directory. For special package types like virtual targets and PHP built-in extensions, a Package may also omit the Artifact field entirely.
@@ -40,7 +41,7 @@ For more on Artifact definitions, see the [Artifact Model](./artifact-model) cha
## php-extension Package Type
A php-extension package represents a PHP extension. Its configuration file is located in the `config/pkg/ext/` directory, and its build class inherits from `PhpExtensionPackage` in the `src/Package/Extension/` directory. PHP extension package configurations include extension name, version, dependencies, build options, and more.
A php-extension package represents a PHP extension. Its configuration file is located in the `config/pkg/ext/` directory. Optional recipe classes are normally placed in `src/Package/Extension/`, registered with `#[Extension]`, and receive the corresponding `PhpExtensionPackage` through callback context. Inheriting from `PhpExtensionPackage` is supported but is not required by the current core recipes.
```yaml
ext-lz4:
@@ -57,7 +58,7 @@ ext-lz4:
depends:
- liblz4
php-extension:
arg-type@unix: '--enable-lz4=@shared_suffix@ --with-lz4-includedir=@build_root_path@'
arg-type@unix: '--enable-lz4@shared_suffix@ --with-lz4-includedir=@build_root_path@'
arg-type@windows: '--enable-lz4'
```
@@ -72,16 +73,18 @@ ext-{ext-name}: # Package name must start with ext- prefix
lang: c # Optional, implementation language of the extension (c / c++ etc.)
frameworks: [] # Optional, list of related macOS framework dependencies
artifact: '{artifact-name}' # Optional; when a string, references an Artifact definition
# with the same name; when an object, is an inline Artifact
artifact: '{artifact-name}' # Optional; when a string, references the named Artifact definition;
# when an object, it is an inline Artifact
# (built-in extensions don't need this field)
# depends / suggests support @windows / @unix / @linux / @macos suffixes
# depends / suggests / tools support @windows / @unix / @linux / @macos suffixes
depends: [] # Optional, hard dependency list (library names as-is, PHP extensions need ext- prefix)
depends@unix: [] # Optional, hard dependencies only effective on Unix platforms
depends@windows: [] # Optional, hard dependencies only effective on Windows platforms
suggests: [] # Optional, optional dependency list (same format as depends)
suggests@unix: []
tools: [] # Optional, host-side build tool dependencies; resolved separately
tools@windows: [] # Optional, platform-specific tool dependencies
# ── php-extension Specific Fields (nested under php-extension: object) ────
php-extension:
@@ -100,7 +103,7 @@ ext-{ext-name}: # Package name must start with ext- prefix
# @shared_path_suffix@ → Expands to =shared,{buildroot} in shared builds,
# expands to ={buildroot} in static builds
arg-type: enable
arg-type@unix: '--enable-{extname}=@shared_suffix@'
arg-type@unix: '--enable-my-extension@shared_suffix@'
arg-type@windows: with-path
zend-extension: false # Optional, true indicates this is a Zend extension (e.g., opcache, xdebug)
@@ -121,7 +124,7 @@ ext-{ext-name}: # Package name must start with ext- prefix
## library Package Type
A library package represents a dependency library that needs to be compiled from source (such as openssl, zlib, etc.). Its configuration file is located in the `config/pkg/lib/` directory, and its build class inherits from `LibraryPackage` in the `src/Package/Library/` directory.
A library package represents a dependency library, such as openssl or zlib, installed from source or a pre-built binary. Its configuration file is located in the `config/pkg/lib/` directory. Optional recipe classes are normally placed in `src/Package/Library/`, registered with `#[Library]`, and receive a `LibraryPackage` through callback context; they do not need to inherit from it.
Taking openssl as an example:
@@ -161,22 +164,27 @@ Allowed fields for `library`:
# ── Common Fields ─────────────────────────────────────────────────────────
description: '..' # Optional, human-readable package description
license: MIT # Optional, SPDX license identifier (for license export)
license: # Optional, license material copied after a source build
type: file # type is file or text; a list of entries is also accepted
path: LICENSE
lang: c # Optional, implementation language of the library (c / c++ etc.)
frameworks: [] # Optional, list of related framework tags
artifact: '{artifact-name}' # Required; when a string, references an Artifact definition
# with the same name; when an object, is an inline Artifact
artifact: '{artifact-name}' # Required; when a string, references the named Artifact definition;
# when an object, it is an inline Artifact
# depends / suggests support @windows / @unix / @linux / @macos suffixes
# depends / suggests / tools support @windows / @unix / @linux / @macos suffixes
depends: [] # Optional, hard dependency list (library names or PHP extension names with ext- prefix)
depends@unix: []
depends@windows: []
suggests: [] # Optional, optional dependency list (same format as depends)
tools: [] # Optional, ToolPackage names required only while building
tools@windows: []
# ── library / target Specific Fields ───────────────────────────────────────
# The following fields are used to verify that artifacts have been correctly
# installed after the build. They support @unix / @windows / @linux / @macos suffixes.
# installed after the build. headers, static-libs, and static-bins support
# @unix / @windows / @linux / @macos suffixes.
# Verify that specified header files or directories exist under buildroot/include/
# Relative paths are based on buildroot/include/, absolute paths are used directly
@@ -229,19 +237,51 @@ The following path placeholders are supported in string values of the `path`, `e
| `{working_dir}` | Working directory (project root) |
| `{download_path}` | Download cache directory (`downloads/`) |
| `{source_path}` | Extracted source directory (`source/`) |
| `{php_sdk_path}` | Windows PHP SDK directory |
| `{spc_msys2_path}` | MSYS2 root directory (`msys64/`) — Windows only |
## tool Package Type
A `tool` package represents an executable needed while building another package, rather than a library linked into the final target. Tool packages may use a pre-built binary or build from source, and install under `pkgroot/` by default, using either a shared `bin/` directory or a configured subdirectory. Packages request them through the top-level `tools` field; this dependency set is resolved independently of `depends` and `suggests`.
```yaml
nasm:
type: tool
artifact:
binary:
windows-x86_64:
type: url
url: 'https://example.com/nasm-win64.zip'
extract:
nasm.exe: '{pkg_root_path}/bin/nasm.exe'
ndisasm.exe: '{pkg_root_path}/bin/ndisasm.exe'
tool:
provides: [nasm.exe, ndisasm.exe]
binary-subdir: bin
min-version: '2.16'
```
The nested `tool` object supports:
| Field | Required | Meaning |
|---|---|---|
| `provides` | Yes | Executable filenames used to decide whether the tool is installed |
| `binary-subdir` | No | Directory below `install-root` containing the executables; defaults to the install root |
| `install-root` | No | Installation root; defaults to `PKG_ROOT_PATH` and supports path placeholders |
| `min-version` | No | Declared minimum version metadata exposed by `ToolPackage`; the installer does not currently enforce it |
Fields inside `tool` may use `@windows`, `@unix`, `@linux`, and `@macos` suffixes. For example, `provides@windows` can list `.exe` names while `provides@unix` lists Unix names.
## target Package Type
A `target` package represents a final build artifact. It inherits from `library`, so it includes all definition fields of `library`. The configuration file for `target` packages is located in the `config/pkg/target/` directory, and its build class inherits from `TargetPackage` in the `src/Package/Target/` directory.
A `target` package represents a final build artifact. It inherits from `library`, so it includes all definition fields of `library`. Its configuration file is located in `config/pkg/target/`. Optional recipe classes are normally placed in `src/Package/Target/`, registered with `#[Target]`, and receive a `TargetPackage`; inheriting from `TargetPackage` is optional.
The only difference from `library` is that a `target` package can be registered as a build target and automatically registers the build command `spc build:{target-name}`.
## virtual-target Package Type
Unlike `target`, a `virtual-target` may not include an `artifact`, meaning it doesn't directly correspond to a buildable entity but is instead an abstract build target, primarily used for dependency management and build scheduling. The configuration file for `virtual-target` is located in the `config/pkg/target/` directory, and its build class inherits from `TargetPackage` in the `src/Package/Target/` directory. Its definition is essentially the same as `target`, but the `artifact` field is optional and typically not set. `virtual-target` is primarily used in the following scenarios:
Unlike `target`, a `virtual-target` may omit `artifact`, meaning it doesn't directly correspond to a buildable entity but is instead an abstract build target, primarily used for dependency management and build scheduling. Its configuration and optional recipe classes use the same directories and `#[Target]` registration mechanism as `target`. Its definition is otherwise essentially the same, but the `artifact` field is optional and typically not set. `virtual-target` is primarily used in the following scenarios:
- Defining an abstract build target for other packages to depend on, without directly corresponding to a buildable entity.
- Serving as a common dependency for multiple `target` packages, simplifying dependency management.
A typical example is the `php-cli`, `php-fpm` build targets for PHP. They have no independent source code and depend on `php-src`, with the final build outcome (CLI or FPM binary) determined through build scheduling.
Typical examples are the `php-cli` and `php-fpm` build targets. They have no independent source and depend on the `php` target, whose Artifact is `php-src`; build scheduling determines whether the CLI or FPM binary is produced.

View File

@@ -29,14 +29,14 @@ spc download [artifacts] [options]
| `--for-packages=<list>` | | Download artifacts needed by the given packages |
| `--without-suggests` | | Skip suggested packages when using `--for-extensions` |
| `--clean` | | Delete existing download cache before fetching |
| `--with-php=<ver>` | | PHP version in `major.minor` format (default: `8.4`) |
| `--with-php=<ver>` | | PHP version in `major.minor` format (default: `8.5`) |
| `--prefer-binary` | `-p` | Prefer pre-built binaries over source archives |
| `--prefer-source` | | Prefer source archives over pre-built binaries |
| `--source-only` | | Only download source artifacts |
| `--binary-only` | | Only download binary artifacts |
| `--parallel=<n>` | `-P` | Number of parallel downloads (default: `1`) |
| `--retry=<n>` | `-R` | Number of retries on failure (default: `0`) |
| `--ignore-cache=<list>` | | Force re-download the specified artifacts |
| `--ignore-cache=<list>` | `-i` | Force re-download the specified artifacts |
| `--no-alt` | | Do not use alternative mirror URLs |
| `--no-shallow-clone` | | Do not clone git repositories shallowly |
| `--custom-url=<src:url>` | `-U` | Override the download URL for a source |
@@ -47,7 +47,7 @@ spc download [artifacts] [options]
```bash
# Download only what the chosen extensions need
spc download --for-extensions="bcmath,openssl,curl" --with-php=8.4
spc download --for-extensions="bcmath,openssl,curl" --with-php=8.5
# Download specific artifacts
spc download "php-src,openssl"
@@ -136,7 +136,7 @@ All downloader options are available with the `--dl-` prefix:
| Option | Description |
|------------------------------------|--------------------------------------------|
| `--dl-with-php=<ver>` | PHP version to download (default: `8.4`) |
| `--dl-with-php=<ver>` | PHP version to download (default: `8.5`) |
| `--dl-prefer-binary` | Prefer pre-built binaries for dependencies |
| `--dl-parallel=<n>` | Number of parallel downloads |
| `--dl-retry=<n>` | Number of retries on failure |
@@ -265,12 +265,12 @@ spc check-update [artifact] [options]
### Options
| Option | Short | Description |
|---|---|---|
| `--json` | | Output results in JSON format |
| Option | Short | Description |
|---|---|------------------------------------------------------------------------------------------|
| `--json` | | Output results in JSON format |
| `--bare` | | Check without requiring the artifact to be downloaded first (old version will be `null`) |
| `--parallel=<n>` | `-p` | Number of parallel update checks (default: `10`) |
| `--with-php=<ver>` | | PHP version context in `major.minor` format (default: `8.4`) |
| `--parallel=<n>` | `-p` | Number of parallel update checks (default: `10`) |
| `--with-php=<ver>` | | PHP version context in `major.minor` format (default: `8.5`) |
### Examples

View File

@@ -26,7 +26,7 @@ The `craft` command reads a `craft.yml` file and handles everything automaticall
Create a `craft.yml` in your working directory and declare the PHP version, extensions, and target SAPIs:
```yaml
php-version: 8.4
php-version: 8.5
extensions: bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer
sapi:
- cli
@@ -80,10 +80,10 @@ If you want to pre-download ahead of time, or if you're working in a slow-networ
```bash
# Download only what the chosen extensions need (recommended)
spc download --for-extensions="bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer" --with-php=8.4
spc download --for-extensions="bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer" --with-php=8.5
# Download by specific package names
spc download "curl,openssl" --with-php=8.4
spc download "curl,openssl" --with-php=8.5
```
Downloads are cached in `downloads/` and reused across builds automatically.

View File

@@ -47,7 +47,7 @@ Build your CLI with [symfony/console](https://symfony.com/doc/current/components
## Community
Join our [Discord server](https://discord.gg/nrSRbpMJ) to ask questions, share your builds, and connect with other StaticPHP users.
Join our [Discord server](https://discord.gg/xf6Rd4pEAk) to ask questions, share your builds, and connect with other StaticPHP users.
## Next steps

View File

@@ -27,18 +27,23 @@ Pick the installation method that fits your use case:
> Fun fact: `spc` itself is a static PHP binary built with StaticPHP. We use StaticPHP to build StaticPHP's own build tool.
```shell
# Linux x86_64
::: code-group
```shell [Linux x86_64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64 -o spc
# Linux arm64
```
```shell [Linux arm64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-aarch64 -o spc
# macOS x86_64 (Intel)
```
```shell [macOS x86_64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-x86_64 -o spc
# macOS arm64 (Apple Silicon)
```
```shell [macOS arm64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-aarch64 -o spc
# Windows x86_64 (PowerShell)
```
```powershell [Windows x86_64]
curl.exe -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x86_64.exe -o spc.exe
```
:::
On Linux and macOS, mark the binary as executable before running it:

View File

@@ -0,0 +1,216 @@
# Migrating from v2
StaticPHP v3 is a ground-up rewrite. The core build workflow (`download → build → combine`) remains familiar, but several commands, options, and configuration fields have changed. This page covers everything you need to update before switching.
::: info Scope
This guide only covers user-facing CLI commands, options, `craft.yml` fields, and `env.ini` variable names. Internal PHP APIs are not covered.
:::
## Documentation URL Change
The official documentation site has moved:
- **v3 docs (current)**: [https://static-php.dev](https://static-php.dev) — the main site now hosts v3 documentation.
- **v2 docs (archived)**: [https://static-php.github.io/v2-docs/](https://static-php.github.io/v2-docs/) — v2 documentation is preserved here for reference.
Update any bookmarks or internal links accordingly.
## `spc` Binary Download URL Change
The nightly `spc` self-contained binary has moved to a new path:
| | URL |
|---|---|
| **v2** | `https://dl.static-php.dev/static-php-cli/spc-bin/nightly/` |
| **v3** | `https://dl.static-php.dev/v3/spc-bin/nightly/` |
Update any CI scripts or bootstrap commands that download the `spc` binary directly. For example:
```bash
# v2
curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
# v3
curl -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64
```
## Removed Commands
| v2 Command | v3 Replacement | Notes |
|---|---|---|
| `del-download` | `spc reset` | `reset` also accepts `--with-pkgroot` and `--with-download` for finer control |
| `del-download --all` | `spc reset --with-download` | Removes the downloads cache directory |
## Removed Options
### `--with-added-patch` / `-P` (build command)
This option allowed injecting external PHP patch scripts at specific build stages. **It has been removed in v3.**
There is no direct drop-in replacement. If you relied on this feature:
- Consider contributing your patches upstream to the StaticPHP repository.
- For project-specific patches, use a custom registry with a package class. See [Writing Package Classes](/en/develop/extending/package-classes) for details.
::: tip Future Plans
A single-file hook API for lightweight patches may be provided in a future release.
:::
### Windows-only: `--with-sdk-binary-dir` and `--vs-ver`
These options are no longer accepted on the command line. In v3, the `php-sdk-binary-tools` dependency has been completely removed. v3 now manages its own **MSYS2** environment to support autotools-based library builds on Windows. Run `spc doctor --install` to download and configure MSYS2 automatically.
If you need to point to a custom MSYS2 installation, set the `SPC_MSYS2_PATH` environment variable to the `msys64` directory (e.g. `C:\msys64`). Visual Studio is now auto-detected by the toolchain — no manual version flag needed.
::: warning Migrating from v2
v2 relied on `php-sdk-binary-tools` and required `--with-sdk-binary-dir` and `--vs-ver` on every build invocation. In v3 these options are gone. Remove them from all CI scripts and run `spc doctor --install` once to set up the Windows build environment.
:::
## Renamed / Deprecated Options
The following options have been renamed. The old names are accepted where noted, but you should update your scripts.
| v2 Option | v3 Option | Status |
|---|---|---|
| `--prefer-pre-built` | `--prefer-binary` / `-p` | Old name kept as a deprecated alias |
| `--with-libs=<list>` | `--with-packages=<list>` | — |
| `--with-suggested-libs` / `-L` | `--with-suggests` | Old `-L` / `-E` flags removed |
| `--with-suggested-exts` / `-E` | `--with-suggests` | Merged into a single flag |
### Example
```bash
# v2
spc build curl,gd --build-cli --with-libs="openssl" -L -E
# v3
spc build curl,gd --build-cli --with-packages="openssl" --with-suggests
```
## Changed `build` Command Behaviour
The `build` command (alias: `build:php`) still works. However, v3 also provides **dedicated single-target commands** that do not require SAPI selection flags:
| v2 | v3 Equivalent |
|---|---|
| `spc build exts --build-cli` | `spc build:php-cli exts` |
| `spc build exts --build-fpm` | `spc build:php-fpm exts` |
| `spc build exts --build-cgi` | `spc build:php-cgi exts` |
| `spc build exts --build-micro` | `spc build:php-micro exts` |
| `spc build exts --build-embed` | `spc build:php-embed exts` |
| `spc build exts --build-frankenphp` | `spc build:frankenphp exts` |
Use `build:php` when you need to build multiple SAPIs in one pass (the `--build-*` flags remain valid there).
### Automatic Download in Build Commands
In v3, all `build:*` commands automatically download any missing dependencies before building. You no longer need to run `spc download` as a separate step:
```bash
# v2 — two steps required
spc download --for-extensions=curl,gd
spc build curl,gd --build-cli
# v3 — one step is enough
spc build:php-cli curl,gd
```
To opt out of the automatic download (for example in CI where sources are pre-cached), pass `--no-download`:
```bash
spc build:php-cli curl,gd --no-download
```
## Changed `download` Command Options
| v2 | v3 | Notes |
|---|---|---|
| `--prefer-pre-built` | `--prefer-binary` / `-p` | Deprecated alias kept |
| `--with-libs` | `--for-libs` | Separate from packages |
| *(no equivalent)* | `--for-packages` | Unified package filter |
| *(no equivalent)* | `--parallel` / `-P` | Parallel downloads |
| *(no equivalent)* | `--retry` / `-R` | Retry on failure |
## Removed Dev Commands
These development utility commands have been removed or consolidated:
| v2 Command | v3 Replacement |
|---|---|
| `dev:extensions` / `list-ext` | `spc dev:info <package>` |
| `dev:ext-version` / `dev:ext-ver` | `spc dev:info <package>` |
| `dev:lib-version` / `dev:lib-ver` | `spc dev:info <package>` |
| `dev:php-version` / `dev:php-ver` | `spc dev:info php-src` |
| `dev:gen-ext-dep-docs` + `dev:gen-lib-dep-docs` | `spc dev:gen-deps-data` |
## Renamed Dev Commands
| v2 | v3 | Notes |
|---|---|---|
| `dev:sort-config` / `sort-config` | `dev:lint-config` | Old alias still accepted |
## New Commands in v3
These commands are new in v3 with no v2 equivalent:
| Command | Description |
|---|---|
| `spc reset` | Clean `buildroot/` and `source/` directories |
| `spc check-update` | Check for newer artifact versions |
| `spc build:php-cli` | Build CLI SAPI (no flags needed) |
| `spc build:php-fpm` | Build PHP-FPM (no flags needed) |
| `spc build:php-cgi` | Build PHP CGI (no flags needed) |
| `spc build:php-micro` | Build phpmicro (no flags needed) |
| `spc build:php-embed` | Build embed SAPI (no flags needed) |
| `spc build:frankenphp` | Build FrankenPHP (no flags needed) |
| `spc dev:shell` | Interactive shell with build environment |
| `spc dev:is-installed` | Check whether a package is installed |
| `spc dev:dump-stages` | Dump all package build stages to JSON |
| `spc dev:dump-capabilities` | Dump buildable/installable capabilities |
| `spc dev:info` | Show configuration info for a package |
## `craft.yml` Changes
### Removed: `build-options.with-added-patch`
The `with-added-patch` key inside `build-options` is no longer parsed and will be silently ignored. Remove it from your `craft.yml`:
```yaml
# v2 — remove this block
build-options:
with-added-patch:
- my-patch.php
```
### `libs` → `packages` (both work)
The top-level `libs` field still works. The preferred v3 field name is `packages`, which is a superset covering libraries and other tool packages:
```yaml
# v2
libs: nghttp2,liblz4
# v3 (preferred)
packages: nghttp2,liblz4
```
## `env.ini` Variable Renames
If you customise `config/env.ini` or export environment variables in CI, update the following names:
| v2 Variable | v3 Variable |
|---|---|
| `SPC_LINUX_DEFAULT_CC` | `SPC_DEFAULT_CC` |
| `SPC_LINUX_DEFAULT_CXX` | `SPC_DEFAULT_CXX` |
| `SPC_LINUX_DEFAULT_AR` | `SPC_DEFAULT_AR` |
| `SPC_LINUX_DEFAULT_LD` | `SPC_DEFAULT_LD` |
| `SPC_LIBC` | `SPC_TARGET` |
`SPC_TARGET` uses a new format that encodes both architecture and libc in a single string, for example:
| v2 | v3 |
|---|---|
| `SPC_LIBC=musl` | `SPC_TARGET=x86_64-linux-musl` |
| `SPC_LIBC=gnu` | `SPC_TARGET=x86_64-linux-gnu.2.17` |
New logging variables were also added (`SPC_ENABLE_LOG_FILE`, `SPC_LOGS_DIR`, `SPC_PRESERVE_LOGS`). Refer to [Environment Variables](/en/guide/env-vars) for details.

View File

@@ -1,20 +1,18 @@
# Package 模型
<!-- TODO: 统一 Package 模型说明library / php-extension / target 类型。
config/pkg/ 下 per-package YAML 格式、depends 字段、平台覆盖(@windows / @unix 写法)。
artifact.source 和 artifact.binary 字段。附注释的 library 和 extension YAML 示例。 -->
## Package 定义
Package 是 StaticPHP 构建系统中的核心概念,代表一个可构建/可安装的单元,如 PHP 扩展、库、构建目标等。
每个 Package 包含构建信息、依赖关系、构建逻辑等,构成了 StaticPHP 的构建模型。Package 的定义主要通过 YAML/JSON 配置文件来实现。`core` 注册表的包配置文件位于 `config/pkg/` 目录下,对应的构建类位于 `src/Package/` 目录
每个 Package 包含构建信息、依赖关系、构建逻辑等,构成了 StaticPHP 的构建模型。Package 的定义主要通过 YAML/JSON 配置文件来实现。`core` Registry 的 Package 配置位于 `config/pkg/` 目录下,可选 recipe class 位于 `src/Package/` 对应的子目录
Package 主要分为种类型:
Package 分为种类型:
- **php-extension**PHP 扩展包,包含 PHP 扩展的构建信息和构建逻辑。
- **library**库包,包含构建工具链、依赖库等的构建信息和构建逻辑
- **library**依赖库 Package通常安装到 `buildroot/`,供其他 Package 编译和链接
- **target**:构建目标包,代表最终的构建产物,如 PHP 二进制、curl 二进制等,继承自 `library` 包类型。
- **virtual-target**:虚构建目标包,代表一个抽象的构建目标,不直接对应构建产物,主要用于依赖管理和构建调度。
- **tool**:宿主机侧构建工具 Package单独安装在 `pkgroot/` 下,不作为链接期库依赖处理。
```yaml
{pkg-name}:
@@ -24,7 +22,7 @@ Package 主要分为四种类型:
## Artifact 定义
Artifact 是独立于 Package 的定义,它包含构建包的源码归档文件或预构建的二进制文件。每个 Artifact 定义了下载 URL、解压方式、构建产物的文件路径等信息。Package 可以通过 `artifact` 字段引用一个或多个 Artifact获取构建所需的源码或二进制文件。
Artifact 是独立于 Package 的定义,它包含构建包的源码归档文件或预构建的二进制文件。每个 Artifact 定义了下载 URL、解压方式、构建产物的文件路径等信息。一个 Package 可以通过 `artifact` 字段引用一个 Artifact,以获取构建所需的源码或二进制文件。
简单来说,默认情况下,一个 Package 对应一个 Artifact如果多个 Package 共用一份源码时,可以定义一个 Artifact 供多个 Package 引用。Artifact 的定义位于 `config/artifact/` 目录下,对应的自定义下载/解压逻辑类位于 `src/Package/Artifact/` 目录下对于虚拟目标、PHP 内置扩展等特殊包类型Package 也可以不设置 Artifact 字段。
@@ -43,7 +41,7 @@ example-library-package:
## php-extension 包类型
php-extension 一个包代表一个 PHP 扩展,它的配置文件位于 `config/pkg/ext/` 目录下,构建类继承自 `PhpExtensionPackage`,位于 `src/Package/Extension/` 目录下。PHP 扩展包的配置文件包含扩展名称、版本、依赖关系、构建选项等信息
php-extension Package 代表一个 PHP 扩展,它的配置文件位于 `config/pkg/ext/` 目录下。可选的 recipe class 通常放在 `src/Package/Extension/`,通过 `#[Extension]` 注册,并从 callback context 接收对应的 `PhpExtensionPackage`。当前 core recipe 支持继承 `PhpExtensionPackage`,但并不要求继承
```yaml
ext-lz4:
@@ -60,7 +58,7 @@ ext-lz4:
depends:
- liblz4
php-extension:
arg-type@unix: '--enable-lz4=@shared_suffix@ --with-lz4-includedir=@build_root_path@'
arg-type@unix: '--enable-lz4@shared_suffix@ --with-lz4-includedir=@build_root_path@'
arg-type@windows: '--enable-lz4'
```
@@ -75,15 +73,17 @@ ext-{ext-name}: # 包名必须以 ext- 前缀开头
lang: c # 可选扩展的实现语言c / c++ 等)
frameworks: [] # 可选相关macOS框架依赖列表
artifact: '{artifact-name}' # 可选;字符串时引用同名 Artifact 定义,
artifact: '{artifact-name}' # 可选;字符串时引用指定名称的 Artifact 定义,
# 对象时为内联 Artifact内置扩展无需此字段
# depends / suggests 支持 @windows / @unix / @linux / @macos 后缀
# depends / suggests / tools 支持 @windows / @unix / @linux / @macos 后缀
depends: [] # 可选硬依赖列表库名直接写PHP 扩展需加 ext- 前缀)
depends@unix: [] # 可选,仅 Unix 平台生效的硬依赖
depends@windows: [] # 可选,仅 Windows 平台生效的硬依赖
suggests: [] # 可选,可选依赖列表(格式同 depends
suggests@unix: []
tools: [] # 可选,宿主机侧构建工具依赖,单独解析
tools@windows: [] # 可选,特定平台的工具依赖
# ── php-extension 专属字段(嵌套在 php-extension: 对象中)─────────────────
php-extension:
@@ -101,7 +101,7 @@ ext-{ext-name}: # 包名必须以 ext- 前缀开头
# @shared_suffix@ → 共享构建时展开为 =shared静态构建时为空
# @shared_path_suffix@ → 共享构建时展开为 =shared,{buildroot},静态构建时为 ={buildroot}
arg-type: enable
arg-type@unix: '--enable-{extname}=@shared_suffix@'
arg-type@unix: '--enable-my-extension@shared_suffix@'
arg-type@windows: with-path
zend-extension: false # 可选true 表示这是 Zend 扩展(如 opcache、xdebug
@@ -120,7 +120,7 @@ ext-{ext-name}: # 包名必须以 ext- 前缀开头
## library 包类型
library 包代表一个需要从源码编译的依赖库(如 openssl、zlib 等),其配置文件位于 `config/pkg/lib/` 目录下,构建类继承自 `LibraryPackage`位于 `src/Package/Library/` 目录下
library Package 代表 openssl、zlib 等依赖库,可以从源码或预构建二进制安装。其配置文件位于 `config/pkg/lib/` 目录下。可选的 recipe class 通常放在 `src/Package/Library/`通过 `#[Library]` 注册,并从 callback context 接收 `LibraryPackage`;不要求继承该类
以 openssl 为例:
@@ -160,20 +160,25 @@ openssl:
# ── 通用字段 ─────────────────────────────────────────────────────────────
description: '...' # 可选,人类可读的包描述
license: MIT # 可选,SPDX 许可证标识符(用于许可证导出)
license: # 可选,从源码构建后复制的许可证内容
type: file # type 可为 file 或 text也可填写多个条目的列表
path: LICENSE
lang: c # 可选库的实现语言c / c++ 等)
frameworks: [] # 可选,相关框架标签列表
artifact: '{artifact-name}' # 必填;字符串时引用同名 Artifact 定义,对象时为内联 Artifact
artifact: '{artifact-name}' # 必填;字符串时引用指定名称的 Artifact 定义,对象时为内联 Artifact
# depends / suggests 支持 @windows / @unix / @linux / @macos 后缀
# depends / suggests / tools 支持 @windows / @unix / @linux / @macos 后缀
depends: [] # 可选,硬依赖列表(库名或 ext- 前缀的 PHP 扩展名)
depends@unix: []
depends@windows: []
suggests: [] # 可选,可选依赖列表(格式同 depends
tools: [] # 可选,仅构建时需要的 ToolPackage 名称
tools@windows: []
# ── library / target 专属字段 ────────────────────────────────────────────
# 以下字段用于构建完成后验证产物是否已正确安装,支持 @unix / @windows / @linux / @macos 后缀
# 以下字段用于构建完成后验证产物是否已正确安装headers、static-libs、static-bins
# 支持 @unix / @windows / @linux / @macos 后缀
# 验证 buildroot/include/ 下是否存在指定头文件或目录
# 相对路径基于 buildroot/include/,绝对路径直接使用
@@ -223,19 +228,51 @@ openssl:
| `{working_dir}` | 工作目录(项目根目录) |
| `{download_path}` | 下载缓存目录(`downloads/` |
| `{source_path}` | 解压源码目录(`source/` |
| `{php_sdk_path}` | Windows PHP SDK 目录 |
| `{spc_msys2_path}` | MSYS2 根目录(`msys64/`)——仅 Windows |
## tool 包类型
`tool` Package 表示构建其他 Package 时需要的可执行工具,而不是链接进最终 target 的库。Tool Package 可以使用预构建二进制,也可以从源码构建,默认安装在 `pkgroot/` 下的共享 `bin/` 或配置的子目录。其他 Package 通过顶层 `tools` 字段请求这些工具;该依赖集合与 `depends``suggests` 分开解析。
```yaml
nasm:
type: tool
artifact:
binary:
windows-x86_64:
type: url
url: 'https://example.com/nasm-win64.zip'
extract:
nasm.exe: '{pkg_root_path}/bin/nasm.exe'
ndisasm.exe: '{pkg_root_path}/bin/ndisasm.exe'
tool:
provides: [nasm.exe, ndisasm.exe]
binary-subdir: bin
min-version: '2.16'
```
嵌套的 `tool` 对象支持:
| 字段 | 是否必填 | 含义 |
|---|---|---|
| `provides` | 是 | 用于判断工具是否已经安装的可执行文件名 |
| `binary-subdir` | 否 | `install-root` 下存放可执行文件的目录;默认就是安装根目录 |
| `install-root` | 否 | 安装根目录;默认为 `PKG_ROOT_PATH`,支持路径占位符 |
| `min-version` | 否 | 由 `ToolPackage` 暴露的最低版本元数据installer 当前不会强制校验 |
`tool` 内的字段可以使用 `@windows``@unix``@linux``@macos` 后缀。例如,`provides@windows` 可以列出 `.exe` 名称,`provides@unix` 列出 Unix 名称。
## target 包类型
`target` 代表一个最终的构建产物,它继承于 `library`,所以包含 `library` 的所有定义字段。`target` 包的配置文件位于 `config/pkg/target/` 目录下,构建类继承自 `TargetPackage`,位于 `src/Package/Target/` 目录下
`target` Package 代表一个最终的构建产物,它继承于 `library`,所以包含 `library` 的所有定义字段。配置文件位于 `config/pkg/target/`。可选的 recipe class 通常放在 `src/Package/Target/`,通过 `#[Target]` 注册,并接收 `TargetPackage`;是否继承 `TargetPackage` 是可选的
`library` 的唯一区别是,`target` 包可以注册成为构建目标,且自动注册构建命令 `spc build:{target-name}`
## virtual-target 包类型
`target` 不同的是`virtual-target` 可以不包含 `artifact`,即不直接对应一个可构建的实体,而是一个抽象的构建目标,主要用于依赖管理和构建调度。`virtual-target` 的配置文件位于 `config/pkg/target/` 目录下,构建类继承自 `TargetPackage`,位于 `src/Package/Target/` 目录下。它的定义与 `target` 基本相同,但 `artifact` 字段可选且通常不设置。`virtual-target` 主要用于以下场景:
`target` 不同,`virtual-target` 可以省略 `artifact`,即不直接对应一个可构建的实体,而是用于依赖管理和构建调度的抽象构建目标。它与 `target` 使用相同的配置目录、可选 recipe class 目录和 `#[Target]` 注册方式。其余定义基本相同,但 `artifact` 字段可选且通常不设置。`virtual-target` 主要用于以下场景:
- 定义一个抽象的构建目标,供其他包依赖,但不直接对应一个可构建的实体。
- 作为多个 `target` 包的公共依赖,简化依赖关系管理。
典型例子 PHP 包的 `php-cli``php-fpm` 构建目标,他们没有独立源码,依赖 `php-src`,通过构建调度决定最终构建成 CLI 还是 FPM 二进制。
典型例子是 `php-cli``php-fpm` 构建目标。它们没有独立源码,依赖 Artifact 为 `php-src``php` target构建调度决定最终成 CLI 还是 FPM 二进制。

View File

@@ -22,32 +22,32 @@ spc download [artifacts] [options]
### 选项
| 选项 | 缩写 | 说明 |
|---|---|---|
| `--for-extensions=<list>` | `-e` | 按扩展名下载其所需的制品 |
| `--for-libs=<list>` | `-l` | 按库名下载其所需的制品 |
| `--for-packages=<list>` | | 按包名下载其所需的制品 |
| `--without-suggests` | | 使用 `--for-extensions` 时跳过建议包 |
| `--clean` | | 下载前删除旧的下载缓存 |
| `--with-php=<ver>` | | PHP 版本,格式为 `major.minor`(默认 `8.4`|
| `--prefer-binary` | `-p` | 优先使用预编译二进制 |
| `--prefer-source` | | 优先使用源码包 |
| `--source-only` | | 仅下载源码制品 |
| `--binary-only` | | 仅下载二进制制品 |
| `--parallel=<n>` | `-P` | 并行下载数(默认 `1`|
| `--retry=<n>` | `-R` | 失败重试次数(默认 `0`|
| `--ignore-cache=<list>` | | 强制重新下载指定制品 |
| `--no-alt` | | 不使用镜像站 |
| `--no-shallow-clone` | | 不使用浅层克隆 |
| `--custom-url=<src:url>` | `-U` | 覆盖指定源的下载地址 |
| `--custom-git=<src:branch:url>` | `-G` | 覆盖为自定义 git 仓库 |
| `--custom-local=<src:path>` | `-L` | 使用本地路径作为制品来源 |
| 选项 | 缩写 | 说明 |
|---|------|------------------------------------|
| `--for-extensions=<list>` | `-e` | 按扩展名下载其所需的制品 |
| `--for-libs=<list>` | `-l` | 按库名下载其所需的制品 |
| `--for-packages=<list>` | | 按包名下载其所需的制品 |
| `--without-suggests` | | 使用 `--for-extensions` 时跳过建议包 |
| `--clean` | | 下载前删除旧的下载缓存 |
| `--with-php=<ver>` | | PHP 版本,格式为 `major.minor`(默认 `8.5` |
| `--prefer-binary` | `-p` | 优先使用预编译二进制 |
| `--prefer-source` | | 优先使用源码包 |
| `--source-only` | | 仅下载源码制品 |
| `--binary-only` | | 仅下载二进制制品 |
| `--parallel=<n>` | `-P` | 并行下载数(默认 `1` |
| `--retry=<n>` | `-R` | 失败重试次数(默认 `0` |
| `--ignore-cache=<list>` | `-i` | 强制重新下载指定制品 |
| `--no-alt` | | 不使用镜像站 |
| `--no-shallow-clone` | | 不使用浅层克隆 |
| `--custom-url=<src:url>` | `-U` | 覆盖指定源的下载地址 |
| `--custom-git=<src:branch:url>` | `-G` | 覆盖为自定义 git 仓库 |
| `--custom-local=<src:path>` | `-L` | 使用本地路径作为制品来源 |
### 示例
```bash
# 按扩展名下载(推荐)
spc download --for-extensions="bcmath,openssl,curl" --with-php=8.4
spc download --for-extensions="bcmath,openssl,curl" --with-php=8.5
# 下载指定制品
spc download "php-src,openssl"
@@ -134,14 +134,14 @@ spc build:php <extensions> [options]
所有下载器选项均可加 `--dl-` 前缀使用:
| 选项 | 说明 |
|---|---|
| `--dl-with-php=<ver>` | 指定下载的 PHP 版本(默认 `8.4`|
| `--dl-prefer-binary` | 优先使用预编译二进制依赖 |
| `--dl-parallel=<n>` | 并行下载数 |
| `--dl-retry=<n>` | 失败重试次数 |
| `--dl-custom-url=<src:url>` | 覆盖指定源的下载地址 |
| `--dl-custom-git=<src:branch:url>` | 覆盖为自定义 git 仓库 |
| 选项 | 说明 |
|---|------------------------|
| `--dl-with-php=<ver>` | 指定下载的 PHP 版本(默认 `8.5` |
| `--dl-prefer-binary` | 优先使用预编译二进制依赖 |
| `--dl-parallel=<n>` | 并行下载数 |
| `--dl-retry=<n>` | 失败重试次数 |
| `--dl-custom-url=<src:url>` | 覆盖指定源的下载地址 |
| `--dl-custom-git=<src:branch:url>` | 覆盖为自定义 git 仓库 |
Downloader 选项传递给 `build:php` 命令时,会被自动下载器在构建前使用。
这样你就可以直接通过构建命令控制下载行为,无需单独执行 `spc download` 命令。
@@ -265,12 +265,12 @@ spc check-update [artifact] [options]
### 选项
| 选项 | 缩写 | 说明 |
|---|---|---|
| `--json` | | 以 JSON 格式输出结果 |
| `--bare` | | 检查时不要求制品已下载(旧版本显示为 null|
| `--parallel=<n>` | `-p` | 并行检查数(默认 `10`|
| `--with-php=<ver>` | | PHP 版本上下文,格式为 `major.minor`(默认 `8.4`|
| 选项 | 缩写 | 说明 |
|---|---|---------------------------------------|
| `--json` | | 以 JSON 格式输出结果 |
| `--bare` | | 检查时不要求制品已下载(旧版本显示为 null |
| `--parallel=<n>` | `-p` | 并行检查数(默认 `10` |
| `--with-php=<ver>` | | PHP 版本上下文,格式为 `major.minor`(默认 `8.5` |
### 示例

View File

@@ -26,7 +26,7 @@ StaticPHP 提供两种构建方式,根据使用场景选择:
在当前目录创建 `craft.yml`,声明要编译的 PHP 版本、扩展和目标 SAPI
```yaml
php-version: 8.4
php-version: 8.5
extensions: bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer
sapi:
- cli
@@ -80,10 +80,10 @@ v3 版本中你可以省略这一步骤直接构建想要的内容Stati
```bash
# 按扩展列表下载(推荐,只下载实际需要的内容)
spc download --for-extensions="bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer" --with-php=8.4
spc download --for-extensions="bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer" --with-php=8.5
# 按依赖包列表下载
spc download "curl,openssl" --with-php=8.4
spc download "curl,openssl" --with-php=8.5
```
下载内容缓存在 `downloads/` 目录,重复构建时会直接复用。

View File

@@ -55,7 +55,7 @@ StaticPHP 支持将 FrankenPHP 连同所需扩展一起静态编译,
## 社区
加入我们的 [Discord 服务器](https://discord.gg/nrSRbpMJ),提问、分享构建成果,与其他 StaticPHP 用户交流。
加入我们的 [Discord 服务器](https://discord.gg/xf6Rd4pEAk),提问、分享构建成果,与其他 StaticPHP 用户交流。
## 接下来

View File

@@ -27,18 +27,23 @@ spc 无须任何依赖,下载即可运行,支持 Linux、macOS 和 Windows
> spc 本身是由 StaticPHP 构建的静态 PHP 二进制,幽默地说:我们用 StaticPHP 构建了 StaticPHP 的构建工具。
```shell
# Linux x86_64
::: code-group
```shell [Linux x86_64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64 -o spc
# Linux arm64
```
```shell [Linux arm64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-aarch64 -o spc
# macOS x86_64 (Intel)
```
```shell [macOS x86_64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-x86_64 -o spc
# macOS arm64 (Apple Silicon)
```
```shell [macOS arm64]
curl -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-aarch64 -o spc
# Windows x86_64 (PowerShell)
```
```powershell [Windows x86_64]
curl.exe -#fSL https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x86_64.exe -o spc.exe
```
:::
*nix 系统下载完成后需要赋予可执行权限:

View File

@@ -0,0 +1,216 @@
# 从 v2 迁移
StaticPHP v3 是一次完整的重写。核心构建流程(`download → build → combine`)保持不变,但部分命令、选项和配置字段已发生变化。本页列出了切换前所有需要更新的内容。
::: info 范围说明
本指南仅涵盖面向用户的 CLI 命令、选项、`craft.yml` 字段和 `env.ini` 变量名称。不涵盖内部 PHP API。
:::
## 文档地址变更
官方文档站点已迁移:
- **v3 文档(当前)**[https://static-php.dev](https://static-php.dev) — 主站现在托管 v3 文档。
- **v2 文档(归档)**[https://static-php.github.io/v2-docs/](https://static-php.github.io/v2-docs/) — v2 文档已归档保留,供参考。
请更新你保存的书签或内部链接。
## `spc` 二进制下载地址变更
nightly `spc` 自包含二进制文件已迁移到新路径:
| | 地址 |
|---|---|
| **v2** | `https://dl.static-php.dev/static-php-cli/spc-bin/nightly/` |
| **v3** | `https://dl.static-php.dev/v3/spc-bin/nightly/` |
请更新所有直接下载 `spc` 二进制的 CI 脚本或初始化命令,例如:
```bash
# v2
curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
# v3
curl -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64
```
## 已移除的命令
| v2 命令 | v3 替代方案 | 说明 |
|---|---|---|
| `del-download` | `spc reset` | `reset` 支持 `--with-pkgroot``--with-download` 以进行更细粒度的控制 |
| `del-download --all` | `spc reset --with-download` | 删除下载缓存目录 |
## 已移除的选项
### `--with-added-patch` / `-P`build 命令)
该选项允许在特定构建阶段注入外部 PHP patch 脚本。**v3 已完全移除此功能。**
目前没有直接的替代方案。如果你依赖此功能,请考虑以下方式:
- 将你的 patch 贡献到 StaticPHP 的上游仓库。
- 对于项目专用的 patch可以使用自定义 registry 并编写 Package 类。详情参见[编写 Package 类](/zh/develop/extending/package-classes)。
::: tip 未来计划
未来版本可能会提供用于轻量级 patch 的单文件 hook API。
:::
### Windows 专有:`--with-sdk-binary-dir` 和 `--vs-ver`
这两个选项已不再被命令行接受。在 v3 中,`php-sdk-binary-tools` 依赖已被完全移除。v3 现在通过管理自己的 **MSYS2** 环境来支持 Windows 上基于 autotools 的库构建。运行 `spc doctor --install` 即可自动下载并配置 MSYS2。
如需指向自定义 MSYS2 安装目录,请设置 `SPC_MSYS2_PATH` 环境变量,值为 `msys64` 目录路径(例如 `C:\msys64`。Visual Studio 版本现在由工具链自动检测,无需手动指定版本号。
::: warning 从 v2 迁移
v2 依赖 `php-sdk-binary-tools`,并在每次构建时需要传入 `--with-sdk-binary-dir``--vs-ver` 参数。在 v3 中这些选项已被移除。请从所有 CI 脚本中删除这些参数,并使用 `spc doctor --install` 一次性完成 Windows 构建环境的配置。
:::
## 已重命名 / 已弃用的选项
以下选项已重命名。部分旧名称仍作为弃用别名被接受,但建议尽快更新脚本。
| v2 选项 | v3 选项 | 状态 |
|---|---|---|
| `--prefer-pre-built` | `--prefer-binary` / `-p` | 旧名称保留为弃用别名 |
| `--with-libs=<list>` | `--with-packages=<list>` | — |
| `--with-suggested-libs` / `-L` | `--with-suggests` | 旧 `-L` / `-E` 已移除 |
| `--with-suggested-exts` / `-E` | `--with-suggests` | 已合并为单一标志 |
### 示例
```bash
# v2
spc build curl,gd --build-cli --with-libs="openssl" -L -E
# v3
spc build curl,gd --build-cli --with-packages="openssl" --with-suggests
```
## `build` 命令行为变化
`build` 命令(别名:`build:php`)仍然可用。但 v3 新增了**专用的单目标构建命令**,无需再传入 SAPI 选择标志:
| v2 | v3 等价命令 |
|---|---|
| `spc build exts --build-cli` | `spc build:php-cli exts` |
| `spc build exts --build-fpm` | `spc build:php-fpm exts` |
| `spc build exts --build-cgi` | `spc build:php-cgi exts` |
| `spc build exts --build-micro` | `spc build:php-micro exts` |
| `spc build exts --build-embed` | `spc build:php-embed exts` |
| `spc build exts --build-frankenphp` | `spc build:frankenphp exts` |
如果需要在一次构建中同时编译多个 SAPI请继续使用 `build:php``--build-*` 标志在该命令下仍然有效)。
### 构建命令自动下载依赖
v3 中,所有 `build:*` 命令在构建前会自动下载缺失的依赖包,不再需要单独执行 `spc download`
```bash
# v2 — 需要两步
spc download --for-extensions=curl,gd
spc build curl,gd --build-cli
# v3 — 一步即可
spc build:php-cli curl,gd
```
如需跳过自动下载(例如在 CI 中源码已预先缓存),可传入 `--no-download`
```bash
spc build:php-cli curl,gd --no-download
```
## `download` 命令选项变化
| v2 | v3 | 说明 |
|---|---|---|
| `--prefer-pre-built` | `--prefer-binary` / `-p` | 弃用别名保留 |
| `--with-libs` | `--for-libs` | 与包过滤分开 |
| *(无等价)* | `--for-packages` | 统一包过滤器 |
| *(无等价)* | `--parallel` / `-P` | 并行下载 |
| *(无等价)* | `--retry` / `-R` | 失败重试 |
## 已移除的 dev 命令
以下开发辅助命令已被移除或合并:
| v2 命令 | v3 替代方案 |
|---|---|
| `dev:extensions` / `list-ext` | `spc dev:info <package>` |
| `dev:ext-version` / `dev:ext-ver` | `spc dev:info <package>` |
| `dev:lib-version` / `dev:lib-ver` | `spc dev:info <package>` |
| `dev:php-version` / `dev:php-ver` | `spc dev:info php-src` |
| `dev:gen-ext-dep-docs` + `dev:gen-lib-dep-docs` | `spc dev:gen-deps-data` |
## 已重命名的 dev 命令
| v2 | v3 | 说明 |
|---|---|---|
| `dev:sort-config` / `sort-config` | `dev:lint-config` | 旧别名仍可用 |
## v3 新增命令
以下命令为 v3 新增v2 中没有对应命令:
| 命令 | 说明 |
|---|---|
| `spc reset` | 清理 `buildroot/``source/` 目录 |
| `spc check-update` | 检查 artifact 的最新版本 |
| `spc build:php-cli` | 构建 CLI SAPI无需标志 |
| `spc build:php-fpm` | 构建 PHP-FPM无需标志 |
| `spc build:php-cgi` | 构建 PHP CGI无需标志 |
| `spc build:php-micro` | 构建 phpmicro无需标志 |
| `spc build:php-embed` | 构建 embed SAPI无需标志 |
| `spc build:frankenphp` | 构建 FrankenPHP无需标志 |
| `spc dev:shell` | 进入带构建环境的交互式 shell |
| `spc dev:is-installed` | 检查某个包是否已正确安装 |
| `spc dev:dump-stages` | 将所有包的构建阶段导出为 JSON |
| `spc dev:dump-capabilities` | 导出包的可构建/可安装能力 |
| `spc dev:info` | 显示某个包的配置信息 |
## `craft.yml` 变化
### 已移除:`build-options.with-added-patch`
`build-options` 下的 `with-added-patch` 键不再被解析,将被静默忽略。请从你的 `craft.yml` 中移除它:
```yaml
# v2 — 请删除此块
build-options:
with-added-patch:
- my-patch.php
```
### `libs` → `packages`(两者均可用)
顶层 `libs` 字段仍然有效。v3 中推荐使用 `packages`,它是 `libs` 的超集,还涵盖其他工具类包:
```yaml
# v2
libs: nghttp2,liblz4
# v3推荐
packages: nghttp2,liblz4
```
## `env.ini` 变量重命名
如果你在 `config/env.ini` 中进行了自定义,或在 CI 中导出了环境变量,请更新以下变量名:
| v2 变量名 | v3 变量名 |
|---|---|
| `SPC_LINUX_DEFAULT_CC` | `SPC_DEFAULT_CC` |
| `SPC_LINUX_DEFAULT_CXX` | `SPC_DEFAULT_CXX` |
| `SPC_LINUX_DEFAULT_AR` | `SPC_DEFAULT_AR` |
| `SPC_LINUX_DEFAULT_LD` | `SPC_DEFAULT_LD` |
| `SPC_LIBC` | `SPC_TARGET` |
`SPC_TARGET` 使用新的格式,将架构与 libc 编码在一个字符串中,例如:
| v2 | v3 |
|---|---|
| `SPC_LIBC=musl` | `SPC_TARGET=x86_64-linux-musl` |
| `SPC_LIBC=gnu` | `SPC_TARGET=x86_64-linux-gnu.2.17` |
v3 还新增了若干日志相关变量(`SPC_ENABLE_LOG_FILE``SPC_LOGS_DIR``SPC_PRESERVE_LOGS`)。详情参见[环境变量](/zh/guide/env-vars)。

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