Add NixOS build and simplify building from source (#100)

This commit is contained in:
Rushmore Mushambi 2022-10-04 18:32:44 +02:00 committed by GitHub
parent 80040152a2
commit 0467b7f04a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 752 additions and 1 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

60
.github/workflows/nix.yml vendored Normal file
View file

@ -0,0 +1,60 @@
name: Nix
on:
- pull_request
- push
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v17
- run: nix flake check --show-trace
build-static:
name: Build static Linux binary
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v17
- uses: cachix/cachix-action@v10
with:
name: surrealdb
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
extraPullNames: nix-community
- run: nix build .#static-binary
- run: ./result/bin/surreal help
build-docker:
name: Build Docker image
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v17
- uses: cachix/cachix-action@v10
with:
name: surrealdb
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
extraPullNames: nix-community
- run: nix build .#docker-image
- run: docker load --input ./result
build-native-linux:
name: Build native Linux binary
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v17
- uses: cachix/cachix-action@v10
with:
name: surrealdb
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
extraPullNames: nix-community
- run: nix build .#x86_64-unknown-linux-gnu
- run: ./result/bin/surreal help

4
.gitignore vendored
View file

@ -35,6 +35,10 @@ Temporary Items
/target/
/lib/target/
.idea/
/result
/bin/
/docker/
/.direnv/
# -----------------------------------
# Specific

View file

@ -20,7 +20,7 @@ rustup component add rustfmt
## Getting started from source
To set up a working **development environment**, ensure that you have `rustup` installed, and fork the project git repository.
To set up a working **development environment**, you can either [use the Nix package manager](pkg/nix#readme) or you can [install dependencies manually](doc/BUILDING.md#building-surrealdb) and ensure that you have `rustup` installed, and fork the project git repository.
> Please note that these instructions are for setting up a functional dev environment. If you just want to install SurrealDB for day-to-day usage and not as a code maintainer use this [installation guide](https://surrealdb.com/docs/install). If you want to get started integrating SurrealDB into your app, view the [integration tutorials](https://surrealdb.com/docs/integration).

6
default.nix Normal file
View file

@ -0,0 +1,6 @@
(import (let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in fetchTarball {
url =
"https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}) { src = ./.; }).defaultNix

View file

@ -359,3 +359,7 @@ docker run --pull --rm -v $PWD:/volume -t clux/muslrust:stable cargo build --rel
Running `cargo build` in an **elevated shell** will now build the `SurrealDB` in Windows OS.
</details>
## Building using the Nix package manager
SurrealDB can be built [using the Nix package manager](../pkg/nix#nix-package-manager).

155
flake.lock Normal file
View file

@ -0,0 +1,155 @@
{
"nodes": {
"crane": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1664412889,
"narHash": "sha256-gyVtTQf3CiXLe1cwNRFxqUqYl9BCmIDvK7hIpzR/oQU=",
"owner": "ipetkov",
"repo": "crane",
"rev": "755acd231a7de182fdc772bee1b2a1f21d4ec9ed",
"type": "github"
},
"original": {
"owner": "ipetkov",
"ref": "v0.7.0",
"repo": "crane",
"type": "github"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1664865507,
"narHash": "sha256-KUonhQPn7SigY+4mfI/UydMQv4nIhBKIqgeU3JAaowI=",
"owner": "nix-community",
"repo": "fenix",
"rev": "93c65e24793653fdc45339022218a9ceca6219dd",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1652776076,
"narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8",
"type": "github"
},
"original": {
"owner": "numtide",
"ref": "v1.0.0",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1664790708,
"narHash": "sha256-fzxmpOPjzOVIt9KeDN4EDPI13xJn+u0uMxheKCWken8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "81a3237b64e67b66901c735654017e75f0c50943",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-22.05-small",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"crane": "crane",
"fenix": "fenix",
"flake-compat": "flake-compat_2",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1664652573,
"narHash": "sha256-mVf9fjQbtYbrVvQSaJOCwArWIvXHrXqVVUhP0x9ZcVY=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "5c28ad193238635189f849c94ffc178f00008b12",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

120
flake.nix Normal file
View file

@ -0,0 +1,120 @@
{
description =
"A scalable, distributed, collaborative, document-graph database, for the realtime web";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.05-small";
flake-utils.url = "github:numtide/flake-utils/v1.0.0";
crane = {
url = "github:ipetkov/crane/v0.7.0";
inputs.nixpkgs.follows = "nixpkgs";
};
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs = inputs:
with inputs;
# Make systems available as variables to prevent typos
with flake-utils.lib.system;
# let-in expressions, very similar to Rust's let bindings. These names
# are used to express the output but not themselves paths in the output.
let
nativeSystems = [ aarch64-linux x86_64-darwin x86_64-linux ];
# Build the output set for each default system and map system sets into
# attributes, resulting in paths such as:
# nix build .#packages.x86_64-linux.<name>
in flake-utils.lib.eachSystem nativeSystems (system:
let
pkgs = import nixpkgs { inherit system; };
util = import ./pkg/nix/util.nix {
inherit system;
inherit (pkgs) lib;
systems = flake-utils.lib.system;
flake = self;
};
mkRustToolchain = target:
with fenix.packages.${system};
combine [
stable.rustc
stable.cargo
targets.${target}.stable.rust-std
];
buildPlatform = pkgs.stdenv.buildPlatform.config;
# Make platforms available as variables to prevent typos
in with util.platforms;
rec {
packages = {
# nix build
default =
packages.${buildPlatform} or packages.x86_64-unknown-linux-gnu;
# nix build .#docker-image
docker-image = import ./pkg/nix/drv/docker.nix {
inherit util;
inherit (pkgs) cacert dockerTools;
package = packages.x86_64-unknown-linux-gnu;
};
# nix build .#static-binary
static-binary = packages.x86_64-unknown-linux-musl;
# nix build .#windows-binary
windows-binary = packages.x86_64-pc-windows-gnu;
} // (pkgs.lib.attrsets.mapAttrs (target: _:
let
spec =
import ./pkg/nix/spec/${target}.nix { inherit pkgs target util; };
in import ./pkg/nix/drv/binary.nix {
inherit pkgs util spec crane;
rustToolchain = mkRustToolchain target;
}) util.platforms);
devShells = {
# nix develop
default =
devShells.${buildPlatform} or devShells.x86_64-unknown-linux-gnu;
# nix develop .#static-binary
static-binary = devShells.x86_64-unknown-linux-musl;
# nix develop .#windows-binary
windows-binary = devShells.x86_64-pc-windows-gnu;
} // (pkgs.lib.attrsets.mapAttrs (target: _:
let
spec = (import ./pkg/nix/spec/${target}.nix) {
inherit pkgs target util;
};
rustToolchain = mkRustToolchain target;
buildSpec = spec.buildSpec;
in pkgs.mkShell (buildSpec // {
hardeningDisable = [ "fortify" ];
depsBuildBuild = buildSpec.depsBuildBuild or [ ]
++ [ rustToolchain ] ++ (with pkgs; [ nixfmt cargo-watch ]);
inherit (util) SURREAL_BUILD_METADATA;
})) util.platforms);
# nix run
apps.default = flake-utils.lib.mkApp { drv = packages.default; };
});
}

151
pkg/nix/README.md Normal file
View file

@ -0,0 +1,151 @@
# Nix package manager
According to [Wikipedia]
> Nix is a cross-platform package manager that utilizes a purely functional deployment model where software is installed into unique directories generated through cryptographic hashes. It is also the name of the tool's programming language. A package's hash takes into account the dependencies, which is claimed to eliminate dependency hell. This package management model advertises more reliable, reproducible, and portable packages.
SurrealDB has support for the Nix package manager. It makes it easier to build the project from source and setting up development environments.
## Table of Contents
- [Running Nix from Docker](#running-nix-from-docker)
* [Building a Docker image (recommended)](#building-a-docker-image--recommended-)
* [Building a static binary](#building-a-static-binary)
- [Installing Nix](#installing-nix)
* [Activating support for Nix Flakes (recommended)](#activating-support-for-nix-flakes--recommended-)
* [Setting up a binary cache (optional)](#setting-up-a-binary-cache--optional-)
- [Installing SurrealDB](#installing-surrealdb)
- [Setting up a development environment](#setting-up-a-development-environment)
* [Setting dependencies up automatically](#setting-dependencies-up-automatically)
* [Manually installing dependencies](#manually-installing-dependencies)
- [Collecting garbage](#collecting-garbage)
## Running Nix from Docker
If all you want is to build a Docker image or a static linux binary and you already have Docker installed, then you can do so without installing anything on your machine.
First, you need to clone this repo and `cd` into it
```
git clone https://github.com/surrealdb/surrealdb.git
cd surrealdb
```
### Building a Docker image (recommended)
A Docker image is recommended because it supports all the features and storage backends that SurrealDB supports. To build a Docker image, run the following command.
```
docker run -it --rm -v $(pwd):/surrealdb -w /surrealdb nixos/nix sh -c "nix-build -A packages.x86_64-linux.docker-image && mkdir docker && cp -vL ./result docker/surreal.tar.gz && rm result"
```
The image will be saved as `docker/surreal.tar.gz`. You can load it using
```
docker load -i docker/surreal.tar.gz
```
### Building a static binary
Please note that currently a static binary is very limited. It doesn't come with any optional features and it only supports the in-memory store, so you can't persist data with it.
To build the static binary, run
```
docker run -it --rm -v $(pwd):/surrealdb -w /surrealdb nixos/nix sh -c "nix-build -A packages.x86_64-linux.static-binary && mkdir bin && cp -v ./result/bin/surreal bin/ && rm result"
```
The binary will be saved as `bin/surreal`.
## Installing Nix
If you want to develop using Nix or you want to build binaries native to your platform then you may need to install Nix. To do so, please follow the official [installation instructions].
### Activating support for Nix Flakes (recommended)
Nix Flakes are an upcoming feature of the Nix package manager. Officially, they are still considered experimental and, as such, are not enabled by default. However, they are already widely adopted by the Nix community. SurrealDB supports Nix both with and without support for Flakes.
To enable support for Flakes, edit either `~/.config/nix/nix.conf` or `/etc/nix/nix.conf` and add:
```
experimental-features = nix-command flakes
```
If the Nix installation is in multi-user mode, you will need to restart the `nix-daemon` after this. If your system uses `systemd`, you can do this by simply running `sudo systemctl restart nix-daemon`.
Because of Flakes' superior user experience, we highly recommend them. For brevity, the rest of this guide will assume that flake support is enabled.
### Setting up a binary cache (optional)
Building SurrealDB and all its dependencies can take a while. To speed up the process, you can take advantage of our binary cache. To do so, you simply need to run the following command:
```
nix run nixpkgs#cachix use surrealdb
```
This will download and run the Cachix command to configure your system to use our binary cache.
## Installing SurrealDB
If all you need to do is run SurrealDB without installing it to your `PATH` then you simply need to run
```
nix run github:surrealdb/surrealdb
```
To install it, use
```
nix profile install github:surrealdb/surrealdb
```
You can target a specific branch, tag or commit by appending it to above commands separated by `/`. For example
```
nix run github:surrealdb/surrealdb/v1.0.0-beta.9
```
If you just want to build the binary, without running it, you can use `nix build` instead of `nix run`. You will then find the binary in `result/bin`.
**NB**: While Nix is cross-platform, currently only building Linux binaries on Linux is supported. The above commands build the default binary, a dynamically linked binary with support for all SurrealDB features. To build a statically linked binary use `nix build github:surrealdb/surrealdb#static-binary`. To build a Docker image use `nix build github:surrealdb/surrealdb#docker-image`. We plan to add support for more platforms in future, in the meantime you can [run Nix from Docker](#running-nix-from-docker) if you would like to build from a different platform.
## Setting up a development environment
Nix can be used to set up C/C++ dependencies for this project in order for Cargo commands to work properly.
If you haven't already done so, you will need to clone this repo and `cd` into it
```
git clone https://github.com/surrealdb/surrealdb.git
cd surrealdb
```
### Setting dependencies up automatically
To make Nix setup dependencies automatically when you switch into this project, you need to install and configure `direnv`. To do so, run the following commands:-
```
nix profile install nixpkgs#direnv
nix profile install nixpkgs#nix-direnv
```
and add `eval "$(direnv hook bash)"` to your `~/.bashrc` or similar file.
Finally, from this project's root directory, run
```
direnv allow
```
### Manually installing dependencies
If you choose not to use `direnv` to automatically setup your dependencies as described above, you can use `nix develop` to manually install the dependencies and configure your environment so that `cargo` commands work normally.
Once your environment is set up, you can use normal `cargo` commands.
## Collecting garbage
Because of the way it works, Nix can use a lot of space on your machine. To reclaim some of that space, you can use `nix-collect-garbage -d`.
[Wikipedia]: https://en.wikipedia.org/wiki/Nix_(package_manager)
[installation instructions]: https://nixos.org/download.html#nix-install-linux

6
pkg/nix/config.nix Normal file
View file

@ -0,0 +1,6 @@
{
# Set the desired FoundationDB version here
# Specify only the major and minor parts using `major.minor` format
# Must be supported by both the foundationdb crate and NixPkgs
fdbVersion = "6.1";
}

27
pkg/nix/drv/binary.nix Normal file
View file

@ -0,0 +1,27 @@
{ pkgs, spec, util, rustToolchain, crane }:
let
featureFlags = let
featureLists = spec.features or [ ];
features = with pkgs.lib; lists.unique (lists.flatten featureLists);
in map (feature: "--features=${feature}") features;
craneLib = (crane.mkLib pkgs).overrideScope' (final: prev: {
cargo = rustToolchain;
rustc = rustToolchain;
});
buildSpec = spec.buildSpec // {
src = craneLib.cleanCargoSource ../../../.;
doCheck = false;
cargoExtraArgs = let flags = [ "--no-default-features" ] ++ featureFlags;
in builtins.concatStringsSep " " flags;
};
cargoArtifacts = craneLib.buildDepsOnly buildSpec;
in craneLib.buildPackage (buildSpec // {
inherit cargoArtifacts;
inherit (util) version SURREAL_BUILD_METADATA;
})

12
pkg/nix/drv/docker.nix Normal file
View file

@ -0,0 +1,12 @@
{ cacert, dockerTools, package, util }:
dockerTools.buildLayeredImage {
name = "surrealdb/surrealdb";
# Unfortunately Docker doesn't support semver's `+` so we are using `_` instead
tag = "v${builtins.replaceStrings [ "+" ] [ "_" ] util.version}";
config = {
Env = [ "SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt" ];
WorkingDir = "/";
Entrypoint = "${package}/bin/${util.packageName}";
};
}

View file

@ -0,0 +1,21 @@
{ pkgs, target, util }:
{
inherit target;
features = with util.features; [ http ];
buildSpec = with pkgs; {
depsBuildBuild = [ clang protobuf perl ];
nativeBuildInputs = [ pkg-config ];
buildInputs = [ openssl binutils ];
CARGO_BUILD_TARGET = target;
LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib";
OPENSSL_NO_VENDOR = "true";
};
}

View file

@ -0,0 +1,21 @@
{ pkgs, target, util }:
{
inherit target;
features = with util.features; [ http ];
buildSpec = with pkgs; {
depsBuildBuild = [ clang protobuf perl ];
nativeBuildInputs = [ pkg-config ];
buildInputs = [ openssl ];
CARGO_BUILD_TARGET = target;
LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib";
OPENSSL_NO_VENDOR = "true";
};
}

View file

@ -0,0 +1,17 @@
{ pkgs, target, util }:
{
inherit target;
features = with util.features; [ default ];
buildSpec = with pkgs; {
strictDeps = true;
depsBuildBuild = [ pkgsCross.mingwW64.stdenv.cc ];
buildInputs = [ pkgsCross.mingwW64.windows.pthreads ];
CARGO_BUILD_TARGET = target;
};
}

View file

@ -0,0 +1,27 @@
{ pkgs, target, util }:
{
inherit target;
features = with util.features;
[ default storage-tikv ]
++ pkgs.lib.lists.optional (util.fdbSupported pkgs.fdbPackages)
[ storage-fdb ];
buildSpec = with pkgs;
let crossCompiling = !util.isNative target;
in {
depsBuildBuild = [ clang cmake gcc10 perl protobuf grpc llvm ]
++ lib.lists.optional crossCompiling qemu;
nativeBuildInputs = [ pkg-config ];
buildInputs = [ openssl ]
++ lib.lists.optional (util.fdbSupported fdbPackages)
(util.fdbPackage fdbPackages);
LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib";
CARGO_BUILD_TARGET = target;
};
}

View file

@ -0,0 +1,17 @@
{ pkgs, target, util }:
{
inherit target;
buildSpec = with pkgs; {
nativeBuildInputs = with pkgsStatic; [ stdenv.cc openssl ];
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
CARGO_BUILD_TARGET = target;
OPENSSL_NO_VENDOR = "true";
OPENSSL_STATIC = "true";
OPENSSL_LIB_DIR = "${pkgsStatic.openssl.out}/lib";
OPENSSL_INCLUDE_DIR = "${pkgsStatic.openssl.dev}/include";
};
}

96
pkg/nix/util.nix Normal file
View file

@ -0,0 +1,96 @@
{ lib, flake, systems, system }:
rec {
inherit systems system;
config = import ./config.nix;
supportedPlatforms = let
specDir = builtins.readDir ./spec;
nixExt = ".nix";
nixFilesFun = key: val:
val == "regular" && lib.strings.hasSuffix nixExt key;
trimNixExtFun = key: val: lib.strings.removeSuffix nixExt key;
nixFiles = lib.attrsets.filterAttrs nixFilesFun specDir;
in lib.attrsets.mapAttrsToList trimNixExtFun nixFiles;
systemPlatforms = let
matchingPlatforms = target:
let targetSystem = targetToSystem target;
in targetSystem == system;
in builtins.filter matchingPlatforms supportedPlatforms;
platforms = let
kvFun = platform: {
name = platform;
value = platform;
};
in builtins.listToAttrs (map kvFun supportedPlatforms);
targetToEnv = target:
let withoutDashes = builtins.replaceStrings [ "-" ] [ "_" ] target;
in lib.strings.toUpper withoutDashes;
targetToUpperEnv = target: lib.strings.toUpper (targetToEnv target);
targetToSystem = with builtins;
target:
let
parts = split "-" target;
arch = elemAt parts 0;
prefix = lib.strings.optionalString (arch == "armv7") "l";
os = elemAt parts 4;
in "${arch}${prefix}-${os}";
isNative = target:
let targetSystem = targetToSystem target;
in targetSystem == system;
cpu = with builtins;
target:
let
parts = split "-" target;
arch = elemAt parts 0;
in if arch == "armv7" then replaceStrings [ "v7" ] [ "" ] arch else arch;
cargoToml = with builtins;
let toml = readFile ../../Cargo.toml;
in fromTOML toml;
packageName = cargoToml.package.name;
fdbPackage = fdbPackages:
let
fdbPkgVersion = builtins.replaceStrings [ "." ] [ "" ] config.fdbVersion;
in fdbPackages."foundationdb${fdbPkgVersion}";
fdbSupported = fdbPackages:
let
package = fdbPackage fdbPackages;
fdbSystems = package.meta.platforms or [ ];
in builtins.elem system fdbSystems;
features = cargoToml.features // {
storage-fdb = let
fdbFeatureVersion =
builtins.replaceStrings [ "." ] [ "_" ] config.fdbVersion;
in [ "surrealdb/kv-fdb-${fdbFeatureVersion}" ];
};
buildMetadata = with lib.strings;
let
lastModifiedDate = flake.lastModifiedDate or flake.lastModified or "";
date = builtins.substring 0 8 lastModifiedDate;
shortRev = flake.shortRev or "dirty";
hasDateRev = lastModifiedDate != "" && shortRev != "";
dot = optionalString hasDateRev ".";
in "${date}${dot}${shortRev}";
version = with lib.strings;
let
hasBuildMetadata = buildMetadata != "";
plus = optionalString hasBuildMetadata "+";
in "${cargoToml.package.version}${plus}${buildMetadata}";
SURREAL_BUILD_METADATA = buildMetadata;
}

6
shell.nix Normal file
View file

@ -0,0 +1,6 @@
(import (let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in fetchTarball {
url =
"https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}) { src = ./.; }).shellNix