From: Austin Seipp Date: Sun, 26 Nov 2017 06:20:14 +0000 (-0600) Subject: nix: add nix expressions for development X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=fa36882a73fbb3fd771c506641a1d70d51c07068;p=bcachefs-tools-debian nix: add nix expressions for development This adds Nix expressions for bcachefs-tools that are modular, work in purely sandboxed build environments (e.g. on NixOS itself, or macOS, where sandboxing is enabled by default), use a fixed copy of Nixpkgs (to avoid hidden, global state) and uses standard build idioms. This change uses a fixed version of Nixpkgs, one that will always be used for every build of bcachefs-tools, for all users, rather than relying on whatever copy of Nixpkgs the user has available. This has a major benefit in that it allows the build to work in sandboxed environments such as NixOS, and it correctly declares all of the necessary dependencies that bcachefs-tools needs. This is done simply by using stdenv.mkDerivation in order to write a "normal" Nix expression, where the previous version used a variant of the stdenv builder, but this isn't needed for the most part. (Doing this has other knock-on benefits, such as the usage of standardized options like `enableParallelBuild = true;` -- allowing `nix-build` to automatically do parallel builds, etc.) Another major benefit of this change is that anyone can now use `nix-shell` to develop/hack on bcachefs-tools incrementally; simply running nix-shell will put you in a Bash shell environment where all of bcachefs-tools' dependencies are proprerly provided, no matter the state of the outside build environment/host operating system: $ nix-shell [nix-shell:~/src/bcachefs-tools]$ make -j4 # works immediately As mentioned before, with this change, by default, nix-build and nix-shell run using a prepackaged copy of an upstream Nixpkgs snapshot. This is done purely to ensure anyone who builds bcachefs-tools using Nix does, in fact, get a reproducible build. Without this, nix-build defaults to using the the `` NIX_PATH entry in order to fetch dependencies; meaning that two users on different channels will get different results (for example, if you have the November 2017 channel but I have the October 2017 channel, the results may be different). With this patch, a user running $ nix-build will always use the exact same copy of nixpkgs to bootstrap the build, regardless of whatever channels the user has. This bootstrap mechanism does not even depend on an existing copy of Nixpkgs itself; e.g. it can work with a completely empty `NIX_PATH`. This is arguably anti-modular, but for end-user applications like bcachefs-tools, fixing the version of Nixpkgs is not normally a huge deal. Users who wish to use a different copy of Nixpkgs can provide this with an argument to nix-build directly, using the `nixpkgs` argument to the expression: $ nix-build --pure --arg nixpkgs 'import {}' This uses the `` provided inside your `NIX_PATH` environment variable to acquire dependencies, which by default is managed using `nix-channel`. If you have a copy of the Nixpkgs source code e.g. from a `git clone`, you may use that too by simply using `-I` to prepend your Nixpkgs to `NIX_PATH` (see `man nix-build` for more): $ nix-build --pure \ -I nixpkgs=$HOME/src/nixpkgs \ --arg nixpkgs 'import {}' Signed-off-by: Austin Seipp --- diff --git a/.gitignore b/.gitignore index 7357d55..7e4ee7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/result bcachefs .* *.o diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..82d4a85 --- /dev/null +++ b/default.nix @@ -0,0 +1,45 @@ +{ nixpkgs ? (import ./nix/nixpkgs.nix) +}: + +with nixpkgs; + +stdenv.mkDerivation rec { + name = "bcachefs-tools-${version}"; + version = "git"; + + src = lib.cleanSource ./.; # NOTE: ignore .git, otherwise things get weird! + + nativeBuildInputs = [ git pkgconfig ]; + buildInputs = + [ liburcu libuuid libaio zlib attr keyutils + libsodium libscrypt + ]; + + patchPhase = '' + # ensure the mkfs and fsck scripts, which are just wrappers around + # 'bcachefs', are patched to refer to the right location inside the + # nix store. (you wouldn't expect built tools to call random outside + # utilities, in general, but the exact tools they were built with.) + # + # TODO FIXME: it would be better to fix this in the 'install' target, + # however, so this works with any bog-standard installation + + substituteInPlace fsck.bcachefs --replace bcachefs $out/bin/bcachefs + substituteInPlace mkfs.bcachefs --replace bcachefs $out/bin/bcachefs + ''; + + enableParallelBuilding = true; + makeFlags = + [ "PREFIX=$(out)" + ]; + + meta = with stdenv.lib; { + description = "Userspace tools for bcachefs"; + homepage = http://bcachefs.org; + license = licenses.gpl2; + platforms = platforms.linux; + maintainers = + [ "Kent Overstreet " + ]; + }; +} diff --git a/nix/fetchnix.nix b/nix/fetchnix.nix new file mode 100644 index 0000000..2f98788 --- /dev/null +++ b/nix/fetchnix.nix @@ -0,0 +1,48 @@ +# `builtins.fetchTarball` only accepts a `sha256` argument in Nix version 1.12 +# or later, so here we provide a function that can provide a compatible interface +# to Nix 1.11 or Nix 1.12 +# +# TODO FIXME: remove this sometime after Nix 1.12 goes stable + +{ url # URL of the nixpkgs tarball to download +, rev # The Git revision of nixpkgs to fetch +, sha256 # The SHA256 of the downloaded data +, system ? builtins.currentSystem # This is overridable if necessary +}: + +with { + ifThenElse = { bool, thenValue, elseValue }: ( + if bool then thenValue else elseValue); +}; + +ifThenElse { + bool = (0 <= builtins.compareVersions builtins.nixVersion "1.12"); + + # In Nix 1.12, we can just give a `sha256` to `builtins.fetchTarball`. + thenValue = (builtins.fetchTarball { inherit url sha256; }); + + # This hack should at least work for Nix 1.11 + elseValue = ( + (rec { + tarball = import { inherit url sha256; }; + builtin-paths = import ; + + script = builtins.toFile "nixpkgs-unpacker" '' + "$coreutils/mkdir" "$out" + cd "$out" + "$gzip" --decompress < "$tarball" | "$tar" -x --strip-components=1 + ''; + + nixpkgs = builtins.derivation { + name = "nixpkgs-${builtins.substring 0 6 rev}"; + + builder = builtins.storePath builtin-paths.shell; + args = [ script ]; + + inherit tarball system; + tar = builtins.storePath builtin-paths.tar; + gzip = builtins.storePath builtin-paths.gzip; + coreutils = builtins.storePath builtin-paths.coreutils; + }; + }).nixpkgs); +} diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json new file mode 100644 index 0000000..a5a11d0 --- /dev/null +++ b/nix/nixpkgs.json @@ -0,0 +1,5 @@ +{ + "url": "https://github.com/nixos/nixpkgs/archive/5ae883b8c3b04e0c4a9c92a5ab3c7c84b9942943.tar.gz", + "rev": "5ae883b8c3b04e0c4a9c92a5ab3c7c84b9942943", + "sha256": "1s2nhax586v2fax7r5qd1s3d2gdg25isva7k7r9pf9x9ay630cmb" +} diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix new file mode 100644 index 0000000..0067366 --- /dev/null +++ b/nix/nixpkgs.nix @@ -0,0 +1,9 @@ +let + # Grab the versions we specified in the JSON file + nixpkgs = builtins.fromJSON (builtins.readFile ./nixpkgs.json); + + # Bootstrap a copy of nixpkgs, based on this. + src = import ./fetchnix.nix { inherit (nixpkgs) url rev sha256; }; + +# We use the default nixpkgs configuration during bootstrap. +in import src { config = {}; } diff --git a/nix/update-nixpkgs.sh b/nix/update-nixpkgs.sh new file mode 100755 index 0000000..770d280 --- /dev/null +++ b/nix/update-nixpkgs.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -e + +if [[ "x$1" == "x" ]]; then + echo "Must provide a revision argument" + echo "Usage:" + echo " ./update-nixpkgs.sh " + echo " ./update-nixpkgs.sh https://github.com/foo/nixpkgs " + exit 1 +fi + +if [[ "x$2" == "x" ]]; then + REV="$1" + URL="https://github.com/nixos/nixpkgs" +else + REV="$2" + URL="$1" +fi + +DOWNLOAD="$URL/archive/$REV.tar.gz" +echo "Updating to nixpkgs revision $REV from $URL" +SHA256=$(nix-prefetch-url "$DOWNLOAD") + +cat > nixpkgs.json <