Building

Prerequisites

cardano-wallet needs nix to build.

Supported versionDependency?
[Nix][]>= 2.5.1Required

Follow the instructions on the [Nix][] page to install and configure Nix.

Warning

Make sure that you have set up the binary cache for Haskell.nix, [according to the instructions][haskell-nix-cache], or you will wait a long time building multiple copies of GHC. If Nix builds GHC, this is an indication that the cache has not been set up correctly.

Commands

> nix build ```

The resulting executable will appear at ./result/bin/cardano-wallet.

Unless you have local changes in your git repo, Nix will download the build from a nix cache rather than building locally. At the moment the cache is available only for developers at CF.

You may also run the executable directly with:

> nix run . -- <cardano wallet arguments>

or more comfortably, for pre-configured networks (mainnet, testnet, ...):

> CARDANO_NODE_SOCKET_PATH=../cardano-node/node.socket

> nix run .#mainnet/wallet -- <optional additional cardano wallet arguments>

You can run the integration tests with:

> nix build -L .#ci.x86_64-linux.tests.run.integration

Cross-compiling with Nix

To build the wallet for Windows, from Linux:

> nix build .#ci.artifacts.win64.release

Building straight from GitHub

The following command will build the master branch, with the resulting executable appearing at ./result/bin/cardano-wallet. To build another branch, add /<branch name, tag, or commit hash> (see Nix Manual: Flake References for syntax). As before, if the target ref has already been built by Hydra, then it will be fetched from cache rather than built locally.

> nix build github:cardano-foundation/cardano-wallet
> ./result/bin/cardano-wallet version
v2022-01-18 (git revision: ce772ff33623e2a522dcdc15b1d360815ac1336a)

Cabal+Nix build

Use the Cabal+Nix build if you want to develop with incremental builds, but also have it automatically download cached builds of all dependencies.

If you run nix develop, it will start a development environment for cardano-wallet. This will contain:

  • cabal-install and a GHC configured with a package database containing all Haskell package dependencies;
  • system library dependencies;
  • a Hoogle index and hoogle command for searching documentation;
  • development tools such as haskell-language-server, hlint, stylish-haskell, and weeder;
  • the sqlite3 command;
  • the Shelley node backend cardano-node and cardano-cli; and
  • other Adrestia utility programs such as cardano-address and bech32

Inside this shell you can use cabal build and ghci for development.

For example, you might start an incremental build of the integration test suite with:

ghcid -c "cabal repl test:integration"

and run the test suite with:

cabal run test:integration
Profiling build with cached dependencies

Use nix develop .#profiled to get a shell where Haskell dependencies are built with profiling enabled. You won't need to rebuild all of the dependencies because they can be downloaded from the Hydra cache.

> nix develop .#profiled

[nix-shell:~/iohk/cardano-wallet]$ cabal build \
    --enable-tests --enable-benchmarks \
    --enable-profiling \
    all

Haskell-Language-Server

The haskell-language-server provides an IDE for developers with some typical features:

  • Jump to definition.
  • Find references.
  • Documentation on hover.
  • etc.

Prerequisites

The following must be installed:

We do not require a special version per-project so these executables can be installed system-wide.

Additionally, the following tools are provided by the cardano-wallet nix development shell:

We require a particular version of each per-project, so it's recommended to use the nix development environment to ensure you have the correct version.

In these instructions we enter a nix development environment using direnv allow rather than nix develop or nix-shell (see Editor Setup).

Setup

haskell-language-server requires some priming to work with cardano-wallet:

# Symlink hie.yaml to hie-direnv.yaml, which is the project configuration for haskell-language-server
ln -sf hie-direnv.yaml hie.yaml

# Build and cache the nix development environment
direnv allow

# Generate a build plan
cabal configure --enable-tests --enable-benchmarks -O0

# Build entire project
cabal build all

This will prime haskell-language-server to work with all modules of the project (tests, benchmarks, etc.) and be fully featured. Without these steps, haskell-language-server may fail to:

  • Find auto-generated modules (such as Paths_* modules).
  • Navigate across projects (jump-to-definition).
  • Provide documentation on hover.

Testing

To test the haskell-language-server, use the following commands (these should be in your $PATH because you executed direnv allow previously, or have entered a nix development environment):

hie-bios check lib/wallet/src/Cardano/Wallet.hs
haskell-language-server lib/wallet/exe/cardano-wallet.hs

Occasionally hie-bios will fail with a Segmentation Fault. In these cases just run hie-bios again.

Note that these commands will only test a couple of files. To test the whole project, see Troubleshooting.

Editor Setup

With a working installation of haskell-language-server, we can integrate with our IDE of choice. See Configuring Your Editor.

IMPORTANT: you need to ensure that your editor invokes the same version of haskell-language-server that we have configured above. A simple way to do that is to launch your editor from within a nix development environment (e.g. nix develop --command 'vim'), or, more practically, to configure your editor with direnv support. Here are some examples:

Troubleshooting

Helpful resources:

The Testing commands only tested a subset of the files in the project. To troubleshoot configuration issues, it's important to determine the source of the error.

If you know the source of the error, you can reproduce it on the command line with haskell-language-server <the file>. There are debug flags which might be useful (see --help).

If you do not know the source of the error, you can test every file in the project with:

# Provide list_sources function.
source "$(dirname "$0")/../cabal-lib.sh"

# Get every file in the project.
mapfile -t srcs < <(list_sources)

# Execute haskell-language-server on every file in the project.
# Note that this command can take upwards of an hour.
haskell-language-server "${srcs[@]}"

Once you can reproduce the error, look through the Worked Examples below and see if you can resolve the issue. If you cannot, raise a GitHub issue (external) or a JIRA issue (internal) with reproduction steps and tag @sevanspowell or @rvl.

Worked Examples

NOTE: hie-bios BIOS Configuration is helpful background reading.

Source Filtering

In the past haskell-language-server failed when processing the lib/wallet/extra/Plutus/FlatInteger.hs file, as it was technically a Haskell file in the repository, but wasn't intended to be compiled with the project.

To fix this issue, we excluded the lib/wallet/extra folder from the project sources.

The bash function list_sources in scripts/cabal-lib.sh is responsible for determining the source files haskell-language-server sees. Modify this function to further remove any other files you wish to exclude:

list_sources() {
  # Exclude lib/wallet/extra. Those files are Plutus scripts intended
  # to be serialised for use in the tests. They are not intended to be built
  # with the project.
  # Exclude prototypes dir because it's a different project.
  git ls-files 'lib/**/*.hs' | grep -v Main.hs | grep -v prototypes/ | grep -v lib/wallet/extra
}
GHCI Flags

There were previously issues debugging overlapping/ambiguous instances as the error message printed by haskell-language-server did not contain enough information. We rectified this by adding -fprint-potential-instances to the GHCI flags of the haskell-language-server BIOS.

The bash function ghci_flags in scripts/cabal-lib.sh is responsible for providing the GHCI flags haskell-language-server uses. Modify this file with any other GHC flags you may require:

ghci_flags() {
  cat <<EOF
-XOverloadedStrings
-XNoImplicitPrelude
-XTypeApplications
-XDataKinds
-fwarn-unused-binds
-fwarn-unused-imports
-fwarn-orphans
-fprint-potential-instances
-Wno-missing-home-modules
EOF

...
}