Compiling and packaging your Rust functions (zip) locally using Cargo Lambda

This is an advanced topic, that has a fairly simple solution if/when using Rust for our Netlify functions.

Using AWS Cargo Lambda

Netlify has a solution for compiling your functions during build using a cross compile target (x86_64-unknown-linux-musl) which is a minimal C library. This uses the cargo compiler by default for simplified cross-compilation. A really complete compiler is to use Zig which has many advantages, so AWS Lambda uses it in their cli tool to compile using cargo-zigbuild for compile of lambda functions in Rust.

Once you run into errors with linking due to cross-compile issues, you will need to consider this solution.

You can use cargo-zigbuild yourself, but cargo-lambda has some great features and will simplify the setup and will be maintained by the aws group. Remember cargo-lambda is using cargo-zigbuild under the hood, so you are just getting the added benefit and features. Also, I haven’t confirmed, but my binaries seemed to be smaller.

Requirements

  • cargo-lambda (install with homebrew)
  • Zig (of course)
  • nasm (if required)

What I needed

  • libpq (postgress client needed if using postgres in your lambda)

Building and placing your assets for deploy

Note: We need to make sure we setup our Netlify functions to use a Rust compatible runtime on AWS. Setup the environment variable in the netlify UI (app.netlify.com) to tell Netlify to use the correct runtime for the lambda: AWS_LAMBDA_JS_RUNTIME= provided.al2023 This is an OS-only runtime used for runtime interface to Rust.

We are going to compile our lambda using a script and it will create the .zip bundle for deploy

#!/bin/bash
# https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
set -euxo pipefail

mkdir -p netlify/functions
# cargo lambda build --release --output-format Zip
cargo lambda build -p hello --release --output-format zip --include netlify-toolchain
# add copy commands as you add functions
cp target/lambda/hello/bootstrap.zip netlify/functions/hello.zip

The netlify-toolchain file might not be required, but I include it because Netlify includes it in theirs.
netlify-toolchain

{"runtime":"rs"}

This can all be done with cargo-zigbuld and zip the files yourself, but cargo-lambda makes it easier.

I compile local due to the amount of time for the compiles and the dependencies needed. Saves on build minutes also.

There is a way to script out the requirements but would require using the homebrew setup on Netlify. I chose not to do that and just compile my lambda functions locally and commit my functions to my repository. I think the best thing to do would also include a version file with the bundle or make sure to debug print the version of the lambda at startup/initialization.