| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 1 | #!/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 Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 22 | # --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 Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 25 | # --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 | # |
| 30 | set -euo pipefail |
| 31 | |
| 32 | DEREKO2VEC_SRC=$(cd "$(dirname "$0")/.." && pwd) |
| 33 | PREFIX=/usr/local |
| 34 | ROCKSDB_PREFIX=$HOME/rocksdb |
| 35 | ROCKSDB_VERSION= |
| 36 | STATIC=1 |
| 37 | STATIC_BINARY=0 |
| 38 | SKIP_DEPS=0 |
| 39 | SKIP_TESTS=0 |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 40 | BUILD_ONLY=0 |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 41 | JOBS= |
| 42 | |
| 43 | usage() { |
| 44 | sed -n '2,26p' "$0" |
| 45 | exit "${1:-0}" |
| 46 | } |
| 47 | |
| 48 | while [ $# -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 Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 57 | --build-only) BUILD_ONLY=1; shift ;; |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 58 | -j) JOBS=$2; shift 2 ;; |
| 59 | -h|--help) usage 0 ;; |
| 60 | *) echo "Unknown option: $1" >&2; usage 1 ;; |
| 61 | esac |
| 62 | done |
| 63 | |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 64 | # Nothing is installed, so nothing of the distribution is needed either |
| 65 | if [ $BUILD_ONLY = 1 ]; then |
| 66 | SKIP_DEPS=1 |
| 67 | fi |
| 68 | |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 69 | if [ -z "$JOBS" ]; then |
| 70 | JOBS=$(getconf _NPROCESSORS_ONLN 2> /dev/null || sysctl -n hw.ncpu) |
| 71 | fi |
| 72 | export CMAKE_BUILD_PARALLEL_LEVEL=$JOBS |
| 73 | |
| 74 | step() { printf '\n=== %s ===\n' "$*"; } |
| 75 | |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 76 | # Root is needed only where the target is not writable |
| 77 | NEED_ROOT= |
| 78 | if ! [ -w "$PREFIX" ] && ! { [ ! -e "$PREFIX" ] && [ -w "$(dirname "$PREFIX")" ]; }; then |
| 79 | NEED_ROOT=1 |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 80 | fi |
| 81 | |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 82 | # 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. |
| 84 | root() { |
| 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 Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 98 | # The rocksdb and the compression libraries of homebrew are below |
| 99 | # /opt/homebrew on Apple Silicon, which is not searched by default |
| 100 | BREW_PREFIX= |
| 101 | if command -v brew > /dev/null; then |
| 102 | BREW_PREFIX=$(brew --prefix) |
| 103 | fi |
| 104 | |
| 105 | # --- 1. the packages of the distribution ------------------------------------- |
| 106 | if [ $SKIP_DEPS = 0 ]; then |
| 107 | step "Installing the packages of the distribution" |
| 108 | if command -v dnf > /dev/null; then |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 109 | root dnf install -y cmake gcc-c++ git make pkgconf-pkg-config \ |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 110 | 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 Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 113 | root dnf install -y rocksdb-devel || true |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 114 | elif command -v apt-get > /dev/null; then |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 115 | root apt-get update |
| 116 | root apt-get install -y cmake g++ git make pkg-config \ |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 117 | 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 |
| 124 | fi |
| 125 | |
| 126 | # --- 2. rocksdb -------------------------------------------------------------- |
| 127 | static_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 | |
| 138 | DISTRO_ROCKSDB= |
| 139 | if { 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 |
| 143 | fi |
| 144 | |
| 145 | ROCKSDB_PREFIX_USED= |
| 146 | ROCKSDB_SHARED_BUILT=0 |
| 147 | if [ -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 |
| 155 | else |
| 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 |
| 164 | fi |
| 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 Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 169 | if [ $BUILD_ONLY = 0 ] && [ $ROCKSDB_SHARED_BUILT = 1 ] && [ "$(uname)" = Linux ] && [ -n "$NEED_ROOT" ]; then |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 170 | RDB_LIBDIR=$(dirname "$(find "$ROCKSDB_PREFIX_USED" -name 'librocksdb.so' | head -1)") |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 171 | echo "$RDB_LIBDIR" | root tee /etc/ld.so.conf.d/rocksdb-prefix.conf > /dev/null |
| 172 | root ldconfig |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 173 | fi |
| 174 | |
| 175 | # --- 3. collocatordb --------------------------------------------------------- |
| 176 | step "collocatordb" |
| 177 | WORK=$(mktemp -d) |
| 178 | trap 'rc=$?; if [ $rc = 0 ]; then rm -rf "$WORK"; else echo "Keeping $WORK for a look at what went wrong" >&2; fi' EXIT |
| 179 | git clone "https://korap.ids-mannheim.de/gerrit/ids-kl/collocatordb" "$WORK/collocatordb" |
| 180 | CDB_PREFIXES=$ROCKSDB_PREFIX_USED |
| 181 | if [ -n "$BREW_PREFIX" ]; then |
| 182 | CDB_PREFIXES=${CDB_PREFIXES:+$CDB_PREFIXES;}$BREW_PREFIX |
| 183 | fi |
| 184 | cmake -S "$WORK/collocatordb" -B "$WORK/collocatordb/build" \ |
| 185 | -DCMAKE_INSTALL_PREFIX="$PREFIX" \ |
| 186 | ${CDB_PREFIXES:+-DCMAKE_PREFIX_PATH=$CDB_PREFIXES} |
| 187 | cmake --build "$WORK/collocatordb/build" -j "$JOBS" |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 188 | CDB_STAGE= |
| 189 | if [ $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" |
| 194 | else |
| 195 | root cmake --install "$WORK/collocatordb/build" |
| 196 | if [ "$(uname)" = Linux ] && [ -n "$NEED_ROOT" ]; then |
| 197 | root ldconfig |
| 198 | fi |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 199 | fi |
| 200 | if [ $SKIP_TESTS = 0 ]; then |
| Marc Kupietz | 9052f85 | 2026-08-09 19:46:19 +0200 | [diff] [blame^] | 201 | if [ -n "$CDB_STAGE" ]; then |
| 202 | # staged, not installed, and no ldconfig - the test binaries find the |
| 203 | # shared collocatordb in the build directory |
| 204 | env LD_LIBRARY_PATH="$WORK/collocatordb/build${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \ |
| 205 | DYLD_LIBRARY_PATH="$WORK/collocatordb/build${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}" \ |
| 206 | ctest --test-dir "$WORK/collocatordb/build" --output-on-failure |
| 207 | else |
| 208 | ctest --test-dir "$WORK/collocatordb/build" --output-on-failure |
| 209 | fi |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 210 | fi |
| 211 | |
| 212 | # --- 4. dereko2vec ----------------------------------------------------------- |
| 213 | step "dereko2vec" |
| 214 | # A stale build directory would silently keep the collocatordb and rocksdb it |
| 215 | # was once configured with, and an install manifest of a root install breaks a |
| 216 | # later install without sudo. Start over, the build takes a minute. |
| 217 | rm -rf "$DEREKO2VEC_SRC/build" |
| 218 | CMAKE_PREFIXES=$PREFIX |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 219 | if [ -n "$CDB_STAGE" ]; then |
| 220 | CMAKE_PREFIXES="$CDB_STAGE;$CMAKE_PREFIXES" |
| 221 | fi |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 222 | if [ -n "$ROCKSDB_PREFIX_USED" ]; then |
| 223 | CMAKE_PREFIXES="$CMAKE_PREFIXES;$ROCKSDB_PREFIX_USED" |
| 224 | fi |
| 225 | if [ -n "$BREW_PREFIX" ]; then |
| 226 | CMAKE_PREFIXES="$CMAKE_PREFIXES;$BREW_PREFIX" |
| 227 | fi |
| 228 | STATIC_FLAG= |
| 229 | if [ $STATIC_BINARY = 1 ]; then |
| 230 | STATIC_FLAG=-DSTATIC_DEREKO2VEC=ON |
| 231 | elif [ $STATIC = 1 ]; then |
| 232 | STATIC_FLAG=-DSTATIC_ROCKSDB=ON |
| 233 | fi |
| 234 | cmake -S "$DEREKO2VEC_SRC" -B "$DEREKO2VEC_SRC/build" \ |
| 235 | -DCMAKE_INSTALL_PREFIX="$PREFIX" \ |
| 236 | -DCMAKE_PREFIX_PATH="$CMAKE_PREFIXES" \ |
| 237 | $STATIC_FLAG |
| 238 | cmake --build "$DEREKO2VEC_SRC/build" -j "$JOBS" |
| 239 | if [ $SKIP_TESTS = 0 ]; then |
| 240 | ctest --test-dir "$DEREKO2VEC_SRC/build" --output-on-failure |
| 241 | fi |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 242 | if [ $BUILD_ONLY = 0 ]; then |
| 243 | root cmake --install "$DEREKO2VEC_SRC/build" |
| 244 | fi |
| Marc Kupietz | 11df785 | 2026-08-09 14:59:09 +0200 | [diff] [blame] | 245 | |
| 246 | step "Done" |
| Marc Kupietz | 98804e5 | 2026-08-09 17:47:36 +0200 | [diff] [blame] | 247 | if [ $BUILD_ONLY = 1 ]; then |
| 248 | echo "dereko2vec and vecs2mmap are in $DEREKO2VEC_SRC/build" |
| 249 | echo "Nothing was installed. Install them with:" |
| 250 | echo " sudo cmake --install \"$DEREKO2VEC_SRC/build\"" |
| 251 | if [ $STATIC = 0 ] && [ $ROCKSDB_SHARED_BUILT = 1 ]; then |
| 252 | RDB_LIBDIR=$(dirname "$(find "$ROCKSDB_PREFIX_USED" -name 'librocksdb.so' | head -1)") |
| 253 | echo "With --shared the programs need the rocksdb library at runtime, e.g." |
| 254 | echo " LD_LIBRARY_PATH=$RDB_LIBDIR $DEREKO2VEC_SRC/build/dereko2vec" |
| 255 | fi |
| 256 | else |
| 257 | echo "dereko2vec and vecs2mmap are in $PREFIX/bin" |
| 258 | fi |