Git Product home page Git Product logo

cache-flake-inputs's Introduction

cache-flake-inputs

Premise:

  • You have a large or otherwise inconvenient-to-fetch (i.e. requires auth) non-flake flake input.
  • You cannot switch to using a fetcher to grab this input instead for Reasons (i.e. requires auth).
  • You provide a substituter for users of your flake that contains binaries for all of your flake outputs.
  • You would like for users of your flake to not need to fetch your large flake input themselves and to instead just fetch artifacts from your substituter.

The problem:

  • Flake inputs are fetched lazily (once locking has happened)
  • But: in order to actually produce the derivation (which is then substituted and not built locally) for any of this flake's outputs, we need to, at eval time, reference our flake's inputs. The moment we do this, the flake input is fetched, even though we may never actually use the contents of the flake's nix store path.

NOTE: users that already have your substituter added (not as an extra-substituter in a flake but on the command-line or in nix.conf) appear to use the substituter to fetch flake inputs, when possible. However, these inputs will still be fetched "eagerly" (at eval time).

Eventually we can maybe use fetch-closure (experimental) for this use case but in the meantime...

This flake provides an expression that conditionally replaces flake inputs with fixed output derivations that are assumed to be accessible to the user of the flake (i.e. because they are in a substituter that comes with the flake).

example

{
  nixConfig = {
    # A substituter that you provide.
    extra-substituters = [
      "https://rrbutani.cachix.org"
    ];
    extra-trusted-public-keys = [
      "rrbutani.cachix.org-1:FUpcK9RyZjjdOm8qherJl9+wfTGf6ptANvH6LZF63Ro="
    ];
  };

  inputs = {
    # A large unwieldy flake input (an example).
    llvm = {
      url = github:llvm/llvm-project?ref=llvmorg-14.0.6;
      flake = false;
    };

    flu.url = github:numtide/flake-utils;
    nixpkgs.url = github:nixOS/nixpkgs/22.05;

    cfi-override.url = github:boolean-option/true;
    cfi = {
      url = github:rrbutani/cache-flake-inputs;

      # You can set `cfi-override.url` (above) to `github:boolean-option/false`
      # to disable `cacheInputs`.
      #
      # This is useful for changing the behavior of your flake dependencies.
      #
      # For example, rdeps of this flake can set `inputs.cfi-override.follows`
      # on this flake to an input pointing to `github:boolean-option/false` to
      # override our default.
      inputs.cache-flake-inputs-global-override.follows = "cfi-override";
    };
  };

  outputs = inputs@{ flu, cfi, nixpkgs, ... }: with flu.lib; eachDefaultSystem (sys: let
    knownCachedNarHashes = {
      # Keys should match the names of your flake inputs.
      "llvm" = {
        # Hashes should match what's in your `flake.lock`.
        "sha256-vffu4HilvYwtzwgq+NlS26m65DGbp6OSSne2aje1yJE=" = true;
      };
    };

    np = import nixpkgs { system = sys; };
    inputs' = cfi.lib.${sys}.cacheInputs {
      inherit inputs knownCachedNarHashes;
      lockFile = ./flake.lock;

      # This tells `cfi` to assume that we can indeed use substituters to get the
      # things `knownCachedNarHashes` says we can.
      #
      # If this is set to `false`, `cfi` will effectively do nothing; derivations
      # in `inputs'` will be equivalent to the ones in `inputs` and flake inputs
      # will be fetched eagerly during evaluation.
      useSubstituters = true;

      # We already have a `nixpkgs` instance so pass it along.
      #
      # This is optional; if omitted, `cfi` will use it's own `nixpkgs` flake
      # input โ€” which you can override with `inputs.cfi.inputs.nixpkgs.follows`).
      nixpkgs = np;
    };

    pkgC = src: np.stdenvNoCC.mkDerivation {
      name = "example";
      src = src;
      unpackPhase = "true";
      installPhase = ''
        cat $src/libunwind/CMakeLists.txt | grep PACKAGE_VERSION | cut -d' ' -f4- | cut -d')' -f1 | head -1 > $out
      '';
    };

    # Both `pkgA` and `pkgB` are in the substituter listed at the top of this flake.

    # Building `pkgA` will require fetching LLVM.
    pkgA = pkgC inputs.llvm;

    # Building `pkgB` will not.
    pkgB = pkgC inputs'.llvm;
  in {
    packages = {
      default = pkgB;
      inherit pkgA pkgB;
    };
  });
}

(available with a flake.lock here)

cache-flake-inputs's People

Contributors

rrbutani avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.