@@ -1,178 +1,56 @@
11#!/usr/bin/env sh
22
3−fail() {
4− echo "Try '$0 --help'." >&2
5− exit 2
6−}
3+if [ "$#" -lt 2 ]; then
4+ cat <<EOF
75
8−build() {
9− linkdir=$(mktemp -d)
10− nix build "$@" --out-link "$linkdir/result"
11− readlink "$linkdir/result"
12−}
6+Usage: $0 TARGET EXECUTABLE
137
14−check_arg() {
15− if [ $# -le 1 ]
16− then
17− echo "error: flag '$1' requires an argument" >&2
18− fail
19− fi
20−}
8+Create a single-file bundle from the nixpkgs attribute "TARGET".
9+EXECUTABLE should be relative to the TARGET's output path.
2110
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.
11+For example:
6412
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
13+$ $0 hello /bin/hello
14+$ ./hello
15+Hello, world!
7216
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
8017EOF
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
10318
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")
19+ exit 1
11420fi
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")"
145−fi
22+nix_file=`dirname $0`/default.nix
14623
147−# Apply default for --bin
24+target="$1"
25+shift
14826
149−if [ -z ${bin+x} ]
150−then
151− bin=$(ls "$target_path/bin" | head -1)
27+extraTargets=
28+if [ "$#" -gt 1 ]; then
29+ while [ "$#" -gt 1 ]; do
30+ extraTargets="$extraTargets $1"
31+ shift
32+ done
15233fi
15334
154−# Determine bootstrap function -- This seems like a total hack!
35+exec="$1"
36+shift
15537
15638bootstrap=nix-bootstrap
157−if ! [ -z "$extra_target_paths" ]; then
39+if [ "$target" = "nix-bundle" ] || [ "$target" = "nixStable" ] || [ "$target" = "nixUnstable" ] || [ "$target" = "nix" ]; then
40+ bootstrap=nix-bootstrap-nix
41+elif ! [ -z "$extraTargets" ]; then
15842 bootstrap=nix-bootstrap-path
15943fi
16044
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
45+expr="with import <nixpkgs> {}; with import $nix_file {}; $bootstrap { target = $target; extraTargets = [ $extraTargets ]; run = \"$exec\"; }"
16646
16747out=$(nix-store --no-gc-warning -r $(nix-instantiate --no-gc-warning -E "$expr"))
16848
169−# Copy the created bundle to the working directory
170−
17149if [ -z "$out" ]; then
17250 >&2 echo "$0 failed. Exiting."
17351 exit 1
17452elif [ -t 1 ]; then
175− filename=$(basename $bin)
53+ filename=$(basename $exec)
17654 echo "Nix bundle created at $filename."
17755 cp -f $out $filename
17856else