Building MozJS with Nix

WORK IN PROGRESS

Nix is a package manager and build system for Linux and macOS. It is designed to be able to self-host an operating system (called NixOS) and to be able to run alongside an existing UNIX system (such as Ubuntu or macOS).

= Getting started =

Each step in this tutorial can be found in the mozjs-example GitHub repository. You can follow along with the commits in the repository, since each one corresponds to a step here.

Start out by installing the nix package manager.

= Set up a crate =

We'll start] by putting some files and Cargo dependencies. Why are we even going to bother with Nix? Because this crate depends on SpiderMonkey (that's MozJS, or the Firefox JavaScript engine), and that has very specific dependencies on its C compiler and available libraries.

You can "cargo build" if you want, but unless you have libclang lying around, it won't build.

As is normal for Rust projects, this will generate a Cargo.toml and a source file]. The example code has added some code, plus a couple of dependencies.

= Set up niv =

This step is going to depend on niv, the nix version manager and the tool we use to handle auto-updating dependencies.

Once that's installed, we'll use niv to generate a dependency file for the project repository itself. By making the nix repository a fixed constant, we can promise that as long as you have a spec-compliant nix interpreter, you'll be able to build the app itself.

The result will be two files: nix/sources.json and nix/sources.nix. The nix file is a script for importing the json file. The nix file is identical across almost all nix projects, since its purpose is just to bootstrap it, while the json file (since it's json) is easy to automatically update.

= Set up crate2nix and nix-shell =

The result of running the niv command will be a new couple of lines in the dependencies file (and also switch to a newer version of nixpkgs itself, because the Rust compiler in the old version of nixpkgs is really, really old).

To really use it, though, we'll want to create a nix-shell file. Let's do a couple of things to make everything easier for us.

Then let's write the shell.nix file, which actually defines the shell proper.

Now, if you run nix-shell, it should pull in crate2nix and let you use it.

= Using Nix and crate2nix as the build system for a Rust package =

The nixpkgs repository provides two high-level functions for building Rust crates: buildRustPackage and buildRustCrate. The buildRustPackage function is a wrapper for invoking Cargo, while buildRustCrate is a wrapper for invoking the rustc compiler.

To get the latest version of rust in the Nix build system, you can use the nixpkgs-mozilla overlay.

Building a Rust crate using crate2nix
Because Nix is designed to handle build caching and dependencies itself, some prefer to use the crate2nix script generator. This script converts a Cargo.lock file to a Cargo.nix script, which can then be loaded into a larger Nix project. The Cargo.nix script uses buildRustCrate, using Nix's own infrastructure to download from crates.io (or from a Nix build cache) and avoiding Cargo entirely.