From fe3cd15f81358ba79cccdc42ee6bb0d54baf9af5 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 6 Jul 2026 20:39:44 +0800 Subject: [PATCH 1/4] feat(docs): add agent guide, build class patterns, log triage, and AI instructions --- .github/copilot-instructions.md | 52 +++++ .../staticphp-build-troubleshooting/SKILL.md | 56 +++++ .../agents/openai.yaml | 4 + .../references/log-triage.md | 209 ++++++++++++++++++ .../staticphp-package-maintenance/SKILL.md | 55 +++++ .../agents/openai.yaml | 4 + .../references/build-class-patterns.md | 143 ++++++++++++ .../references/package-reference.md | 157 +++++++++++++ AGENTS.md | 58 +++++ 9 files changed, 738 insertions(+) create mode 100644 .github/copilot-instructions.md create mode 100644 .github/skills/staticphp-build-troubleshooting/SKILL.md create mode 100644 .github/skills/staticphp-build-troubleshooting/agents/openai.yaml create mode 100644 .github/skills/staticphp-build-troubleshooting/references/log-triage.md create mode 100644 .github/skills/staticphp-package-maintenance/SKILL.md create mode 100644 .github/skills/staticphp-package-maintenance/agents/openai.yaml create mode 100644 .github/skills/staticphp-package-maintenance/references/build-class-patterns.md create mode 100644 .github/skills/staticphp-package-maintenance/references/package-reference.md create mode 100644 AGENTS.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..e47fe1df --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,52 @@ +# StaticPHP v3 AI Instructions + +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`. + +Use the repository skills when the task matches them: + +- `.github/skills/staticphp-package-maintenance`: adding, changing, reviewing, or validating package, artifact, extension, library, target, or tool definitions. +- `.github/skills/staticphp-build-troubleshooting`: diagnosing build, download, doctor, shell, terminal, CI, or log failures. + +## 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. +- `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 +php 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. diff --git a/.github/skills/staticphp-build-troubleshooting/SKILL.md b/.github/skills/staticphp-build-troubleshooting/SKILL.md new file mode 100644 index 00000000..b93f4c7e --- /dev/null +++ b/.github/skills/staticphp-build-troubleshooting/SKILL.md @@ -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..console.log`, `lib..cmake-error.log`, `lib..cmake-configure.log`, `lib..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. diff --git a/.github/skills/staticphp-build-troubleshooting/agents/openai.yaml b/.github/skills/staticphp-build-troubleshooting/agents/openai.yaml new file mode 100644 index 00000000..2afaef5c --- /dev/null +++ b/.github/skills/staticphp-build-troubleshooting/agents/openai.yaml @@ -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." diff --git a/.github/skills/staticphp-build-troubleshooting/references/log-triage.md b/.github/skills/staticphp-build-troubleshooting/references/log-triage.md new file mode 100644 index 00000000..8c5d07b7 --- /dev/null +++ b/.github/skills/staticphp-build-troubleshooting/references/log-triage.md @@ -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..console.log`: copied Autoconf `config.log` for a library when available. +- `lib..cmake-configure.log`: copied CMake 3.26+ configure log. +- `lib..cmake-error.log`: copied CMake error log. +- `lib..cmake-output.log`: copied CMake output log. + +Logs are created when `SPC_ENABLE_LOG_FILE` is true. Old `*.log` files are cleaned unless the preserve-log env is true. Note the current code checks `SPC_PRESERVE_LOG`, while `config/env.ini` and docs mention `SPC_PRESERVE_LOGS`; verify this mismatch when diagnosing log retention behavior. + +## 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..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..cmake-error.log` and `lib..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. diff --git a/.github/skills/staticphp-package-maintenance/SKILL.md b/.github/skills/staticphp-package-maintenance/SKILL.md new file mode 100644 index 00000000..cc9b2ca4 --- /dev/null +++ b/.github/skills/staticphp-package-maintenance/SKILL.md @@ -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. diff --git a/.github/skills/staticphp-package-maintenance/agents/openai.yaml b/.github/skills/staticphp-package-maintenance/agents/openai.yaml new file mode 100644 index 00000000..40923512 --- /dev/null +++ b/.github/skills/staticphp-package-maintenance/agents/openai.yaml @@ -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." diff --git a/.github/skills/staticphp-package-maintenance/references/build-class-patterns.md b/.github/skills/staticphp-package-maintenance/references/build-class-patterns.md new file mode 100644 index 00000000..0604e12d --- /dev/null +++ b/.github/skills/staticphp-package-maintenance/references/build-class-patterns.md @@ -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. diff --git a/.github/skills/staticphp-package-maintenance/references/package-reference.md b/.github/skills/staticphp-package-maintenance/references/package-reference.md new file mode 100644 index 00000000..a51d7ed4 --- /dev/null +++ b/.github/skills/staticphp-package-maintenance/references/package-reference.md @@ -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 +``` diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..64982189 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,58 @@ +# 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. + +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. +- `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. From 8533702cf60fb9e0687e2922a97aba0c04c56bf9 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 6 Jul 2026 21:19:55 +0800 Subject: [PATCH 2/4] oops --- config/env.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/env.ini b/config/env.ini index a3e9aa70..0be1abdf 100644 --- a/config/env.ini +++ b/config/env.ini @@ -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 From b9def51f8603fdd37c3894b274d687af4b611bd8 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 6 Jul 2026 21:20:20 +0800 Subject: [PATCH 3/4] Simplify redundant github instruction --- .github/copilot-instructions.md | 61 +++++++++------------------------ 1 file changed, 16 insertions(+), 45 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e47fe1df..cfe03ed6 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,52 +1,23 @@ -# StaticPHP v3 AI Instructions +# 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`: adding, changing, reviewing, or validating package, artifact, extension, library, target, or tool definitions. -- `.github/skills/staticphp-build-troubleshooting`: diagnosing build, download, doctor, shell, terminal, CI, or log failures. +- `.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. -## Project Map +## Quick Reference -- `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. -- `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 -php 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. +- **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/` From 03f1313eec070f35115ff4c602b54ade216961fd Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 6 Jul 2026 21:20:38 +0800 Subject: [PATCH 4/4] chore --- .../staticphp-build-troubleshooting/references/log-triage.md | 2 +- AGENTS.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/skills/staticphp-build-troubleshooting/references/log-triage.md b/.github/skills/staticphp-build-troubleshooting/references/log-triage.md index 8c5d07b7..96f5d6a5 100644 --- a/.github/skills/staticphp-build-troubleshooting/references/log-triage.md +++ b/.github/skills/staticphp-build-troubleshooting/references/log-triage.md @@ -21,7 +21,7 @@ Default log directory is `log/`, controlled by `SPC_LOGS_DIR`. The important fil - `lib..cmake-error.log`: copied CMake error log. - `lib..cmake-output.log`: copied CMake output log. -Logs are created when `SPC_ENABLE_LOG_FILE` is true. Old `*.log` files are cleaned unless the preserve-log env is true. Note the current code checks `SPC_PRESERVE_LOG`, while `config/env.ini` and docs mention `SPC_PRESERVE_LOGS`; verify this mismatch when diagnosing log retention behavior. +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 diff --git a/AGENTS.md b/AGENTS.md index 64982189..2292f0a4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,7 @@ If your agent does not automatically discover skills from `.github/skills`, read - `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.