Nix Progress (Part 3)
This blog entry is a continuation of the Nix Progress and Nix Progress (Part 2) blog entries. It discusses some of the things that I have learned.
Default Values
Nix functions can provide default values for arguments using syntax like the following:
{ compiler ? "ghc8104"
, nixpkgs ? null
}:
In this example, the default compiler
value is specified
in the argument list while the nixpkgs
value has a default
of null
and is determined in the body of the function (not
shown). When should a value be specified, and when should
null
be used?
TTC
Nix configuration consists of a shell.nix
file that
configures a shell environment for development and testing. There is no
default.nix
file. The arguments in shell.nix
are like the above, and the default compiler is set in a single
location: the argument list.
LiterateX
Nix configuration, on the other hand, has both a
default.nix
and a shell.nix
. Both files
include a compiler
argument. In this case, the default
value should be null
and the compiler value should be
determined in the body of the function defined in
default.nix
. The default compiler is set in a single
location, in default.nix
. If a default value were specified
like in the example above, then the default compiler would need to be
specified in two separate files, which is not preferred because one
could be forgotten during maintenance and lead to issues.
The default for the nixpkgs
argument is
null
in both cases. One might consider the option of
setting the known working nixpkgs
revision hash for the
default compiler as the default value for nixpkgs
, but this
should be avoided because of types. The nixpkgs
argument is
a path type, not a (revision) string type. In the current
implementation, the following possibilities are supported:
- When a
nixpkgs
path is provided, it is used. - When a supported (tested) compiler is selected and a
nixpkgs
path is not provided, a known working revisions ofnixpkgs
is used. - When a non-supported (non-tested) compiler is selected and a
nixpkgs
path is not provided, packages configured on the filesystem (<nixpkgs>
) are used.
isShell
Flag
In projects that have both a default.nix
and
shell.nix
configuration, I needed to figure out how to add
build tools to the shell using the appropriate revision of
nixpkgs
. I ended up adding an isShell
argument
to the function defined in default.nix
, with a default
value of false
. The shell.nix
implementation
imports default.nix
with the value set to
true
. This allows the tooling to be added using the
appropriate revision, keeping all of the revision logic in one
place.
Problematic
default.nix
?
Before getting help from Divam, I used a fixed nixpkgs
revision in default.nix
. This is problematic because other
software that uses the library via Nix by fetching the tarball from
GitHub likely uses a different revision.
LiterateX makes use of TTC, so I tried it out to see what happens. At least in this simple case, it worked without issue! I suspect that it works because no system libraries are used.
Broken Flags
When refactoring the Nix configuration for the LiterateX animation, I initially planned on using GHC 8.10.4 with the nix-versions revision. The build failed immediately, reporting that the diagrams-cairo package was marked as “broken!” I was happy to get a quick error instead of waiting a long time for it to eventually fail.
The broken
flag is a standard meta-attribute that can be passed as an argument to
mkDerivation
. Investigating, I found the flag set in the
derivation used in my attempted build: haskell-packages.nix.
A comment says that this file is auto-generated. The configuration-hackage2nix.yaml
file is where the package is actually marked as broken.