Skip to content

Commit

Permalink
[nix]: use flakes
Browse files Browse the repository at this point in the history
Flakes are a new (experimental) of Nix. Here we add a `flake.nix` for
the repository, which allows us to use its outputs easily elsewhere. For
example, you could say `nix run github:anoma/anoma -- client` on any
machine to launch the anoma client from scratch.

- The `Cargo.nix` and `crate-checksums.json` files (created with
  `crate2nix`) are now checked in git, because flakes' evaluation is
  stricter in that untracked files are not available in expressions.
  Another option would be to do IFD with `crate2nix`, but I couldn't
  get this to work because of the brittle Cargo dependency vendoring.
  This is hardly a Nix issue though; `cargo vendor` also fails.
- Added a `generateCargoNix` derivation for updating the generated
  files: `nix run .#generateCargoNix`.
- Replaced `shell.nix` and `default.nix` with `flake-compat` shims. This
  means that `nix-build` and `nix-shell` work very much like they used
  to.
- Added `scripts/ci/nix-check.sh` which checks the flake functionality.
  This is not yet integrated to the CI, though.
  • Loading branch information
SimSaladin authored and juped committed Jan 18, 2022
1 parent 1e17942 commit 5babb40
Show file tree
Hide file tree
Showing 17 changed files with 478 additions and 116 deletions.
84 changes: 76 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,22 @@ After installation, the main `anoma` executable will be available on path.

