glove/setup.sh
2026-07-29 17:32:40 -04:00

146 lines
3.9 KiB
Bash
Executable file

#!/bin/sh
set -eu
script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)
cd "$script_dir"
usage() {
printf '%s\n' "usage: ./setup.sh [Debug|Release]" >&2
printf '%s\n' " GLOVE_INSTALL_PREFIX=/absolute/prefix ./setup.sh [Debug|Release]" >&2
}
build_type=${1:-Release}
if [ "$#" -gt 1 ]; then
usage
exit 2
fi
case "$build_type" in
Debug)
preset=dev
;;
Release)
preset=release
;;
-h|--help)
usage
exit 0
;;
*)
usage
exit 2
;;
esac
case "$(uname -s)" in
Darwin|Linux)
;;
*)
printf '%s\n' "setup.sh supports macOS and Linux only" >&2
exit 1
;;
esac
for command_name in cmake ninja; do
if ! command -v "$command_name" >/dev/null 2>&1; then
printf 'missing required command: %s\n' "$command_name" >&2
exit 1
fi
done
if [ -z "${CC:-}" ]; then
CC=clang
export CC
fi
if [ -z "${CXX:-}" ]; then
CXX=clang++
export CXX
fi
for compiler in "$CC" "$CXX"; do
if ! command -v "$compiler" >/dev/null 2>&1; then
printf 'missing required compiler: %s\n' "$compiler" >&2
exit 1
fi
done
probe_dir=$(mktemp -d "${TMPDIR:-/tmp}/glove-cxx-probe.XXXXXX")
trap 'rm -rf "$probe_dir"' 0 HUP INT TERM
probe_source=$probe_dir/required_features.cpp
probe_binary=$probe_dir/required_features
cat >"$probe_source" <<'EOF'
#include <expected>
int main() {
std::expected<int, int> value{1};
return *value - 1;
}
EOF
supports_required_cxx_features() {
# CXXFLAGS is an operator-owned compiler flag list and intentionally uses
# shell field splitting here, matching conventional build-tool behavior.
# shellcheck disable=SC2086
"$CXX" ${CXXFLAGS:-} "$@" -std=c++23 "$probe_source" -o "$probe_binary" \
>/dev/null 2>&1
}
if ! supports_required_cxx_features; then
case "$(uname -s):${CXXFLAGS:-}" in
Linux:*"-stdlib="*)
printf '%s\n' \
"selected C++ compiler/library lacks required C++23 features" >&2
exit 1
;;
Linux:*)
if supports_required_cxx_features -stdlib=libc++; then
CXXFLAGS="${CXXFLAGS:+${CXXFLAGS} }-stdlib=libc++"
export CXXFLAGS
printf '%s\n' \
"Default C++ library lacks required C++23 support; using libc++." \
"Set CXXFLAGS explicitly to select another compatible library."
else
printf '%s\n' \
"selected C++ compiler/library lacks required C++23 features" \
"Install a compatible standard library or set CC, CXX, and CXXFLAGS explicitly." \
>&2
exit 1
fi
;;
*)
printf '%s\n' \
"selected C++ compiler/library lacks required C++23 features" \
"Select a compatible compiler and standard library with CC, CXX, and CXXFLAGS." \
>&2
exit 1
;;
esac
fi
if [ -z "${GLOVE_INSTALL_PREFIX:-}" ] && [ -z "${HOME:-}" ]; then
printf '%s\n' "HOME or GLOVE_INSTALL_PREFIX is required" >&2
exit 1
fi
install_prefix=${GLOVE_INSTALL_PREFIX:-${HOME}/.local}
case "$install_prefix" in
/*)
;;
*)
printf '%s\n' "GLOVE_INSTALL_PREFIX must be an absolute path" >&2
exit 2
;;
esac
printf 'Configuring Glove (%s)...\n' "$build_type"
cmake --preset "$preset"
cmake --build --preset "$preset"
ctest --preset "$preset"
cmake --install "build/$preset" --prefix "$install_prefix"
printf '\nInstalled Glove to %s\n' "$install_prefix"
printf '%s\n' "Next:"
printf ' %s/bin/glove setup guide\n' "$install_prefix"
printf ' %s/bin/glove setup --dry-run\n' "$install_prefix"
printf ' %s/bin/glove setup --yes\n' "$install_prefix"
printf ' %s/bin/glove daemon start\n' "$install_prefix"
printf ' %s/bin/glove doctor\n' "$install_prefix"