static-php-cli icon indicating copy to clipboard operation
static-php-cli copied to clipboard

[RFC] 3.0 Updates - Structure Changes

Open crazywhalecc opened this issue 2 months ago • 6 comments

[RFC] 3.0 Updates - Structure

Refactoring libraries, extensions and PhpBuilder with Attributes

For most of src/SPC/builder/linux/library/*.php, it just contains a name and use trait. It's useless and redundant.

For more portability and integrity, we change package and extensions to Attribute-defined way.

The example of a library file:

libjpeg.php in src/SPC/Library/:

<?php

namespace SPC\Library;

use SPC\attribute\Package\Library;
use SPC\util\executor\UnixCMakeExecutor;

#[Library('libjpeg')]
class libjpeg
{
    #[VersionGetterFromSource] // This will extract source first to get, after this, it will remove the source
    // When it not be defined, the `getVersion()` will return 'unknown' directly.
    public function versionGetter(): string
    {
        // match set(VERSION 3.1.0) version number in CMakeLists.txt
        return preg_match('/set\(VERSION (\d+\.\d+\.\d+)\)/', "{$this->getSourceDir()}/CMakeLists.txt", $matches) ? $matches[1] : 'unknown';
    }
    
    #[PatchBeforeBuild]
    public function patchBeforeBuild(): bool
    {
        // patch things here
    }

    #[BuildFor('Linux')]
    #[BuildFor('Darwin')]
    public function buildUnix(): void
    {
        UnixCMakeExecutor::create($this)
            ->addConfigureArgs(
                '-DENABLE_STATIC=ON',
                '-DENABLE_SHARED=OFF',
            )
            ->build();
        // patch pkgconfig
        $this->patchPkgconfPrefix(['libjpeg.pc', 'libturbojpeg.pc']);
    }

    #[BuildFor('Windows')]
    public function buildWindows(): void
    {
        // Windows stuff ...
    }
}

For extensions, we will refactor all the calling method as attributes.

gd.php in src/SPC/Extension/:

<?php

namespace SPC\Extension;

use SPC\Attribute\Package\Extension;
use SPC\store\FileSystem;

#[Extension('gd')]
class gd
{
    #[PatchBefore('php', 'configure')] // Run before PHP configure stage
    public function patchBeforePhpConfigure(): bool
    {
        FileSystem::replaceFileStr('xxx', 'xxx', 'yyy');
        return true; // true to patched, false to skip
    }

    #[PatchAfter('php', 'configure')]
    public function patchAfterPackageStage(): bool
    {
        // Do something after PHP configure stage
    }
    
    #[CustomPhpConfigureArg('Darwin')]
    #[CustomPhpConfigureArg('Linux')]
    public function customArgs(): string
    {
        return '--enable-XXX --with-XXX';
    }
}

This refactoring will make the code more readable and maintainable.

Refactoring SAPI Builds

The SAPI build process can also be refactored using attributes to define build steps and configurations.

<?php

namespace SPC\Target;

use SPC\Attribute\Package\Target;

#[Target('php')]
class Php
{
    #[DefineStage('prepare-unix')]
    public function prepareBuild(): void
    {

    }

    #[DefineStage('buildconf-unix')]
    public function buildconf(): void
    {

    }

    #[DefineStage('configure-unix')]
    public function configure(): void
    {

    }

    #[DefineStage('make-unix')]
    public function make(): void
    {

    }

    #[BuildFor('Linux')]
    #[BuildFor('Darwin')]
    public function buildForUnix(): void
    {
        target()->runStage('prepare-unix');
        target()->runStage('buildconf-unix');
        target()->runStage('configure-unix');
        target()->runStage('make-unix');
        
        $this->deployBinaries();
    }

    #[BuildFor('Windows')]
    public function BuildForWindows(): void
    {
        target()->runStage('prepare-windows');
        target()->runStage('buildconf-windows');
        target()->runStage('configure-windows');
        
        if (target()->getOption('build-micro')) {
            target()->runStage('make-micro-unix');
        }
        // ... other sapi as well
        
        $this->deployBinaries();
    }
}

This will also allow us to easily inject patching for some target build stage like patching extension before php configure:

#[PatchBefore('php', 'configure')]
public function patchBeforePhpConfigure(): bool
{
    // patch code here
}

Moreover, we can also call the same process for some virtual targets, like we build micro SAPI only using build:php-micro:

PhpMicro.php:

#[BuildFor('Linux')]
public function buildMicro(): void
{
    target('php')->runStage('buildconf-unix');
    target('php')->runStage('configure-unix');
    target('php')->runStage('make-micro-unix');
    // ...
}

If you have any question or have better suggestions, please leave comment here with quote.

crazywhalecc avatar Nov 05 '25 04:11 crazywhalecc