Is there a way to diasable caching crates?

I'm on a Linux live USB. A temporary file system. Rust minimal profile is around 500 MB.

I'm trying to just download and run Deno's Roll Your Own JavaScript Runtime Roll your own JavaScript runtime.

I keep running out of space when downloading the tokio crate, or when running cargo build --release, when I get that far.

I start at under 1 GB of available disk space.

E.g.,

user@user:~/bin/runjs$ cargo add tokio --features=default
    Updating crates.io index
      Adding tokio v1.41.0 to dependencies
             Features:
             - bytes
             - fs
             - full
             - io-std
             - io-util
             - libc
             - macros
             - mio
             - net
             - parking_lot
             - process
             - rt
             - rt-multi-thread
             - signal
             - signal-hook-registry
             - socket2
             - sync
             - test-util
             - time
             - tokio-macros
             - tracing
             - windows-sys
user@user:~/bin/runjs$ cargo run
  # ...
  Downloaded tokio v1.41.0
  Downloaded deno_core_icudata v0.0.73
  Downloaded v8 v0.106.0
error: failed to unpack package `v8 v0.106.0`

Caused by:
  failed to unpack entry at `v8-0.106.0/v8/src/wasm/wasm-module-builder.h`

Caused by:
  failed to unpack `/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v8-0.106.0/v8/src/wasm/wasm-module-builder.h`

Caused by:
  failed to unpack `v8-0.106.0/v8/src/wasm/wasm-module-builder.h` into `/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v8-0.106.0/v8/src/wasm/wasm-module-builder.h`

Caused by:
  No space left on device (os error 28)

The goal is to complete a download of tokio and a cargo build --release of the above code in the article for around 500 MB, so I can still have around 200 MB left on disk.

I noticed that in the .cargo directory there are the archives and the extracted folders. Is there a way to automatically delete the archives when the crate is extracted so I am not carrying around the crate archives, too?

Alternatively, is it possible to instruct cargo to write the crate archives to an external USB device, and symlink to those dependencies in ~/.cargo , instead of writing the crates to ~/.cargo ?

Are you trying to cross-compile? Maybe the solution is to not attempt to build on a host with only 1GB (presumably limited by system RAM).

To the question you asked, sometimes you can cut down on dependencies by disabling unneeded feature flags. It doesn't help in this case because deno_core has about 180 dependencies that cannot be disabled.

Until someone puts in the work to optimize dependencies, your best option may be building on a larger host and downloading the binary within the live CD environment.

Nothing is preventing you from mounting ~/.cargo to your USB drive before starting cargo. No need to symlink anything. It just seems weird to insist that building in this environment is the right course of action.

2 Likes

Unfortunately, temporary junk created during the build easily grows to many gigabytes, even for small crates (100×-1000× size increase). You probably won't be able to compile anything in just 200MB ;(

  • Rust/Cargo easily produces gigabytes of debug info for even small crates. Make sure to disable debug info completely. See profiles.

  • Disable incremental build cache. This is another dir that just grows and grows.

You can delete ~/.cargo/registry/ before/after a build, but Cargo will need the downloaded and decompressed files to be there during the build.

4 Likes

Nothing is preventing you from mounting ~/.cargo to your USB drive before starting cargo.

Kindly explain precisely how you would do that.

It just seems weird to insist that building in this environment is the right course of action.

I've been experimenting on a live Linux USB for years. The way I see it, if it can't be built in a temporary file system with ~1 GB of total space, it's probably too expensive for standalone embedded systems where the source code of any compilers is also included in the "file".

C, C++, probably because of gcc is already on Linux. Python, WASI, can all be compiled for less than 1 GB deposit. With deno compile we can get a 78 MB executable from a 135 MB deno executable. Just for an example. Rust might spit out a 4 MB executabloe, at the cost of 465 MB more, initally. It's a balance, depending on the requirement and environment.

Assuming your USB drive is at /dev/sbd1 and you've already emptied ~/.cargo for mount(8):

# mount /dev/sdb1 ~/.cargo

This doesn't align with my expectations. An "embedded system" doesn't have to run Linux. There are many bare metal platforms where the default is cross compiling. Raspberry Pi Pico, ESP-32, even wasm32.

Having said that, I do not know of any efforts to make the compiler run on small machines.

2 Likes

I've got this now

[profile.dev]
opt-level = 3
debug = false
strip = "debuginfo"
debug-assertions = false
overflow-checks = true
lto = true
panic = "abort"
incremental = false
codegen-units = 16
rpath = false

I'm going to try mounting ~/.cargo to a USB to see if that works.

if only your disk space is constrained, and you still have 2-3GB of RAM, your best bet is mounting the target dir to a zramfs to try to save space via compression.

1GB is just so far below "typical hard drive sizes", you're going to have issues.

and Rust has the philosophy that it's better to waste resources at compile time than at runtime. which makes sense considering you're basically always cross compiling for embedded workflows.

How to handle

 /home/user/.cargo/bin/cargo: No such file or directory

after

sudo mount /dev/sdb1 ~/.cargo

?

Can you explain the approach, in detail?

Any reason we can't just atomatically delete the unpacked archives programmatically? That will reduce space.

rustup, cargo, and all of the compiler toolchains are installed to ~/.cargo by default. After mounting the USB drive, you can install rustup and your toolchains to the USB drive.

Isn't there more to it than just using mount? We have to set PATH to include the USB device, too, right?

It sure would be helpful is somebody wrote up a piece about how to store cargo and company on an external drive, and use them as if they were on the OS file system.

We have to set PATH to include the USB device, too, right?

adding ~/.cargo/bin to PATH is part of normal cargo setup. PATH doesn't care what drive the files are on, it just cares about their filepath.

1 Like

So mount ~/.cargo to the external drive before or after running the following?

I'm looking for a roadmap to do this, 'cause it ain't happening using ordinary Rust installation methods.

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --profile minimal --default-toolchain nightly

mount ~/.cargo before doing anything.

mounting disks earlier is almost always better, there's a reason /etc/fstab is automounted at boot.

Even though ~/.cargo doesn't exist at that point?

I'll try to get this going over the next couple of days.

yes, create it and mount it.

cargo doesn't create the dir until it needs to put stuff into it, at which point, it needs to already be mounted.

The .cargo directory is created when I run the install script. I'll try to get this working when I have time over the next couple of days.

Ok, well you should still be able to create it beforehand.

I've never actually used the install script, I just install rustup via system package manager.

codegen-units=16 will duplicate shared code 16 times. LTO will write all code twice, and use exponentially more memory.

Use 1 unit and thin lto.

1 Like