folk-builder 0.2.0

Custom binary builder for Folk — generates and compiles a Folk server with selected plugins
Documentation

folk-builder

Generates and compiles a PHP extension (folk.so) that runs the Folk application server inside PHP.

Folk replaces Swoole/RoadRunner/FrankenPHP: your PHP process loads folk.so, which embeds a high-performance HTTP server (axum/hyper + tokio) with ZTS multi-worker threads.

Quick Start

1. Install folk-builder

cargo install folk-builder

Or build from source:

git clone https://github.com/Folk-Project/folk-builder
cd folk-builder
cargo build --release
# Binary at target/release/folk-builder

2. Create build config

Create folk.build.toml:

[build]
output = "folk"                    # Extension name (produces folk.so)

[[plugin]]
crate_name = "folk-plugin-http"    # HTTP server plugin
version = "0.2"
config_key = "http"

3. Build the extension

folk-builder build --config folk.build.toml --output-dir .

This generates a Cargo project, compiles it, and produces folk.so.

Requirements:

  • Rust 1.88+
  • PHP 8.2+ (NTS or ZTS) with php-config in PATH
  • For multi-worker: PHP must be compiled with ZTS (--enable-zts)

4. Load and run

Create folk.toml (server config):

[workers]
script = "server.php"
count = 4           # Number of worker threads (requires ZTS PHP)
max_jobs = 100000

[http]
listen = "0.0.0.0:8080"

[log]
filter = "warn"

Create server.php:

<?php
require __DIR__ . '/vendor/autoload.php';

// Start the Folk server (non-blocking).
if (!folk_is_worker_thread()) {
    $server = new Folk\Server('folk.toml');
    $server->start();
}

// Create worker loop and register handlers.
$loop = new \Folk\Sdk\Worker\WorkerLoop();
$loop->registerHttpHandler(new MyHttpHandler());
$loop->run();

Run:

php -d extension=./folk.so server.php

Build Config Reference

[build]

Field Type Required Description
output string yes Extension name (without .so)
folk_ext_path string no Local path to folk-ext crate (for development)
folk_api_path string no Local path to folk-api crate (for development)

[[plugin]]

Field Type Required Description
crate_name string yes Rust crate name
version string no Version (default: "0.2")
path string no Local path (overrides version)
git string no Git URL (overrides version)
config_key string yes Key in folk.toml for plugin config

Available plugins

Plugin Crate Description
HTTP folk-plugin-http HTTP/1.1 server (axum/hyper)
gRPC folk-plugin-grpc gRPC server
Jobs folk-plugin-jobs Background job queue
Metrics folk-plugin-metrics Prometheus metrics endpoint
Process folk-plugin-process Process management signals

Docker

For production, build folk.so in a multi-stage Docker image:

FROM php:8.3-zts AS builder

RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
    | sh -s -- -y --default-toolchain 1.88.0
ENV PATH="/root/.cargo/bin:${PATH}"

RUN apt-get update && apt-get install -y \
    pkg-config libclang-dev clang && rm -rf /var/lib/apt/lists/*

WORKDIR /build
COPY folk-builder/ /build/folk-builder/
RUN cd /build/folk-builder && cargo build --release

RUN cat > /build/folk.build.toml << 'TOML'
[build]
output = "folk"

[[plugin]]
crate_name = "folk-plugin-http"
version = "0.2"
config_key = "http"
TOML

RUN /build/folk-builder/target/release/folk-builder build \
    --config /build/folk.build.toml --output-dir /build/

# --- Runtime ---
FROM php:8.3-zts
COPY --from=builder /build/folk.so /usr/local/lib/php/extensions/folk.so
RUN echo "extension=folk.so" > /usr/local/etc/php/conf.d/folk.ini

Architecture

PHP loads folk.so
  |
  +-- Main thread (worker #1)
  |     folk_worker_run() -> Rust dispatch loop
  |       recv Value -> value_to_zval -> call_user_function -> zval_to_value
  |
  +-- folk-tokio thread
  |     axum HTTP server, worker pool, plugin registry
  |
  +-- ZTS workers #2..N (requires ZTS PHP)
        ts_resource -> php_request_startup -> execute worker script

Zero JSON serialization. Data passes as direct zval arrays between Rust and PHP.

Performance

Raw JSON, Docker, 2 CPU:

Workers Req/sec
1 ~27,000
4 ~55,000

Laravel, Docker, 2 CPU, 4 workers: ~3,600 rps

License

MIT