fix(make): harden dx-cli preflight against wrong-binary collisions #82

Merged
sameh-farouk merged 2 commits from fix/dx-preflight-wrong-binary into development 2026-04-21 18:24:28 +00:00
Member

Summary

Fixes make build-wasm (and related targets) so they no longer fail cryptically when an unrelated dx binary is earlier on PATH than Dioxus CLI — and auto-installs Dioxus CLI on first build so fresh machines bootstrap transparently.

Closes #81.

The original bug

command -v dx in _check-dx is satisfied by any executable named dx. Common collisions seen in the wild:

  • /usr/bin/dx → OpenDX (data-visualization tool) on Debian/Ubuntu
  • /opt/homebrew/bin/dx → Deno's deno x shim on macOS with Homebrew
  • anything else packaged as dx in a system-managed directory

With the wrong dx first on PATH, the preflight "passes", then dx build runs against e.g. OpenDX and produces:

/usr/bin/dx : unrecognized parameter:  [1]
(use -help to get usage information)
make: *** [Makefile:110: build-wasm] Error 1

Unreadable, and nothing points at PATH shadowing as the cause.

The fix

Pin $(DX) to ~/.cargo/bin/dx unconditionally. No PATH lookup, no ambiguity. That's where cargo install dioxus-cli puts the binary, which is the one path of true.

DX := $(HOME)/.cargo/bin/dx

Auto-install on first build. _check-dx now bootstraps Dioxus CLI instead of erroring:

  • $(DX) missing → cargo install dioxus-cli --locked
  • $(DX) exists but is not Dioxus (rare) → cargo install ... --force
  • cargo itself missing → fail with a pointer to https://rustup.rs

Post-install validation ($(DX) --version | grep -qi dioxus) remains as defense-in-depth.

All rule recipes that previously called dx now call $(DX): web, dev, desktop, build, build-wasm.

Behaviour matrix

State Before After
Fresh box, no dx anywhere Error: "Install dioxus-cli" Auto-installs on first make build-wasm (3-10 min), then proceeds
Dioxus already at ~/.cargo/bin/dx Works if on PATH; silently wrong if something else is earlier Always uses the cargo binary directly
OpenDX/Deno dx on PATH, no Dioxus Cryptic failure mid-build Auto-installs Dioxus to ~/.cargo/bin/dx, uses it
Wrong binary placed at ~/.cargo/bin/dx Detects, cargo install --force replaces it
No cargo installed at all Same cryptic failure Fails fast: "Install Rust first: https://rustup.rs"

Commits

  1. a2acc0a fix(make): harden dx-cli preflight against wrong-binary collisions — the original error-clearly approach.
  2. 31336bb fix(make): auto-install Dioxus CLI when missing or wrong — upgraded to auto-install.

Happy to squash into one on merge.

Verified

On macOS dev box with Dioxus CLI already installed at ~/.cargo/bin/dx:

$ make -n build-wasm
if [ ! -x "/Users/sameh/.cargo/bin/dx" ] || ! "/Users/sameh/.cargo/bin/dx" --version 2>&1 | grep -qi dioxus; then
    ... (install branch — not taken)
fi
echo "Building WASM (debug)..."
/Users/sameh/.cargo/bin/dx build --package hero_os_app --web --features web --no-default-features

Preflight is a no-op when Dioxus is already present. Builds proceed against the cargo-installed binary directly.

On Debian dev box with OpenDX at /usr/bin/dx and no Dioxus CLI, the original (commit 1) behaviour was confirmed correct — clear error instead of cryptic failure. Commit 2 extends that to auto-install instead of error.

Notes

  • --locked in cargo install pins transitive dep versions to what dioxus-cli's own Cargo.lock specifies — reproducible installs.
  • First-run message explicitly calls out the 3-10 min cost so make build-wasm doesn't appear to hang.
  • Diff: +26 -13 on Makefile, no other files touched.
