-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkAppImage_WriteClosure.nix
92 lines (80 loc) · 2.94 KB
/
mkAppImage_WriteClosure.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
{ lib
, runCommand
, squashfsTools
, writeTextFile
# mkappimage-specific, passed from flake.nix
, mkappimage-runtime # runtimes are an executable that mount the squashfs part of the appimage and start AppRun
, mkappimage-apprun # appruns contain an AppRun executable that does setup and launches entrypoint
}:
# actual arguments
{ program # absolute path of executable to start
# output name
, pname ? (lib.last (builtins.split "/" program))
, name ? "${pname}.AppImage"
# advanced appimage configuration
, squashfsArgs ? [ ] # additional arguments to pass to mksquashfs
}:
let
commonArgs = [
"-offset $(stat -L -c%s ${lib.escapeShellArg mkappimage-runtime})" # squashfs comes after the runtime
"-all-root" # chown to root
] ++ squashfsArgs;
# Workaround for writeClosure bug.
#
# Due to a bug in Nix, writeClosure with a path *under* a nix store path (e.g.
# /nix/store/...-hello/bin/hello) raises the error "path '$program' is not in
# the Nix store".
#
# See: https://github.com/ralismark/nix-appimage/issues/16
# See: https://github.com/NixOS/nixpkgs/issues/316652
# See: https://github.com/NixOS/nix/pull/10549
#
# This should be fixed in the latest version of Nix, however version where
# this bug is present are still common, so we work around it by using the old
# implementation of writeReferencesToFile from
# https://github.com/NixOS/nixpkgs/blob/e99021ff754a204e38df619ac908ac92885636a4/pkgs/build-support/trivial-builders/default.nix#L628-L640
writeReferencesToFile = path: runCommand "runtime-deps"
{
exportReferencesGraph = [ "graph" path ];
}
''
touch $out
while read path; do
echo $path >> $out
read dummy
read nrRefs
for ((i = 0; i < nrRefs; i++)); do read ref; done
done < graph
'';
in
runCommand name
{
nativeBuildInputs = [ squashfsTools ];
} ''
if ! test -x ${program}; then
echo "Entrypoint '${program}' is NOT Executable (Or It wasn't found)"
echo "Maybe it is a multi-call Program?"
fi
mksquashfs ${builtins.concatStringsSep " " ([
# first run of mksquashfs copies the nix/store closure and additional files
"$(cat ${writeReferencesToFile program})"
"$out"
# additional files
(lib.concatMapStrings (x: " -p ${lib.escapeShellArg x}") [
# symlink entrypoint to the executable to run
"entrypoint s 555 0 0 ${program}"
])
"-no-strip" # don't strip leading dirs, to preserve the fact that everything's in the nix store
] ++ commonArgs)}
mksquashfs ${builtins.concatStringsSep " " ([
# second run of mksquashfs adds the apprun
# no -no-strip since we *do* want to strip leading dirs now
"${mkappimage-apprun}"
"$out"
"-no-recovery" # i don't know what a recovery file is but it gives "No such file or directory"
] ++ commonArgs)}
# add the runtime to the start
dd if=${lib.escapeShellArg mkappimage-runtime} of=$out conv=notrunc
# make executable
chmod 755 $out
''