rustscript-embedded 0.3.2

Embedded RustScript VMBC runtime with a no_std host-function ABI
Documentation
Import("env")

import os
import pathlib
import subprocess

PROJECT_DIR = pathlib.Path(env.subst("$PROJECT_DIR")).resolve()
PIO_ENV = env.subst("$PIOENV")
RUST_TARGET = env.GetProjectOption("custom_rust_target")
TARGET_DIR = PROJECT_DIR / ".pio" / "rust-target"
GENERATED_DIR = PROJECT_DIR / ".pio" / "generated" / PIO_ENV
SOURCE = PROJECT_DIR / "programs" / "esp32-blinky.rss"
VMBC = GENERATED_DIR / "program.vmbc"
HEADER = GENERATED_DIR / "program_vmbc.h"
ARCHIVE = TARGET_DIR / RUST_TARGET / "release" / "librustscript_embedded.a"


def run(command, environment=None):
    print("micro-rustscript:", " ".join(str(item) for item in command))
    clean_env = os.environ.copy() if environment is None else environment.copy()
    clean_env.pop("RUSTFLAGS", None)
    subprocess.run(command, cwd=PROJECT_DIR, env=clean_env, check=True)


def write_header(payload):
    rows = []
    for offset in range(0, len(payload), 12):
        chunk = payload[offset : offset + 12]
        rows.append("    " + ", ".join(f"0x{byte:02x}" for byte in chunk) + ",")
    content = "\n".join(
        [
            "#pragma once",
            "",
            "#include <stddef.h>",
            "#include <stdint.h>",
            "",
            "static const uint8_t RUSTSCRIPT_PROGRAM_VMBC[] = {",
            *rows,
            "};",
            "static const size_t RUSTSCRIPT_PROGRAM_VMBC_LEN = sizeof(RUSTSCRIPT_PROGRAM_VMBC);",
            "",
        ]
    )
    if not HEADER.exists() or HEADER.read_text() != content:
        HEADER.write_text(content)


GENERATED_DIR.mkdir(parents=True, exist_ok=True)
build_environment = os.environ.copy()
build_environment["CARGO_TARGET_DIR"] = str(TARGET_DIR)
build_environment.pop("RUSTFLAGS", None)

run(
    [
        "cargo",
        "build",
        "--release",
        "--target",
        RUST_TARGET,
        "--no-default-features",
        "--features",
        "arduino",
    ],
    build_environment,
)
run(
    [
        "cargo",
        "run",
        "--quiet",
        "--bin",
        "rustscript-compile-vmbc",
        "--",
        str(SOURCE),
        str(VMBC),
    ],
    build_environment,
)

if not ARCHIVE.is_file() or ARCHIVE.stat().st_size == 0:
    raise RuntimeError(f"missing Rust static library: {ARCHIVE}")
if not VMBC.is_file() or VMBC.stat().st_size == 0:
    raise RuntimeError(f"missing VMBC output: {VMBC}")

write_header(VMBC.read_bytes())
env.Append(CPPPATH=[str(PROJECT_DIR / "include"), str(GENERATED_DIR)])
env.Append(LIBS=[env.File(str(ARCHIVE))])