Skip to content

[RFC] 3.0 Updates - Structure Changes #960

@crazywhalecc

Description

@crazywhalecc

[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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFCRequest for commentshelp wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions