on master help sign in
nix-bundle.sh: Modernize CLI
14157e0haslersn
nix-bundle.sh+134−25
@@ -1,56 +1,165 @@
1#!/usr/bin/env sh
1#!/usr/bin/env sh
2
2
3−if [ "$#" -lt 2 ]; then
3+fail() {
4− cat <<EOF
4+ echo "Try '$0 --help'." >&2
5+ exit 2
6+}
5
7
6−Usage: $0 TARGET EXECUTABLE
8+build() {
9+ linkdir=$(mktemp -d)
10+ nix build "$@" --out-link "$linkdir/result"
11+ readlink "$linkdir/result"
12+}
7
13
8−Create a single-file bundle from the nixpkgs attribute "TARGET".
14+check_arg() {
9−EXECUTABLE should be relative to the TARGET's output path.
15+ if [ $# -le 1 ]
16+ then
17+ echo "error: flag '$1' requires an argument" >&2
18+ fail
19+ fi
20+}
10
21
11−For example:
22+nix_file=`dirname $0`/default.nix
23+
24+# Read arguments
25+
26+build_flags=()
27+unset bin
28+targets=()
29+
30+while [ $# -ne 0 ]
31+do
32+ case "$1" in
33+ -f|--file|-I|--include)
34+ check_arg "$@"
35+ build_flags+=("$1")
36+ shift
37+ build_flags+=("$1")
38+ shift
39+ ;;
40+ --arg|--argstr)
41+ if [ $# -le 2 ]
42+ then
43+ echo "error: flag '$1' requires two arguments" >&2
44+ fail
45+ fi
46+ build_flags+=("$1")
47+ shift
48+ build_flags+=("$1")
49+ shift
50+ build_flags+=("$1")
51+ shift
52+ ;;
53+ --bin)
54+ check_arg "$@"
55+ shift
56+ bin="$1"
57+ shift
58+ ;;
59+ -h|--help)
60+ cat <<EOF >&2
61+Usage: $0 <FLAGS>... [<TARGET>] <targets>...
12
62
13−$ $0 hello /bin/hello
63+Summary: Similar to nix build, but creates a single-file bundle.
14−$ ./hello
15−Hello, world!
16
64
65+Flags:
66+ --arg <NAME> <EXPR> argument to be passed to Nix functions
67+ --argstr <NAME> <STRING> string-valued argument to be passed to Nix functions
68+ -f, --file <FILE> evaluate FILE rather than the default
69+ -I, --include <PATH> add a path to the list of locations used to look up <...> file names
70+ --bin <BINARY> the binary to bundle, relative to TARGET's output path
71+
72+Examples:
73+
74+ To bundle GNU Hello from NixOS 19.03:
75+ $ $0 -f channel:nixos-19.03 hello --bin /bin/hello
76+
77+ To bundle the executable from within a project that has a default.nix for build:
78+ $ $0 --bin /bin/name-of-the-executable
17EOF
79EOF
80+ exit 0
81+ ;;
82+ --)
83+ shift
84+ break
85+ ;;
86+ -*)
87+ echo "error: unrecognized flag '$1'" >&2
88+ fail
89+ ;;
90+ *)
91+ targets+=("$1")
92+ shift
93+ ;;
94+ esac
95+done
96+
97+while [ $# -ne 0 ]
98+do
99+ targets+=("$1")
100+ shift
101+done
18
102
19− exit 1
103+# Check if all required arguments were passed
104+
105+if [ -z ${bin+x} ]
106+then
107+ echo "error: flag '--bin' is required" >&2
108+ fail
20fi
109fi
21
110
22−nix_file=`dirname $0`/default.nix
111+# Create tmp directory for the links produced by `nix build`
112+
113+linkdir=$(mktemp -d)
114+build_flags+=("--out-link")
115+build_flags+=("$linkdir/result")
116+
117+# Build targets
23
118
24−target="$1"
119+target_path=
25−shift
120+extra_target_paths=
26
121
27−extraTargets=
122+for target in "${targets[@]}"
28−if [ "$#" -gt 1 ]; then
123+do
29− while [ "$#" -gt 1 ]; do
124+ nix build "${build_flags[@]}" "$target" || exit $?
30− extraTargets="$extraTargets $1"
125+ if [ -z "$target_path" ]
31− shift
126+ then
127+ target_path="$(readlink "$linkdir/result")"
128+ else
129+ extra_target_paths="$extra_target_paths $(readlink "$linkdir/result")"
130+ fi
32− done
131+done
132+
133+if [ -z "$target_path" ]
134+then
135+ nix build "${build_flags[@]}" || exit $?
136+ target_path="$(readlink "$linkdir/result")"
33fi
137fi
34
138
35−exec="$1"
139+# Determine bootstrap function -- This seems like a total hack!
36−shift
37
140
38bootstrap=nix-bootstrap
141bootstrap=nix-bootstrap
39−if [ "$target" = "nix-bundle" ] || [ "$target" = "nixStable" ] || [ "$target" = "nixUnstable" ] || [ "$target" = "nix" ]; then
142+if [ "${targets[0]}" = "nix-bundle" ] || [ "${targets[0]}" = "nixStable" ] || [ "${targets[0]}" = "nixUnstable" ] || [ "${targets[0]}" = "nix" ]; then
40 bootstrap=nix-bootstrap-nix
143 bootstrap=nix-bootstrap-nix
41−elif ! [ -z "$extraTargets" ]; then
144+elif ! [ -z "$extra_target_paths" ]; then
42 bootstrap=nix-bootstrap-path
145 bootstrap=nix-bootstrap-path
43fi
146fi
44
147
148+# Run bootstrap function
149+
45−expr="with import <nixpkgs> {}; with import $nix_file {}; $bootstrap { target = $target; extraTargets = [ $extraTargets ]; run = \"$exec\"; }"
150+expr="(with import $nix_file {}; $bootstrap { target = $target_path; extraTargets = [$extra_target_paths ]; run = \"$bin\"; })"
151+
152+echo $expr
46
153
47out=$(nix-store --no-gc-warning -r $(nix-instantiate --no-gc-warning -E "$expr"))
154out=$(nix-store --no-gc-warning -r $(nix-instantiate --no-gc-warning -E "$expr"))
48
155
156+# Copy the created bundle to the working directory
157+
49if [ -z "$out" ]; then
158if [ -z "$out" ]; then
50 >&2 echo "$0 failed. Exiting."
159 >&2 echo "$0 failed. Exiting."
51 exit 1
160 exit 1
52elif [ -t 1 ]; then
161elif [ -t 1 ]; then
53− filename=$(basename $exec)
162+ filename=$(basename $bin)
54 echo "Nix bundle created at $filename."
163 echo "Nix bundle created at $filename."
55 cp -f $out $filename
164 cp -f $out $filename
56else
165else