Skip to content

native modules: build each crate separately with crate2nix - #3861

Merged
jeff-hykin merged 5 commits into
jeff/fix/native_build_cargo_pathfrom
jeff/feat/crate2nix_native_modules
Sep 1, 2026
Merged

native modules: build each crate separately with crate2nix#3861
jeff-hykin merged 5 commits into
jeff/fix/native_build_cargo_pathfrom
jeff/feat/crate2nix_native_modules

Conversation

@jeff-hykin

Copy link
Copy Markdown
Member

Stacked on #3770 jeff/fix/native_build_cargo_path.

Replaces the single workspace cargoHash with crate2nix. Cargo.nix is
generated from Cargo.lock and gives one derivation per crate, so each crate
gets its own store path and is cached individually. Previously any Cargo.lock
change invalidated the one aggregate hash and rebuilt the whole workspace, and
a lock bump on main broke the hash on branches that never touched rust.

Side effect: this also drops the importCargoLock download path, which returns
403 for crates.io/api/v1/crates/<name>/<version>/download. crate2nix fetches
static.crates.io, which does not.

Adding a native module no longer touches flake.nix. examples/native-modules/deps.nix
is added here as the case that proves it:

_: {
  binaries = [ "dimos-native-module-examples" ];
}

crate-hashes.json is no longer committed. Its keys name a git dependency's
branch with no rev, so a committed copy goes stale as soon as that branch moves;
the hashes are already inlined in Cargo.nix.

Regenerate after any Cargo.lock or member Cargo.toml change:

bin/regen-cargo-nix

The cargo-nix-current job fails if the committed Cargo.nix does not match.

Build times measured locally:

build time
ray_tracing, cold 11m43s
mls_planner, immediately after 21.8s
examples, brand-new module 41.7s

Cargo.nix gives every crate its own derivation, so editing one module
does not rebuild the others and each crate caches on its own. Measured:
a cold ray_tracing build is 11m43s, and mls_planner right after is 21.8s.

It also removes the aggregate cargoHash, which had to be re-pasted by
hand whenever Cargo.lock moved -- including from main, which breaks
branches that never touched rust, because CI builds the merge commit.
The replacement failure mode is a stale generated file, which the new
cargo-nix-current job prints as a diff instead of a number to re-paste.

Regenerate with bin/regen-cargo-nix. The generated pair is excluded from
the byte-rewriting pre-commit hooks so it stays reproducible, and
Cargo.nix is exempted from the large-files check -- LFS would be wrong
for a file CI has to diff as text.
Adding a module is now a deps.nix and nothing else, so the examples can be
real build targets instead of a workspace member nothing referenced. They
build in 42s here because every crate under them is already a store path.

Doubles as the regression test for that claim: if adding a module ever starts
requiring a flake.nix edit again, this file is the one that stops building.
Its keys are scoped to a git dependency's branch and carry no rev, so a
committed copy silently goes stale the second that branch moves, pinning a
hash that no longer matches the revision Cargo.lock resolves to. That is the
exact failure this whole change set exists to remove.

It is also redundant: it is only crate2nix's prefetch cache, and the hashes
are already inlined in Cargo.nix. Regenerating with the file absent produces
a byte-identical Cargo.nix, so nothing in the repo depends on it.

Dropping it also retires two problems rather than papering over them: it no
longer needs a pre-commit exclusion (pretty-format-json was rewriting it on
every commit, which had already introduced a trailing newline the generator
never emits), and it no longer needs an editorconfig exception for that
missing final newline.
crate2nix shells out to `cargo metadata`, so the generated file depends on
whichever cargo is on PATH. The generator itself was pinned by flake.lock but
cargo was not: locally that was a rustup 1.98.0, while the toolchain this repo
pins for its clippy and fmt hooks is 1.94.0, and CI would have used whatever
the runner image ships.

The two happen to agree today -- checked by regenerating under 1.94.0 and
getting a byte-identical Cargo.nix -- so this fixes a latent problem rather
than a live one. Worth doing anyway: the failure it prevents is a diff that
only appears on the machine with the odd cargo, which is the hardest kind to
read when cargo-nix-current is what reports it.
I had commented it as crate2nix's per-crate override hook. It is not: the
`crateConfig` argument Cargo.nix defaults to this path is declared and then
never read anywhere in the generated file. Overrides added here would have
silently done nothing, which is a worse trap than having no file at all.

