Nix Flake with 1-step Workflow

This commit is contained in:
James Brock 2022-12-11 00:14:35 +09:00
parent c65c3d2f1a
commit 780780be5c
8 changed files with 467 additions and 5 deletions

View File

@ -145,6 +145,64 @@ This has a key drawback: steps 2 and 3 really ought to be a single step.
Because the `spago.dhall` file doesn't contain any cryptographic verification
of the dependencies, we can't do this as a pure one-step derivation.
## 1-Step Workflow with `flake.nix`
The 1-Step Workflow requires an impure Nix build.
There is a `flake.nix` which provides a package for building a PureScript
project in a Nix derivation. The package is a function
named `spago2nix_nativeBuildInputs` which has a “type signature” like this:
```nix
{
spago-dhall ? "spago.dhall", # the main spago.dhall file name, i.e. "spago.dhall"
srcs-dhall # array of .dhall files, i.e. [./spago.dhall ./packages.dhall]
}: []
```
The `spago2nix_nativeBuildInputs` function takes as inputs the PureScript
projects Spago `.dhall` files, and produces as output an array of
derivations to include in a `nativeBuildInputs`. For a derivation which
has those `nativeBuildInputs`, the PureScript project can be built
in the `buildPhase` by executing `build-spago-style`.
Example:
```nix
stdenv.mkDerivation {
name = "my-purescript-project";
nativeBuildInputs = [
easy-purescript-nix.purs
] ++ (
spago2nix_nativeBuildInputs {
srcs-dhall = [./spago.dhall ./packages.dhall];
}
);
src = nixpkgs.nix-gitignore.gitignoreSource [ ".git" ] ./.;
unpackPhase = ''
cp -r $src/src .
cp -r $src/test .
install-spago-style
'';
buildPhase = ''
build-spago-style "./src/**/*.purs" "./test/**/*.purs"
'';
installPhase = ''
mkdir -p $out
mv output $out/
'';
}
```
For another example, see [`test-flake/flake.nix`](test-flake/flake.nix)
in this repository which shows how to build the __uint__ package.
The `flake.nix` also has an `app` for running `spago2nix` off of Github,
for example:
```sh
nix run github:justinwoo/spago2nix#spago2nix
```
## Further Reading

60
flake.lock Normal file
View File

