diff --git a/README.md b/README.md index 5112ed4..bdaa6be 100644 --- a/README.md +++ b/README.md @@ -50,13 +50,13 @@ When using in your own Nix derivation, the best practice is calling generated sc ```nix { pkgs, stdenv }: -let +let spagoPkgs = import ./spago-packages.nix { inherit pkgs; }; in pkgs.stdenv.mkDerivation rec { # < ... > - buildPhase = - '' + buildPhase = + '' ${spagoPkgs.installSpagoStyle} # == spago2nix install ${spagoPkgs.buildSpagoStyle} # == spago2nix build ${spagoPkgs.buildFromNixStore} # == spago2nix build @@ -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 +project’s 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 @@ -154,8 +212,8 @@ Here is a blog post I did about this project: &2 + exit 1 \ No newline at end of file diff --git a/nix/nix-prefetch-git-patched.nix b/nix/nix-prefetch-git-patched.nix new file mode 100644 index 0000000..b6e1b02 --- /dev/null +++ b/nix/nix-prefetch-git-patched.nix @@ -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 ] \ No newline at end of file diff --git a/test-flake/.gitignore b/test-flake/.gitignore new file mode 100644 index 0000000..c4a847d --- /dev/null +++ b/test-flake/.gitignore @@ -0,0 +1 @@ +/result diff --git a/test-flake/flake.lock b/test-flake/flake.lock new file mode 100644 index 0000000..d59e4db --- /dev/null +++ b/test-flake/flake.lock @@ -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 +} diff --git a/test-flake/flake.nix b/test-flake/flake.nix new file mode 100644 index 0000000..3a59cec --- /dev/null +++ b/test-flake/flake.nix @@ -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/ + ''; + }; + }); +}