Skip to main content
This page builds the reference hello node for macOS and Linux and checks it with the exact introspection Omega runs at install time. Windows nodes are COM servers with a different build; see Windows at the end.

Prerequisites

  • A checkout of golain-io/omega-rs. Your node depends on its node-abi crate (Rust) or header (C), and you verify with the omega-agent binary it builds.
  • A Rust toolchain, or a C compiler for the C path.
  • For Linux builds from a Mac: cross and Docker.

Rust

The whole node is one crate with one dependency. Start by copying hello-node/ from the Omega repository, or write the two files below.
Everything Omega calls is generated by export_node!. Your code is the Node trait: a domain, a capabilities document, a health answer, and one invoke function. Build it:
Confirm the five exports are visible:
You should see node_abi_version, node_capabilities, node_domain, node_health, and node_invoke. Nothing else needs to be exported.

C or C++

Include the header Omega owns and define the same five functions. The header documents the buffer protocol every string-returning export uses: always write the byte length needed to *out_len, copy only if the caller’s buffer is large enough, and return OMEGA_NODE_BUF_TOO_SMALL otherwise. Omega retries with a buffer of that size.
hello_node.c
In C you write the JSON by hand and there is no panic containment, so node_invoke must never crash or throw. In C++ wrap the body of every export in try / catch (...) and return a positive code from the catch. A crash is contained to the child process, but it is reported as a dispatch failure with no message, which tells an operator nothing.

Cross-compile a Linux .so from a Mac

Omega’s own Raspberry Pi builds use cross, and a node builds the same way. It needs Docker running.
The library lands at target/<triple>/release/libhello_node.so.
A .so links against the glibc of the image it was built in, and the device must have that version or newer. cross’s current images carry a newer glibc than Debian bookworm, so a node built with them fails to load on a bookworm Pi with a GLIBC_2.xx not found error. Pin cross 0.2.5, which uses older images, or build on the oldest distribution you must support. Check with objdump -T libhello_node.so | grep GLIBC_ | sort -u before shipping.
A pure-Rust node with no C dependencies can also be built with rustup target add <triple> and plain cargo build --target, but the moment a dependency compiles C you need a cross toolchain, which is what cross provides.

Verify with Omega

Omega has a hidden subcommand that does exactly what a device does when it registers a node: load the library in a fresh process, check the ABI, and call node_domain, node_capabilities, and node_health.
If this prints, the device will register your node. If it errors, the message names the failing export. Build omega-agent from the same repository revision you built against:
Run the verification on the target platform. A Linux .so cannot be introspected on a Mac.

Windows

A Windows node is an out-of-process COM server, not a C-ABI DLL. Build it from the windows-com-node reference with the MSVC toolchain, register it with regsvr32, and check it with the verify.exe that ships beside it. Three things differ from the Unix path and are documented in that README:
  • Your node needs its own CLSID and LIBID. The interface ID is Omega’s and never changes.
  • The class must be registered with a COM surrogate so CLSCTX_LOCAL_SERVER activation succeeds.
  • Your type library must importlib("omega_node.tlb"), the library Omega itself embeds and registers, and declare only your coclass.
The capabilities, health, and invoke JSON, and the return-code rules in Node contract, are identical.

Next

  • Node contract: what to return, and what the platform does with each code.
  • Ship a node: upload it as a release artifact and register it with a place_file step.