Help understanding error compiling Rust to WASM in NixOS

I’m working on a Rust library and I tried adding the following flake.nix file so I can get a development shell with all needed dependencies:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
    let
      pkgs = import nixpkgs { inherit system; };
    in
      {
        devShells.default = pkgs.mkShell {
          nativeBuildInputs = with pkgs; [
            rustup
            wasm-bindgen-cli
            wasm-pack
            binaryen
            protobuf
          ];
        };
      }
    );
}

When I try to compile to WASM by running cargo build --target wasm32-unknown-unknown --release, I get an error but I have no idea what it is saying.

   Compiling shared v0.1.0 (/home/user/src/lib)
error: linking with `rust-lld` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="  <I omitted this due to the character limit on discourse>
  = note: rust-lld: error: unknown file type: /home/user/src/lib/target/wasm32-unknown-unknown/release/deps/libsecp256k1_sys-73da753343bc1281.rlib(lax_der_parsing.o)
          

error: could not compile `shared` due to previous error

Could someone please help me understand what this error means?
I am new to Rust so it could just be something simple I’m getting wrong.

I have also put a reproducible copy on GitHub: GitHub - emccorson/shared
I had to omit part of the error message due to the character limits on Discourse, but the full message is in the GitHub README.

2 Likes

The build failed because the linker, lld, failed. The reason is likely in the rest of the log above.

1 Like

If you run file on the troublesome file, it may tell you it’s the wrong architecture. You can potentially try CC=clang cargo build (your args...) after adding clang to the shell. May also want to try CC=emcc if I recall correctly.

I was reminded of the gcc related issues I’ve had with trying to build wasm in the past by reading rust-lld: error: unknown file type: secp256k1.o · Issue #14 · bytecodealliance/wasi · GitHub

1 Like

Setting CC=clang worked! Thank you both for the help.

In my case, I ended up using pkgs.mkShell.override { stdenv = pkgs.clangStdenv; } which sets CC for me.

For me, targeting wasm32-unknown-unknown with pkgs.rustc-wasm32 only worked after adding llvmPackages.bintools (per the docs) and specifying RUSTFLAGS=“-C linker=lld”

EDIT: setting RUSTFLAGS was a footgun as it can override other RUSTFLAGS set for instance in .cargo/config.toml. Best to declare a linker specifically for a given target.

CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_LINKER = "lld";

Hope it helps someone else.

1 Like