nix_for_rustaceans/slides/slides.md
2024-07-09 20:55:42 +02:00

3.9 KiB

marp lang title description theme transition paginate _paginate
true en-US Marp CLI example Hosting Marp slide deck on the web nix_talk fade true false

Nix for Rustaceans

Kateřina "Kate" Churanová


What is Nix

  • Purely functional programming language
  • Package manager
  • Linux distribution (NixOS)
  • multiplatform (Linux, Mac OS, BSD-ish)

What is Nix NOT

  • Easy to learn
  • Well documented
  • Opinionated

Nix derivation

  • "Package"
  • evaluates to store derivation in /nix/store/
  • 2n45ikclc8d5fhzkvg1197qlc2zk3s64-rustc-1.77.2.drv

Nix flake

  • Unstable, but widely used
  • New way of creating nix derivations
  • Lock file version pinning
  • Allows reproducibility

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  outputs =
    { self, nixpkgs }:
    {
      packages.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.hello;
      packages.x86_64-linux.foobar = nixpkgs.legacyPackages.x86_64-linux.fortune;
    };
}

bg width:80%


Nix developer shell

  • nix develop
  • builds all flake dependencies, but not the flake itself
  • sets up the development environment

Nix direnv


Frameworks


Flake parts - Minimal modular framework

Dev environment management

  • Devshell
  • Devenv

Rust project building

  • NCI (Nix cargo integration)

Basic flake parts project

{
  inputs = {
    flake-parts.url = "github:hercules-ci/flake-parts";
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };

  outputs = inputs@{ flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      imports = [
        # Modules go here
      ];
      systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
      perSystem = { config, self', inputs', pkgs, system, ... }: {
        packages.default = pkgs.hello;
      };
    };
}

Fun begins with Rust

flake.nix

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    nci = {
      url = "github:yusdacra/nix-cargo-integration";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-parts = {
      url = "github:hercules-ci/flake-parts";
      inputs.nixpkgs-lib.follows = "nixpkgs";
    };
  };

outputs = inputs @ {
    flake-parts,
    nci,
    ...
  }:
    flake-parts.lib.mkFlake {inherit inputs;} {
      systems = ["x86_64-linux"];
      imports = [
        nci.flakeModule
        ./crates.nix
      ];
      perSystem = {
        pkgs,
        config,
        ...
      }: let
        crateName = "my-crate"
        crateOutputs = config.nci.outputs.${crateName};
      in {
        devShells.default = crateOutputs.devShell;
        packages.default = crateOutputs.packages.release;
      };
    };

crates.nix

{...}: {
  perSystem = {
    pkgs,
    config,
    ...
  }: let
    crateName = "my-crate";
  in {
    nci.projects."simple".path = ./.;
    nci.crates.${crateName} = {};
  };
}

Why all of this though?

  • Reproducible environment with pinned Rust version
  • Predictable dependencies
  • Plenty of other tools for your disposal
  • Extremely simple generation of lightweight OCI containers

          packages.container = pkgs.dockerTools.streamLayeredImage {
            name = crateName;
            tag = "latest";
            contents = [ ];
            config = {
              Cmd = [ "${crateOutputs.packages.release}/bin/my-crate" ];
            };
          };