Skip to content

Generators

vladyslav-kinzerskiy edited this page Jun 15, 2026 · 1 revision

Generators

The artheia CLI is a Click command group. Beyond parse and check-addresses (the validation pair), every command is a gen-* generator or part of the rig/manifest pipeline. The full, verified catalog (artheia --help):

Validation

command what it does
parse <art> Resolve + validate the merged model (package.art + component.art), print it tree(1)-style. Resolves extern forward-decls recursively. Flags mirror unix tree: -L <depth>, -d (containers only), -f <FQN>, --no-recurse.
check-addresses <art> Assert every node's TIPC (type, instance) is unique across the whole system (follows import recursively, so it catches cross-FC collisions). Exits non-zero on a clash. Run before manifest/dist generation.

C++ scaffolds

command emits
gen-app The C++ application scaffold — lib/ + main/ + impl/ + the .proto. See the lib/main/impl split below.
gen-routing Per-process routing headers for a composition: LocalRef<T> for in-process prototypes, RemoteRef<T, tipc_type, instance> for prototypes owned elsewhere. User code calls cast/call identically; overload resolution picks the path. (Usually invoked internally by gen-app.)

Wire + deploy artifacts

command emits
gen-proto <art> --out <dir> One .proto per message. Run nanopb on the output for .pb.{c,h}.
gen-netgraph <art> --out <file> A JSON netgraph (nodes + compositions + wiring). -R/--recursive unions every reachable file; --catalog resolves gateway_route signal refs to bus addresses. Feeds the supervisor (passive GUI/stats view).
gen-psp-netgraph --catalog <c> --out <f> A per-bus PSP netgraph (PDU → bus-address LUT) from an AUTOSAR catalog.json. Loaded at startup by the gateway daemon (active CAN/FlexRay routing).
gen-manifest <art> <out.py> The Functional-Cluster manifest Python module (services/manifest/service.py). FC list comes from cluster Services; emits SwComponent / Executable / Process triples per member.
gen-etcd <art> --out <file> The etcd seed schema for all node params.
gen-params <art> --out <file> The per-FC static params JSON (one section per node, keyed by prototype = kNodeName). Read once at boot by the runtime config singleton.

Config-schema / migration tooling

These form the config-migration chain (see the Theia wiki for the lifecycle).

command emits
gen-schema <art> --out <file> ONE combined config-schema JSON for every FC config <Msg> binding: per config_type, the stable shape digest + proto type + field shape + bound nodes. The spine of the migration tooling.
gen-config-defaults <art> --out <f> The declared config-field defaults (the .art field = value on a config <Msg>), keyed by node prototype + config_type + digest. The first-boot seed source.
gen-migration --from <s1> --to <s2> --out <dir> Diff two gen-schema outputs and scaffold per-node migration transform JSONs (one per config whose digest changed), pre-filled with auto-derivable add/remove/rename rules + a custom-hook stub. Also (re)writes the migration BUILD plugin entries.
gen-transform <transform.json> --out <f> --schema <s> Generate a migration-plugin .cc (+ write-once custom sidecar) from a transform.json rule-set. dlopen'd by per (works on the nanopb struct — no JSON, no libprotobuf at runtime).

Rig / deploy-manifest pipeline

command emits
gen-rig <art> -c <Comp> --out <rig.py> Bootstrap a vendor rig.py from a top-level composition (groups prototype … on process P by process, emits SwComponent + Executable + Process + a SoftwareSpecification delta). Deployment-specific decisions land as TODO markers.
gen-rig-combine <modules…> --out <rig.py> Combine generated manifest modules (services + apps) into one rig.py.
generate-manifest <target> Emit the per-machine deploy manifest set (machine/application/service/execution.json + index.json) for a rig module. --flat emits a single-JSON view.
executor emit <target> Emit the supervisor manifest (executor.json) for a rig. --machine slices the tree to one machine.
gui emit <target> Emit the GUI manifest (machines.json) — each Machine's services/com gRPC endpoint, one row per machine.
rig-deps <target> Emit the rig's component structure as JSON; consumed by the Bazel rig() module extension to wire SwComponent.bazel_target refs into per-machine bundles.
audit-manifest <art> <rig> Left-join an .art system tree against a vendor rig.py and report manifest gaps (cluster member → ApplicationManifest, composition → SwComponent, prototype-with-process → Process). Exits 1 on gaps.

<target> for the rig commands is a dotted module path exporting a Rig or SoftwareSpecification (e.g. vendor.vehicles.tornado.arsyscomp); --rig selects the export name when a module has several.

AUTOSAR PSP import + codecs

These turn vendor bus databases (DBC / FIBEX) into .art + catalogs + C codecs.

