I'm pretty happy with a pattern I stumbled into last year for using Nix to provision dependencies for a task-/utility-oriented Makefile.
For a while I've wanted the rough equivalent of a nix-shell shebang--but for Makefiles. The naive approach is something like:
naive
1#!/usr/bin/env nix-shell
2#! nix-shell -i gnumake -p hello
3
4.PHONY: all
5all:
6 @echo nice hello
7 hello --version
But this won't quite work either way we can run it. If we run the following:
1make --makefile=naive all > make-naive.console
2./naive > naive.console
The first one fails because, of course, make doesn't give a hoot about our shebang:
make-naive.console
1nice hello
2hello --version
3make: hello: No such file or directory
4make: *** [naive:7: all] Error 127
and the second fails because we need to be able to pass an -f
flag to use make
as a shebang interpreter:
naive.console
1gnumake: Nothing to be done for `naive'.
All we really need to do (though it'd be nice to get some sugar in Nix for this...) is to run nix-shell
with the dependencies, echo the shell's PATH, and export this PATH in the makefile:
nix-make
1export PATH := $(shell nix-shell -p hello --run 'echo $$PATH')
2
3.PHONY: all
4all:
5 @echo nice hello
6 hello --version
When we run make --makefile=nix-make all
, we get what we want:
nix-make.console
1nice hello
2hello --version
3hello (GNU Hello) 2.12.1-6fe9
4Copyright (C) 2020 Free Software Foundation, Inc.
5License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
6This is free software: you are free to change and redistribute it.
7There is NO WARRANTY, to the extent permitted by law.
8
9Written by Karl Berry, Sami Kerola, Jim Meyering,
10and Reuben Thomas.
If you'd like to see a non-toy use, here's how I use this in resholve:
1{ pkgs ? import <nixpkgs> { } }:
2
3with pkgs;
4let
5 # wordswurst = callPackage ../wordswurst { };
6 wordswurst = callPackage
7 (fetchFromGitHub {
8 owner = "abathur";
9 repo = "wordswurst";
10 rev = "df2b4873ea66d904bb863ee9f0e21be1ebaab9be";
11 hash = "sha256-aN29FphL6Bh5ts/5/ydso5vVFeB/6b5hj+6fynvoYus=";
12 })
13 { };
14in
15pkgs.mkShell {
16 buildInputs = [ nix coreutils gnused groff util-linux wordswurst sassc ];
17}
1#! /usr/bin/env make
2#export PATH := $(shell nix-shell -p nix coreutils gnused groff util-linux --run 'echo $$PATH')
3export PATH := $(shell nix-shell make.nix --run 'echo $$PATH')
4
5.PHONY: apologeez ci clean update
6
7apologeez:
8 @echo Sorry--the Makefile is a lie. I just use this for dev tasks atm.
9 @echo See README.md / https://github.com/abathur/resholve
10
11all: apologeez
12install: apologeez
13uninstall: apologeez
14
15.local : *.nix setup.cfg setup.py test.sh demo tests/* resholve.1 resholve _resholve/*
16 touch .local
17
18
19result-ci: .local
20 @echo Building ci.nix
21 @nix-build --out-link result-ci ci.nix
22 @touch result-ci result-ci/* || true # TODO: fails on MU
23
24ci: result-ci
25
26result-quick: .local
27 @echo Building quick.nix
28 @nix-build --out-link result-quick quick.nix
29 @touch result-quick result-quick/* || true # TODO: fails on MU
30
31quick: result-quick
32
33clean:
34 rm .local result-ci result-quick docs/README.nixpkgs.md
35
36result-ci/test.txt result-ci/demo.txt result-ci/nix-demo.txt: result-ci
37
38timings.md: bits/timings.md.pre bits/timings.md.post result-ci/test.txt
39 @echo Building timings.md
40 @cat bits/timings.md.pre \
41 result-ci/test.txt \
42 bits/timings.md.post \
43 > timings.md
44
45demos.md: bits/demos.md.pre bits/demos.md.mid bits/demos.md.post result-ci/demo.txt result-ci/nix-demo.txt
46 @echo Building demos.md
47 @cat bits/demos.md.pre \
48 result-ci/demo.txt \
49 bits/demos.md.mid \
50 result-ci/nix-demo.txt \
51 bits/demos.md.post \
52 | sed -E 's@/nix/store/[a-z0-9]{32}-@/nix/store/...-@g' > demos.md
53
54resholve.1: docs/manpage.wwst docs/manpage.css docs/content.wwst
55 @echo Building manpage
56 @wordswurst $< > $@
57
58docs/README.nixpkgs.md: docs/markdown.wwst docs/markdown.css docs/content.wwst
59 @echo "Building Nixpkgs README (markdown)"
60 @wordswurst $< > $@
61
62docs/%.css: docs/%.scss
63 @echo Sassing $@ from $<
64 @sassc --omit-map-comment $< $@
65
66docs/resholve.1.txt: resholve.1
67 @echo Building plain-text copy of manpage
68 @groff -m mdoc -T utf8 $< | col -bx > $@
69
70_resholve/strings.py: docs/strings.wwst docs/strings.css docs/content.wwst
71 @echo Wursting $@ from $<
72 @wordswurst $< > $@
73
74update: timings.md demos.md docs/resholve.1.txt docs/README.nixpkgs.md