Skip to content

hdgarrood/haskell-incremental-nix-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

haskell-nix-incremental-example

Created by Jade Lovelace (@lf-) and I at NixCon 2022, based on a suggestion by Jonas Chevalier (@zimbatm).

This repository contains a proof-of-concept of one approach that can be used with GHC 9.4 to enable incremental Nix builds for Haskell projects. Please note that this project configuration only works with GHC 9.4 and later, because previous versions of GHC use source file timestamps to determine whether source files have changed, and timestamps are not reliable enough for incremental builds in many settings (such as CI).

An "incremental" build setup is one that allows us to save time and effort by only recompiling things that have changed since the previous compile. In CI, we will usually accomplish this by uploading certain files to the cache at the end of a build, and then restoring them at the start of the next build.

The idea in this example is to create a separate Nix output incremental to hold the contents of the dist/build directory, which will allow GHC to perform incremental builds.

To see this repository in action, begin by running:

$ nix-build -A build.all

This command should produce three symbolic links: result, result-doc, and result-incremental.

Now make a change to M2.hs like this:

 greetTarget :: String
 {-# NOINLINE greetTarget #-}
-greetTarget = "world"
+greetTarget = "incremental haskell nix"

And run nix-build again, like this:

$ nix-build -A build.all --argstr previousIncrementalOutput $(readlink result-incremental)

This builds the build target in default.nix again, except this time, the previousIncrementalOutput variable is set to the nix store path that contains the .o and .hi files from the previous compile, which enables incremental builds. Note the following in the output:

building
Preprocessing executable 'haskell-incremental-example' for haskell-incremental-example-1.0.0..
Building executable 'haskell-incremental-example' for haskell-incremental-example-1.0.0..
[1 of 3] Compiling M2               ( M2.hs, dist/build/haskell-incremental-example/haskell-incremental-example-tmp/M2.o ) [Source file changed]
[4 of 4] Linking dist/build/haskell-incremental-example/haskell-incremental-example [Objects changed]

M2 is recompiled because its source has changed, but neither of the other two modules are recompiled, even though they both depend on M2! This is because the interface of M2 has not changed, and GHC is able to spot this and determine that no rebuild of the other modules is necessary.

License (CC0)

CC0

To the extent possible under law, Harry Garrood and Jade Lovelace have waived all copyright and related or neighbouring rights to haskell-nix-incremental-example. This work is published from: United Kingdom.

About

Example to illustrate how to set up incremental Haskell Nix builds

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published