1#!/usr/bin/env bash
 2#
 3# This script installs an up-to-date version of CMake.
 4#
 5# For MacOS use Homebrew to install the latest version.
 6#
 7# For Ubuntu use the official KitWare Apt repository with backports.
 8# See: https://apt.kitware.com/
 9#
10# For other systems (RHEL 8.x, 9.x, AmazonLinux, SUSE, Fedora, Arch, etc)
11# use the official CMake installer script from KitWare.
12#
13# Note this is similar to how GitHub Actions runners install cmake:
14# https://github.com/actions/runner-images/blob/main/images/ubuntu/scripts/build/install-cmake.sh
15#
16# Upstream:  3.30.4 (2024-09-27)
17
18set -euo pipefail
19
20
21if [[ "$(uname -s)" == "darwin" ]]; then
22  brew --version >/dev/null \
23    || echo "Error: Homebrew is required to install cmake on MacOS." && exit 1
24  echo "Installing cmake via Homebrew (can't pin to old versions)."
25  brew install cmake
26  exit 0
27elif [ "$(uname -s)" != "Linux" ]; then
28  echo "Error: This script is intended for MacOS/Linux systems only."
29  exit 1
30elif [ -z "${1:-}" ]; then
31  echo "Usage: $0 [3.30.4]"
32  exit 1
33fi
34CMAKE_VERSION="${CMAKE_VERSION:-${1:-3.30.4}}"
35
36if [ "$(whoami)" = root ]; then SUDO=; else SUDO="$(command -v sudo || command -v doas || true)"; fi
37
38if cmake --version 2>/dev/null | grep -q "$CMAKE_VERSION"; then
39  echo "CMake $CMAKE_VERSION is already installed."
40  exit 0
41elif [ -e /usr/local/bin/cmake ]; then
42  echo "Warning: existing cmake found at /usr/local/bin/cmake. Skipping installation."
43  exit 0
44elif [ -e /etc/apt/sources.list.d/kitware.list ]; then
45  echo "Warning: existing KitWare repository found. Skipping installation."
46  exit 0
47elif [ -e /etc/lsb-release ] && grep -qP 'DISTRIB_ID=Ubuntu' /etc/lsb-release; then
48  curl -fsSL https://apt.kitware.com/keys/kitware-archive-latest.asc \
49    | $SUDO gpg --dearmor - \
50    | $SUDO tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
51  echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" \
52    | $SUDO tee /etc/apt/sources.list.d/kitware.list >/dev/null
53  $SUDO apt-get update
54  $SUDO apt-get install -y kitware-archive-keyring cmake
55else
56  arch="$(uname -m)"
57  if [ "$arch" != "x86_64" ] && [ "$arch" != "aarch64" ]; then
58    echo "Error. Only x86_64 and aarch64 are supported."
59    exit 1
60  fi
61  tempdir=$(mktemp -d)
62  pushd "$tempdir"
63    CMAKE_REPO="https://github.com/Kitware/CMake"
64    CMAKE_INSTALLER="cmake-$CMAKE_VERSION-linux-$arch.sh"
65    curl -fsSL --output cmake-$CMAKE_VERSION-SHA-256.txt \
66      "$CMAKE_REPO/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-SHA-256.txt"
67    curl -fsSL --output $CMAKE_INSTALLER \
68      "$CMAKE_REPO/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-linux-$arch.sh"
69    # workaround for old versions of sha256sum not having --ignore-missing
70    grep -F "cmake-$CMAKE_VERSION-linux-$arch.sh" "cmake-$CMAKE_VERSION-SHA-256.txt" \
71      | sha256sum -c \
72      | grep -qP "^${CMAKE_INSTALLER}: OK"
73    chmod +x cmake-$CMAKE_VERSION-linux-$arch.sh
74    $SUDO ./cmake-$CMAKE_VERSION-linux-$arch.sh --prefix=/usr/local --skip-license
75  popd
76  rm -rf "$tempdir"
77fi