Create a package

A PLeX package is a source repository with a synps.toml. It can publish graph objects for the Compiler, Orchestration modules for portable control flow, Native providers, codecs, graph hooks, or static libraries used by another build package.

Package identity

[package]
name = "example"
version = "0.1.0"
description = "Reusable PLeX component"
include_directories = ["include"]

name and version are required. include_directories adds public include roots inherited by consumers in addition to the normal layout include path.

Publish a graph object

[build.graph]
namespace = "example"
toolchain = "cpp"
sources = ["src/graph.cpp"]
exports = ["graph"]
#include <mln/sdk/module.hpp>
#include <syn/package.hpp>

class Graph final : public Mln::Sdk::Module {
    public:
        Graph() { name = "model"; }

        std::vector<Mln::Sdk::Tensor>
        graph(std::span<const Mln::Sdk::Tensor> inputs) override {
            // Build and return the graph outputs.
            return {inputs.at(0)};
        }
};

PUBLISH(graph, Graph{});

For graph build packages, namespace controls the physical namespace of functions emitted by the Compiler. If omitted, SYNaPSe derives it from the project and package name.

Publish orchestration

[build.orchestration]
toolchain = "cpp"
sources = ["src/entrypoint.cpp", "src/orchestration.cpp"]

Use ENTRYPOINT(Type) to mark the application entrypoint. In an orchestration build it emits the Wasm adapter; in a native build it registers the equivalent native adapter. A graph-only package needs no artificial orchestration: its compiled graph entrypoint is indexed directly in the artifact.

Publish a Native provider

[build.native.provider]
toolchain = "cpp"
sources = ["src/provider.cpp"]
libraries = ["example"]

Native providers use the typed PUBLISH(module, name, return_type, args...) and, when manual ABI access is required, PUBLISH_RAW(module, name) from <mln/sdk/native.hpp>. A provider .so exposes one mln_native_module() registration with the symbols registered by its translation units. These native macros are distinct from the graph-package PUBLISH(symbol, object) above.

Publish a Compiler object

Codecs and graph hooks are also Graph build packages using IREE because the Compiler loads them on the build host. Export them with PUBLISH(symbol, object) and list the same symbol in exports.

Build-package fields

The complete schema is in synps.toml. Common fields are:

Field Meaning
namespace physical graph namespace
toolchain language family or explicit compatible toolchain
sources, includes source and input paths
libraries, library_directories link configuration
defines preprocessor definitions
artifact expected toolchain-produced filename when the toolchain chooses it
exports names published by a build-time graph package; orchestration uses its implicit forward export
uses separately built component artifacts consumed during linking or building
extends build packages absorbed into this component

Declare package variables

[package.variables]
context = { type = "uint32", required = true, min = 1, max = 32768, define = "APP_CONTEXT" }
mode = { type = "string", default = "default", define = "APP_MODE", facets = ["orchestration"] }

Supported variable types are string, boolean/bool, integer/int64, uint32, float/number, array, and table. Numeric schemas can set min/max. The root project configures a dependency under [packages.<name>]. define exposes a configured scalar to compiled source. Optional facets limits that definition to the named build-package facets, so changing it does not invalidate unrelated artifacts.

Declare capabilities

[capabilities]
provides = ["encoder"]
requires = ["storage"]

Capabilities let projects connect package roles without making packages depend on one another's source repositories.

Keep deployment out of the package

Do not hardcode root graph policies, target devices, checkpoint locations, or application entrypoint composition in a reusable package unless they are truly part of the package contract. Those choices normally belong to the consuming project.