The file still has to exist -- `bin/build-native-modules --inputs-hash` walks
nix path literals textually, cannot evaluate the `builtins.pathExists` guard
around this one, and exits 1 with "reference './crate-config.nix' does not
exist". Verified by moving the file away. Kept an empty file rather than
teaching that parser about conditional paths, since a parser that learns to
skip guarded references can also skip one that matters.
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This change moves Rust native-module builds to generated per-crate Nix derivations, exposes dedicated flake outputs for module executables, and adds a freshness check for generated Cargo metadata. It also updates native-module launch configuration, makes native LCM transport honor LCM_DEFAULT_URL, and replaces MLS surface closing with a tiled distance-transform implementation.

The LCM URL parsing behavior was exercised with compiled tests covering valid UDP multicast URLs, optional TTL values, and malformed URL fallback behavior. The MLS morphology implementation was compared against direct L1 dilation and erosion across exhaustive, randomized, and regression geometry; the compared behavior matched.

T-Rex validation blocked

  • Tool: nix is unavailable, so the root-flake commands that build the ray-tracing and MLS native-module packages could not run.
  • Package: the Python configuration harness stopped before production path resolution and process launch because psutil is unavailable in the validation environment.

Confidence Score: 5/5

No confirmed defect blocks merging.

No review findings remain after the focused LCM parsing and surface-closing failure paths were exercised and contradicted the predicted regressions. The unavailable Nix and Python dependency limited coverage of the output-link launch path but did not demonstrate a defect.

Files Needing Attention: The root-flake launch path in flake.nix, dimos/mapping/ray_tracing/module.py, and dimos/navigation/nav_3d/mls_planner/mls_planner_native.py should be exercised in an environment with Nix available.

T-Rex T-Rex Logs

What T-Rex did

  • The focused native-module configuration wrapper was executed from /home/user/repo, confirming the package-to-binary mappings for dimos-voxel-ray-tracing and dimos-mls-planner, and that a prior release build produced voxel_ray_tracing and mls_planner; the run noted that Nix is unavailable and halted on ModuleNotFoundError: No module named 'psutil' before production configuration could resolve its working directory and output-link.
  • A locked Cargo test compiled and ran the focused LCM URL parsing tests; all three tests passed.
  • A standalone Rust harness compared the revised chamfer closing implementation with direct L1 dilation followed by erosion and passed 262,144 exhaustive 4×4 cases across radii 0–3, 2,400 deterministic randomized 32×24 cases across radii 1–8, and center-hole and no-bridge regressions; focused surface tests also passed on the prior revision and the changed revision.
  • The results disprove the predicted morphology-output regression, as the chamfer comparison harness results and surface tests passed for both revisions.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "Describe crate-config.nix as the placeho..." | Re-trigger Greptile

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

@@                         Coverage Diff                          @@
##           jeff/fix/native_build_cargo_path    #3861      +/-   ##
====================================================================
+ Coverage                             77.60%   77.66%   +0.06%     
====================================================================
  Files                                  1317     1323       +6     
  Lines                                124792   125487     +695     
  Branches                              10868    10931      +63     
====================================================================
+ Hits                                  96841    97457     +616     
- Misses                                24816    24885      +69     
- Partials                               3135     3145      +10     
Flag Coverage Δ
OS-ubuntu-24.04-arm 74.33% <100.00%> (+0.08%) ⬆️
OS-ubuntu-latest 74.87% <100.00%> (+0.07%) ⬆️
Py-3.10 74.87% <100.00%> (+0.07%) ⬆️
Py-3.11 74.87% <100.00%> (+0.08%) ⬆️
Py-3.12 74.86% <100.00%> (+0.07%) ⬆️
Py-3.13 74.87% <100.00%> (+0.07%) ⬆️
Py-3.14 74.87% <100.00%> (+0.07%) ⬆️
Py-3.14t 74.87% <100.00%> (+0.07%) ⬆️
SelfHosted-Large 30.24% <100.00%> (+0.02%) ⬆️
SelfHosted-Linux 34.75% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
dimos/mapping/ray_tracing/module.py 100.00% <100.00%> (ø)
...avigation/nav_3d/mls_planner/mls_planner_native.py 100.00% <100.00%> (ø)

... and 11 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added the ready-to-merge Required CI checks have passed on this PR label Sep 1, 2026
@jeff-hykin
jeff-hykin merged commit 0e1d204 into jeff/fix/native_build_cargo_path Sep 1, 2026
30 checks passed
@jeff-hykin
jeff-hykin deleted the jeff/feat/crate2nix_native_modules branch September 1, 2026 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Required CI checks have passed on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant