Last active
March 16, 2025 14:05
-
-
Save aleph-ra/cbed5ae5ce45b5155da884171452fb46 to your computer and use it in GitHub Desktop.
AdaptiveCpp installation script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Stop command echoing | |
set +x | |
# Propogate errors and fail on error | |
set -euo pipefail | |
# Default log level: INFO | |
QUIET_MODE=false | |
# Debug mode off | |
DEBUG_MODE=false | |
# Logging function | |
log() { | |
local level="$1" | |
local message="$2" | |
local timestamp | |
timestamp=$(date +"%Y-%m-%d %H:%M:%S") | |
case "$level" in | |
INFO) | |
[[ $QUIET_MODE == false ]] && echo -e "\033[1;34m[$timestamp] [INFO]\033[0m $message" | |
;; | |
WARN) | |
echo -e "\033[1;33m[$timestamp] [WARN]\033[0m $message" >&2 | |
;; | |
ERROR) | |
echo -e "\033[1;31m[$timestamp] [ERROR]\033[0m $message" >&2 | |
;; | |
*) | |
echo -e "\033[1;36m[$timestamp] [UNKNOWN]\033[0m $message" >&2 | |
;; | |
esac | |
} | |
# Function to check if running inside Docker or Podman or other containerized envs | |
is_in_container() { | |
[[ -f /.dockerenv ]] && return 0 | |
grep -qE '(docker|podman)' /proc/self/cgroup 2>/dev/null && return 0 | |
grep -q 'containerd' /proc/self/cgroup 2>/dev/null && return 0 | |
[[ -f /run/.containerenv ]] && return 0 | |
return 1 | |
} | |
# Function to check for sudo privileges | |
check_sudo() { | |
if ! is_in_container && ! sudo -n true 2>/dev/null; then | |
log WARN "This script requires sudo privileges. Please enter your password." | |
sudo -v || { log ERROR "Failed to acquire sudo privileges. Exiting."; exit 1; } | |
fi | |
} | |
# Function to check if a command exists | |
command_exists() { | |
command -v "$1" &>/dev/null | |
} | |
# Function to install missing dependencies | |
install_dependencies() { | |
local dependencies=("git" "software-properties-common" "cmake" "make" "wget") | |
local missing=() | |
for dep in "${dependencies[@]}"; do | |
if ! command_exists "$dep"; then | |
missing+=("$dep") | |
fi | |
done | |
if (( ${#missing[@]} > 0 )); then | |
log INFO "Installing missing dependencies: ${missing[*]}" | |
$SUDO apt update -y | |
export DEBIAN_FRONTEND=noninteractive # avoid fresh OS timezone setting | |
$SUDO apt install -y "${missing[@]}" | |
else | |
log INFO "All dependencies are already installed." | |
fi | |
} | |
# Function to check LLVM/Clang version | |
check_llvm_clang_version() { | |
local llvm_version=$(llvm-config-$1 --version 2>/dev/null | cut -d. -f1 || echo "0") | |
local clang_version=$(clang++-$1 --version 2>/dev/null | awk '/version/ {print $4}' | cut -d. -f1 || echo "0") | |
[[ "$llvm_version" -ne "0" && "$clang_version" -ne "0" ]] | |
} | |
# Function to return LLVM/Clang version found in a specified range | |
check_llvm_clang_versions_in_range() { | |
local min_version=$1 | |
local max_version=$2 | |
local found_version=0 | |
for (( version=min_version; version<=max_version; version++ )); do | |
if check_llvm_clang_version $version; then | |
found_version=$version | |
fi | |
done | |
echo $found_version | |
} | |
#### AdaptiveCpp Install Script #### | |
ADAPTIVE_CPP_URL="https://github.com/AdaptiveCpp/AdaptiveCpp" | |
DEFAULT_INSTALL_PREFIX="/usr/local" | |
DEFAULT_KEEP_SOURCE_FILES=false | |
MINIMUM_LLVM_VERSION=14 | |
INSTALL_PREFIX="$DEFAULT_INSTALL_PREFIX" | |
LLVM_VERSION="" | |
KEEP_SOURCE_FILES=$DEFAULT_KEEP_SOURCE_FILES | |
# Parse arguments | |
while [[ "$#" -gt 0 ]]; do | |
case $1 in | |
--acpp-install-prefix) INSTALL_PREFIX="$2"; shift ;; | |
--llvm-version) LLVM_VERSION="$2"; shift ;; | |
--keep-source-files) KEEP_SOURCE_FILES=true ;; | |
--quiet) QUIET_MODE=true ;; | |
--debug) DEBUG_MODE=true ;; | |
*) log ERROR "Unknown parameter: $1"; exit 1 ;; | |
esac | |
shift | |
done | |
# Enable debugging if requested | |
if [[ $DEBUG_MODE == true ]]; then | |
log INFO "Debug mode enabled." | |
set -x | |
fi | |
SUDO=$(is_in_container && echo "" || echo "sudo") | |
log INFO "Installing AdaptiveCPP to $INSTALL_PREFIX..." | |
# Ensure sudo privileges if not in Docker | |
check_sudo | |
# Install dependencies | |
install_dependencies | |
# Check for LLVM/Clang versions | |
if [[ $LLVM_VERSION ]]; then | |
if check_llvm_clang_version $LLVM_VERSION; then | |
FOUND_LLVM_VERSION=$LLVM_VERSION | |
else | |
FOUND_LLVM_VERSION=0 | |
fi | |
else | |
# Get the latest stable version from apt.llvm.org | |
LLVM_VERSION=$(wget -q -O - https://apt.llvm.org/llvm.sh | grep -oP '(?<=CURRENT_LLVM_STABLE=)[0-9]+') | |
FOUND_LLVM_VERSION=$(check_llvm_clang_versions_in_range $MINIMUM_LLVM_VERSION $LLVM_VERSION) | |
fi | |
# Install LLVM/Clang if needed | |
if [ $FOUND_LLVM_VERSION -eq 0 ]; then | |
log INFO "Downloading and installing LLVM/Clang..." | |
wget -q https://apt.llvm.org/llvm.sh || { log ERROR "Failed to download LLVM setup script."; exit 1; } | |
chmod +x llvm.sh | |
log INFO "Installing LLVM/Clang version $LLVM_VERSION..." | |
$SUDO ./llvm.sh "$LLVM_VERSION" | |
# Revert command echoing if not in debug mode | |
if [[ $DEBUG_MODE == false ]]; then | |
set +x | |
fi | |
# Cleanup | |
rm -f llvm.sh | |
else | |
LLVM_VERSION=$FOUND_LLVM_VERSION | |
log INFO "Found LLVM/Clang version $FOUND_LLVM_VERSION. Skipping LLVM/Clang installation." | |
fi | |
# Ensure installation of required llvm-clang packages | |
$SUDO apt install -y \ | |
"libclang-${LLVM_VERSION}-dev" "clang-tools-${LLVM_VERSION}" \ | |
"libomp-${LLVM_VERSION}-dev" "llvm-${LLVM_VERSION}-dev" "lld-${LLVM_VERSION}" | |
# Get LLVM/Clang paths | |
LLVM_DIR=$(llvm-config-${LLVM_VERSION} --cmakedir) | |
log INFO "LLVM cmake path is $LLVM_DIR" | |
CLANG_EXECUTABLE_PATH=$(which clang++-${LLVM_VERSION}) | |
log INFO "Clang++ executable path is $LLVM_DIR" | |
# Install libstdc++ for Clang | |
GCC_VERSION=$(clang++-${LLVM_VERSION} -v 2>&1 | awk -F/ '/Selected GCC/ {print $NF}') | |
log INFO "Installing libstdc++ version $GCC_VERSION..." | |
$SUDO apt install -y "libstdc++-${GCC_VERSION}-dev" | |
# Install Boost libraries for acpp | |
log INFO "Installing boost dependencies..." | |
$SUDO apt install -y libboost-fiber-dev libboost-context-dev libboost-test-dev | |
# Clone and build AdaptiveCpp | |
if [[ ! -d "AdaptiveCpp" ]]; then | |
log INFO "Cloning AdaptiveCpp repository..." | |
git clone "$ADAPTIVE_CPP_URL" | |
fi | |
cd AdaptiveCpp | |
rm -rf build && mkdir -p build && cd build | |
log INFO "Configuring build with CMake..." | |
CXX=$CLANG_EXECUTABLE_PATH cmake -DCMAKE_INSTALL_PREFIX="$INSTALL_PREFIX" -DLLVM_DIR="$LLVM_DIR" -DCLANG_EXECUTABLE_PATH="$CLANG_EXECUTABLE_PATH" .. | |
log INFO "Building and installing AdaptiveCpp..." | |
$SUDO make install | |
# Back to main pwd | |
cd ../.. | |
# Clean up source files if not required | |
if [[ $KEEP_SOURCE_FILES == false ]]; then | |
log INFO "Removing source files as --keep-source-files is not set." | |
rm -rf AdaptiveCpp | |
fi | |
# Verify AdaptiveCpp installation | |
if ACPP_VERSION=$(acpp --acpp-version | grep 'AdaptiveCpp version:' | awk '{print $3}'); then | |
log INFO "\033[1;32mAdaptiveCpp version $ACPP_VERSION has been installed to $INSTALL_PREFIX.\033[0m" | |
else | |
log ERROR "Failed to verify AdaptiveCpp installation." | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The script can be used directly for installations as follows:
curl -L https://gist.githubusercontent.com/aleph-ra/cbed5ae5ce45b5155da884171452fb46/raw/772ed488a66f051400db59e2d760ab3e8abb95e2/install_acpp.sh | bash
Or by downloading it and running with available flags as follows:
chmod +x install_acpp.sh
./install_acpp.sh --install-prefix /opt/adaptivecpp --llvm-version 16