Skip to content

StaticPHP v3#980

Open
crazywhalecc wants to merge 731 commits intov3from
v3-dev
Open

StaticPHP v3#980
crazywhalecc wants to merge 731 commits intov3from
v3-dev

Conversation

@crazywhalecc
Copy link
Copy Markdown
Owner

@crazywhalecc crazywhalecc commented Nov 30, 2025

Important notes

STATUS: dev -> alpha -> beta -> rc -> stable

Contribution notes:

  • Before we released the first alpha version, any changes should be merged into v3-dev, not v3.
  • After we released the first alpha version, any changes should be merged into v3 and we will deprecate v3-dev branch.
  • The structure of StaticPHP v3 may be changed before beta version.
  • Publishing new RFC is welcome.

RFCs

Progress of refactoring

bin/ refactoring

  • bin/spc for v3
  • bin/spc-alpine-docker
  • bin/spc-gnu-docker
  • bin/docker-entrypoint.sh
  • bin/setup-runtime

v3 new modules

  • Registry module loading for all configs and packages (StaticPHP v3 #980)
  • Vendor mode support
    • Separate a dedicated bootstrap file for initialization (StaticPHP v3 #980) (src/bootstrap.php)
    • Add init-registry command for vendor user

Commands refactoring

  • ConsoleApplication dynamic generating commands for target type packages (StaticPHP v3 #980)

  • Custom commands in external registry (StaticPHP v3 #980)

  • DownloadCommand

  • BaseCommand

  • BuildLibsCommand

  • BuildPHPCommand -> BuildTargetCommand with php package

    • Options
      • --with-libs: Keep for compatibility, add --with-packages option (StaticPHP v3 #980)
      • --build-shared
      • --build-all: Special parsing in v3 (StaticPHP v3 #980)
      • --no-strip, --disable-opcache-jit, --build-{sapi}, --with-config-file-path, --with-config-file-scan-dir, --with-hardcoded-ini, --with-micro-fake-cli, --with-added-patch (-P), --without-micro-ext-test, --with-upx-pack, --with-micro-logo, --enable-micro-win32, --with-frankenphp-app has been moved to php package definition (StaticPHP v3 #980)
      • Implementation status
        • no-strip
        • disable-opcache-jit
        • with-config-file-path
        • with-config-file-scan-dir
        • with-hardcoded-ini
        • with-micro-fake-cli
        • with-addeed-patch
        • without-micro-ext-test
        • with-upx-pack
        • with-micro-logo
        • enable-micro-win32
        • with-frankenphp-app
        • build-shared
        • with-packages (with-libs)
        • build-all
        • build-{sapi} except build-frankenphp (StaticPHP v3 #980)
        • build-frankenphp
        • with-suggests (with-suggested-libs, with-suggested-exts)
        • no-download (StaticPHP v3 #980)
        • Download options in build command (StaticPHP v3 #980)
        • with-clean
    • Build information printing: refactored to attribute #[StaticPHP\Attribute\Package\Info] (StaticPHP v3 #980)
    • Bind build extra info to ExceptionHandler
    • Validate packages before building and after extracting (StaticPHP v3 #980)
    • Patch static-php-cli version to PHP has been moved to php package build stage before (StaticPHP v3 #980)
    • Display build PHP result in terminal
    • Export licenses and build extensions and lib info after building
  • CraftCommand

  • DeleteDownloadCommand

  • DoctorCommand (StaticPHP v3 #980) (Just command, not Doctor items)

  • DumpExtensionsCommand

  • DumpLicenseCommand

  • ExtractCommand (Just command, not Extractor)

  • InstallPkgCommand ->InstallPackageCommand

    • PackageInstaller calling
    • Options
      • skip-extract
  • MicroCombineCommand

  • SPCConfigCommand

    • SPCConfigUtil calling
    • Options
  • SwitchPhpVersionCommand

  • Dev commands

    • AllExtCommand
    • EnvCommand
    • ExtVerCommand
    • GenerateExtDepDocsCommand
    • GenerateExtDocCommand
    • GenerateLibDepDocsCommand
    • LibVerCommand
    • PackLibCommand
    • PhpVerCommand
    • SortConfigCommand

Doctor module

  • Core framework refactored (StaticPHP v3 #980)
    • Doctor main class
    • DoctorLoader for loading check items
    • CheckResult for storing check results
    • Attribute-based check system: #[CheckItem], #[OptionalCheck], #[FixItem]
  • Doctor check items
    • OSCheck (migrated from v2's OSCheckList)
    • Re2cVersionCheck
    • PkgConfigCheck
    • MacOSToolCheck (migrated from v2's MacOSToolCheckList)
    • LinuxMuslCheck
    • LinuxToolCheck (v2 has LinuxToolCheckList)
    • BSDToolCheck (v2 has BSDToolCheckList)
    • WindowsToolCheck (v2 has WindowsToolCheckList)
    • ZigCheck (v2 has ZigCheck)

Legacy modules (v2 only - SPC namespace)

These modules exist in v2 but are refactored/merged into new v3 modules:

  • store/ - Deprecated and refactored
    • Downloader → StaticPHP\Artifact\ArtifactDownloader
    • LockFile → StaticPHP\Artifact\ArtifactCache
    • CurlHook → Merged into StaticPHP\Artifact\ArtifactDownloader
    • FileSystem → StaticPHP\Util\FileSystem
    • DirDiff → StaticPHP\Util\DirDiff
    • SourcePatcher → StaticPHP\Util\SourcePatcher (partial)
    • PackageManager, SourceManager → Removed (functionality in new Package/Artifact systems)
    • pkg/ → Migrated to src/Package/
    • source/ → Migrated to Artifact system

@crazywhalecc crazywhalecc added the mixed PR This PR contains multiple updates label Nov 30, 2025
@crazywhalecc crazywhalecc self-assigned this Dec 4, 2025
Comment thread src/StaticPHP/Command/InstallPackageCommand.php Outdated
@crazywhalecc
Copy link
Copy Markdown
Owner Author

crazywhalecc commented Dec 11, 2025

We should chat about what features we no longer want to support and what we want to rework.

@henderkes There's no urgent things. Just when you return from your vacation, and if you have time, it would be best we could discuss what modifications are still needed for the current framework of v3. Please feel free to contact me if you'd like.

Currently I've finished the major part of framework according to RFC, but I haven't ported most of the implementation yet, mainly to prevent major changes to the framework structure from requiring massive modifications.

And for anyone: If you have any feedback on the framework design, please let me know.

@henderkes
Copy link
Copy Markdown
Collaborator

I haven't had much of a look yet and the changelist is quite massive, so it might be a good idea to chat about it one evening after I had a rough glance. I'll give everything (especially vendor mode) a play and rewrite the static-php/packages properly on top of the new branch.

Might have to add versioned packages to it first though, because that's the part still holding up apk and proper apt support.

@crazywhalecc
Copy link
Copy Markdown
Owner Author

crazywhalecc commented Dec 11, 2025

For a quick reference for command mode, in the current branch, the available commands:

  • bin/spc doctor on Windows, macOS, Linux (linux is not fully tested)
  • bin/spc build:libs libedit on *nix
  • bin/spc build:php-cli readline on *nix
  • bin/spc build bcmath --build-cli --debug (--build-XXX and --debug has been marked as deprecated)
  • bin/spc build:libs onig on Windows
  • bin/spc download {some packages}
  • bin/spc download --for-extensions={some extensions}
  • bin/spc extract {some package}
  • bin/spc install-pkg {some package}
  • bin/spc spc-config {some extensions} (still using extension as argument)

The remaining commands and some of the option implementations may not have been tested.

@crazywhalecc
Copy link
Copy Markdown
Owner Author

Might have to add versioned packages to it first though

You mean the dependencies' version from artifacts?

@henderkes
Copy link
Copy Markdown
Collaborator

Might have to add versioned packages to it first though

You mean the dependencies' version from artifacts?

No, I mean versioned .deb packages like php-zts8.3-... Nothing on the spc side.

bin/spc build bcmath --build-cli --debug (--build-XXX and --debug has been marked as deprecated)

Why is --build-cli deprecated? What would be the new way to build multiple SAPIs at once?

@crazywhalecc
Copy link
Copy Markdown
Owner Author

crazywhalecc commented Dec 12, 2025

Why is --build-cli deprecated? What would be the new way to build multiple SAPIs at once?

I'm thinking of something like sapis arguments for build:php cli,fpm {extensions} command, not original build --build-XXX command. But it needs to separate build and build:php command, it will break compatibility.

I haven't decided any changes yet, but anyway we should current deprecate build command behavior. It should be building pacakge, not building php with extensions.

@crazywhalecc crazywhalecc added the RFC Request for comments label Feb 6, 2026
@crazywhalecc crazywhalecc requested a review from henderkes April 15, 2026 02:08
@crazywhalecc
Copy link
Copy Markdown
Owner Author

static-php-cli 3.0.0-alpha1 Release

static-php-cli v3 is a ground-up rewrite of the project, bringing a modern PHP 8.4+ architecture, dramatically improved user experience, and a flexible plugin system. This release represents months of work reimagining how static PHP binaries should be built.

Highlights

Concurrent Parallel Downloads

The download system now supports fiber-based parallel downloads out of the box. Use --parallel N to download multiple artifacts concurrently, significantly reducing the time spent fetching sources and pre-built binaries.

Improved Terminal Output

Terminal output has been completely redesigned. Build progress is now color-coded with clear status indicators, structured indentation for build stages, and smart verbosity levels (-v, -vv, -vvv). Log noise is reduced by default — only actionable information is shown, while full logs are written to file when needed.

Check for Updates

A new check-update command lets you check whether newer versions of any artifact (library, extension source, PHP release) are available, with optional --json output for CI integration.

Developer Tooling

New dev:* commands provide deep introspection into the build system:

  • dev:dump-stages — Visualize all build stages and their hooks
  • dev:dump-capabilities — Export installable/buildable capabilities as JSON
  • dev:package-info — Inspect package metadata and dependencies
  • dev:lint-config — Validate configuration files
  • dev:shell — Interactive shell inside the build environment
  • dev:is-installed — Query whether a package has been built

Windows

FrankenPHP and embed SAPI

v2 had no Windows support for FrankenPHP, and embed SAPI on Windows was marked as incomplete. v3 fully implements both: php-embed builds a genuine static library (phpNNembed.lib) on Windows, and FrankenPHP can be cross-compiled for Windows using the LLVM/Clang toolchain bundled with Visual Studio. PE metadata (version info and icon) is embedded automatically during the build as part of the standard release workflow.

Expanded Extension Support

v3 adds explicit Windows build support for 13+ external/PECL extensions, including amqp, mongodb, yaml, msgpack, parallel, lz4, zstd, xlswriter, and more. Combined with the 56 built-in extensions, Windows builds now have access to the same broad extension ecosystem available on Linux and macOS.


Architecture

PHP 8.4 Attribute-Driven Build System

v3 replaces the v2 inheritance-based builder hierarchy with a declarative attribute system built on PHP 8.4 attributes:

#[Library('openssl')]
class openssl {
    #[BuildFor('Linux')]
    #[BuildFor('Darwin')]
    public function buildUnix(LibraryPackage $lib): void {
        UnixAutoconfExecutor::create($lib)->configure()->make();
    }

    #[BuildFor('Windows')]
    public function buildWin(LibraryPackage $lib): void { /* ... */ }
}

Platform-specific logic is selected at runtime via #[BuildFor]. Build lifecycle hooks (#[BeforeStage], #[AfterStage], #[PatchBeforeBuild]) allow packages to interact with each other's build stages without tight coupling.

Dependency Injection

v3 is built on PHP-DI with full autowiring support. Build services, configuration, and runtime utilities are injected automatically into commands, build classes, and stage methods via ApplicationContext.

Unified Package Model

v2 maintained three separate configuration tracks: source.json for download sources, lib.json for libraries, and ext.json for extensions, each with their own dependency fields (lib-depends, ext-depends).

v3 unifies everything into a single per-package YAML configuration with a flat depends field. Libraries, PHP extensions, and build targets are all "packages" with a type discriminator:

# config/pkg/lib/curl.yml
curl:
  type: library
  artifact:
    source:
      type: ghrel
      repo: curl/curl
      match: curl-.+\.tar\.gz
    binary: hosted
  depends:
    - openssl
    - zlib
  depends@windows:
    - openssl
    - zlib

Platform-specific overrides use @ notation (depends@windows, static-libs@unix) instead of v2's suffix convention (lib-depends-windows, static-libs-unix).

Flattened Dependency Graph

v2 required maintaining two parallel dependency trees (lib-depends and ext-depends). v3 collapses these into a single depends list — extensions reference libraries directly (e.g., openssl), and other extensions with the ext- prefix (e.g., ext-openssl). The dependency resolver performs topological sorting with virtual-target promotion, optional dependency support (suggests), and reverse-lookup for debugging why a package was included.

Registry and Plugin System

v3 introduces a registry-based architecture defined in spc.registry.yml. The core registry declares where packages, doctor checks, artifacts, and commands are loaded from. External registries can be added via the SPC_REGISTRIES environment variable, enabling third-party packages, custom build logic, and vendor-specific configurations without modifying the core codebase.

System-Independent Core

v2 used a platform-specific builder inheritance hierarchy (LinuxBuilder / MacOSBuilder / WindowsBuilder extending UnixBuilderBase / BuilderBase). v3 decouples the build orchestration from the OS layer entirely. Platform-specific utilities are isolated into LinuxUtil, MacOSUtil, WindowsUtil classes, while PackageInstaller and PackageBuilder operate system-independently.

Direct CMake Execution

v2 required wrapper BAT scripts (makeSimpleWrapper()) to invoke CMake within the Visual Studio SDK environment. v3 introduces WindowsCMakeExecutor, which detects the Visual Studio installation directly via vswhere.exe and invokes CMake without any wrapper scripts, using the same executor interface as Unix builds:

WindowsCMakeExecutor::new($lib)
    ->configure('-DBUILD_SHARED_LIBS=OFF')
    ->make();

Configuration

Per-Package YAML

Each package now has its own YAML configuration file under config/pkg/, organized by type (lib/, ext/, target/). This replaces v2's monolithic JSON files and makes it easier to review, override, and extend package definitions.

PECL Source Type

v3 adds native PECL download support. External extensions hosted on PECL can be declared simply as:

ext-redis:
  type: php-extension
  artifact:
    source:
      type: pecl
      name: redis

This eliminates the boilerplate download URL configuration required in v2.

Environment Variables

Build environment is now managed through config/env.ini with support for user overrides via config/env.custom.ini. All build paths, toolchain settings, concurrency options, and platform detection variables are centralized and documented in one place.

License Metadata

Package configurations now include structured license metadata (license, license-files), and a dedicated LicenseDumper utility collects and exports all dependency licenses for compliance.


Package Ecosystem

v3 ships with 75 system libraries and 112 PHP extension configurations (56 built-in + 56 external/PECL), covering the same breadth as v2 with improved configuration quality.


Breaking Changes

v3 is a complete rewrite. All internal APIs, configuration formats, and extension points have changed. If you are using static-php-cli as a library (vendor mode) or maintaining custom extensions/libraries, you will need to migrate to the new architecture. The CLI interface (bin/spc) remains largely compatible for end users running craft, download, build:*, and doctor commands.

Key migration points:

  • Configuration migrated from JSON (lib.json, ext.json, source.json) to per-package YAML
  • lib-depends / ext-depends merged into unified depends
  • Platform suffixes changed from -unix / -windows to @unix / @windows
  • Builder classes replaced by attribute-annotated package classes
  • Custom extensions must adopt #[Extension] attribute and new lifecycle hooks

@crazywhalecc
Copy link
Copy Markdown
Owner Author

@claude[agent] Review

@henderkes
Copy link
Copy Markdown
Collaborator

henderkes commented Apr 15, 2026

Lol I can't select it here, only in issues.
@claude review this

@henderkes
Copy link
Copy Markdown
Collaborator

@claude[agent] hello review?
@claude review please?

I'll take a while to meaningfully review this. It will be a lot of work to get through it all and switch our packages to it.

@crazywhalecc
Copy link
Copy Markdown
Owner Author

I'll take a while to meaningfully review this. It will be a lot of work to get through it all and switch our packages to it.

Considering that almost all parts have been refactored, if you are going to refactor packages repo, it might be faster to refer to the documentation after my documentation is complete.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mixed PR This PR contains multiple updates RFC Request for comments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants