@@ -1,170 +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−# Create tmp directory for the links produced by `nix build`
105−
106−linkdir=$(mktemp -d)
107−build_flags+=("--out-link")
108−build_flags+=("$linkdir/result")
109−
110−# Build targets
111−
112−target_path=
113−extra_target_paths=
114−
115−for target in "${targets[@]}"
116−do
117− nix build "${build_flags[@]}" "$target" || exit $?
118− out_link="$linkdir/$(ls "$linkdir")"
119− if [ -z "$target_path" ]
120− then
121− target_path="$(readlink "$out_link")"
122− else
123− extra_target_paths="$extra_target_paths $(readlink "$out_link")"
124− fi
125− rm "$out_link"
126−done
127−
128−if [ -z "$target_path" ]
129−then
130− nix build "${build_flags[@]}" || exit $?
131− out_link="$(ls "$linkdir")"
132− target_path="$(readlink "$out_link")"
21+
22+ exit 1
13323fi
13424
135−# Apply default for --bin
25+nix_file=$(dirname "$0")/default.nix
26+
27+target="$1"
28+shift
13629
137−if [ -z ${bin+x} ]
138−then
139− 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
14036fi
14137
142−# Determine bootstrap function -- This seems like a total hack!
38+exec="$1"
39+shift
14340
14441bootstrap=nix-bootstrap
145−if [ "${targets[0]}" = "nix-bundle" ] || [ "${targets[0]}" = "nixStable" ] || [ "${targets[0]}" = "nixUnstable" ] || [ "${targets[0]}" = "nix" ]; then
42+if [ "$target" = "nix-bundle" ] || [ "$target" = "nixStable" ] || [ "$target" = "nixUnstable" ] || [ "$target" = "nix" ]; then
14643 bootstrap=nix-bootstrap-nix
147−elif ! [ -z "$extra_target_paths" ]; then
44+elif [ -n "$extraTargets" ]; then
14845 bootstrap=nix-bootstrap-path
14946fi
15047
151−# Run bootstrap function
152−
153−expr="(with import $nix_file {}; $bootstrap { target = $target_path; extraTargets = [$extra_target_paths ]; run = \"$bin\"; })"
154−
155−echo $expr
48+expr="with import <nixpkgs> {}; with import $nix_file {}; $bootstrap { target = $target; extraTargets = [ $extraTargets ]; run = \"$exec\"; }"
15649
157−out=$(nix-store --no-gc-warning -r $(nix-instantiate --no-gc-warning -E "$expr"))
50+drv=$(nix-instantiate --no-gc-warning -E "$expr")
15851
159−# Copy the created bundle to the working directory
52+out=$(nix-store --no-gc-warning --realize "$drv")
16053
16154if [ -z "$out" ]; then
16255 >&2 echo "$0 failed. Exiting."
16356 exit 1
16457elif [ -t 1 ]; then
165− filename=$(basename $bin)
58+ filename=$(basename "$exec")
16659 echo "Nix bundle created at $filename."
167− cp -f $out $filename
60+ cp -f "$out" "$filename"
16861else
169− cat $out
62+ echo "$out"
17063fi