Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions logos-developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ The full set of available fields:
| `view` | Yes (`ui_qml`) | -- | Relative path to the QML entry file (e.g. `Main.qml`). Required for `ui_qml` modules. |
| `dependencies` | No | `[]` | Other Logos module names this depends on. Each entry must match the `name` field in that dependency's `metadata.json`. |
| `interface_dependencies` | No | `[]` | Header *interfaces* this module binds at runtime, decoupled from any concrete module. Each entry is `{ name, file, impl_class?, input? }` — see [Dependency interfaces](#dependency-interfaces) and the [tutorial](tutorial-interface-dependencies.md). |
| `dependency_overrides` | No | `{}` | Per-dependency LIDL-contract source overrides, keyed by dependency name → `{ file, input?, impl_class? }`. Forces where a dependency's interface is read from; normally auto-resolved from the dep's `lidl` output. See [§9.2 Module Dependencies](#92-module-dependencies). |
| `include` | No | `[]` | Additional files (e.g. shared libraries like `libwaku.so`, `libwaku.dylib`) to bundle alongside the plugin in the output. |
| `nix.packages.build` | No | `[]` | Nix packages for build time |
| `nix.packages.runtime` | No | `[]` | Nix packages for runtime |
Expand Down Expand Up @@ -1103,6 +1104,27 @@ Each entry in `dependencies` must match the `name` field in that module's own `m

When your module is installed via `lgpm`, its dependencies are automatically resolved and installed first. When loaded via `logos-basecamp`, core module dependencies are loaded before your module.

#### How dependencies are consumed — the LIDL contract

Each module publishes a small, language-neutral **LIDL interface contract** as a cheap flake output (`packages.<system>.lidl`), generated from its source with no plugin compile. When you depend on a module, the builder generates the typed `modules().<dep>` wrapper **from that published LIDL** — so building (or packaging) your module **does not build the dependency module**. The only step that still builds and bundles dependency plugins is the standalone-app run (`nix run` / `#run`), which has to, because it loads them.
Comment thread
dlipicar marked this conversation as resolved.

This is the same `logos-cpp-generator` from [§8.2](#82-the-c-sdk-code-generator), just driven by the dependency's LIDL contract — the same kind of `.lidl`/`.h` contract `interface_dependencies` uses — instead of inspecting a compiled plugin. Inspecting a compiled plugin (as §8.2 describes) is the manual/standalone path; for declared module dependencies the builder uses the contract path, which is why no dependency plugin is built.

Because the contract is LIDL, the dependency's implementation language doesn't matter: the pipeline is `source → LIDL → C++` for a C++ module today, and `Rust → LIDL → C++` for a Rust module tomorrow — the same generated `modules().<dep>` wrapper either way.

> **Transitional fallback.** A dependency built by an older `logos-module-builder` won't expose a `lidl` output yet; for those the builder falls back to the previous behavior (build the dependency and copy its generated headers), so mixed dependency graphs keep working.

To force a specific contract source for a dependency — a committed `.lidl`, a header in another repo, etc. — add a `dependency_overrides` entry keyed by the dependency name:

```json
"dependencies": ["calc_module"],
"dependency_overrides": {
"calc_module": { "file": "interfaces/calc.lidl" }
}
```

Each override is `{ file, input?, impl_class? }`: `file` is the `.lidl`/`.h` path (relative to this repo, or to the flake `input` if given), and `impl_class` is required for a `.h` file. Most modules never need this — auto-resolution from the dependency's `lidl` output is the default.

### 9.3 Exposing Prometheus Metrics

Infra operators monitor logos.dev nodes with Prometheus. The
Expand Down
4 changes: 2 additions & 2 deletions outputs/tutorial-composing-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Three small config files declare the module, its dependency on `calc_module`, an

### 2.1 `metadata.json` — declare the dependency

The one field that matters here is `dependencies`: listing `calc_module` tells the builder to fetch `calc_module`'s headers and event metadata and generate a typed wrapper for it. The dependency name **must match** `calc_module`'s own `metadata.json` `name`.
The one field that matters here is `dependencies`: listing `calc_module` tells the builder to read `calc_module`'s published LIDL interface contract and generate a typed wrapper for it — without building `calc_module` itself. The dependency name **must match** `calc_module`'s own `metadata.json` `name`.

```json
{
Expand Down Expand Up @@ -427,7 +427,7 @@ nix flake update --override-input calc_module path:../logos-calc-module
git add flake.lock
```

Now build the full package. For a universal module with a dependency, this is where `logos-cpp-generator` runs over both `src/calc_aggregator_impl.h` and `calc_module`'s exported interface, emitting the plugin glue **and** the typed `modules().calc_module` wrapper under `generated_code/`:
Now build the full package. For a universal module with a dependency, this is where `logos-cpp-generator` runs over both `src/calc_aggregator_impl.h` and `calc_module`'s published LIDL contract, emitting the plugin glue **and** the typed `modules().calc_module` wrapper under `generated_code/` — note `calc_module`'s own plugin is not built here, only its LIDL is read:

```bash
nix build
Expand Down
4 changes: 2 additions & 2 deletions tests/tutorial-composing-modules.test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ sections:
steps:
- title: "`metadata.json` — declare the dependency"
text: |
The one field that matters here is `dependencies`: listing `calc_module` tells the builder to fetch `calc_module`'s headers and event metadata and generate a typed wrapper for it. The dependency name **must match** `calc_module`'s own `metadata.json` `name`.
The one field that matters here is `dependencies`: listing `calc_module` tells the builder to read `calc_module`'s published LIDL interface contract and generate a typed wrapper for it — without building `calc_module` itself. The dependency name **must match** `calc_module`'s own `metadata.json` `name`.
Comment thread
dlipicar marked this conversation as resolved.
file:
path: metadata.json
language: json
Expand Down Expand Up @@ -425,7 +425,7 @@ sections:
nix flake update --override-input calc_module path:../logos-calc-module
- run: "git add flake.lock"
post_text: |
Now build the full package. For a universal module with a dependency, this is where `logos-cpp-generator` runs over both `src/calc_aggregator_impl.h` and `calc_module`'s exported interface, emitting the plugin glue **and** the typed `modules().calc_module` wrapper under `generated_code/`:
Now build the full package. For a universal module with a dependency, this is where `logos-cpp-generator` runs over both `src/calc_aggregator_impl.h` and `calc_module`'s published LIDL contract, emitting the plugin glue **and** the typed `modules().calc_module` wrapper under `generated_code/` — note `calc_module`'s own plugin is not built here, only its LIDL is read:
- run: "nix build"

- title: "Check the output"
Expand Down
Loading