mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-07 08:45:40 +08:00
feat(docs): add agent guide, build class patterns, log triage, and AI instructions
This commit is contained in:
143
.github/skills/staticphp-package-maintenance/references/build-class-patterns.md
vendored
Normal file
143
.github/skills/staticphp-package-maintenance/references/build-class-patterns.md
vendored
Normal 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.
|
||||
Reference in New Issue
Block a user