blob: 33a2a22269522b1e9805802adf563113caf6a420 [file] [log] [blame]
Marc Kupietz11df7852026-08-09 14:59:09 +02001#!/usr/bin/env bash
2#
3# Installs dereko2vec and everything it needs, in one go:
4#
5# 1. the packages of the distribution (dnf, apt-get or brew)
6# 2. rocksdb, but only where the distribution has none or none with the
7# static library (scripts/build-rocksdb.sh)
8# 3. collocatordb
9# 4. dereko2vec, with the fast static link of rocksdb and collocatordb
10#
11# Works on Fedora, Rocky Linux, RHEL, Debian, Ubuntu and MacOS.
12#
13# Options:
14# --shared link rocksdb and collocatordb shared (default:
15# static, which is about 22% faster when indexing)
16# --prefix DIR install there instead of /usr/local
17# --rocksdb-prefix DIR build rocksdb into DIR instead of $HOME/rocksdb
18# --rocksdb-version V build rocksdb version V instead of the one of the
19# distribution
20# --skip-deps do not install the packages of the distribution
21# --skip-tests do not run ctest
Marc Kupietz98804e52026-08-09 17:47:36 +020022# --build-only build everything but install nothing: no packages of
23# the distribution, no root needed, the binaries stay
24# in the build directory
Marc Kupietz11df7852026-08-09 14:59:09 +020025# --static-binary build dereko2vec as a completely static binary
26# (needs static compression libraries, which Debian
27# and Ubuntu ship and Fedora, Rocky and RHEL do not)
28# -j N build with N jobs (default: all cores)
29#
30set -euo pipefail
31
32DEREKO2VEC_SRC=$(cd "$(dirname "$0")/.." && pwd)
33PREFIX=/usr/local
34ROCKSDB_PREFIX=$HOME/rocksdb
35ROCKSDB_VERSION=
36STATIC=1
37STATIC_BINARY=0
38SKIP_DEPS=0
39SKIP_TESTS=0
Marc Kupietz98804e52026-08-09 17:47:36 +020040BUILD_ONLY=0
Marc Kupietz11df7852026-08-09 14:59:09 +020041JOBS=
42
43usage() {
44 sed -n '2,26p' "$0"
45 exit "${1:-0}"
46}
47
48while [ $# -gt 0 ]; do
49 case $1 in
50 --shared) STATIC=0; shift ;;
51 --static-binary) STATIC_BINARY=1; shift ;;
52 --prefix) PREFIX=$2; shift 2 ;;
53 --rocksdb-prefix) ROCKSDB_PREFIX=$2; shift 2 ;;
54 --rocksdb-version) ROCKSDB_VERSION=$2; shift 2 ;;
55 --skip-deps) SKIP_DEPS=1; shift ;;
56 --skip-tests) SKIP_TESTS=1; shift ;;
Marc Kupietz98804e52026-08-09 17:47:36 +020057 --build-only) BUILD_ONLY=1; shift ;;
Marc Kupietz11df7852026-08-09 14:59:09 +020058 -j) JOBS=$2; shift 2 ;;
59 -h|--help) usage 0 ;;
60 *) echo "Unknown option: $1" >&2; usage 1 ;;
61 esac
62done
63
Marc Kupietz98804e52026-08-09 17:47:36 +020064# Nothing is installed, so nothing of the distribution is needed either
65if [ $BUILD_ONLY = 1 ]; then
66 SKIP_DEPS=1
67fi
68
Marc Kupietz11df7852026-08-09 14:59:09 +020069if [ -z "$JOBS" ]; then
70 JOBS=$(getconf _NPROCESSORS_ONLN 2> /dev/null || sysctl -n hw.ncpu)
71fi
72export CMAKE_BUILD_PARALLEL_LEVEL=$JOBS
73
74step() { printf '\n=== %s ===\n' "$*"; }
75
Marc Kupietz98804e52026-08-09 17:47:36 +020076# Root is needed only where the target is not writable
77NEED_ROOT=
78if ! [ -w "$PREFIX" ] && ! { [ ! -e "$PREFIX" ] && [ -w "$(dirname "$PREFIX")" ]; }; then
79 NEED_ROOT=1
Marc Kupietz11df7852026-08-09 14:59:09 +020080fi
81
Marc Kupietz98804e52026-08-09 17:47:36 +020082# Runs a command as root. Prefer sudo, fall back to su, which prompts for the
83# root password - a server may well have only that.
84root() {
85 if [ -z "$NEED_ROOT" ] || [ "$(id -u)" = 0 ]; then
86 "$@"
87 elif command -v sudo > /dev/null; then
88 sudo "$@" || su -c "$*"
89 elif command -v su > /dev/null; then
90 su -c "$*"
91 else
92 echo "Installing to $PREFIX needs root, but there is neither sudo nor su." >&2
93 echo "Use --prefix with a directory you can write to." >&2
94 return 1
95 fi
96}
97
Marc Kupietz11df7852026-08-09 14:59:09 +020098# The rocksdb and the compression libraries of homebrew are below
99# /opt/homebrew on Apple Silicon, which is not searched by default
100BREW_PREFIX=
101if command -v brew > /dev/null; then
102 BREW_PREFIX=$(brew --prefix)
103fi
104
105# --- 1. the packages of the distribution -------------------------------------
106if [ $SKIP_DEPS = 0 ]; then
107 step "Installing the packages of the distribution"
108 if command -v dnf > /dev/null; then
Marc Kupietz98804e52026-08-09 17:47:36 +0200109 root dnf install -y cmake gcc-c++ git make pkgconf-pkg-config \
Marc Kupietz11df7852026-08-09 14:59:09 +0200110 snappy-devel zlib-devel bzip2-devel lz4-devel libzstd-devel
111 # Rocky Linux and RHEL have no rocksdb-devel everywhere, that is what
112 # step 2 is for
Marc Kupietz98804e52026-08-09 17:47:36 +0200113 root dnf install -y rocksdb-devel || true
Marc Kupietz11df7852026-08-09 14:59:09 +0200114 elif command -v apt-get > /dev/null; then
Marc Kupietz98804e52026-08-09 17:47:36 +0200115 root apt-get update
116 root apt-get install -y cmake g++ git make pkg-config \
Marc Kupietz11df7852026-08-09 14:59:09 +0200117 librocksdb-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev
118 elif command -v brew > /dev/null; then
119 brew install cmake rocksdb snappy zlib bzip2 lz4 zstd
120 else
121 echo "No dnf, apt-get or brew - install cmake, a C++ compiler, git, rocksdb" >&2
122 echo "and the devel packages of snappy, zlib, bzip2, lz4 and zstd by hand." >&2
123 fi
124fi
125
126# --- 2. rocksdb --------------------------------------------------------------
127static_rocksdb_of_the_distribution() {
128 local f
129 for f in /usr/lib64/librocksdb.a /usr/lib/librocksdb.a /usr/lib/*/librocksdb.a; do
130 [ -e "$f" ] && return 0
131 done
132 if command -v brew > /dev/null && brew list --versions rocksdb > /dev/null 2>&1; then
133 [ -e "$(brew --prefix rocksdb)/lib/librocksdb.a" ] && return 0
134 fi
135 return 1
136}
137
138DISTRO_ROCKSDB=
139if { command -v rpm > /dev/null && rpm -q rocksdb > /dev/null 2>&1; } ||
140 { command -v dpkg-query > /dev/null && dpkg-query -W librocksdb-dev > /dev/null 2>&1; } ||
141 { command -v brew > /dev/null && brew list --versions rocksdb > /dev/null 2>&1; }; then
142 DISTRO_ROCKSDB=1
143fi
144
145ROCKSDB_PREFIX_USED=
146ROCKSDB_SHARED_BUILT=0
147if [ -n "$DISTRO_ROCKSDB" ] && [ -z "$ROCKSDB_VERSION" ]; then
148 if [ $STATIC = 1 ] && ! static_rocksdb_of_the_distribution; then
149 step "rocksdb: building the static library, same version as the distribution"
150 "$DEREKO2VEC_SRC/scripts/build-rocksdb.sh" --static-only -p "$ROCKSDB_PREFIX"
151 ROCKSDB_PREFIX_USED=$ROCKSDB_PREFIX
152 else
153 step "rocksdb: the one of the distribution is used"
154 fi
155else
156 if [ -z "$DISTRO_ROCKSDB" ]; then
157 step "rocksdb: no rocksdb package - building the shared and the static library"
158 else
159 step "rocksdb: building version $ROCKSDB_VERSION as asked"
160 fi
161 "$DEREKO2VEC_SRC/scripts/build-rocksdb.sh" -p "$ROCKSDB_PREFIX" ${ROCKSDB_VERSION:+-v "$ROCKSDB_VERSION"}
162 ROCKSDB_PREFIX_USED=$ROCKSDB_PREFIX
163 ROCKSDB_SHARED_BUILT=1
164fi
165
166# Programs that link the shared rocksdb of the prefix have to find it. Only a
167# system-wide install can register the directory; for one below $HOME the
168# programs carry the rpath of the libraries they were linked against.
Marc Kupietz98804e52026-08-09 17:47:36 +0200169if [ $BUILD_ONLY = 0 ] && [ $ROCKSDB_SHARED_BUILT = 1 ] && [ "$(uname)" = Linux ] && [ -n "$NEED_ROOT" ]; then
Marc Kupietz11df7852026-08-09 14:59:09 +0200170 RDB_LIBDIR=$(dirname "$(find "$ROCKSDB_PREFIX_USED" -name 'librocksdb.so' | head -1)")
Marc Kupietz98804e52026-08-09 17:47:36 +0200171 echo "$RDB_LIBDIR" | root tee /etc/ld.so.conf.d/rocksdb-prefix.conf > /dev/null
172 root ldconfig
Marc Kupietz11df7852026-08-09 14:59:09 +0200173fi
174
175# --- 3. collocatordb ---------------------------------------------------------
176step "collocatordb"
177WORK=$(mktemp -d)
178trap 'rc=$?; if [ $rc = 0 ]; then rm -rf "$WORK"; else echo "Keeping $WORK for a look at what went wrong" >&2; fi' EXIT
179git clone "https://korap.ids-mannheim.de/gerrit/ids-kl/collocatordb" "$WORK/collocatordb"
180CDB_PREFIXES=$ROCKSDB_PREFIX_USED
181if [ -n "$BREW_PREFIX" ]; then
182 CDB_PREFIXES=${CDB_PREFIXES:+$CDB_PREFIXES;}$BREW_PREFIX
183fi
184cmake -S "$WORK/collocatordb" -B "$WORK/collocatordb/build" \
185 -DCMAKE_INSTALL_PREFIX="$PREFIX" \
186 ${CDB_PREFIXES:+-DCMAKE_PREFIX_PATH=$CDB_PREFIXES}
187cmake --build "$WORK/collocatordb/build" -j "$JOBS"
Marc Kupietz98804e52026-08-09 17:47:36 +0200188CDB_STAGE=
189if [ $BUILD_ONLY = 1 ]; then
190 # install into a staging prefix only, where the dereko2vec build below
191 # finds the static library and the header
192 CDB_STAGE=$WORK/stage
193 cmake --install "$WORK/collocatordb/build" --prefix "$CDB_STAGE"
194else
195 root cmake --install "$WORK/collocatordb/build"
196 if [ "$(uname)" = Linux ] && [ -n "$NEED_ROOT" ]; then
197 root ldconfig
198 fi
Marc Kupietz11df7852026-08-09 14:59:09 +0200199fi
200if [ $SKIP_TESTS = 0 ]; then
201 ctest --test-dir "$WORK/collocatordb/build" --output-on-failure
202fi
203
204# --- 4. dereko2vec -----------------------------------------------------------
205step "dereko2vec"
206# A stale build directory would silently keep the collocatordb and rocksdb it
207# was once configured with, and an install manifest of a root install breaks a
208# later install without sudo. Start over, the build takes a minute.
209rm -rf "$DEREKO2VEC_SRC/build"
210CMAKE_PREFIXES=$PREFIX
Marc Kupietz98804e52026-08-09 17:47:36 +0200211if [ -n "$CDB_STAGE" ]; then
212 CMAKE_PREFIXES="$CDB_STAGE;$CMAKE_PREFIXES"
213fi
Marc Kupietz11df7852026-08-09 14:59:09 +0200214if [ -n "$ROCKSDB_PREFIX_USED" ]; then
215 CMAKE_PREFIXES="$CMAKE_PREFIXES;$ROCKSDB_PREFIX_USED"
216fi
217if [ -n "$BREW_PREFIX" ]; then
218 CMAKE_PREFIXES="$CMAKE_PREFIXES;$BREW_PREFIX"
219fi
220STATIC_FLAG=
221if [ $STATIC_BINARY = 1 ]; then
222 STATIC_FLAG=-DSTATIC_DEREKO2VEC=ON
223elif [ $STATIC = 1 ]; then
224 STATIC_FLAG=-DSTATIC_ROCKSDB=ON
225fi
226cmake -S "$DEREKO2VEC_SRC" -B "$DEREKO2VEC_SRC/build" \
227 -DCMAKE_INSTALL_PREFIX="$PREFIX" \
228 -DCMAKE_PREFIX_PATH="$CMAKE_PREFIXES" \
229 $STATIC_FLAG
230cmake --build "$DEREKO2VEC_SRC/build" -j "$JOBS"
231if [ $SKIP_TESTS = 0 ]; then
232 ctest --test-dir "$DEREKO2VEC_SRC/build" --output-on-failure
233fi
Marc Kupietz98804e52026-08-09 17:47:36 +0200234if [ $BUILD_ONLY = 0 ]; then
235 root cmake --install "$DEREKO2VEC_SRC/build"
236fi
Marc Kupietz11df7852026-08-09 14:59:09 +0200237
238step "Done"
Marc Kupietz98804e52026-08-09 17:47:36 +0200239if [ $BUILD_ONLY = 1 ]; then
240 echo "dereko2vec and vecs2mmap are in $DEREKO2VEC_SRC/build"
241 echo "Nothing was installed. Install them with:"
242 echo " sudo cmake --install \"$DEREKO2VEC_SRC/build\""
243 if [ $STATIC = 0 ] && [ $ROCKSDB_SHARED_BUILT = 1 ]; then
244 RDB_LIBDIR=$(dirname "$(find "$ROCKSDB_PREFIX_USED" -name 'librocksdb.so' | head -1)")
245 echo "With --shared the programs need the rocksdb library at runtime, e.g."
246 echo " LD_LIBRARY_PATH=$RDB_LIBDIR $DEREKO2VEC_SRC/build/dereko2vec"
247 fi
248else
249 echo "dereko2vec and vecs2mmap are in $PREFIX/bin"
250fi