Nix Cook Book
tropf
ABSTRACT
My personal recipes when using nix .
1. Intro
Nix refers to the operating system NixOS, the package
manager and associated repository nixpkgs, and the func-
tional language nix itself. I use all three, because I like
its focus towards reproducability.
It declarative approach breaks with many habits and
also tools, so in this document I attempt to make some notes
how to tackle challenges I encountered in using nix.
2. Parameterized Packages in Flakes
To create multiple versions of the same package (deri-
vation) with different parameters use callPackage. Note the
trailing {} to immedeately create a valid derivation.
mypkg = pkgs.callPackage ({doCheck ? false}: stdenv.mkDerivation rec {
inherit doCheck;
checkTarget = "test";
cmakeFlags = (if doCheck then [
"-DBUILD_TESTING=TRUE"
] else []);
}) {};
mypkg_with_tests = selfpkgs.mypkg.override {doCheck = true;};
3. Include nix Include Dirs in Exported Compile Commands
When exporting cmake compile commands the nix-defined
include dirs (extracted by querying g++) will not be in-
cluded. You can manually add them with a (hacky) sed com-
mand.
13 September 2023
-2-
> This modifies JSON with sed and is evil. Use at
your own risk.
nix develop && cd build
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
sed -e "s,$(which g++),$(which g++) $(g++ -xc++ -E -Wp,-v /dev/null 2>&1 | sed -n '/^ /{s/^ / -I/;H};${x;s/\n//g;p}'),g" -i compile_commands.json
# note: this is maybe already called automatically by your editor
rc -J .
4. Creating Debuggable Builds
By default, nix will enable all sorts of optimiza-
tions/security options ("fortifications") in C/C++ programs.
This can make debugging very hard, as it optimizes code
out/reorders your code, even using Debug cmake build type.
To disable these modifications set: hardeningDisable =
[ "all" ]
In full context this may be used as such:
buildInputs = [
cmake
gcc
] ++ (if doCheck then [
catch2
cmakeCurses
gdb
] else []);
cmakeFlags = (if doCheck then [
"-DBUILD_TESTING=TRUE"
"-DCMAKE_BUILD_TYPE=Debug"
] else []);
hardeningDisable = if doCheck then [ "all" ] else [];
5. Build without Tests, but Develop with Tests
You can specify different targets for nix build and nix
develop such that they refer to different deviations:
defaultPackage.x86_64-linux = mypkg;
devShells.x86_64-linux.default = mypkg_with_tests;
13 September 2023
-3-
6. Ensure Locales Exist
The CI infrastructure I use lacks some locales. When
building plots etc., the font handling doesn't work due to
these missing locales. Disturbingly, my local nix build in-
vocation finds the locales and looks completely fine, while
the CI version does not. To fix this set the following
variables inside the stdenv invocation:
LOCALE_ARCHIVE = "${glibcLocales.override {allLocales = false; locales=["en_US.UTF-8/UTF-8"];}}/lib/locale/locale-archive";
LC_ALL = "en_US.utf8";
7. Load System Config From Flake
To investigate the configuration generated by a flake
run (in the directory with the system's flake.nix):
$ nix repl
nix-repl> :lf .
Added 13 variables.
nix-repl> nixosConfigurations.kurt.config.programs.git.enable
true
8. nixos-shell Base Image
The command nixos-shell spawns a shell with a nixos VM.
One might view it as nix shell on steroids. It is available
on github and can be
installed directly through nixpkgs. (I.e., there is no ex-
tra option/module required.)
The following is a base configuration that I commonly
use. It mounts the current directory under /mnt, configures
nix to enable flake support, and adds some packages. It in-
cludes a normal (non-root) user account (useful for the
mount).
13 September 2023
-4-
{ pkgs, ... }: {
boot.kernelPackages = pkgs.linuxPackages_latest;
nixos-shell.mounts = {
mountHome = false;
extraMounts = {
"/mnt" = ./.;
};
};
users.users.mensch.isNormalUser = true;
nix = {
package = pkgs.nixUnstable;
settings.trusted-users = [ "root" "user" ];
extraOptions = ''
experimental-features = nix-command flakes
'';
};
programs.git.enable = true;
environment.systemPackages = with pkgs; [
moreutils tree jq htop
];
}
13 September 2023