build(install.sh): added auto installer
This commit is contained in:
@@ -1,10 +1,3 @@
|
||||
boost_dep = dependency('boost', version: '>=1.8.0')
|
||||
|
||||
if not boost_dep.found()
|
||||
message('❌ Boost library not found. Note that Boost is a system dependency and must be installed seperatly.')
|
||||
message('GridFire includes a Boost auto installation script, attempting to run it now (this will require some user input)...')
|
||||
run_res = run_command('./install.sh', check: true)
|
||||
boost_dep = dependency('boost', version: '>=1.8.0', required: true)
|
||||
endif
|
||||
boost_dep = dependency('boost', version: '>=1.8.0', required: true)
|
||||
|
||||
|
||||
|
||||
410
install.sh
Executable file
410
install.sh
Executable file
@@ -0,0 +1,410 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# install.sh - Comprehensive interactive installation script for GridFire
|
||||
#
|
||||
# This script performs the following actions:
|
||||
# 1. Checks for essential system dependencies:
|
||||
# - A C++ compiler (g++ or clang++)
|
||||
# - Python 3 development headers
|
||||
# - CMake
|
||||
# - Meson
|
||||
# - Boost libraries
|
||||
# 2. If run with the --tui flag, it provides a text-based user interface
|
||||
# to select and install missing dependencies.
|
||||
# 3. If run without flags, it prompts the user interactively for each missing dependency.
|
||||
# 4. Provides detailed installation instructions for various Linux distributions and macOS.
|
||||
# 5. Once all dependencies are met, it runs the meson setup and build commands.
|
||||
# 6. Logs all operations to a file for easy debugging.
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# --- Configuration ---
|
||||
LOGFILE="GridFire_Installer.log"
|
||||
BUILD_DIR="build"
|
||||
|
||||
# --- ANSI Color Codes ---
|
||||
RED="\033[0;31m"
|
||||
GREEN="\033[0;32m"
|
||||
YELLOW="\033[0;33m"
|
||||
BLUE="\033[0;34m"
|
||||
NC="\033[0m" # No Color
|
||||
|
||||
# --- Logging and Utility Functions ---
|
||||
|
||||
# Log a message to stdout and to the log file.
|
||||
log() {
|
||||
local message="$1"
|
||||
# Print the colored message to the terminal.
|
||||
echo -e "${message}"
|
||||
# Strip ANSI color codes and append to the log file.
|
||||
echo -e "${message}" | sed 's/\x1B\[[0-9;]*[mK]//g' >> "$LOGFILE"
|
||||
}
|
||||
|
||||
# Prompt the user for a yes/no answer.
|
||||
prompt_yes_no() {
|
||||
local prompt_msg="$1"
|
||||
local answer
|
||||
while true; do
|
||||
read -p "$(echo -e "${YELLOW}${prompt_msg}${NC}") " answer
|
||||
case "$answer" in
|
||||
[Yy]* ) return 0;;
|
||||
[Nn]* ) return 1;;
|
||||
* ) echo "Please answer yes or no.";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Show the help message and exit.
|
||||
show_help() {
|
||||
echo "Usage: ./install.sh [options]"
|
||||
echo
|
||||
echo "This script checks for dependencies, installs them, and builds the project."
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " --tui Run in Text-based User Interface mode for interactive dependency installation."
|
||||
echo " --help, -h Show this help message and exit."
|
||||
echo " --clean Remove the build directory and log file before starting."
|
||||
echo
|
||||
echo "The script will automatically detect your OS and suggest the correct package manager commands."
|
||||
echo "All output is logged to ${LOGFILE}."
|
||||
}
|
||||
|
||||
# --- OS Detection ---
|
||||
OS_NAME=$(uname -s)
|
||||
DISTRO_ID="unknown"
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
DISTRO_ID=$ID
|
||||
fi
|
||||
if [[ "$OS_NAME" == "Darwin" ]]; then
|
||||
OS_NAME="macOS"
|
||||
fi
|
||||
|
||||
# --- Dependency Check Functions ---
|
||||
|
||||
# Check for a C++ compiler.
|
||||
check_compiler() {
|
||||
if command -v g++ &>/dev/null; then
|
||||
COMPILER_CMD="g++"
|
||||
log "${GREEN}[OK] Found C++ compiler: $(g++ --version | head -n1)${NC}"
|
||||
return 0
|
||||
elif command -v clang++ &>/dev/null; then
|
||||
COMPILER_CMD="clang++"
|
||||
log "${GREEN}[OK] Found C++ compiler: $(clang++ --version | head -n1)${NC}"
|
||||
return 0
|
||||
else
|
||||
log "${RED}[FAIL] No C++ compiler (g++ or clang++) found.${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check for Python 3 development headers.
|
||||
check_python_dev() {
|
||||
if python3-config --includes &>/dev/null; then
|
||||
log "${GREEN}[OK] Found Python 3 development headers.${NC}"
|
||||
return 0
|
||||
else
|
||||
log "${RED}[FAIL] Python 3 development headers not found.${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check for CMake.
|
||||
check_cmake() {
|
||||
if command -v cmake &>/dev/null; then
|
||||
log "${GREEN}[OK] Found CMake: $(cmake --version | head -n1)${NC}"
|
||||
return 0
|
||||
else
|
||||
log "${RED}[FAIL] CMake not found.${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check for Meson.
|
||||
check_meson() {
|
||||
if command -v meson &>/dev/null; then
|
||||
log "${GREEN}[OK] Found Meson: $(meson --version)${NC}"
|
||||
return 0
|
||||
else
|
||||
log "${RED}[FAIL] Meson not found.${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if Boost is installed and available to Meson.
|
||||
check_boost() {
|
||||
log "${BLUE}[Info] Checking for Boost dependency using Meson...${NC}"
|
||||
if meson introspect --dependencies -C "$BUILD_DIR" 2>/dev/null | grep -q "boost.*found: YES"; then
|
||||
log "${GREEN}[OK] Boost dependency is already met in the Meson build directory.${NC}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# A simple meson dependency check as a fallback
|
||||
local test_dir="meson-boost-test"
|
||||
rm -rf "$test_dir" && mkdir "$test_dir"
|
||||
cat > "$test_dir/meson.build" <<EOF
|
||||
project('boost-check', 'cpp')
|
||||
boost_dep = dependency('boost', required: true)
|
||||
EOF
|
||||
if meson setup "$test_dir/build" "$test_dir" &>/dev/null; then
|
||||
log "${GREEN}[OK] Found Boost libraries.${NC}"
|
||||
rm -rf "$test_dir"
|
||||
return 0
|
||||
else
|
||||
log "${RED}[FAIL] Boost libraries not found by Meson.${NC}"
|
||||
rm -rf "$test_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# --- Dependency Installation Functions ---
|
||||
|
||||
# Execute an installation command.
|
||||
run_install_cmd() {
|
||||
local cmd="$1"
|
||||
log "${BLUE}[Exec] Running: ${cmd}${NC}"
|
||||
if prompt_yes_no "Execute this command? (y/n):"; then
|
||||
eval "${cmd}" 2>&1 | tee -a "$LOGFILE"
|
||||
return $?
|
||||
else
|
||||
log "${YELLOW}[Skip] User skipped installation command.${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get installation command for a given dependency.
|
||||
get_install_cmd() {
|
||||
local dep_name="$1"
|
||||
local cmd=""
|
||||
case "$OS_NAME" in
|
||||
"macOS")
|
||||
case "$dep_name" in
|
||||
"compiler") cmd="xcode-select --install" ;;
|
||||
"python-dev") cmd="brew install python3" ;;
|
||||
"cmake") cmd="brew install cmake" ;;
|
||||
"meson") cmd="brew install meson" ;;
|
||||
"boost") cmd="brew install boost" ;;
|
||||
"dialog") cmd="brew install dialog" ;;
|
||||
esac
|
||||
;;
|
||||
"Linux")
|
||||
case "$DISTRO_ID" in
|
||||
"ubuntu"|"debian"|"linuxmint")
|
||||
case "$dep_name" in
|
||||
"compiler") cmd="sudo apt-get install -y build-essential" ;;
|
||||
"python-dev") cmd="sudo apt-get install -y python3-dev" ;;
|
||||
"cmake") cmd="sudo apt-get install -y cmake" ;;
|
||||
"meson") cmd="sudo apt-get install -y meson" ;;
|
||||
"boost") cmd="sudo apt-get install -y libboost-all-dev" ;;
|
||||
"dialog") cmd="sudo apt-get install -y dialog" ;;
|
||||
esac
|
||||
;;
|
||||
"fedora")
|
||||
case "$dep_name" in
|
||||
"compiler") cmd="sudo dnf install -y gcc-c++" ;;
|
||||
"python-dev") cmd="sudo dnf install -y python3-devel" ;;
|
||||
"cmake") cmd="sudo dnf install -y cmake" ;;
|
||||
"meson") cmd="sudo dnf install -y meson" ;;
|
||||
"boost") cmd="sudo dnf install -y boost-devel" ;;
|
||||
"dialog") cmd="sudo dnf install -y dialog" ;;
|
||||
esac
|
||||
;;
|
||||
"arch"|"manjaro")
|
||||
case "$dep_name" in
|
||||
"compiler") cmd="sudo pacman -S --noconfirm base-devel" ;;
|
||||
"python-dev") cmd="sudo pacman -S --noconfirm python" ;;
|
||||
"cmake") cmd="sudo pacman -S --noconfirm cmake" ;;
|
||||
"meson") cmd="sudo pacman -S --noconfirm meson" ;;
|
||||
"boost") cmd="sudo pacman -S --noconfirm boost" ;;
|
||||
"dialog") cmd="sudo pacman -S --noconfirm dialog" ;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
log "${YELLOW}[Warn] Unsupported Linux distribution: ${DISTRO_ID}. Cannot provide install commands.${NC}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
log "${YELLOW}[Warn] Unsupported OS: ${OS_NAME}. Cannot provide install commands.${NC}"
|
||||
;;
|
||||
esac
|
||||
echo "$cmd"
|
||||
}
|
||||
|
||||
# --- Main Logic ---
|
||||
|
||||
# Run the Meson setup and build process.
|
||||
run_meson_build() {
|
||||
log "\n${BLUE}--- Starting Meson Build ---${NC}"
|
||||
if [ ! -f "meson.build" ]; then
|
||||
log "${RED}[FATAL] meson.build file not found in the current directory. Cannot proceed.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "${BLUE}[Info] Running meson setup...${NC}"
|
||||
if ! meson setup "${BUILD_DIR}"; then
|
||||
log "${RED}[FATAL] Meson setup failed. Check the output above and in ${LOGFILE} for details.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
log "${GREEN}[Success] Meson setup complete.${NC}"
|
||||
|
||||
log "${BLUE}[Info] Running meson compile...${NC}"
|
||||
if ! meson compile -C "${BUILD_DIR}"; then
|
||||
log "${RED}[FATAL] Meson compile failed. Check the output above and in ${LOGFILE} for details.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "\n${GREEN}--- Build Successful! ---${NC}"
|
||||
log "${GREEN}The project has been built in the '${BUILD_DIR}' directory.${NC}"
|
||||
}
|
||||
|
||||
# Run the TUI for dependency installation.
|
||||
run_tui() {
|
||||
if ! command -v dialog &>/dev/null; then
|
||||
log "${YELLOW}[Warn] The 'dialog' utility is not installed. It is required for TUI mode.${NC}"
|
||||
local install_cmd
|
||||
install_cmd=$(get_install_cmd "dialog")
|
||||
if [ -n "$install_cmd" ]; then
|
||||
if prompt_yes_no "Would you like to install it now? (y/n):"; then
|
||||
eval "$install_cmd"
|
||||
if ! command -v dialog &>/dev/null; then
|
||||
log "${RED}[FATAL] Failed to install 'dialog'. Cannot run in TUI mode.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "${RED}[FATAL] Cannot run in TUI mode without 'dialog'. Exiting.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "${RED}[FATAL] Cannot automatically install 'dialog' on your system. Please install it manually and try again.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local choices
|
||||
choices=$(dialog --clear --backtitle "Project Dependency Installer" \
|
||||
--title "Install Dependencies" \
|
||||
--checklist "Select dependencies to install. Dependencies marked with (*) are missing." 20 70 5 \
|
||||
"compiler" "C++ Compiler (g++ or clang++)" "$([[ ${DEP_STATUS[compiler]} == "FAIL" ]] && echo "on" || echo "off")" \
|
||||
"python-dev" "Python 3 Dev Headers" "$([[ ${DEP_STATUS[python-dev]} == "FAIL" ]] && echo "on" || echo "off")" \
|
||||
"cmake" "CMake" "$([[ ${DEP_STATUS[cmake]} == "FAIL" ]] && echo "on" || echo "off")" \
|
||||
"meson" "Meson Build System" "$([[ ${DEP_STATUS[meson]} == "FAIL" ]] && echo "on" || echo "off")" \
|
||||
"boost" "Boost Libraries" "$([[ ${DEP_STATUS[boost]} == "FAIL" ]] && echo "on" || echo "off")" \
|
||||
3>&1 1>&2 2>&3)
|
||||
|
||||
clear
|
||||
|
||||
if [ -z "$choices" ]; then
|
||||
log "${YELLOW}[Info] No dependencies selected for installation.${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
for choice in $choices; do
|
||||
local dep
|
||||
dep=$(echo "$choice" | tr -d '"')
|
||||
log "\n${BLUE}--- Installing ${dep} ---${NC}"
|
||||
local install_cmd
|
||||
install_cmd=$(get_install_cmd "$dep")
|
||||
if [ -n "$install_cmd" ]; then
|
||||
run_install_cmd "$install_cmd"
|
||||
else
|
||||
log "${RED}[Error] No automatic installation command available for '${dep}' on your system.${NC}"
|
||||
log "${RED}Please install it manually.${NC}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# --- Script Entry Point ---
|
||||
main() {
|
||||
# Handle command-line arguments
|
||||
if [[ " $@ " =~ " --help " ]] || [[ " $@ " =~ " -h " ]]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ " $@ " =~ " --clean " ]]; then
|
||||
log "${BLUE}[Info] Cleaning up previous build...${NC}"
|
||||
rm -rf "$BUILD_DIR" "$LOGFILE"
|
||||
fi
|
||||
|
||||
# Start logging
|
||||
echo "" > "$LOGFILE"
|
||||
log "--- Project Installation Log ---"
|
||||
log "Date: $(date)"
|
||||
log "OS: ${OS_NAME}, Distro: ${DISTRO_ID}"
|
||||
|
||||
# Perform all dependency checks
|
||||
log "\n${BLUE}--- Checking System Dependencies ---${NC}"
|
||||
declare -A DEP_STATUS
|
||||
check_compiler; DEP_STATUS[compiler]=$?
|
||||
check_python_dev; DEP_STATUS[python-dev]=$?
|
||||
check_cmake; DEP_STATUS[cmake]=$?
|
||||
check_meson; DEP_STATUS[meson]=$?
|
||||
check_boost; DEP_STATUS[boost]=$?
|
||||
|
||||
local all_deps_met=0
|
||||
for status in "${DEP_STATUS[@]}"; do
|
||||
if [ "$status" -ne 0 ]; then
|
||||
all_deps_met=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $all_deps_met -eq 0 ]; then
|
||||
log "\n${GREEN}--- All dependencies are met! ---${NC}"
|
||||
run_meson_build
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "\n${YELLOW}--- Some dependencies are missing ---${NC}"
|
||||
|
||||
if [[ " $@ " =~ " --tui " ]]; then
|
||||
run_tui
|
||||
else
|
||||
# Interactive command-line prompts
|
||||
for dep in "${!DEP_STATUS[@]}"; do
|
||||
if [ "${DEP_STATUS[$dep]}" -ne 0 ]; then
|
||||
local install_cmd
|
||||
install_cmd=$(get_install_cmd "$dep")
|
||||
if [ -n "$install_cmd" ]; then
|
||||
if prompt_yes_no "Dependency '${dep}' is missing. Attempt to install it now? (y/n):"; then
|
||||
run_install_cmd "$install_cmd"
|
||||
fi
|
||||
else
|
||||
log "${RED}[Error] No automatic installation command available for '${dep}' on your system. Please install it manually.${NC}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Final check before build
|
||||
log "\n${BLUE}--- Re-checking dependencies after installation attempts ---${NC}"
|
||||
check_compiler; DEP_STATUS[compiler]=$?
|
||||
check_python_dev; DEP_STATUS[python-dev]=$?
|
||||
check_cmake; DEP_STATUS[cmake]=$?
|
||||
check_meson; DEP_STATUS[meson]=$?
|
||||
check_boost; DEP_STATUS[boost]=$?
|
||||
|
||||
all_deps_met=0
|
||||
local failed_deps=""
|
||||
for dep in "${!DEP_STATUS[@]}"; do
|
||||
if [ "${DEP_STATUS[$dep]}" -ne 0 ]; then
|
||||
all_deps_met=1
|
||||
failed_deps+="${dep} "
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $all_deps_met -eq 0 ]; then
|
||||
log "\n${GREEN}--- All dependencies are now met! ---${NC}"
|
||||
run_meson_build
|
||||
else
|
||||
log "\n${RED}[FATAL] The following dependencies are still missing: ${failed_deps}${NC}"
|
||||
log "${RED}Please install them manually and re-run this script.${NC}"
|
||||
log "${RED}Check ${LOGFILE} for detailed error messages.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run the main function
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user