postjevsql.git / tools / configure.sh
1#!/usr/bin/env bash
2# Write .buckconfig.local: the paths buck2 needs and cannot find itself, because the prelude's C shim
3# execs its tools by absolute path and never searches PATH.
4#
5#     tools/configure.sh
6#
7# It reads the tools from PATH (`clang`, `ar`, `python3`, `rustc`) and each Postgres major's install
8# prefix from POSTJEVSQL_PG_<major> (for example POSTJEVSQL_PG_17=/usr/lib/postgresql/17: a directory
9# holding bin/postgres, bin/initdb and bin/pg_config). `mise run configure` sets them. Override any
10# tool with CLANG, CLANGXX, AR, PYTHON; the majors are PG_MAJORS in build/defs.bzl. The file is
11# rewritten only when its content changes, and by rename: buck2 logs any write as a changed file and
12# would read a half-written one as a changed config.
13set -euo pipefail
14cd "$(dirname "$0")/.."
15
16need() { command -v "$1" >/dev/null 2>&1 || { echo "configure: $1 is not on PATH (mise run configure, or mise install)" >&2; exit 1; }; }
17abs() { realpath "$(command -v "$1")"; }
18cc="${CLANG:-$(command -v clang || true)}"
19bindir="$([ -z "$cc" ] || dirname "$cc")"
20# mise exposes a conda tool through small wrapper scripts in <prefix>/.mise-bins; the programs are in <prefix>/bin.
21case "$bindir" in */.mise-bins) bindir="$(dirname "$bindir")/bin" ;; esac
22# conda-forge's clang ships the C++ driver only under its versioned name (clang++-23), which is still the C++
23# driver, and its own `ar` beside it; mise exposes just `clang` on PATH, so look in the real directory.
24cxx="${CLANGXX:-}"
25if [ -z "$cxx" ] && [ -n "$bindir" ]; then
26  cxx="$(ls "$bindir"/clang++ "$bindir"/clang++-[0-9]* 2>/dev/null | head -1 || true)"
27fi
28[ -n "$cxx" ] || cxx="$(command -v clang++ || true)"
29ar="${AR:-}"
30if [ -z "$ar" ] && [ -n "$bindir" ] && [ -x "$bindir/ar" ]; then ar="$bindir/ar"; fi
31[ -n "$ar" ] || ar="$(command -v ar || true)"
32python="${PYTHON:-$(command -v python3 || true)}"
33for pair in "clang:$cc" "clang++:$cxx" "ar:$ar" "python3:$python"; do
34  [ -n "${pair#*:}" ] || { echo "configure: no ${pair%%:*} found (set ${pair%%:*} on PATH, or see the override variables in this script's header)" >&2; exit 1; }
35done
36need rustc
37
38# The compiler's identity keys buck's cache by compiler (toolchains/BUCK): release and commit.
39identity="rustc-$(rustc -vV | sed -n 's/^release: //p')-$(rustc -vV | sed -n 's/^commit-hash: //p' | cut -c1-12)"
40
41majors=$(sed -n 's/^PG_MAJORS = \[\(.*\)\].*/\1/p' build/defs.bzl | tr -d '" ' | tr ',' ' ')
42[ -n "$majors" ] || { echo "configure: build/defs.bzl has no PG_MAJORS list" >&2; exit 1; }
43per_major=""
44newest=""
45for m in $majors; do
46  var="POSTJEVSQL_PG_$m"
47  prefix="${!var:-}"
48  [ -n "$prefix" ] && [ -x "$prefix/bin/postgres" ] && [ -x "$prefix/bin/pg_config" ] || {
49    echo "configure: $var must name a PostgreSQL $m install (a directory with bin/postgres and bin/pg_config)" >&2; exit 1; }
50  per_major="$per_major
51postgres_bin_$m = $prefix/bin
52pg_config_$m = $prefix/bin/pg_config"
53  newest="$prefix/bin"
54done
55
56tmp=".buckconfig.local.tmp"
57cat > "$tmp" <<CFG
58[toolchain]
59cc = $cc
60cxx = $cxx
61ar = $ar
62python = $python
63[rust]
64rustc_identity = $identity
65[postjevsql]
66postgres_bin = $newest$per_major
67CFG
68if cmp -s "$tmp" .buckconfig.local 2>/dev/null; then rm "$tmp"; else mv "$tmp" .buckconfig.local; fi