command emits
import-dbc --dbc <f> --bus <name> --out <dir> Import a DBC: package.art (message per CAN frame + value-table enums) + catalog.json (bus, can_id, dlc, per-signal layout).
import-fibex --fibex <f> --bus <name> --out <dir> Import a FIBEX cluster: package.art (message per FlexRay frame) + catalog.json (slot, cycle, channel, per-signal layout).
gen-autosar-system --catalog <c…> --out <f> --package <p> Emit system.art with one mega-node per bus, each carrying a sender port per PDU; forward-declares the PDU interfaces locally so the file parses standalone.
gen-platform-protos --out-src … --out-proto … Unified FlexRay+CAN codec generator with cross-bus layout dedup — shared codec fns + per-bus dispatch tables + proto files in one pass.
gen-fibex-codec --fibex <f> --namespace <ns> --out <d> proto3 + FlexRay decoder/dispatch from a FIBEX + signal CSV.
gen-can-codec --dbc <f> --namespace <ns> --out <d> proto3 + CAN encoder/decoder from a DBC + signal CSV.
gen-codec-dispatch --psp-root <r> --out <d> dispatch_local.c for libpsp_local.so from a PSP root (linker dead-strips unreferenced encode/decode symbols).
gen-app-dispatch --psp-root <r> --csv <f> --out <d> Per-application dispatch glue (dispatch_table.{c,h}, hercules_filter.h, ns_wrapper.h).
gen-gw-types --psp-root <r> --out <d> gw_bus_types.h (stable GwBusId enum + helpers) from PSP manifests.
gen-psp-registry --can-namespaces <ns…> --out <d> psp_can_registry.{c,h} aggregating CAN namespaces into one psp_can_lookup() for libpsp.so.
gen-signal-filter --vendor-root <r> --out <csv> Walk a vendor tree for gateway_route signal refs, cross-reference the catalog, emit signal_filter.csv.
signal-filter Interactive REPL for searching platform signals and building a signal_filter.csv.

gen-app: the lib/main/impl split

gen-app is the primary C++-from-.art path. It has two modes:

--kind target emits
fc (default) a Functional-Cluster package.art lib/ + main/ + impl/ (Bazel) + the .proto under --proto-out
lib a standalone app's component.art lib/ + impl/ + a vendored copy of platform/runtime/ + generated proto + a top-level CMakeLists.txt (plain CMake, no Bazel, no main/ — the app owns its own main and runnable lifecycle)

The fc command

artheia gen-app --kind fc \
    services/<fc>/system/<fc>/package.art \
    --out        services/<fc>/ \
    --proto-out  platform/proto/ \
    --ns         ara::<fc> \
    --force
flag meaning
<art_file> the spec — services/<fc>/system/<fc>/package.art (loader merges the sibling component.art)
--out the impl tree root, services/<fc>/ (kept DISTINCT from the .art spec dir)
--proto-out where the .proto lands (platform/proto/); run nanopb on it for .pb.{c,h}
--ns C++ namespace, e.g. ara::log (default: the .art package flattened with underscores, e.g. system_services_sm)
--composition <Name> emit ONE app for a single composition (per-process layout); --out becomes the parent dir and the composition name is appended
--force overwrite the write-once impl/ slices

What lands where

services/<fc>/
  lib/                       ── AUTO-GENERATED, DO NOT EDIT (rewritten every run)
    <Node>.hh                  the GenServer / GenStateM / GenRunnable subclass
    <Node>_netgraph.hh         signal → destination projection for this node
    <fc>_codecs.hh             FC-wide inbound RemoteCodec specializations
    Log.hh                     per-FC logging context
    BUILD.bazel
  main/                      ── AUTO-GENERATED, DO NOT EDIT (rewritten every run)
    main.cc                    entrypoint: constructs nodes, joins the TipcMux
    BUILD.bazel
  impl/                      ── HAND-OWNED (first-time-only; --force to overwrite)
    <Node>_handlers.cc         your handler bodies (the only files you edit)
    <Node>_state.hh            the node's state struct
    BUILD.bazel

lib/ + main/ are a pure projection of the .art — rewritten verbatim every run. impl/<Node>_handlers.cc and impl/<Node>_state.hh carry your business logic; gen-app refuses to overwrite them unless --force. To change anything in lib/ / main/, change the .art (or the Jinja template) and regenerate — never edit the generated file.

A multi-node FC decomposes per node: each node gets its own <Node>.hh, <Node>_netgraph.hh, and the write-once impl/<Node>_handlers.cc + impl/<Node>_state.hh, sharing <fc>_codecs.hh + Log.hh. Regenerating one node never disturbs a sibling's hand-written code.

Which base class

.art node base class handler contract
node atomic (no statem) GenServer handle_cast(Msg, State), handle_call(Req, State) → Reply
node atomic + statem { … } GenStateM per-state handle_event(State, Event, …)
node runnable GenRunnable do_start(), do_loop(), do_stop()

Selection: runnable wins, else statem, else plain GenServer.

Regen-stability guard

A self-test enforces the contract: committed lib/, main/, and impl/BUILD.bazel must equal gen-app's output byte-for-byte; only impl/<Node>_handlers.cc / _state.hh are exempt (detected by their HAND-OWNED banner). If it fails, the fix is never to hand-edit a generated file — change the .art and regenerate, or fix the template and regenerate every FC.

artheia wiki

Install

pip install artheia

artheia · artheia-lsp · artheia-mcp

Related wikis

Clone this wiki locally