fix(cross): fail loudly when a dep publishes nothing for the target system - #199
Merged
Conversation
…ystem
Two fixes, both found while chasing why chat_ui's Windows build died on
`fatal error: chat_module_api.h: No such file or directory`.
**The silent fallback.** Resolving a transitional header-copy dependency
did `input.packages.${system} or null`, and on null fell back to `input`
itself. For a flake input that is the dependency's SOURCE TREE, so the
plugin build gets a header root with no generated headers in it and fails
far away inside a generated TU — or, worse, succeeds against whatever
stale headers happen to be checked in. chat_module v0.2.2 publishes only
the four native systems, so every x86_64-windows consumer of it resolved
its headers to the chat_module checkout.
A flake that publishes `packages` but nothing for this system is now an
error naming the dep, the system, and what it does publish. The fallback
survives only for a genuinely bare-derivation input (no `packages` attr
at all), which is the pre-refactor shape it exists for.
**One resolver, not two.** That logic was copy-pasted into
mkLogosModule.nix (core modules) and buildCppPlugin.nix (ui_qml view
modules). It now lives once in common.nix and both call it. This is not
tidying: chat_ui is a view module, so a fix applied only to
mkLogosModule.nix left the case that motivated it untouched — which is
exactly what happened on the first attempt here.
Also single-sources the Windows build platform from
logos-nix's `windowsBuildSystems` instead of repeating "x86_64-linux" as
a literal in two places. Pinning it (rather than using the evaluating
system) is deliberate: it keeps packages.x86_64-windows.* one
well-defined derivation whoever evaluates it, so a Darwin and a Linux
checkout agree and share a cache. Widening it is now a change in
logos-nix, not here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Same silent-fallback shape as the header-copy resolver, one level out:
when a dependency published no usable package for the target system,
`collectAllModuleDeps` fell through to `input` -- putting the dep's
SOURCE TREE where an LGX package belongs. mkStandaloneApp then ships a
directory of .cpp files in place of a module, and the failure only shows
up at runtime as a module that never loads.
The two autoBundleLgx throws right above it already guard the adjacent
case ("a silent fallback would cause mkStandaloneApp to silently omit
the dependency at runtime"), so this closes the remaining hole in the
same function.
A bare-derivation input (no `packages` attr at all) still takes the
fallback -- that is the shape it exists for.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📊 Doc-test reportsThe four ways to wrap a C library plus the two cross-language composition tours — each scaffolded into real modules, built against this commit, loaded in logoscore, and driven — rendered alongside the commands actually run and their output (updated each run, commit Pages can take a minute to update after the run finishes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three fixes, all the same shape, all found while chasing why
chat_ui's Windows build died onfatal error: chat_module_api.h: No such file or directory.The silent fallback
Resolving a transitional header-copy dependency did
input.packages.${system} or null, and on null fell back toinputitself. For a flake input that is the dependency's source tree — so the plugin build gets a header root with no generated headers in it, and fails far away inside a generated TU. Or, worse, succeeds against whatever stale headers happen to be checked in.chat_module0.2.2 publishes only the four native systems, so everyx86_64-windowsconsumer silently resolved its headers to the chat_module checkout. The symptom pointed at an include path; the cause was three layers up.A flake that publishes
packagesbut nothing for this system is now an error:The fallback survives only for a genuinely bare-derivation input (no
packagesattr at all), which is the pre-refactor shape it exists for.The same hole in collectAllModuleDeps
One level out,
collectAllModuleDepsfell through toinputwhen a dependency published no usable package for the target — putting the dep's source tree where an LGX package belongs.mkStandaloneAppthen ships a directory of.cppfiles in place of a module, and it only shows up at runtime as a module that never loads.The two
autoBundleLgxthrows immediately above already guard the adjacent case, with the comment "a silent fallback would cause mkStandaloneApp to silently omit the dependency at runtime". This closes the remaining hole in the same function.One resolver, not two
The header-copy logic was copy-pasted into
mkLogosModule.nix(core modules) andbuildCppPlugin.nix(ui_qml view modules). It now lives once incommon.nixand both call it.This is not tidying.
chat_uiis a view module, so the first version of this fix — applied only tomkLogosModule.nix— left the exact case that motivated it untouched, and the verification run caught it still resolving happily. Two copies of a resolver is how that happens.Single-sourced Windows build platform
"x86_64-linux"was repeated as a literal in two places incommon.nix; it now comes from logos-nix'swindowsBuildSystems, which is where the decision and its reasoning already live.Pinning it rather than using the evaluating system is deliberate, and worth stating since it can read as a limitation: it keeps
packages.x86_64-windows.*one well-defined derivation no matter who evaluates it, so a Darwin and a Linux checkout agree and share a cache. A Darwin dev realises it through a Linux remote builder — which is what nixpkgs' own mingw cross assumes too. Widening it is now a one-line change in logos-nix rather than an edit here.Verification
Before/after evaluation with both trees exported the same way (
git archive), so the only variable is the change:chat_uiapps.x86_64-linux(thecollectAllModuleDepspath)s0mxf9yz…s0mxf9yz…— byte-identicalchat_uipackages.x86_64-linux4ip9ygq…4ip9ygq…— byte-identicalcapability_modulex86_64-linux / x86_64-windowsLOGOS_MODULE_BUILDER_ROOTdifferschat_uipackages.x86_64-windowschat_ui'sappsoutput is the one that matters for the second fix — it is a real UI module with dependencies, and it exercisescollectAllModuleDepsend to end.For
capability_moduleI diffed the derivations rather than just the hashes:inputDrvs,inputSrcsand every otherenvkey are identical, and the sole delta is the builder's own source path, which necessarily moves whenever any file in this repo changes.Follow-up
chat_modulegains itsx86_64-windowstarget in logos-co/logos-chat-module#65 and its follow-on, which is what makes the first error above stop firing forchat_ui.🤖 Generated with Claude Code