@ -0,0 +1,60 @@
{
"nodes": {
"easy-purescript-nix": {
"flake": false,
"locked": {
"lastModified": 1670198178,
"narHash": "sha256-5KkyNpPakv4xIP2ba0S5GX+dcmd3AcO9kPhwa482BbA=",
"owner": "justinwoo",
"repo": "easy-purescript-nix",
"rev": "7a4cb3cd6ca53566ea1675692eab0aa13907ff09",
"type": "github"
},
"original": {
"owner": "justinwoo",
"repo": "easy-purescript-nix",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1670507980,
"narHash": "sha256-riNZa0xzM1it3pzxciwALeMs+0CsBMWIW2FqulzK8vM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2787fc7d1e51404678614bf0fe92fc296746eec0",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"easy-purescript-nix": "easy-purescript-nix",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

96
flake.nix Normal file
View File

@ -0,0 +1,96 @@
{
description = "PureScript build derivations from spago.dhall";
nixConfig.sandbox = "relaxed";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
easy-purescript-nix = {
url = "github:justinwoo/easy-purescript-nix";
flake = false;
};
};
outputs = { self, ... }@inputs:
inputs.flake-utils.lib.eachSystem ["x86_64-linux"] (system:
let
nixpkgs = inputs.nixpkgs.legacyPackages.${system};
easy-purescript-nix = import inputs.easy-purescript-nix {pkgs = nixpkgs;};
nix-prefetch-git-patched = import ./nix/nix-prefetch-git-patched.nix nixpkgs;
spago2nix = import ./default.nix {
pkgs = nixpkgs // {
nix-prefetch-git = nix-prefetch-git-patched;
};
};
# Generate spago-package.nix file from PureScript project Spago files.
spago-packages-nix = {
spago-dhall ? "spago.dhall", # the main spago.dhall file name, i.e. "spago.dhall"
srcs-dhall # array of .dhall files, i.e. [./spago.dhall ./packages.dhall]
}:
nixpkgs.stdenv.mkDerivation {
# https://zimbatm.com/notes/nix-packaging-the-heretic-way
# So that spago2nix can fetch packages from Github.
__noChroot = true;
# We need HTTPS to fetch from github.
SYSTEM_CERTIFICATE_PATH = "${nixpkgs.cacert}/etc/ssl/certs";
SSL_CERT_FILE = "${nixpkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
NIX_SSL_CERT_FILE = "${nixpkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
GIT_SSL_CAINFO = "${nixpkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
name = "spago-packages";
nativeBuildInputs = [
spago2nix
easy-purescript-nix.spago
];
srcs = srcs-dhall;
unpackPhase = ''
for _src in $srcs; do
cp "$_src" $(stripHash "$_src")
done
'';
buildPhase = ''
spago2nix generate 4 -- --config ${spago-dhall} --global-cache skip
'';
installPhase = ''
mkdir $out
cp spago-packages.nix $out/
'';
};
# Produce nativeBuildInputs from PureScript project Spago files.
#
# For a derivation which has those nativeBuildInputs,
# the PureScript project can be build in the buildPhase by executing
# install-spago-style or build-spago-style.
spago2nix_nativeBuildInputs = args@{
spago-dhall ? "spago.dhall", # the main spago.dhall file name, i.e. "spago.dhall"
srcs-dhall # array of .dhall files, i.e. [./spago.dhall ./packages.dhall]
}:
let
# https://nixos.wiki/wiki/Import_From_Derivation
ifd = import "${spago-packages-nix args}/spago-packages.nix" {pkgs=nixpkgs;};
in
[ ifd.installSpagoStyle ifd.buildSpagoStyle ];
in
{
packages = {
inherit spago2nix;
inherit spago-packages-nix;
inherit spago2nix_nativeBuildInputs;
};
apps = {
spago2nix = {
type = "app";
program = "${spago2nix}/bin/spago2nix";
};
};
}
);
}

View File

@ -0,0 +1,14 @@
diff --git a/nix-prefetch-git b/nix-prefetch-git
index 43f7c5a..a04566b 100755
--- a/nix-prefetch-git
+++ b/nix-prefetch-git
@@ -430,9 +430,6 @@ else
# Compute the hash.
hash=$(nix-hash --type $hashType --base32 "$tmpFile")
- # Add the downloaded file to the Nix store.
- finalPath=$(nix-store --add-fixed --recursive "$hashType" "$tmpFile")
-
if test -n "$expHash" -a "$expHash" != "$hash"; then
echo "hash mismatch for URL \`$url'. Got \`$hash'; expected \`$expHash'." >&2
exit 1

View File

@ -0,0 +1,36 @@
# taken from NixOS/nixpkgs
# https://github.com/NixOS/nixpkgs/blob/379690ba90695a6cefe20c2d51dfcd44a1e8b562/pkgs/tools/package-management/nix-prefetch-scripts/default.nix
#
# We patch nix-prefetch-git so that it doesn't call nix-store --add-fixed,
# because it requires access to the Nix daemon, which is not accessible
# in a build phase for spago2nix.
{ lib, stdenv, stdenvNoCC, gnused, nix, coreutils, findutils, gawk, git, path, makeWrapper, ... }:
let
mkPrefetchScript = tool: src: deps:
stdenv.mkDerivation {
name = "nix-prefetch-${tool}";
nativeBuildInputs = [ makeWrapper ];
dontUnpack = true;
installPhase = ''
install -vD ${src} $out/bin/$name;
wrapProgram $out/bin/$name \
--prefix PATH : ${lib.makeBinPath (deps ++ [ gnused nix ])} \
--set HOME /homeless-shelter
'';
preferLocalBuild = true;
};
patched-file = stdenvNoCC.mkDerivation {
src = "${path}/pkgs/build-support/fetchgit";
name = "nix-prefetch-git-patched";
patches = [ ./nix-prefetch-git-no-store.patch ];
phases = [ "unpackPhase" "patchPhase" "installPhase" ];
installPhase = ''
cp nix-prefetch-git $out
'';
};
in
mkPrefetchScript "git" patched-file [ coreutils findutils gawk git ]

1
test-flake/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/result

142
test-flake/flake.lock Normal file
View File

@ -0,0 +1,142 @@
{
"nodes": {
"easy-purescript-nix": {
"flake": false,
"locked": {
"lastModified": 1670198178,
"narHash": "sha256-5KkyNpPakv4xIP2ba0S5GX+dcmd3AcO9kPhwa482BbA=",
"owner": "justinwoo",
"repo": "easy-purescript-nix",
"rev": "7a4cb3cd6ca53566ea1675692eab0aa13907ff09",
"type": "github"
},
"original": {
"owner": "justinwoo",
"repo": "easy-purescript-nix",
"type": "github"
}
},
"easy-purescript-nix_2": {
"flake": false,
"locked": {
"lastModified": 1670198178,
"narHash": "sha256-5KkyNpPakv4xIP2ba0S5GX+dcmd3AcO9kPhwa482BbA=",
"owner": "justinwoo",
"repo": "easy-purescript-nix",
"rev": "7a4cb3cd6ca53566ea1675692eab0aa13907ff09",
"type": "github"
},
"original": {
"owner": "justinwoo",
"repo": "easy-purescript-nix",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1670507980,
"narHash": "sha256-riNZa0xzM1it3pzxciwALeMs+0CsBMWIW2FqulzK8vM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2787fc7d1e51404678614bf0fe92fc296746eec0",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1670507980,
"narHash": "sha256-riNZa0xzM1it3pzxciwALeMs+0CsBMWIW2FqulzK8vM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2787fc7d1e51404678614bf0fe92fc296746eec0",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"easy-purescript-nix": "easy-purescript-nix",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"spago2nix": "spago2nix",
"uint": "uint"
}
},
"spago2nix": {
"inputs": {
"easy-purescript-nix": "easy-purescript-nix_2",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 0,
"narHash": "sha256-afN+dUKmI8qscuWOdKnGNRcXJT2II82wGz1WczVm47k=",
"path": "..",
"type": "path"
},
"original": {
"path": "..",
"type": "path"
}
},
"uint": {
"flake": false,
"locked": {
"lastModified": 1656899371,
"narHash": "sha256-HVYg43V/FlH+5cufN+cYA5Smy8hjTo8awdgyhZhfPzA=",
"owner": "purescript-contrib",
"repo": "purescript-uint",
"rev": "e5b5dbfcbab400976491da04d2eb71880fcc747b",
"type": "github"
},
"original": {
"owner": "purescript-contrib",
"repo": "purescript-uint",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

55
test-flake/flake.nix Normal file
View File

@ -0,0 +1,55 @@
# To test, run:
#
# nix build
#
{
description = "Test uint build with spago2nix_nativeBuildInputs";
nixConfig.sandbox = "relaxed";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
spago2nix.url = "path:..";
easy-purescript-nix = {
url = "github:justinwoo/easy-purescript-nix";
flake = false;
};
uint = {
url = "github:purescript-contrib/purescript-uint";
flake = false;
};
};
outputs = { self, uint, spago2nix, flake-utils, ... }@inputs:
flake-utils.lib.eachSystem ["x86_64-linux"] (system:
let
nixpkgs = inputs.nixpkgs.legacyPackages.${system};
easy-purescript-nix = import inputs.easy-purescript-nix {pkgs = nixpkgs;};
in
{
packages.default = nixpkgs.stdenv.mkDerivation {
name = "test-uint";
src = uint;
nativeBuildInputs = [
easy-purescript-nix.purs-0_15_4
] ++ (
spago2nix.packages.${system}.spago2nix_nativeBuildInputs {
srcs-dhall = [
"${uint}/spago.dhall" "${uint}/packages.dhall"];
}
);
unpackPhase = ''
cp -r $src/src .
install-spago-style
'';
buildPhase = ''
build-spago-style "./src/**/*.purs"
'';
installPhase = ''
mkdir -p $out
mv output $out/
'';
};
});
}