#!/usr/bin/env bash # # check-tools.sh — verify the xrpld development tooling is present and runnable. # # Works on Linux, macOS, and Windows (Git Bash / MSYS). For every expected tool # it runs a version probe, collecting anything that is missing or fails to run, # and prints a summary at the end (exiting non-zero if anything is missing). # # The tool set is platform-aware: # - Linux: the full Nix CI environment (see nix/packages.nix, nix/ci-env.nix), # with GCC, Clang and the sanitizer/coverage tooling. This script is # run during the Nix Docker image build (nix/docker/Dockerfile), so # the Linux list is kept in sync with that environment. # - macOS: the same tooling, minus GCC/g++/gcov/mold # - Windows: the core build tools only (CMake, Conan, Git, Python). # MSVC is expected to be provided separately and is not checked here. # # Some tools (clang-format, clang-tidy, doxygen, gcovr, gh, git-cliff, gpg, # pre-commit, run-clang-tidy) are present in our Linux CI images and in local # development setups, but not in the macOS CI environment. They are checked # everywhere except when running in CI on macOS. # # Tools that Nix also exposes under a version-suffixed name (`clang-tidy-22`, # `g++-15`, ...) are probed under both names: a suffixed name can break while # the plain one still works (see mkVersionedToolLinks in nix/packages.nix). # # Environment variables: # CI if set, skip the tools above when on macOS. # CHECK_TOOLS_SKIP_CLONE if set, skip the git-over-HTTPS connectivity check. set -uo pipefail # Version suffixes of the Nix tool links, tracking nix/packages.nix. gcc_version=15 llvm_version=22 missing=() checked=0 # tool_path # Fully resolved path of a tool, so the snapshots record which derivation # provides it. Prints nothing when it isn't on PATH. tool_path() { local path path="$(command -v "$1" 2>/dev/null)" || return 0 readlink -f "${path}" 2>/dev/null || printf '%s' "${path}" } # check [probe-command...] # Runs the probe (default: " --version"), capturing both stdout and # stderr, and prints three lines: the status and name, the first non-blank line # of the probe output (its version, or the error when it failed), and the tool's # resolved path. Records as missing if it is not found or exits non-zero. check() { local name="$1" shift local -a probe=("$@") if [ "${#probe[@]}" -eq 0 ]; then probe=("${name}" --version) fi checked=$((checked + 1)) local output version path path="$(tool_path "${name}")" if output="$("${probe[@]}" 2>&1)"; then printf ' ✅ %s\n' "${name}" else printf ' ❌ %s\n' "${name}" missing+=("${name}") fi version="$(printf '%s\n' "${output}" | grep -m1 '[^[:space:]]' || true)" printf ' %s\n' "${version:-(no output)}" printf ' %s\n' "${path:-(not found)}" } case "$(uname -s)" in Linux*) os=linux ;; Darwin*) os=macos ;; MINGW* | MSYS* | CYGWIN*) os=windows ;; *) echo "Unknown OS: $(uname -s)" >&2 exit 1 ;; esac echo "Detected OS: ${os} ($(uname -s) $(uname -m))" echo echo "Core build tools:" check cmake check conan check git if [ "${os}" = "windows" ]; then check python python --version else check python3 fi # The full development toolchain. Available from Nix on Linux and macOS; on # Windows these are typically not installed, so they are skipped. if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then echo echo "Development tooling:" check ccache check clang check "clang-${llvm_version}" check clang++ check "clang++-${llvm_version}" check ClangBuildAnalyzer check curl check file check less check make # net-tools netstat reports "net-tools X.Y"; macOS ships BSD netstat with no # version flag, so fall back to a presence marker there. check netstat sh -c 'command -v netstat >/dev/null && { netstat --version 2>&1 | grep -m1 -oE "net-tools [0-9.]+" || echo present; }' check ninja check perl perl -e 'print "$^V\n"' check pkg-config check vim check zip bash -c 'zip --version 2>&1 | grep -m1 -oE "Zip [0-9.]+"' # These tools are present in our Linux CI images and in local development # setups, but not in the macOS CI environment. So check them everywhere # except when running in CI on macOS. if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then check clang-apply-replacements check "clang-apply-replacements-${llvm_version}" check clang-format check "clang-format-${llvm_version}" # clang-tidy leads --version with the LLVM banner, not the version. tidy_probe="--version | grep -m1 -oE 'LLVM version [0-9.]+'" check clang-tidy sh -c "clang-tidy ${tidy_probe}" check "clang-tidy-${llvm_version}" sh -c "clang-tidy-${llvm_version} ${tidy_probe}" check dot check doxygen check gcovr check gh check git-cliff check git-lfs check gpg # pre-commit, or its alternative implementation prek check pre-commit sh -c 'pre-commit --version || prek --version' check run-clang-tidy run-clang-tidy --help check "run-clang-tidy-${llvm_version}" "run-clang-tidy-${llvm_version}" --help fi fi # Rust toolchain. Part of the Nix commonPackages, so available on both Linux # and macOS. The cargo plugins are invoked through cargo (`cargo `), which # resolves the matching `cargo-` binary on PATH; `--version` is offline and # does not need a Cargo project. if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then echo echo "Rust toolchain:" check cargo check cargo-audit cargo audit --version check cargo-llvm-cov cargo llvm-cov --version check cargo-nextest cargo nextest --version check clippy-driver check rust-analyzer check rustc check rustfmt fi # GCC is the default compiler on Linux. macOS uses the system Apple Clang # instead, so GCC/g++/gcov are not expected there. if [ "${os}" = "linux" ]; then echo echo "GCC toolchain:" check gcc check "gcc-${gcc_version}" check g++ check "g++-${gcc_version}" check cpp check "cpp-${gcc_version}" check gcov echo echo "Mold:" check mold fi if [ "${os}" = "windows" ]; then echo echo "Note: on Windows the C++ compiler is MSVC, which is provided" echo " separately (e.g. via Visual Studio) and is not checked here." fi # A simple test to verify that git can clone a repository over HTTPS # (i.e. the CA bundle is wired up). Clone to a temp dir and clean up. if [ -n "${CHECK_TOOLS_SKIP_CLONE:-}" ]; then echo echo "Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set)." else echo echo "Connectivity check:" checked=$((checked + 1)) tmp_clone="$(mktemp -d)" if git clone --depth 1 https://github.com/XRPLF/actions.git "${tmp_clone}/actions" >/dev/null 2>&1; then printf ' ✅ git clone over HTTPS\n' else printf ' ❌ git clone over HTTPS\n' missing+=("git-https-clone") fi rm -rf "${tmp_clone}" fi echo if [ "${#missing[@]}" -eq 0 ]; then echo "✅ All ${checked} checked tools are present and runnable." else echo "❌ Missing or non-functional tools (${#missing[@]} of ${checked}):" >&2 for tool in "${missing[@]}"; do echo " - ${tool}" >&2 done exit 1 fi