## Summary Fixes `make build-wasm` (and related targets) so they no longer fail cryptically when an unrelated `dx` binary is earlier on `PATH` than Dioxus CLI — and auto-installs Dioxus CLI on first build so fresh machines bootstrap transparently. Closes #81. ## The original bug `command -v dx` in `_check-dx` is satisfied by **any** executable named `dx`. Common collisions seen in the wild: - `/usr/bin/dx` → OpenDX (data-visualization tool) on Debian/Ubuntu - `/opt/homebrew/bin/dx` → Deno's `deno x` shim on macOS with Homebrew - anything else packaged as `dx` in a system-managed directory With the wrong `dx` first on PATH, the preflight "passes", then `dx build` runs against e.g. OpenDX and produces: ``` /usr/bin/dx : unrecognized parameter: [1] (use -help to get usage information) make: *** [Makefile:110: build-wasm] Error 1 ``` Unreadable, and nothing points at PATH shadowing as the cause. ## The fix **Pin `$(DX)` to `~/.cargo/bin/dx` unconditionally.** No PATH lookup, no ambiguity. That's where `cargo install dioxus-cli` puts the binary, which is the one path of true. ```makefile DX := $(HOME)/.cargo/bin/dx ``` **Auto-install on first build.** `_check-dx` now bootstraps Dioxus CLI instead of erroring: - `$(DX)` missing → `cargo install dioxus-cli --locked` - `$(DX)` exists but is not Dioxus (rare) → `cargo install ... --force` - `cargo` itself missing → fail with a pointer to https://rustup.rs Post-install validation (`$(DX) --version | grep -qi dioxus`) remains as defense-in-depth. All rule recipes that previously called `dx` now call `$(DX)`: `web`, `dev`, `desktop`, `build`, `build-wasm`. ## Behaviour matrix | State | Before | After | |---|---|---| | Fresh box, no dx anywhere | Error: "Install dioxus-cli" | Auto-installs on first `make build-wasm` (3-10 min), then proceeds | | Dioxus already at `~/.cargo/bin/dx` | Works if on PATH; silently wrong if something else is earlier | Always uses the cargo binary directly | | OpenDX/Deno `dx` on PATH, no Dioxus | Cryptic failure mid-build | Auto-installs Dioxus to `~/.cargo/bin/dx`, uses it | | Wrong binary placed at `~/.cargo/bin/dx` | — | Detects, `cargo install --force` replaces it | | No `cargo` installed at all | Same cryptic failure | Fails fast: "Install Rust first: https://rustup.rs" | ## Commits 1. `a2acc0a fix(make): harden dx-cli preflight against wrong-binary collisions` — the original error-clearly approach. 2. `31336bb fix(make): auto-install Dioxus CLI when missing or wrong` — upgraded to auto-install. Happy to squash into one on merge. ## Verified On macOS dev box with Dioxus CLI already installed at `~/.cargo/bin/dx`: ``` $ make -n build-wasm if [ ! -x "/Users/sameh/.cargo/bin/dx" ] || ! "/Users/sameh/.cargo/bin/dx" --version 2>&1 | grep -qi dioxus; then ... (install branch — not taken) fi echo "Building WASM (debug)..." /Users/sameh/.cargo/bin/dx build --package hero_os_app --web --features web --no-default-features ``` Preflight is a no-op when Dioxus is already present. Builds proceed against the cargo-installed binary directly. On Debian dev box with OpenDX at `/usr/bin/dx` and no Dioxus CLI, the original (commit 1) behaviour was confirmed correct — clear error instead of cryptic failure. Commit 2 extends that to auto-install instead of error. ## Notes - `--locked` in `cargo install` pins transitive dep versions to what dioxus-cli's own `Cargo.lock` specifies — reproducible installs. - First-run message explicitly calls out the 3-10 min cost so `make build-wasm` doesn't appear to hang. - Diff: +26 -13 on `Makefile`, no other files touched.
fix(make): harden dx-cli preflight against wrong-binary collisions
Some checks failed
Build and Test / build (pull_request) Failing after 6s
a2acc0af32
`command -v dx` in _check-dx is satisfied by any executable named `dx`
on PATH, including:

  - /usr/bin/dx  → OpenDX (data-visualization) on Debian/Ubuntu
  - /opt/homebrew/bin/dx → Deno's `deno x` shim on macOS with Homebrew
  - any other name-collision

The preflight then "succeeds" and build/serve targets invoke the wrong
`dx`, producing cryptic errors like:

    /usr/bin/dx : unrecognized parameter: [1]
    make: *** [Makefile:110: build-wasm] Error 1

Two changes:

1. Resolve `dx` deterministically. Prefer ~/.cargo/bin/dx (where
   `cargo install dioxus-cli` installs it) before falling back to
   whatever's on PATH. Assigned to `DX`.

2. Validate after resolution. Run `$(DX) --version` and grep for
   "dioxus" in the output. If absent, the found binary is not
   Dioxus CLI; print the resolved path, the install command, and
   the PATH-order hint, then exit.

All targets that called `dx` now call `$(DX)`: web, dev, desktop,
build, build-wasm.

Behaviour unchanged on any machine where Dioxus CLI is the only `dx`
on PATH, or where ~/.cargo/bin/dx is Dioxus CLI.
fix(make): auto-install Dioxus CLI when missing or wrong
Some checks failed
Build and Test / build (pull_request) Failing after 3s
31336bbfe8
Previous commit made _check-dx error clearly when dx was missing or
the resolved binary was not Dioxus. Better UX: just install it.

Two auto-install paths:

1. $(DX) missing — cargo install dioxus-cli --locked. Common case on
   fresh machines.
2. $(DX) exists but is not Dioxus CLI — cargo install ... --force,
   overwriting whatever ended up there.

Pin $(DX) to $(HOME)/.cargo/bin/dx unconditionally (dropped the PATH
fallback) so the Makefile's behaviour is deterministic and cannot be
influenced by an unrelated `dx` earlier on PATH. cargo install puts
Dioxus CLI at that exact path, which is what we want.

Post-install validation remains (checks `--version` output contains
"dioxus") as defense-in-depth. Fails fast if cargo itself is not
installed — points at rustup.rs instead.

First `make build-wasm` on a fresh machine takes 3-10 min extra to
compile dioxus-cli; subsequent runs are no-ops.
sameh-farouk merged commit 7a3932faa0 into development 2026-04-21 18:24:28 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_os!82
No description provided.