Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ YubiHSM Rust community bindings.

The Rust and Haskell library can be built using Nix as follows,

```
```sh
# Rust
nix build .#yubihsm-ed-sign-rust
# Haskell
Expand All @@ -21,7 +21,7 @@ nix build .#yubihsm-ed-sign-haskell

You can also use `cabal` or `cargo` from inside of `nix develop` shell. For example,

```sh-session
```sh
nix develop
cd ./rustbits
cargo test
Expand All @@ -31,7 +31,7 @@ cabal build

To test the Haskell->Rust integration works, a Cabal executable is provided. You can run it as:

```
```sh-session
❯ nix run
thread '<unnamed>' panicked at 'could not connect to YubiHSM: Error(Context { kind: ProtocolError, source: Some(Error(Context { kind: ProtocolError, source: Some(Error(Context { kind: UsbError, source: Some(Message("no YubiHSM 2 devices detected")) })) })) })', src/lib.rs:39:49
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Expand All @@ -48,6 +48,15 @@ Aborted (core dumped)
- <kbd>Ctrl+Shift+P</kbd> to run command "Nix-Env: Select Environment" and then select `shell.nix`.
- The extension will ask you to reload VSCode at the end. Do it.

### Development workflows

Some useful development works.

- When editing the Haskell library, run `nix develop -c ghcid` to get fast compile feedback.
- When editing the Haskell executable, run `nix develop -c ghcid -c 'cabal repl exe:yubihsm-ed-sign'` to get fast compile feedback.
- Add `-T :main` inside of `-c` argument if you also want to run the main entrypoint.
- For Haskell repl, `nix develop -c cabal repl`

## Directory structure

- `rustbits` is the Rust code
Expand Down
104 changes: 53 additions & 51 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 51 additions & 34 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,56 @@
flake-compat.flake = false;
flake-compat.inputs.nixpkgs.follows = "nixpkgs";

# Rust inputs
# - crate2nix provides developer environments, unlike the Rust support in nixpkgs.
# - rust-overlay provides the suite of Rust toolchains we need for IDE
# support, etc. It is also fairly easy to switch between different Rust
# channels.
crate2nix.url = "github:kolloch/crate2nix";
crate2nix.flake = false;
rust-overlay.url = "github:oxalica/rust-overlay";
# Crane is used to provide Rust build and development environments.
# https://ipetkov.dev/blog/introducing-crane/
#
# Eventually, we may want to switch over to the dream2nix-based
# https://github.com/yusdacra/nix-cargo-integration (whilst still using
# Crane as the backend) once we figure out how to use it in a multi-language
# flake like ours.
crane.url = "github:ipetkov/crane";
crane.inputs.nixpkgs.follows = "nixpkgs";
};

outputs = { self, nixpkgs, ... }@inputs:
outputs = { self, nixpkgs, crane, ... }@inputs:
let
# A function that produces Flake outputs for the given system.
#
# Define the entire flake inside this function, which factors out the
# 'system' at top-level var.
outputsFor = system:
let
name = "yubihsm-ed-sign";
pkgs = import nixpkgs {
inherit system;
overlays = rust.overlays;
};
pkgs = inputs.nixpkgs.legacyPackages.${system};
mergeDevShells = import ./nix/mergeDevShells.nix { inherit pkgs; };
rust = import ./nix/rust.nix ({ inherit pkgs; } // inputs);

# Nix for Rust development environment and build
#
# - `(rustProject false).rootCrate` gives the Rust crate, the
# `build.lib` attribute of which returns the derivation for the
# library in Cargo.toml
# - `rustProject false` gives the library crate.
# - `rustProject true` gives the dev shell.
rustProject = returnShellEnv:
rust.developPackage {
inherit returnShellEnv name;
root = ./rustbits;
};
let
src = ./rustbits;
cargoArtifacts = crane.lib.${system}.buildDepsOnly {
inherit src;
};
rustbits-crate = crane.lib.${system}.buildPackage {
inherit src cargoArtifacts;
};
rustbits-devShell = pkgs.mkShell {
inputsFrom = [ rustbits-crate ];
nativeBuildInputs = with pkgs; [
cargo
rustc
rust-analyzer
];
# This is needed for rust-analyzer to work.
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
# For downstream projects (eg: Haskell) to access the rustbits
# in their runtime tools like repls and language servers.
LD_LIBRARY_PATH = "${rustbits-crate}/lib";
};
in
if returnShellEnv then rustbits-devShell else rustbits-crate;

# Nix for Haskell development environment and build
#
Expand All @@ -58,7 +71,8 @@
haskellProject = returnShellEnv:
# NOTE: developPackage internally uses callCabal2nix
pkgs.haskellPackages.developPackage {
inherit returnShellEnv name;
inherit returnShellEnv;
name = "yubihsm-ed-sign";
root = ./.;
withHoogle = false;
overrides = self: super: with pkgs.haskell.lib; {
Expand All @@ -67,10 +81,7 @@
# Example:
# > NanoID = self.callCabal2nix "NanoID" inputs.NanoID { };
# Assumes that you have the 'NanoID' flake input defined.

# The 3c99cfdd88 suffix is the Rust compiler hash
# cf. https://stackoverflow.com/a/28335376/55246
yubihsm_ed_sign-3c99cfdd88 = (rustProject false).rootCrate.build.lib;
yubihsmedsign = rustProject false;
};
modifier = drv:
pkgs.haskell.lib.overrideCabal drv (drv: {
Expand All @@ -83,19 +94,25 @@
};
in
{
devShell =
mergeDevShells
[
(haskellProject true)
(rustProject true)
];
devShells = {
haskell = haskellProject true;
rust = rustProject true;
default =
mergeDevShells
[
self.devShells.${system}.haskell
self.devShells.${system}.rust
];
};

packages = {
yubihsm-ed-sign-rust = (rustProject false).rootCrate.build.lib;
yubihsm-ed-sign-rust = rustProject false;
yubihsm-ed-sign-haskell = haskellProject false;
};

# For commpat with older Nix
defaultPackage = self.packages.${system}.yubihsm-ed-sign-haskell;
devShell = self.devShells.${system}.default;
};
in
inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] outputsFor;
Expand Down
Loading