@@ -1,180 +1,63 @@
11#!/usr/bin/env sh
22
3−fail() {
4− echo "Try '$0 --help'." >&2
5− exit 2
6−}
7−
8−build() {
9− linkdir=$(mktemp -d)
10− nix build "$@" --out-link "$linkdir/result"
11− readlink "$linkdir/result"
12−}
13−
14−check_arg() {
15− if [ $# -le 1 ]
16− then
17− echo "error: flag '$1' requires an argument" >&2
18− fail
19− fi
20−}
21−
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>...
62−
63−Summary: Similar to nix build, but creates a single-file bundle.
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; defaults to
71− the lexicographically first file inside /bin
72−
73−Examples:
74−
75− To bundle GNU Hello from NixOS 19.03:
76− $ $0 -f channel:nixos-19.03 hello --bin /bin/hello
77−
78− To bundle the executable from within a project that has a default.nix for build:
79− $ $0 --bin /bin/name-of-the-executable
3+if [ "$#" -lt 2 ]; then
4+ cat <<EOF
5+
6+Usage: $0 TARGET EXECUTABLE
7+
8+Create a single-file bundle from the nixpkgs attribute "TARGET".
9+EXECUTABLE should be relative to the TARGET's output path.
10+
11+The TARGET is either an attribute in nixpkgs, or an absolute path to the
12+store.
13+
14+For example:
15+
16+$ $0 hello /bin/hello
17+$ ./hello
18+Hello, world!
19+
8020EOF
81− exit 0
82− ;;
83− --)
84− shift
85− break
86− ;;
87− -*)
88− echo "error: unrecognized flag '$1'" >&2
89− fail
90− ;;
91− *)
92− targets+=("$1")
93− shift
94− ;;
95− esac
96−done
97−
98−while [ $# -ne 0 ]
99−do
100− targets+=("$1")
101− shift
102−done
103−
104−# Add application-specific extra targets
105−
106−if [ "${targets[0]}" = "nix-bundle" ] || [ "${targets[0]}" = "nixStable" ] || [ "${targets[0]}" = "nixUnstable" ] || [ "${targets[0]}" = "nix" ]
107−then
108− targets+=("bash")
109− targets+=("bzip2")
110− targets+=("coreutils")
111− targets+=("gnutar")
112− targets+=("gzip")
113− targets+=("xz")
114−fi
11521
116−# Create tmp directory for the links produced by `nix build`
117−
118−linkdir=$(mktemp -d)
119−build_flags+=("--out-link")
120−build_flags+=("$linkdir/result")
121−
122−# Build targets
123−
124−target_path=
125−extra_target_paths=()
126−
127−for target in "${targets[@]}"
128−do
129− nix build "${build_flags[@]}" "$target" || exit $?
130− out_link="$linkdir/$(ls "$linkdir")"
131− if [ -z "$target_path" ]
132− then
133− target_path="$(readlink "$out_link")"
134− else
135− extra_target_paths+=("\"$(readlink "$out_link")\"")
136− fi
137− rm "$out_link"
138−done
139−
140−if [ -z "$target_path" ]
141−then
142− nix build "${build_flags[@]}" || exit $?
143− out_link="$(ls "$linkdir")"
144− target_path="$(readlink "$out_link")"
22+ exit 1
14523fi
14624
147−# Apply default for --bin
25+nix_file=$(dirname "$0")/default.nix
26+
27+target="$1"
28+shift
14829
149−if [ -z ${bin+x} ]
150−then
151− bin=$(ls "$target_path/bin" | head -1)
30+extraTargets=
31+if [ "$#" -gt 1 ]; then
32+ while [ "$#" -gt 1 ]; do
33+ extraTargets="$extraTargets $1"
34+ shift
35+ done
15236fi
15337
154−# Determine bootstrap function -- This seems like a total hack!
38+exec="$1"
39+shift
15540
15641bootstrap=nix-bootstrap
157−if ! [ -z "$extra_target_paths" ]; then
42+if [ "$target" = "nix-bundle" ] || [ "$target" = "nixStable" ] || [ "$target" = "nixUnstable" ] || [ "$target" = "nix" ]; then
43+ bootstrap=nix-bootstrap-nix
44+elif [ -n "$extraTargets" ]; then
15845 bootstrap=nix-bootstrap-path
15946fi
16047
161−# Run bootstrap function
162−
163−expr="(with import $nix_file {}; $bootstrap { target = \"$target_path\"; extraTargets = [ ${extra_target_paths[@]} ]; run = \"$bin\"; })"
164−
165−echo $expr
48+expr="with import <nixpkgs> {}; with import $nix_file {}; $bootstrap { target = $target; extraTargets = [ $extraTargets ]; run = \"$exec\"; }"
16649
167−out=$(nix-store --no-gc-warning -r $(nix-instantiate --no-gc-warning -E "$expr"))
50+drv=$(nix-instantiate --no-gc-warning -E "$expr")
16851
169−# Copy the created bundle to the working directory
52+out=$(nix-store --no-gc-warning --realize "$drv")
17053
17154if [ -z "$out" ]; then
17255 >&2 echo "$0 failed. Exiting."
17356 exit 1
17457elif [ -t 1 ]; then
175− filename=$(basename $bin)
58+ filename=$(basename "$exec")
17659 echo "Nix bundle created at $filename."
177− cp -f $out $filename
60+ cp -f "$out" "$filename"
17861else
179− cat $out
62+ echo "$out"
18063fi