crate2nix

repository·master·Indexed 19 days ago

https://github.com/nix-community/crate2nix

crate2nix is a tool that generates Nix build files for Rust/Cargo projects. It enables precise, incremental builds by treating each crate in a dependency tree as an individual Nix derivation. Version 0.15.0 supports generating Nix expressions or a pre-resolved JSON representation of a workspace to move feature resolution and platform filtering from Nix eval-time to Rust.

Tokens
21.1K
Snippets
72
Records
98
Agent score
67%

What's inside crate2nix

  1. What is crate2nix?

    master

    crate2nix is a tool that builds Rust projects crate-by-crate using Nix. It leverages cargo_metadata to ensure the dependency tree and versions exactly match your Cargo.lock file.

    Key benefits include:

    • Hermetic CI builds: Only rebuild changed crates to save time.
    • Smart Caching: Caches individual crate builds to minimize Nix rebuilds.
    • Native Dependency Support: Uses the NixOS buildRustCrate function to handle libraries with non-Rust dependencies.
    • Nix Ecosystem Integration: Compatible with remote builds, minimal Docker images, and cloud deployments.
    • Flexible Nix Generation: Can optionally generate Cargo.nix during evaluation time so it doesn't need to be committed to version control.
  2. Understand crate2nix generation strategies

    master

    crate2nix supports two main strategies for converting Cargo projects to Nix:

    1. Manual (crate2nix generate): Generates a Cargo.nix file. This provides full build parallelism and avoids Import From Derivation (IFD) issues, but you must manually regenerate the file whenever your dependencies change.
    2. Auto (Import From Derivation): Automatically stays in sync with Cargo.lock, but may reduce build parallelism.
  3. Understand the documentation project structure

    master

    The documentation is built using Starlight and Astro. The project structure is as follows:

    • src/content/docs/: Contains all .md or .mdx files. Each file is exposed as a route based on its filename.
    • src/assets/: Place images here to embed them in Markdown using relative links.
    • public/: Place static assets (like favicons) here.
    • astro.config.mjs: Astro configuration file.
    • package.json: NPM dependencies and scripts.
    • tsconfig.json: TypeScript configuration.
    .
    ├── public/
    ├── src/
    │   ├── assets/
    │   ├── content/
    │   │   ├── docs/
    │   │   └── config.ts
    │   └── env.d.ts
    ├── astro.config.mjs
    ├── package.json
    └── tsconfig.json
  4. How tools.nix automates Cargo.nix generation

    master

    The tools.nix file provides the logic to generate a Cargo.nix file during Nix evaluation time. This ensures that Cargo.nix is always synchronized with your Cargo.lock file.

    Workflow

    1. Lockfile Reading: Nix reads the Cargo.lock file to identify locked versions and hashes.
    2. Impurity-free Fetching: Dependencies are fetched using the hashes from the lockfile to maintain reproducibility.
    3. Vendoring: Fetched dependencies are used to create a vendored folder and the necessary configuration to fetch from it.
    4. Offline Generation: crate2nix is executed within a derivation to generate the Cargo.nix file offline.
    5. Automatic Import: The generated file is automatically imported into your Nix code using the import from derivation feature, allowing you to use it like any standard Cargo.nix file.
  5. Understand the build file generation phases

    master

    The crate2nix build file generation process is divided into five distinct phases. Understanding these phases is useful if you are contributing to the project or need to understand how a specific part of the generation pipeline works:

    1. cargo metadata: Invokes cargo metadata using the cargo_metadata crate to retrieve the initial project structure.
    2. indexing metadata: Processes the metadata by package ID to allow for efficient joining of "Node" and "Package" information, producing metadata::IndexedMetadata.
    3. resolving: Uses the indexed metadata to resolve dependencies and aggregate all necessary build information into a resolve::CrateDerivation.
    4. pre-fetching: Uses the prefetch module to pre-fetch crates.io packages to determine their sha256 hashes.
    5. rendering: Uses the render module to generate the final Nix files via the build.nix.tera template.
  6. Use a custom Rust toolchain with crate2nix via Nix overlays

    master

    You can use a specific Rust toolchain (e.g., from fenix) with crate2nix by providing an overlay to nixpkgs that replaces the default rustc and cargo with your desired toolchain. This is useful when you need a specific version of the Rust compiler or specific target support not provided by the default Nixpkgs Rust package.

    {
      description = "containix";
    
      inputs = {
        nixpkgs.url = "github:NixOS/nixpkgs/24.05";
        fenix = {
          url = "github:nix-community/fenix";
          inputs.nixpkgs.follows = "nixpkgs";
        };
        flake-utils.url = "github:numtide/flake-utils";
        crate2nix.url = "github:nix-community/crate2nix";
      };
    
      outputs = {
        self,
        nixpkgs,
        flake-utils,
        fenix,
        crate2nix,
      }: flake-utils.lib.eachDefaultSystem (
        system: 
        let
          # 1. Select your custom toolchain
          toolchain = fenix.packages.${system}.stable.defaultToolchain;
    
          # 2. Apply an overlay to nixpkgs to use that toolchain
          pkgs = import nixpkgs {
            inherit system;
            overlays = [
              (final: prev: {
                rustc = toolchain;
                cargo = toolchain;
              })
            ];
          };
    
          # 3. Use the overlaid pkgs to call crate2nix
          crate2nix' = pkgs.callPackage (import "${crate2nix}/tools.nix") {};
          cargoNix = crate2nix'.appliedCargoNix {
            name = "my-crate";
            src = ./.;
          };
        in
        {
          packages = {
            default = cargoNix.rootCrate.build;
          };
        }
      );
    }
  7. Run crate2nix without installation using Nix Flakes

    master

    If you have Nix Flakes enabled, you can run crate2nix directly without installing it to your system. You can choose between a stable version from nixpkgs or the latest development version from the GitHub repository.

    To run the stable version from nixpkgs:

    nix run nixpkgs#crate2nix -- help

    To run the latest development version from the nix-community/crate2nix repository:

    nix run github:nix-community/crate2nix -- help
  8. Run an individual integration test

    master

    If you want to avoid running the full suite, you can run a specific integration test from the checks attribute set in tests.nix. Many tests build projects located in the sample_projects folder.

    To run a specific test (e.g., bin_with_lib_dep):

    nix-build \
      -o ./crate2nix/target/nix-results ./tests.nix -A checks.bin_with_lib_dep

    To run a test that is currently marked as skipped (e.g., empty_cross.forceSkipped):

    nix-build \
        -o ./crate2nix/target/nix-results ./tests.nix -A checks.empty_cross.forceSkipped
    nix-build \
      -o ./crate2nix/target/nix-results ./tests.nix -A checks.bin_with_lib_dep
  9. Install crate2nix using traditional Nix (non-flake)

    master

    If you are using a traditional Nix installation without Flakes, you can use nix-env to install crate2nix.

    To install the stable version from nixpkgs (recommended):

    nix-channel --update # optional: updates your channels
    nix-env -i -f '<nixpkgs>' -A crate2nix

    To install the latest development version from the master branch tarball:

    nix-env -i -f https://github.com/nix-community/crate2nix/tarball/master
    nix-env -i -f '<nixpkgs>' -A crate2nix