-
Notifications
You must be signed in to change notification settings - Fork 91
/
default.nix
144 lines (137 loc) · 3.9 KB
/
default.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
{ stdenv
, autoPatchelfHook
, bash
, coreutils
, libredirect
, lndir
, makeWrapper
, qLibs
, rlwrap
, runCommand
, shellcheck
, util-linux
, writeTextFile
}:
let
# From https://code.kx.com/q4m3/14_Introduction_to_Kdb+/#1481-the-environment-variables,
# set QHOME to the location of `q.k`.
# To pass in a license, invoke q with QLIC set to the *directory* in which
# kc.lic is located.
# Other .q (or .k) files are loaded with `\l path/to/file`.
# .so files are loaded by defining their name/path when defining the function:
# https://code.kx.com/q/interfaces/using-c-functions/
version = "4.0-2020.05.04";
# Package that contains just the stdlib
q-stdlib = writeTextFile {
name = "q-stdlib-${version}";
destination = "/q/q.k";
text = builtins.readFile ./q.k;
};
# The Q unwrapped binary
q-bin = stdenv.mkDerivation {
pname = "q-bin";
inherit version;
dontUnpack = true;
nativeBuildInputs = [
autoPatchelfHook
];
doBuild = false;
installPhase = ''
runHook preInstall
install -Dm755 ${./q} $out
runHook postInstall
'';
};
# This is a wrapper for the Q binary that is extended with a number of
# features.
#
# See the comments in the script for more details.
q-wrapper = writeTextFile {
name = "q-${version}";
destination = "/bin/q";
executable = true;
checkPhase = "${shellcheck}/bin/shellcheck $out/bin/q";
text = ''
#!${bash}/bin/bash
# A wrapper for the Q binary extended with more environment variables.
#
# See the table below in the Globals for more details.
set -euo pipefail
### Globals ###
# On which CPU the process should be pinned.
: "''${QCPU:=}"
# In which folder the database should be stored.
: "''${QDB:=''${QHOME:-$QHOME/db}}"
# A root folder for the Q binary to load libraries from.
: "''${QHOME:=}"
# Extend QHOME with a list of paths to load libraries from. The paths
# must be absolute.
: "''${QLIB:=}"
# Override in which directory to look for to load the Q license.
: "''${QLIC:=}"
# This is the load order, by order of precedence
QLIB=''${QHOME:+$QHOME:}''${QLIB:+$QLIB:}${qLibs}/q:${q-stdlib}/q
# Temporary work dir with all of QLIB merged into.
qhome=$(${coreutils}/bin/mktemp -d)
### Functions ###
log() {
echo "[''$$]$*" >&2
}
# Cleanup to execute on process termination.
at_exit() {
local ret=$? pid=
set +e
# Make sure to forward the signal
pid=$(jobs -p)
if [[ -n $pid ]]; then
log "killing $pid"
kill "$pid"
wait "$pid"
fi
if [[ -n $qhome ]]; then
log "cleaning $qhome"
rm -rf "$qhome"
fi
exit "$ret"
}
### Main ###
# Setup a callback on process termination
trap at_exit EXIT
# Build the symlink tree
IFS=:
for dir in $QLIB; do
${lndir}/bin/lndir -silent "$dir" "$qhome"
done
IFS=' '
# Change directory into the Q DB
if [[ -n $QDB ]]; then
cd "$QDB"
else
log "warn: QDB and QHOME are unset. The db will be written to the current directory."
fi
# Point Q to the symlink filesystem
export QHOME=$qhome
cmd=(${q-bin} "$@")
# Wrap if stdin is interactive
# XXX: this breaks libredirect
# if [[ -t 0 ]]; then
# cmd=(${rlwrap}/bin/rlwrap "''${cmd[@]}")
# fi
log "QCPU=$QCPU"
# Bind to one CPU
if [[ -n $QCPU ]]; then
${util-linux}/bin/taskset -pc "$QCPU" ''$$
else
${util-linux}/bin/taskset -p ''$$
fi
log "QDB=$QDB"
log "QHOME=$QHOME"
log "QLIB=$QLIB"
log "QLIC=$QLIC"
log "\$''${cmd[*]}"
# Run!
NIX_REDIRECTS=/q/=$QHOME/ LD_PRELOAD=${libredirect}/lib/libredirect.so "''${cmd[@]}"
'';
};
in
q-wrapper