To find how to use it, check out the [User Guide section of the docs](https://docs.anoma.network/master/user-guide/).

If you are running NixOS or at least the Nix package manager, you may opt to
install Anoma as a Nix derivation like so:
If you have Nix, you may opt to build and install Anoma using Nix. The Nix
integration also takes care of making a compatible version of Tendermint
available.

```shell
nix-shell --run "crate2nix generate --no-default-features --features 'std ABCI'"
nix-build -A anoma
nix-env -i ./result
# Nix 2.4 and later
nix profile install

# All versions of Nix
nix-env -f . -iA anoma
```

For more detailed instructions and more install options, see the [Install
section](https://docs.anoma.network/master/user-guide/install.html) of the User
Guide.

## ⚙️ Development

```shell
Expand All @@ -52,12 +59,73 @@ ANOMA_DEV=true make

### Using Nix

If you are running NixOS or at least the Nix package manager, you may opt in to
all the dependencies via Nix by simply entering the Nix shell environment:
You may opt to get all of the dependencies to develop Anoma by entering the
development shell:

```shell
# Nix 2.4 and above
nix develop

# All versions of Nix
nix-shell
make
```

Inside the shell, all of the `make` targets work as usual:

```shell
# Build the WASM modules without docker
make build-wasm-scripts

# Development build (uses cargo)
ANOMA_DEV=true make
```

---

It is also possible to use the Nix Rust infrastructure instead of Cargo to
build the project crates. This method uses `crate2nix` to derive Nix
expressions from `Cargo.toml` and `Cargo.lock` files. The workspace members are
exposed as packages in `flake.nix` with a `rust_` prefix. Variants where the
`ABCI-plus-plus` feature flag is enabled are exposed with a `:ABCI-plus-plus`
suffix.

```shell
# List all packages
nix flake show

# Build the `anoma_apps` crate with `ABCI-plus-plus` feature
nix build .#rust_anoma_apps:ABCI-plus-plus

# Build the (default) anoma package. It consists of wrappers for the Anoma
# binaries (`rust_anoma_apps`) that ensure `tendermint` is in `PATH`.
nix build .#anoma
```

Advantages:

- Excellent build reproducibility (all dependencies pinned).
- Individual crates are stored as Nix derivations and therefore cached in the
Nix store.
- Makes it possible to build Nix derivations of the binaries. Cargo build
doesn't work in the Nix build environment because network access is not
allowed, meaning that Cargo can't fetch dependencies; `cargo vendor` could be
used to prefetch everything for Cargo, but `cargo vendor` does not work on
our project at the moment.

Disadvantages:

- Only works for Linux and Darwin targets. WASM builds in particular are not
possible with this method. Although, while `crate2nix` doesn't support
targeting WASM, we should be able to build the WASM modules via Cargo - if
only `cargo vendor` worked.

__Note:__ If you have modified the Cargo dependencies (changed `Cargo.lock`),
it is necessary to recreate the `Cargo.nix` expressions with `crate2nix`.
Helpers are provided as flake apps (Nix 2.4 and later):

```shell
nix run .#generateCargoNix
nix run .#generateCargoNixABCI-plus-plus
```

### Before submitting a PR, pls make sure to run the following:
Expand Down
43 changes: 13 additions & 30 deletions default.nix
Original file line number Diff line number Diff line change
@@ -1,30 +1,13 @@
{ pkgs ? import ./nix { }
# Allows specifying Rust features for anoma crates.
, features ? ["std" "ABCI"]
# Allows overriding Tendermint derivation.
, tendermint ? pkgs.tendermint
, ... }:
let
packages = rec {
apps = pkgs.cargoNix.workspaceMembers.anoma_apps.build.override { inherit features; };

# By default we want to have executables that have the correct "tendermint" and
# "anoma*" executables available in PATH no matter how the user calls anoma etc.
anoma = pkgs.runCommandNoCC "anoma" {
nativeBuildInputs = [ pkgs.makeWrapper ];
} ''
mkdir -p $out/bin
for exe in ${apps}/bin/* ${tendermint}/bin/*; do
makeWrapper $exe $out/bin/$(basename $exe) \
--prefix PATH : ${apps}/bin:${tendermint}/bin
done
'';

docs = pkgs.callPackage ./docs { };

wasm = pkgs.runCommand "anoma-wasm" { } ''
mkdir -p $out/wasm
cp ${./wasm/checksums.json} $out/wasm/checksums.json
'';
};
in packages
# NOTE the "anoma" and "wasm" top-level atrtibutes + the "features" can be
# removed when all code that use this default.nix is adapted.
{ features ? [ "default" ], ... }:
let lf = (import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash; }
) {
src = ./.;
}).defaultNix; in
lf // { inherit (lf.packages.${builtins.currentSystem}) anoma wasm; }
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ In short:
Using Nix:

```bash
nix-shell --run "make serve"
nix develop ..#anoma-docs -c make serve
```
25 changes: 25 additions & 0 deletions docs/src/user-guide/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ Last, to build and install anoma you can run the following command:
make install
```

## Nix

If you have [Nix](https://nixos.org/), you can get Anoma easily as a flake. For
this to work, make sure that you have Nix 2.4 or later and that you have
`experimental-features = nix-command flakes` in your `~/.config/nix/nix.conf`.

```shell
# Install to user profile
nix profile install github:anoma/anoma/<revision>

# Run without installing
nix run github:anoma/anoma/<revision> -- --help

# Enter a shell where anoma executables are available
nix run github:anoma/anoma/<revision>
```

Set `<revision>` to the git tag, branch or hash you want.

With Nix versions older than 2.4, use this command instead:

```shell
nix-env -f https://github.com/anoma/anoma/archive/<revision>.tar.gz -iA default
```

## Github release

Go to [anoma github release page](https://github.com/anoma/anoma/releases) and download the last release.
Expand Down
109 changes: 109 additions & 0 deletions flake.lock

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

86 changes: 86 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
description = "Anoma";

inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.rust-overlay.url = "github:oxalica/rust-overlay";
inputs.flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};


outputs = { self, nixpkgs, flake-utils, rust-overlay, flake-compat }:
let
supportedSystems = [ "x86_64-linux" "x86_64-darwin" ];
in

with nixpkgs.lib;
with flake-utils.lib;

eachSystem supportedSystems (system:

let
overlays = [ (import rust-overlay) ] ++ import nix/overlays.nix;

pkgs = import nixpkgs { inherit system overlays; };

cargoNix = pkgs.cargoNixWith [ "default" ];
cargoNix-ABCI-plus-plus = pkgs.cargoNixWith [ "ABCI-plus-plus" ];

# By default we want to have executables that have the correct "tendermint" and
# "anoma*" executables available in PATH no matter how the user calls `anoma`,
# `anoma` calls `anoman`, `anoman` calls `tendermint` and so on.
mkAnoma = apps: pkgs.runCommandNoCC "anoma" { nativeBuildInputs = [ pkgs.makeWrapper ]; } ''
mkdir -p $out/bin
for exe in ${apps}/bin/* ${pkgs.tendermint}/bin/*; do
makeWrapper $exe $out/bin/$(basename $exe) \
--prefix PATH : ${apps}/bin:${pkgs.tendermint}/bin
done
'';
in
{
defaultApp = self.apps.${system}.anoma;

apps = {
anoma = mkApp { drv = self.packages.${system}.anoma; };
generateCargoNix = mkApp { drv = pkgs.generateCargoNix [ "default" ]; };
generateCargoNixABCI-plus-plus = mkApp { drv = pkgs.generateCargoNix [ "ABCI-plus-plus" ]; };
};

devShell = with pkgs; pkgs.mkShell {
packages = [
cargoWrapper
using-nightly
rustfmt
clippy
miri
rustc
clang
llvmPackages.libclang
protobuf
openssl
# Needed to build WASM modules (provides `wasm-opt`)
binaryen
# Needed at runtime
tendermint
] ++ lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security ];
LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib";
PROTOC = "${protobuf}/bin/protoc";
PROTOC_INCLUDE = "${protobuf}/include";
};

defaultPackage = self.packages.${system}.anoma;

packages = {
anoma = mkAnoma cargoNix.workspaceMembers.anoma_apps.build;
"anoma:ABCI-plus-plus" = mkAnoma cargoNix-ABCI-plus-plus.workspaceMembers.anoma_apps.build;

inherit (pkgs) wasm anoma-docs;

# wasm src build - broken
#inherit (pkgs) anoma-wasm;
}
// mapAttrs' (n: v: nameValuePair ("rust_" + n) v.build) cargoNix.workspaceMembers
// mapAttrs' (n: v: nameValuePair ("rust_" + n + ":ABCI-plus-plus") v.build) cargoNix-ABCI-plus-plus.workspaceMembers;
});
}
7 changes: 2 additions & 5 deletions docs/default.nix → nix/anoma-docs.nix
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
{ pkgs ? import ../nix { }
}:

with pkgs;
{ stdenv, nix-gitignore, mdbook, mdbook-mermaid, mdbook-linkcheck }:

stdenv.mkDerivation {
name = "anoma-docs";
src = nix-gitignore.gitignoreSource [] ./.;
src = nix-gitignore.gitignoreSource [ ] ../docs;
buildInputs = [ mdbook mdbook-mermaid mdbook-linkcheck ];

patchPhase = ''
Expand Down
Loading

0 comments on commit 5babb40

Please sign in to comment.