about summary refs log tree commit diff
path: root/nix/writers
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-04-23T20·04+0200
committerProfpatsch <mail@profpatsch.de>2021-04-24T10·23+0000
commiteb41eef6127216543d8b28c9c423ac1be0a4ee24 (patch)
treec01e67c4062711b3623841e8e56791ec8a14edc1 /nix/writers
parent7e888c3c7bb36f6ab6e83d4a6f6a755ff4156791 (diff)
chore(nix): move rustSimple from users.Profpatsch.writers r/2547
I think it’s solid enough to use in a wider context.

Change-Id: If53e8bbb6b90fa88d73fb42730db470e822ea182
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3055
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: lukegb <lukegb@tvl.fyi>
Diffstat (limited to 'nix/writers')
-rw-r--r--nix/writers/default.nix97
-rw-r--r--nix/writers/tests/rust.nix68
2 files changed, 165 insertions, 0 deletions
diff --git a/nix/writers/default.nix b/nix/writers/default.nix
new file mode 100644
index 0000000000..f43761865f
--- /dev/null
+++ b/nix/writers/default.nix
@@ -0,0 +1,97 @@
+{ depot, pkgs, lib, ... }:
+
+let
+  bins = depot.nix.getBins pkgs.s6-portable-utils [ "s6-ln" "s6-ls" "s6-touch" ]
+    ;
+
+  linkTo = name: path: depot.nix.runExecline.local name {} [
+    "importas" "out" "out"
+    bins.s6-ln "-s" path "$out"
+  ];
+
+  # Build a rust executable.
+  # Takes all arguments that `pkgs.buildRustCrate` accepts.
+  # Rather leaky abstraction.
+  rustSimple = args@{name, ...}: src:
+    linkTo name "${rustSimpleBin args src}/bin/${name}";
+
+  # Like `rustSimple`, but put the binary in `$out/bin/`.
+  rustSimpleBin = {
+    name,
+    dependencies ? [],
+    doCheck ? true,
+    ...
+  }@args: src:
+    (if doCheck then testRustSimple else pkgs.lib.id)
+    (pkgs.buildRustCrate ({
+      pname = name;
+      version = "1.0.0";
+      crateName = name;
+      crateBin = [ name ];
+      dependencies = dependencies;
+      src = pkgs.runCommandLocal "write-main.rs" {
+        src = src;
+        passAsFile = [ "src" ];
+      } ''
+        mkdir -p $out/src/bin
+        cp "$srcPath" $out/src/bin/${name}.rs
+        find $out
+      '';
+    } // args));
+
+  # Build a rust library, that can be used as dependency to `rustSimple`.
+  # Wrapper around `pkgs.buildRustCrate`, takes all its arguments.
+  rustSimpleLib = {
+    name,
+    dependencies ? [],
+    doCheck ? true,
+    ...
+  }@args: src:
+    (if doCheck then testRustSimple else pkgs.lib.id)
+    (pkgs.buildRustCrate ({
+      pname = name;
+      version = "1.0.0";
+      crateName = name;
+      dependencies = dependencies;
+      src = pkgs.runCommandLocal "write-lib.rs" {
+        src = src;
+        passAsFile = [ "src" ];
+      } ''
+        mkdir -p $out/src
+        cp "$srcPath" $out/src/lib.rs
+        find $out
+      '';
+    } // args));
+
+  /* Takes a `buildRustCrate` derivation as an input,
+    * builds it with `{ buildTests = true; }` and runs
+    * all tests found in its `tests` dir. If they are
+    * all successful, `$out` will point to the crate
+    * built with `{ buildTests = false; }`, otherwise
+    * it will fail to build.
+    *
+    * See also `nix.drvSeqL` which is used to implement
+    * this behavior.
+    */
+  testRustSimple = rustDrv:
+    let
+      crate = buildTests: rustDrv.override { inherit buildTests; };
+      tests = depot.nix.runExecline.local "${rustDrv.name}-tests-run" {} [
+        "importas" "out" "out"
+        "if" [
+          "pipeline" [ bins.s6-ls "${crate true}/tests" ]
+          "forstdin" "-o0" "test"
+          "importas" "test" "test"
+          "${crate true}/tests/$test"
+        ]
+        bins.s6-touch "$out"
+      ];
+    in depot.nix.drvSeqL [ tests ] (crate false);
+
+in {
+  inherit
+    rustSimple
+    rustSimpleBin
+    rustSimpleLib
+    ;
+}
diff --git a/nix/writers/tests/rust.nix b/nix/writers/tests/rust.nix
new file mode 100644
index 0000000000..4b87676118
--- /dev/null
+++ b/nix/writers/tests/rust.nix
@@ -0,0 +1,68 @@
+{ depot, pkgs, ... }:
+
+let
+  inherit (depot.nix.writers)
+    rustSimple
+    rustSimpleLib
+    rustSimpleBin
+    ;
+
+  inherit (pkgs)
+    coreutils
+    ;
+
+  run = drv: depot.nix.runExecline.local "run-${drv.name}" {} [
+    "if" [ drv ]
+    "importas" "out" "out"
+    "${coreutils}/bin/touch" "$out"
+  ];
+
+  rustTransitiveLib = rustSimpleLib {
+    name = "transitive";
+  } ''
+    pub fn transitive(s: &str) -> String {
+      let mut new = s.to_string();
+      new.push_str(" 1 2 3");
+      new
+    }
+
+    #[cfg(test)]
+    mod tests {
+      use super::*;
+
+      #[test]
+      fn test_transitive() {
+        assert_eq!(transitive("foo").as_str(), "foo 1 2 3")
+      }
+    }
+  '';
+
+  rustTestLib = rustSimpleLib {
+    name = "test_lib";
+    dependencies = [ rustTransitiveLib ];
+  } ''
+    extern crate transitive;
+    use transitive::{transitive};
+    pub fn test() -> String {
+      transitive("test")
+    }
+  '';
+
+  rustWithLib = run (rustSimple {
+    name = "rust-with-lib";
+    dependencies = [ rustTestLib ];
+  } ''
+    extern crate test_lib;
+
+    fn main() {
+      assert_eq!(test_lib::test(), String::from("test 1 2 3"));
+    }
+  '');
+
+
+in depot.nix.utils.drvTargets {
+  inherit
+    rustTransitiveLib
+    rustWithLib
+    ;
+}