trunk-rs / trunk

Build, bundle & ship your Rust WASM application to the web.
https://trunkrs.dev/
Apache License 2.0
3.27k stars 236 forks source link

Supporting pure build toolchains #732

Open psionic-k opened 4 months ago

psionic-k commented 4 months ago

Writing this relatively late for me, so expect inaccuracies.

In order to ensure reproducibility and avoid unidentified supply chain surface area, Nix and Guix etc seek to build from within a sandbox.

To accomplish this, the network access for dependencies happens separately from any build and cargo is directed to the location of these pre-fetched dependencies and made to succeed somewhat painstakingly.

Since providing and using the dependencies for a Rust build output are pretty tightly related, it makes sense to output the wasm and then hand it to trunk to complete the steps of running bindgen and bundling.

Have you seen any of this done or considered it yet?

ctron commented 4 months ago

Nope. However, IIRC trunk has a nixos package, and an --offline switch. Wouldn't that work?

psionic-k commented 4 months ago

Indeed I used the nix package to run trunk, and I will that package as a build dependency to build an application.

For context, Nix builds are only done for deployment. The goal is to complete every build step in a sandbox using only upstream outputs or resources that can be content hashed. Cargo --offline is part of the picture, but we also need to purely provide the resources that enable --offline to succeed. Basically, where does the target directory or a bunch of -L flags come from?

Cargo is one piece. Broadly, any steps that might try to access the network will need some treatment. I don't really use SASS etc, so maybe you can help me out at identifying other potential sources of network access used by trunk build. The usual way of handling these is to purify dependency fetching and then do anything that can be done in a sandbox as normally as possible.

To make the cargo step pure, as far as Trunk is concerned, I only need to specify the path where Trunk can find my cargo outputs and proceed with bindgen and so on. I will complete the cargo build independently before handing off to Trunk. This probably means I just use an option to delegate part of the cargo pipeline.

In case you are curious about the delegation, purifying cargo builds to succeed in a sandbox can be broken into three steps:

  1. All dependency fetching is converted to pure, reproducible specifications, basically something that has a content hash
  2. Builds are done within a sandbox that can only access inputs from 1 and outputs are recorded in a pure store
  3. Any downstream Rust builds are configured to use the pure inputs from 2.

All of the Nix tools for building a Rust binary use variations of steps 1-3 and varying degrees of composition of steps (step 3).

ctron commented 4 months ago

I don't know about nix, so I can't help much there.

But to my understanding, you would need to pull in all inputs (tools and source) through some trusted mechanism. May the by nix or just trusting your local source. So I guess, like a container, you would need to assemble some build environment with nix, which has all the tools required pre-populated. And then run trunk with --offline, to other use the local tools, or fail if they are missing.

After that, just provide that environment your own sources, as well as the vendored ones. cargo should take care of the rest.

So I think this should already be possible.

psionic-k commented 3 months ago

Ping me if anyone looks for Nix support. I have a pretty good idea of the scope of the work needed. It's minor surgery.

However, I decided to go full stack for now. Since I have in independent API server, I may go back to Trunk. I was just interested in getting SSR for at least the client-independent rendering to do fine with SEO and low / no javascript.

Nub commented 1 month ago

Ping me if anyone looks for Nix support. I have a pretty good idea of the scope of the work needed. It's minor surgery.

However, I decided to go full stack for now. Since I have in independent API server, I may go back to Trunk. I was just interested in getting SSR for at least the client-independent rendering to do fine with SEO and low / no javascript.

I would love to hear if you identified a fix, I am currently struggling with deploying and app in nix via trunk due to the runtime deps it wants to download, and it fails to even search your path if you provide them in a sane manner.

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.07s
2024-05-16T01:39:21.511820Z  INFO fetching cargo artifacts
2024-05-16T01:39:21.596186Z  INFO processing WASM for frontend
2024-05-16T01:39:21.621080Z ERROR ❌ error
error from HTML pipeline

Caused by:
    0: error from asset pipeline
    1: couldn't find application wasm-bindgen
Error: error from HTML pipeline

Caused by:
    0: error from asset pipeline
    1: couldn't find application wasm-bindgen

[merops@nixos:~/src/themis/frontend]$ wasm-bindgen
Invalid arguments.

Usage:
    wasm-bindgen [options] <input>
    wasm-bindgen -h | --help
    wasm-bindgen -V | --version
Nub commented 1 month ago

And to make things worse if you let it download bins they don't run as expected

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.07s
2024-05-16T01:44:32.924352Z  INFO fetching cargo artifacts
2024-05-16T01:44:33.007139Z  INFO processing WASM for frontend
2024-05-16T01:44:33.030969Z  INFO downloading wasm-bindgen version="0.2.92"
2024-05-16T01:44:34.215630Z  INFO installing wasm-bindgen
2024-05-16T01:44:34.302538Z  INFO calling wasm-bindgen for frontend
Could not start dynamically linked executable: /home/merops/.cache/trunk/wasm-bindgen-0.2.92/wasm-bindgen
NixOS cannot run dynamically linked executables intended for generic
linux environments out of the box. For more information, see:
https://nix.dev/permalink/stub-ld
2024-05-16T01:44:34.304254Z ERROR ❌ error
error from HTML pipeline

Caused by:
    0: error from asset pipeline
    1: wasm-bindgen call returned a bad status
Error: error from HTML pipeline

Caused by:
    0: error from asset pipeline
    1: wasm-bindgen call returned a bad status
ctron commented 1 month ago

Looks like there's a hint:

For more information, see: https://nix.dev/permalink/stub-ld

One aspect of trunk is to manage the required CLIs for you. If you opt-out of this, you need to take care of this yourself. And if you want to use it, trunk can only do this for environments for which the dependencies/tools support it.

It looks like wasm-bindgen released a binary which doesn't run on nixos. I wouldn't see this as an issue of trunk though.

Judging from the error message, it looks like you're running an older version of trunk. Could you run trunk --version and paste the output? If it's anything before 0.19.x, I would recommend to upgrade, as there have been many improvements to the management of tools.

ctron commented 1 month ago

I am not sure what needs to be done here. It feels more like a discussion. So maybe this should be transformed into one.