mirror of
https://github.com/ilyakooo0/nix-bundle.git
synced 2024-09-11 06:55:53 +03:00
Merge pull request #48 from haslersn/enhancement/modern-cli
nix-bundle.sh: Modernize CLI
This commit is contained in:
commit
4300437ede
178
nix-bundle.sh
178
nix-bundle.sh
@ -1,56 +1,178 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
if [ "$#" -lt 2 ]; then
|
||||
cat <<EOF
|
||||
fail() {
|
||||
echo "Try '$0 --help'." >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
Usage: $0 TARGET EXECUTABLE
|
||||
build() {
|
||||
linkdir=$(mktemp -d)
|
||||
nix build "$@" --out-link "$linkdir/result"
|
||||
readlink "$linkdir/result"
|
||||
}
|
||||
|
||||
Create a single-file bundle from the nixpkgs attribute "TARGET".
|
||||
EXECUTABLE should be relative to the TARGET's output path.
|
||||
|
||||
For example:
|
||||
|
||||
$ $0 hello /bin/hello
|
||||
$ ./hello
|
||||
Hello, world!
|
||||
|
||||
EOF
|
||||
|
||||
exit 1
|
||||
check_arg() {
|
||||
if [ $# -le 1 ]
|
||||
then
|
||||
echo "error: flag '$1' requires an argument" >&2
|
||||
fail
|
||||
fi
|
||||
}
|
||||
|
||||
nix_file=`dirname $0`/default.nix
|
||||
|
||||
target="$1"
|
||||
shift
|
||||
# Read arguments
|
||||
|
||||
extraTargets=
|
||||
if [ "$#" -gt 1 ]; then
|
||||
while [ "$#" -gt 1 ]; do
|
||||
extraTargets="$extraTargets $1"
|
||||
build_flags=()
|
||||
unset bin
|
||||
targets=()
|
||||
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-f|--file|-I|--include)
|
||||
check_arg "$@"
|
||||
build_flags+=("$1")
|
||||
shift
|
||||
build_flags+=("$1")
|
||||
shift
|
||||
;;
|
||||
--arg|--argstr)
|
||||
if [ $# -le 2 ]
|
||||
then
|
||||
echo "error: flag '$1' requires two arguments" >&2
|
||||
fail
|
||||
fi
|
||||
build_flags+=("$1")
|
||||
shift
|
||||
build_flags+=("$1")
|
||||
shift
|
||||
build_flags+=("$1")
|
||||
shift
|
||||
;;
|
||||
--bin)
|
||||
check_arg "$@"
|
||||
shift
|
||||
bin="$1"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<EOF >&2
|
||||
Usage: $0 <FLAGS>... [<TARGET>] <targets>...
|
||||
|
||||
Summary: Similar to nix build, but creates a single-file bundle.
|
||||
|
||||
Flags:
|
||||
--arg <NAME> <EXPR> argument to be passed to Nix functions
|
||||
--argstr <NAME> <STRING> string-valued argument to be passed to Nix functions
|
||||
-f, --file <FILE> evaluate FILE rather than the default
|
||||
-I, --include <PATH> add a path to the list of locations used to look up <...> file names
|
||||
--bin <BINARY> the binary to bundle, relative to TARGET's output path; defaults to
|
||||
the lexicographically first file inside /bin
|
||||
|
||||
Examples:
|
||||
|
||||
To bundle GNU Hello from NixOS 19.03:
|
||||
$ $0 -f channel:nixos-19.03 hello --bin /bin/hello
|
||||
|
||||
To bundle the executable from within a project that has a default.nix for build:
|
||||
$ $0 --bin /bin/name-of-the-executable
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "error: unrecognized flag '$1'" >&2
|
||||
fail
|
||||
;;
|
||||
*)
|
||||
targets+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
targets+=("$1")
|
||||
shift
|
||||
done
|
||||
|
||||
# Add application-specific extra targets
|
||||
|
||||
if [ "${targets[0]}" = "nix-bundle" ] || [ "${targets[0]}" = "nixStable" ] || [ "${targets[0]}" = "nixUnstable" ] || [ "${targets[0]}" = "nix" ]
|
||||
then
|
||||
targets+=("bash")
|
||||
targets+=("bzip2")
|
||||
targets+=("coreutils")
|
||||
targets+=("gnutar")
|
||||
targets+=("gzip")
|
||||
targets+=("xz")
|
||||
fi
|
||||
|
||||
exec="$1"
|
||||
shift
|
||||
# Create tmp directory for the links produced by `nix build`
|
||||
|
||||
linkdir=$(mktemp -d)
|
||||
build_flags+=("--out-link")
|
||||
build_flags+=("$linkdir/result")
|
||||
|
||||
# Build targets
|
||||
|
||||
target_path=
|
||||
extra_target_paths=()
|
||||
|
||||
for target in "${targets[@]}"
|
||||
do
|
||||
nix build "${build_flags[@]}" "$target" || exit $?
|
||||
out_link="$linkdir/$(ls "$linkdir")"
|
||||
if [ -z "$target_path" ]
|
||||
then
|
||||
target_path="$(readlink "$out_link")"
|
||||
else
|
||||
extra_target_paths+=("\"$(readlink "$out_link")\"")
|
||||
fi
|
||||
rm "$out_link"
|
||||
done
|
||||
|
||||
if [ -z "$target_path" ]
|
||||
then
|
||||
nix build "${build_flags[@]}" || exit $?
|
||||
out_link="$(ls "$linkdir")"
|
||||
target_path="$(readlink "$out_link")"
|
||||
fi
|
||||
|
||||
# Apply default for --bin
|
||||
|
||||
if [ -z ${bin+x} ]
|
||||
then
|
||||
bin=$(ls "$target_path/bin" | head -1)
|
||||
fi
|
||||
|
||||
# Determine bootstrap function -- This seems like a total hack!
|
||||
|
||||
bootstrap=nix-bootstrap
|
||||
if [ "$target" = "nix-bundle" ] || [ "$target" = "nixStable" ] || [ "$target" = "nixUnstable" ] || [ "$target" = "nix" ]; then
|
||||
bootstrap=nix-bootstrap-nix
|
||||
elif ! [ -z "$extraTargets" ]; then
|
||||
if ! [ -z "$extra_target_paths" ]; then
|
||||
bootstrap=nix-bootstrap-path
|
||||
fi
|
||||
|
||||
expr="with import <nixpkgs> {}; with import $nix_file {}; $bootstrap { target = $target; extraTargets = [ $extraTargets ]; run = \"$exec\"; }"
|
||||
# Run bootstrap function
|
||||
|
||||
expr="(with import $nix_file {}; $bootstrap { target = \"$target_path\"; extraTargets = [ ${extra_target_paths[@]} ]; run = \"$bin\"; })"
|
||||
|
||||
echo $expr
|
||||
|
||||
out=$(nix-store --no-gc-warning -r $(nix-instantiate --no-gc-warning -E "$expr"))
|
||||
|
||||
# Copy the created bundle to the working directory
|
||||
|
||||
if [ -z "$out" ]; then
|
||||
>&2 echo "$0 failed. Exiting."
|
||||
exit 1
|
||||
elif [ -t 1 ]; then
|
||||
filename=$(basename $exec)
|
||||
filename=$(basename $bin)
|
||||
echo "Nix bundle created at $filename."
|
||||
cp -f $out $filename
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user