2025-07-29 09:05:47 -04:00
#!/usr/bin/env bash
#
2025-07-29 09:25:44 -04:00
# install.sh - Comprehensive interactive installation script for GridFire.
2025-07-29 09:05:47 -04:00
#
# This script performs the following actions:
2025-07-29 10:54:49 -04:00
# 1. Checks for essential system dependencies against required minimum versions.
2025-07-29 09:25:44 -04:00
# 2. If run with the --tui flag, it provides a comprehensive text-based user interface
# to select and install dependencies, configure the build, and run build steps.
2025-07-29 09:05:47 -04:00
# 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.
2025-07-29 09:25:44 -04:00
# 5. Once all dependencies are met, it can run the meson setup, compile, install, and test commands.
2025-07-29 09:05:47 -04:00
# 6. Logs all operations to a file for easy debugging.
set -o pipefail
2025-07-29 11:40:01 -04:00
# --- Default Configuration ---
2025-07-29 09:05:47 -04:00
LOGFILE = "GridFire_Installer.log"
2025-07-29 10:54:49 -04:00
NOTES_FILE = "notes.txt"
2025-07-29 11:22:39 -04:00
CONFIG_FILE = "gridfire_build.conf"
2025-07-29 13:44:43 -04:00
VENV_DIR = ".venv"
2025-07-29 10:54:49 -04:00
MIN_GCC_VER = "13.0.0"
MIN_CLANG_VER = "16.0.0"
MIN_MESON_VER = "1.5.0"
2025-07-29 11:40:01 -04:00
BOOST_CHECKED = false
2025-07-29 11:41:58 -04:00
BOOST_OKAY = true
2025-07-29 14:36:23 -04:00
USING_VENV = false
2025-07-29 09:25:44 -04:00
# --- Build Configuration Globals ---
2025-07-29 09:05:47 -04:00
BUILD_DIR = "build"
2025-07-29 09:25:44 -04:00
INSTALL_PREFIX = "/usr/local"
2025-07-29 15:25:50 -04:00
MESON_BUILD_TYPE = "release"
2025-07-29 09:25:44 -04:00
MESON_LOG_LEVEL = "info"
MESON_PKG_CONFIG = "true"
MESON_NUM_CORES = $( getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1)
2025-07-29 10:54:49 -04:00
C_COMPILER = ""
2025-07-29 09:44:29 -04:00
CC_COMPILER = ""
2025-07-29 10:54:49 -04:00
FC_COMPILER = ""
declare -A VALID_COMPILERS
2025-07-29 11:22:39 -04:00
declare -A MESON_ADVANCED_OPTS
# --- Initialize default advanced options ---
MESON_ADVANCED_OPTS[ "b_lto" ] = "false"
MESON_ADVANCED_OPTS[ "strip" ] = "false"
MESON_ADVANCED_OPTS[ "unity" ] = "off"
MESON_ADVANCED_OPTS[ "warning_level" ] = "1"
MESON_ADVANCED_OPTS[ "backend" ] = "ninja"
MESON_ADVANCED_OPTS[ "werror" ] = "false"
MESON_ADVANCED_OPTS[ "b_pch" ] = "true"
MESON_ADVANCED_OPTS[ "b_coverage" ] = "false"
MESON_ADVANCED_OPTS[ "default_library" ] = "shared"
2025-07-29 15:25:50 -04:00
MESON_ADVANCED_OPTS[ "optimization" ] = 2
2025-07-29 11:22:39 -04:00
2025-07-29 09:05:47 -04:00
# --- 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 "
}
2025-07-29 10:54:49 -04:00
# Version comparison function. Returns 0 if v1=v2, 1 if v1>v2, 2 if v1<v2
vercomp( ) {
local v1 = $1 v2 = $2
if [ [ " $v1 " = = " $v2 " ] ] ; then return 0; fi
local IFS = .
read -ra v1_parts <<< " $v1 "
read -ra v2_parts <<< " $v2 "
local i
# Pad the shorter version array with zeros
local len1 = ${# v1_parts [@] }
local len2 = ${# v2_parts [@] }
if ( ( len1 > len2 ) ) ; then
for ( ( i = len2; i<len1; i++) ) ; do v2_parts[ i] = 0; done
elif ( ( len2 > len1 ) ) ; then
for ( ( i = len1; i<len2; i++) ) ; do v1_parts[ i] = 0; done
fi
for i in " ${ !v1_parts[@] } " ; do
local p1 = ${ v1_parts [i] }
local p2 = ${ v2_parts [i] }
# Ensure parts are integers before comparison
if ! [ [ " $p1 " = ~ ^[ 0-9] +$ ] ] ; then p1 = 0; fi
if ! [ [ " $p2 " = ~ ^[ 0-9] +$ ] ] ; then p2 = 0; fi
if ( ( p1 > p2 ) ) ; then return 1; fi
if ( ( p1 < p2 ) ) ; then return 2; fi
done
return 0
2025-07-29 09:05:47 -04:00
}
2025-07-29 12:25:42 -04:00
# 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
}
2025-07-29 10:54:49 -04:00
2025-07-29 09:05:47 -04:00
# 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:"
2025-07-29 09:25:44 -04:00
echo " --tui Run in Text-based User Interface mode for interactive dependency installation and build control."
2025-07-29 09:05:47 -04:00
echo " --help, -h Show this help message and exit."
echo " --clean Remove the build directory and log file before starting."
2025-07-29 11:22:39 -04:00
echo " --config FILE Load a configuration file on startup."
2025-07-29 09:05:47 -04:00
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 ---
2025-07-29 09:25:44 -04:00
check_command( ) {
command -v " $1 " & >/dev/null
}
2025-07-29 13:44:43 -04:00
is_externally_managed( ) {
# Check for the PEP 668 marker file
local py_prefix
2025-07-29 14:36:23 -04:00
py_prefix = $( python3 -c "import sysconfig; print(sysconfig.get_path(\"stdlib\"))" )
2025-07-29 13:44:43 -04:00
if [ -f " $py_prefix /EXTERNALLY-MANAGED " ] ; then
2025-07-29 14:36:23 -04:00
log " ${ YELLOW } Python is externally managed ${ NC } "
USING_VENV = true
2025-07-29 13:44:43 -04:00
return 0 # 0 means true in bash
else
2025-07-29 14:36:23 -04:00
log " ${ YELLOW } Python is not externally managed ${ NC } "
2025-07-29 13:44:43 -04:00
return 1 # 1 means false
fi
}
get_pip_cmd( ) {
if [ -d " $VENV_DIR " ] ; then
echo " $VENV_DIR /bin/pip "
else
echo "python3 -m pip"
fi
}
2025-07-29 14:36:23 -04:00
get_meson_cmd( ) {
if [ -d " $VENV_DIR " ] ; then
echo " $VENV_DIR /bin/meson "
else
echo "meson"
fi
}
2025-07-29 10:54:49 -04:00
set_compilers( ) {
if [ [ " $CC_COMPILER " = = *"clang++" * ] ] ; then
C_COMPILER = $( echo " $CC_COMPILER " | sed 's/clang++/clang/' )
# Try to find a corresponding flang or fallback to gfortran
local fc_ver = $( echo " $C_COMPILER " | grep -oE '[0-9]+' )
if check_command " flang- $fc_ver " ; then
FC_COMPILER = " flang- $fc_ver "
elif check_command "flang" ; then
FC_COMPILER = "flang"
elif check_command "gfortran" ; then
FC_COMPILER = "gfortran"
else
FC_COMPILER = ""
fi
elif [ [ " $CC_COMPILER " = = *"g++" * ] ] ; then
C_COMPILER = $( echo " $CC_COMPILER " | sed 's/g++/gcc/' )
FC_COMPILER = $( echo " $CC_COMPILER " | sed 's/g++/gfortran/' )
if ! check_command " $FC_COMPILER " ; then
# Fallback to generic gfortran if versioned one not found
if check_command "gfortran" ; then
FC_COMPILER = "gfortran"
else
FC_COMPILER = ""
fi
fi
else
C_COMPILER = ""
FC_COMPILER = ""
fi
}
2025-07-29 09:05:47 -04:00
check_compiler( ) {
2025-07-29 10:54:49 -04:00
VALID_COMPILERS = ( )
local potential_gccs = ( "g++-14" "g++-13" "g++" )
local potential_clangs = ( "clang++-17" "clang++-16" "clang++" )
for cc in " ${ potential_gccs [@] } " ; do
if check_command " $cc " ; then
local ver; ver = $( $cc -dumpversion | grep -oE '[0-9]+(\.[0-9]+)*' | head -n1)
if [ [ -n " $ver " ] ] ; then
vercomp " $ver " " $MIN_GCC_VER "
if [ [ $? -ne 2 ] ] ; then
VALID_COMPILERS[ " g++ ( $ver ) " ] = " $cc "
break # Found a valid one, stop searching for g++
fi
fi
fi
done
2025-07-29 09:44:29 -04:00
2025-07-29 10:54:49 -04:00
for cc in " ${ potential_clangs [@] } " ; do
if check_command " $cc " ; then
local ver; ver = $( $cc --version | head -n1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
if [ [ -n " $ver " ] ] ; then
vercomp " $ver " " $MIN_CLANG_VER "
if [ [ $? -ne 2 ] ] ; then
VALID_COMPILERS[ " clang++ ( $ver ) " ] = " $cc "
break # Found a valid one
fi
fi
fi
done
if [ ${# VALID_COMPILERS [@] } -gt 0 ] ; then
if ! [ [ " ${ VALID_COMPILERS [*] } " = ~ " ${ CC_COMPILER } " ] ] ; then
# Correctly get the first value from the associative array
local keys = ( " ${ !VALID_COMPILERS[@] } " )
local first_key = " ${ keys [0] } "
CC_COMPILER = " ${ VALID_COMPILERS [ $first_key ] } "
fi
set_compilers
log " ${ GREEN } [OK] Found valid C++ compiler(s). Using C: ' ${ C_COMPILER } ', C++: ' ${ CC_COMPILER } ', FC: ' ${ FC_COMPILER } '. ${ NC } "
return 0
else
log " ${ RED } [FAIL] No valid C++ compiler found (GCC >= ${ MIN_GCC_VER } or Clang >= ${ MIN_CLANG_VER } ). ${ NC } "
CC_COMPILER = ""
C_COMPILER = ""
FC_COMPILER = ""
return 1
2025-07-29 09:44:29 -04:00
fi
2025-07-29 09:05:47 -04:00
}
2025-07-29 13:44:43 -04:00
check_pip( ) {
if python3 -m pip --version & >/dev/null; then
log " ${ GREEN } [OK] Found pip. ${ NC } "
return 0
else
log " ${ RED } [FAIL] pip not found. ${ NC } "
return 1
fi
}
2025-07-29 09:05:47 -04:00
check_python_dev( ) {
2025-07-29 09:25:44 -04:00
if check_command python3 && python3-config --includes & >/dev/null; then
2025-07-29 09:05:47 -04:00
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
}
2025-07-29 09:44:29 -04:00
check_meson_python( ) {
2025-07-29 13:44:43 -04:00
if [ -d " $VENV_DIR " ] ; then
if " $VENV_DIR /bin/python3 " -c "import mesonpy" & >/dev/null; then
log " ${ GREEN } [OK] Found meson-python package (in venv). ${ NC } "
return 0
fi
fi
2025-07-29 09:44:29 -04:00
if python3 -c "import mesonpy" & >/dev/null; then
log " ${ GREEN } [OK] Found meson-python package. ${ NC } "
return 0
else
log " ${ RED } [FAIL] meson-python package not found. ${ NC } "
return 1
fi
}
2025-07-29 09:05:47 -04:00
check_cmake( ) {
2025-07-29 09:25:44 -04:00
if check_command cmake; then
2025-07-29 09:05:47 -04:00
log " ${ GREEN } [OK] Found CMake: $( cmake --version | head -n1) ${ NC } "
return 0
else
log " ${ RED } [FAIL] CMake not found. ${ NC } "
return 1
fi
}
check_meson( ) {
2025-07-29 13:44:43 -04:00
local meson_cmd = "meson"
if [ -d " $VENV_DIR " ] ; then
meson_cmd = " $VENV_DIR /bin/meson "
fi
if check_command " $meson_cmd " ; then
local ver; ver = $( $meson_cmd --version)
2025-07-29 10:54:49 -04:00
vercomp " $ver " " $MIN_MESON_VER "
if [ [ $? -ne 2 ] ] ; then
log " ${ GREEN } [OK] Found Meson ${ ver } . ${ NC } "
return 0
else
log " ${ RED } [FAIL] Meson version ${ ver } is too old. Need >= ${ MIN_MESON_VER } . ${ NC } "
return 1
fi
else
log " ${ RED } [FAIL] Meson not found. ${ NC } "
return 1
fi
2025-07-29 09:05:47 -04:00
}
2025-07-29 14:36:23 -04:00
check_ninja( ) {
if check_command ninja; then
log " ${ GREEN } [OK] Found Ninja: $( ninja --version | head -n1) ${ NC } "
return 0
else
log " ${ RED } [FAIL] Ninja not found. ${ NC } "
return 1
fi
}
2025-07-29 15:25:50 -04:00
check_venv( ) {
if python3 -m venv --help >/dev/null 2>& 1; then
return 0
else
return 1
fi
}
2025-07-29 09:05:47 -04:00
check_boost( ) {
2025-07-29 11:40:01 -04:00
log " ${ BLUE } [Info] Performing comprehensive check for compatible Boost library... ${ NC } "
if [ -z " $CC_COMPILER " ] ; then
log " ${ YELLOW } [Warn] C++ compiler not set, skipping comprehensive Boost check. ${ NC } "
return 1
fi
local test_dir = "boost-compile-test"
rm -rf " $test_dir " && mkdir -p " $test_dir "
# Create the test C++ file that uses problematic headers
cat > " $test_dir /test_boost.cpp " <<EOF
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/odeint.hpp>
using state_type = boost::numeric::ublas::vector<double>;
void dummy_system( const state_type & x, state_type & dxdt, double t) {
if ( x.size( ) > 0 && dxdt.size( ) > 0) {
dxdt[ 0] = 1.0;
}
}
int main( ) {
boost::numeric::ublas::vector<double> v( 3) ;
v[ 0] = 1.23;
state_type x( 1) ;
x[ 0] = 1.0;
boost::numeric::odeint::runge_kutta4<state_type> stepper;
stepper.do_step( dummy_system, x, 0.0, 0.1) ;
return 0;
}
EOF
# Create the test meson.build file
cat > " $test_dir /meson.build " <<EOF
project( 'boost-compile-check' , 'cpp' , default_options: [ 'cpp_std=c++23' ] )
2025-07-29 09:05:47 -04:00
boost_dep = dependency( 'boost' , required: true )
2025-07-29 11:40:01 -04:00
executable( 'test_boost' , 'test_boost.cpp' , dependencies: [ boost_dep] )
2025-07-29 09:05:47 -04:00
EOF
2025-07-29 11:40:01 -04:00
log " ${ BLUE } [Info] Attempting to compile test project against Boost with C++23... ${ NC } "
# Use the globally selected compilers, pipe stdout and stderr to log for debugging
2025-07-29 14:36:23 -04:00
log " ${ BLUE } [Info] Using meson at ${ mesonCMD } ${ NC } "
local mesonCMD = $( get_meson_cmd)
if CC = " ${ C_COMPILER } " CXX = " ${ CC_COMPILER } " $mesonCMD setup " $test_dir /build " " $test_dir " >> " $LOGFILE " 2>& 1 && $mesonCMD compile -C " $test_dir /build " >> " $LOGFILE " 2>& 1; then
2025-07-29 11:40:01 -04:00
log " ${ GREEN } [Success] Boost library is compatible with the current compiler and C++23 standard. ${ NC } "
rm -rf " $test_dir "
return 0
else
log " ${ RED } [FAIL] System Boost library is NOT compatible with C++23 or is missing required components. ${ NC } "
log " ${ YELLOW } [Info] This is common on systems like Ubuntu with older Boost versions. A manual install of a newer Boost is likely required. ${ NC } "
rm -rf " $test_dir "
return 1
fi
2025-07-29 09:05:47 -04:00
}
2025-07-29 11:40:01 -04:00
2025-07-29 09:05:47 -04:00
# --- Dependency Installation Functions ---
2025-07-29 09:44:29 -04:00
get_compiler_install_cmd( ) {
local compiler_to_install = " $1 " # e.g., g++ or clang++
local cmd = ""
case " $OS_NAME " in
"macOS" )
local brew_cmd; brew_cmd = $( command -v brew)
case " $compiler_to_install " in
"g++" ) cmd = " $brew_cmd install gcc " ; ;
2025-07-29 10:54:49 -04:00
"clang++" ) cmd = " $brew_cmd install llvm " ; ; # llvm provides clang
2025-07-29 09:44:29 -04:00
esac
; ;
"Linux" )
case " $DISTRO_ID " in
"ubuntu" | "debian" | "linuxmint" )
case " $compiler_to_install " in
2025-07-29 10:54:49 -04:00
"g++" ) cmd = "sudo apt-get install -y g++-13 gfortran-13" ; ;
"clang++" ) cmd = "sudo apt-get install -y clang-16" ; ;
2025-07-29 09:44:29 -04:00
esac
; ;
"fedora" )
2025-07-29 10:54:49 -04:00
# Fedora usually has recent versions in main repos
2025-07-29 09:44:29 -04:00
case " $compiler_to_install " in
2025-07-29 10:54:49 -04:00
"g++" ) cmd = "sudo dnf install -y gcc-c++ gcc-gfortran" ; ;
2025-07-29 09:44:29 -04:00
"clang++" ) cmd = "sudo dnf install -y clang" ; ;
esac
; ;
"arch" | "manjaro" )
2025-07-29 10:54:49 -04:00
# Arch is rolling release, should be fine
2025-07-29 09:44:29 -04:00
case " $compiler_to_install " in
2025-07-29 10:54:49 -04:00
"g++" ) cmd = "sudo pacman -S --noconfirm gcc gcc-fortran" ; ;
2025-07-29 09:44:29 -04:00
"clang++" ) cmd = "sudo pacman -S --noconfirm clang" ; ;
esac
; ;
esac
; ;
esac
echo " $cmd "
2025-07-29 09:05:47 -04:00
}
2025-07-29 09:44:29 -04:00
2025-07-29 09:05:47 -04:00
get_install_cmd( ) {
local dep_name = " $1 "
local cmd = ""
case " $OS_NAME " in
"macOS" )
2025-07-29 09:25:44 -04:00
[ ! -f /opt/homebrew/bin/brew ] && [ ! -f /usr/local/bin/brew ] && log " ${ YELLOW } Homebrew not found. Please install from https://brew.sh ${ NC } "
local brew_cmd
brew_cmd = $( command -v brew)
2025-07-29 09:05:47 -04:00
case " $dep_name " in
2025-07-29 10:54:49 -04:00
"compiler" ) cmd = " $brew_cmd install gcc llvm " ; ; # Install both
2025-07-29 09:25:44 -04:00
"python-dev" ) cmd = " $brew_cmd install python3 " ; ;
2025-07-29 13:44:43 -04:00
"pip" ) cmd = "python3 -m ensurepip --upgrade" ; ;
2025-07-29 09:44:29 -04:00
"meson-python" ) cmd = "python3 -m pip install meson-python" ; ;
2025-07-29 10:54:49 -04:00
"meson" ) cmd = "python3 -m pip install --upgrade meson" ; ;
2025-07-29 09:25:44 -04:00
"cmake" ) cmd = " $brew_cmd install cmake " ; ;
"boost" ) cmd = " $brew_cmd install boost " ; ;
"dialog" ) cmd = " $brew_cmd install dialog " ; ;
2025-07-29 15:25:50 -04:00
"ninja" ) cmd = " $brew_cmd install ninja " ; ;
"python3-venv" ) cmd = " $brew_cmd install python3 " ; ; # Homebrew installs venv with Python 3
2025-07-29 09:05:47 -04:00
esac
; ;
"Linux" )
case " $DISTRO_ID " in
"ubuntu" | "debian" | "linuxmint" )
case " $dep_name " in
2025-07-29 10:54:49 -04:00
"compiler" ) cmd = "sudo apt-get install -y g++-13 gfortran-13 clang-16" ; ;
2025-07-29 09:05:47 -04:00
"python-dev" ) cmd = "sudo apt-get install -y python3-dev" ; ;
2025-07-29 13:44:43 -04:00
"pip" ) cmd = "sudo apt-get install -y python3-pip" ; ;
2025-07-29 09:44:29 -04:00
"meson-python" ) cmd = "python3 -m pip install meson-python" ; ;
2025-07-29 10:54:49 -04:00
"meson" ) cmd = "python3 -m pip install --upgrade meson" ; ;
2025-07-29 09:05:47 -04:00
"cmake" ) cmd = "sudo apt-get install -y cmake" ; ;
"boost" ) cmd = "sudo apt-get install -y libboost-all-dev" ; ;
"dialog" ) cmd = "sudo apt-get install -y dialog" ; ;
2025-07-29 15:25:50 -04:00
"ninja" ) cmd = "sudo apt-get install -y ninja-build" ; ;
"python3-venv" ) cmd = "sudo apt-get install -y python3-venv" ; ; # Ensure venv is available
2025-07-29 09:05:47 -04:00
esac
; ;
"fedora" )
case " $dep_name " in
2025-07-29 10:54:49 -04:00
"compiler" ) cmd = "sudo dnf install -y gcc-c++ gcc-gfortran clang" ; ;
2025-07-29 09:05:47 -04:00
"python-dev" ) cmd = "sudo dnf install -y python3-devel" ; ;
2025-07-29 13:44:43 -04:00
"pip" ) cmd = "sudo dnf install -y python3-pip" ; ;
2025-07-29 09:44:29 -04:00
"meson-python" ) cmd = "python3 -m pip install meson-python" ; ;
2025-07-29 10:54:49 -04:00
"meson" ) cmd = "python3 -m pip install --upgrade meson" ; ;
2025-07-29 09:05:47 -04:00
"cmake" ) cmd = "sudo dnf install -y cmake" ; ;
"boost" ) cmd = "sudo dnf install -y boost-devel" ; ;
"dialog" ) cmd = "sudo dnf install -y dialog" ; ;
2025-07-29 15:25:50 -04:00
"ninja" ) cmd = "sudo dnf install -y ninja-build" ; ;
"python3-venv" ) cmd = "sudo dnf install -y python3-venv" ; ; # Ensure venv is available
2025-07-29 09:05:47 -04:00
esac
; ;
"arch" | "manjaro" )
case " $dep_name " in
2025-07-29 10:54:49 -04:00
"compiler" ) cmd = "sudo pacman -S --noconfirm gcc gcc-fortran clang" ; ;
2025-07-29 09:05:47 -04:00
"python-dev" ) cmd = "sudo pacman -S --noconfirm python" ; ;
2025-07-29 13:44:43 -04:00
"pip" ) cmd = "sudo pacman -S --noconfirm python-pip" ; ;
2025-07-29 09:44:29 -04:00
"meson-python" ) cmd = "python3 -m pip install meson-python" ; ;
2025-07-29 10:54:49 -04:00
"meson" ) cmd = "python3 -m pip install --upgrade meson" ; ;
2025-07-29 09:05:47 -04:00
"cmake" ) cmd = "sudo pacman -S --noconfirm cmake" ; ;
"boost" ) cmd = "sudo pacman -S --noconfirm boost" ; ;
"dialog" ) cmd = "sudo pacman -S --noconfirm dialog" ; ;
2025-07-29 15:25:50 -04:00
"ninja" ) cmd = "sudo pacman -S --noconfirm ninja" ; ;
"python3-venv" ) cmd = "sudo pacman -S --noconfirm python-virtualenv" ; ; # Ensure venv is available
2025-07-29 09:05:47 -04:00
esac
; ;
2025-07-29 09:25:44 -04:00
*) log " ${ YELLOW } [Warn] Unsupported Linux distribution: ${ DISTRO_ID } . ${ NC } " ; ;
2025-07-29 09:05:47 -04:00
esac
; ;
2025-07-29 09:25:44 -04:00
*) log " ${ YELLOW } [Warn] Unsupported OS: ${ OS_NAME } . ${ NC } " ; ;
2025-07-29 09:05:47 -04:00
esac
echo " $cmd "
}
2025-07-29 09:25:44 -04:00
# --- Build Functions ---
2025-07-29 09:05:47 -04:00
2025-07-29 09:25:44 -04:00
run_meson_setup( ) {
log " \n ${ BLUE } --- Configuring Meson Build --- ${ NC } "
if [ ! -f "meson.build" ] ; then
log " ${ RED } [FATAL] meson.build file not found. Cannot proceed. ${ NC } " ; return 1;
fi
2025-07-29 10:54:49 -04:00
if [ -z " $CC_COMPILER " ] || [ -z " $C_COMPILER " ] ; then
log " ${ RED } [FATAL] No valid C/C++ compiler selected. Configure one first. ${ NC } " ; return 1;
2025-07-29 09:44:29 -04:00
fi
2025-07-29 09:25:44 -04:00
local reconfigure_flag = ""
if [ -d " $BUILD_DIR " ] ; then
reconfigure_flag = "--reconfigure"
log " ${ YELLOW } [Info] Existing build directory found. Will reconfigure. ${ NC } "
fi
2025-07-29 09:05:47 -04:00
2025-07-29 09:25:44 -04:00
local meson_opts = ( )
meson_opts += ( " -Dbuildtype= ${ MESON_BUILD_TYPE } " )
meson_opts += ( " -Dlog_level= ${ MESON_LOG_LEVEL } " )
meson_opts += ( " -Dpkg-config= ${ MESON_PKG_CONFIG } " )
meson_opts += ( " --prefix= ${ INSTALL_PREFIX } " )
2025-07-29 09:05:47 -04:00
2025-07-29 11:22:39 -04:00
# Add advanced options
for key in " ${ !MESON_ADVANCED_OPTS[@] } " ; do
meson_opts += ( " -D ${ key } = ${ MESON_ADVANCED_OPTS [ $key ] } " )
done
2025-07-29 10:54:49 -04:00
log " ${ BLUE } [Info] Using C compiler: ${ C_COMPILER } ${ NC } "
log " ${ BLUE } [Info] Using C++ compiler: ${ CC_COMPILER } ${ NC } "
log " ${ BLUE } [Info] Using Fortran compiler: ${ FC_COMPILER } ${ NC } "
2025-07-29 09:25:44 -04:00
log " ${ BLUE } [Info] Running meson setup with options: ${ meson_opts [*] } ${ NC } "
2025-07-29 14:36:23 -04:00
local mesonCMD = $( get_meson_cmd)
log " ${ BLUE } [Info] Using meson at ${ mesonCMD } ${ NC } "
2025-07-29 10:54:49 -04:00
# Set CC, CXX, and FC environment variables for the meson command
2025-07-29 14:36:23 -04:00
if ! CC = " ${ C_COMPILER } " CXX = " ${ CC_COMPILER } " FC = " ${ FC_COMPILER } " $mesonCMD setup " ${ BUILD_DIR } " " ${ meson_opts [@] } " ${ reconfigure_flag } ; then
2025-07-29 09:25:44 -04:00
log " ${ RED } [FATAL] Meson setup failed. See log for details. ${ NC } " ; return 1;
fi
log " ${ GREEN } [Success] Meson setup complete. ${ NC } "
}
run_meson_compile( ) {
log " \n ${ BLUE } --- Compiling Project --- ${ NC } "
if [ ! -d " $BUILD_DIR " ] ; then
log " ${ RED } [FATAL] Build directory not found. Run setup first. ${ NC } " ; return 1;
fi
log " ${ BLUE } [Info] Running meson compile with ${ MESON_NUM_CORES } cores... ${ NC } "
2025-07-29 14:36:23 -04:00
local mesonCMD = $( get_meson_cmd)
log " ${ BLUE } [Info] Using meson at ${ mesonCMD } ${ NC } "
if ! $mesonCMD compile -C " ${ BUILD_DIR } " -j " ${ MESON_NUM_CORES } " ; then
2025-07-29 09:25:44 -04:00
log " ${ RED } [FATAL] Meson compile failed. See log for details. ${ NC } " ; return 1;
fi
log " ${ GREEN } [Success] Meson compile complete. ${ NC } "
}
run_meson_install( ) {
log " \n ${ BLUE } --- Installing Project --- ${ NC } "
if [ ! -d " $BUILD_DIR " ] ; then
log " ${ RED } [FATAL] Build directory not found. Run setup and compile first. ${ NC } " ; return 1;
fi
log " ${ BLUE } [Info] Running meson install (prefix: ${ INSTALL_PREFIX } )... ${ NC } "
2025-07-29 14:36:23 -04:00
local mesonCMD = $( get_meson_cmd)
log " ${ BLUE } [Info] Using meson at ${ mesonCMD } ${ NC } "
if ! sudo $mesonCMD install -C " ${ BUILD_DIR } " ; then
2025-07-29 09:25:44 -04:00
log " ${ RED } [FATAL] Meson install failed. See log for details. ${ NC } " ; return 1;
fi
log " ${ GREEN } [Success] Meson install complete. ${ NC } "
}
2025-07-29 09:05:47 -04:00
2025-07-29 09:25:44 -04:00
run_meson_tests( ) {
log " \n ${ BLUE } --- Running Tests --- ${ NC } "
if [ ! -d " $BUILD_DIR " ] ; then
log " ${ RED } [FATAL] Build directory not found. Run setup and compile first. ${ NC } " ; return 1;
fi
log " ${ BLUE } [Info] Running meson test... ${ NC } "
2025-07-29 14:36:23 -04:00
local mesonCMD = $( get_meson_cmd)
log " ${ BLUE } [Info] Using meson at ${ mesonCMD } ${ NC } "
if ! $mesonCMD test -C " ${ BUILD_DIR } " ; then
2025-07-29 09:25:44 -04:00
log " ${ RED } [FATAL] Meson tests failed. See log for details. ${ NC } " ; return 1;
fi
log " ${ GREEN } [Success] Tests passed. ${ NC } "
2025-07-29 09:05:47 -04:00
}
2025-07-29 09:25:44 -04:00
# --- TUI Functions ---
check_dialog_installed( ) {
if ! check_command dialog; then
log " ${ YELLOW } [Warn] The 'dialog' utility is required for TUI mode. ${ NC } "
2025-07-29 09:05:47 -04:00
local install_cmd
install_cmd = $( get_install_cmd "dialog" )
if [ -n " $install_cmd " ] ; then
2025-07-29 09:25:44 -04:00
if prompt_yes_no "Attempt to install it now? (y/n):" ; then
2025-07-29 09:05:47 -04:00
eval " $install_cmd "
2025-07-29 09:25:44 -04:00
if ! check_command dialog; then
2025-07-29 09:05:47 -04:00
log " ${ RED } [FATAL] Failed to install 'dialog'. Cannot run in TUI mode. ${ NC } "
2025-07-29 09:25:44 -04:00
return 1
2025-07-29 09:05:47 -04:00
fi
else
log " ${ RED } [FATAL] Cannot run in TUI mode without 'dialog'. Exiting. ${ NC } "
2025-07-29 09:25:44 -04:00
return 1
2025-07-29 09:05:47 -04:00
fi
else
2025-07-29 09:25:44 -04:00
log " ${ RED } [FATAL] Cannot auto-install 'dialog'. Please install it manually. ${ NC } "
return 1
2025-07-29 09:05:47 -04:00
fi
fi
2025-07-29 09:25:44 -04:00
return 0
}
2025-07-29 13:44:43 -04:00
ensure_venv( ) {
if [ ! -d " $VENV_DIR " ] ; then
if dialog --title "Virtual Environment" --yesno " A local Python virtual environment (' ${ VENV_DIR } ') is required for this action. Create it now? " 8 70; then
log " ${ BLUE } [Info] Creating Python virtual environment in ' ${ VENV_DIR } '... ${ NC } "
if ! python3 -m venv " $VENV_DIR " ; then
2025-07-29 14:36:23 -04:00
dialog --msgbox "Failed to create virtual environment. Please ensure 'python4-venv' is installed." 8 60
2025-07-29 13:44:43 -04:00
return 1
fi
log " ${ GREEN } [Success] Virtual environment created. ${ NC } "
else
return 1
fi
fi
return 0
}
2025-07-29 09:25:44 -04:00
run_dependency_installer_tui( ) {
2025-07-29 09:44:29 -04:00
# This function now just calls the check functions to populate status
2025-07-29 09:25:44 -04:00
declare -A DEP_STATUS
2025-07-29 09:44:29 -04:00
check_compiler >/dev/null; DEP_STATUS[ compiler] = $?
2025-07-29 13:44:43 -04:00
check_pip >/dev/null; DEP_STATUS[ pip] = $?
2025-07-29 09:44:29 -04:00
check_python_dev >/dev/null; DEP_STATUS[ python-dev] = $?
2025-07-29 15:25:50 -04:00
check_venv >/dev/null; DEP_STATUS[ python3-venv] = $?
2025-07-29 09:44:29 -04:00
check_meson_python >/dev/null; DEP_STATUS[ meson-python] = $?
check_cmake >/dev/null; DEP_STATUS[ cmake] = $?
check_meson >/dev/null; DEP_STATUS[ meson] = $?
2025-07-29 14:36:23 -04:00
check_ninja >/dev/null; DEP_STATUS[ ninja] = $?
2025-07-29 12:23:43 -04:00
if [ [ $BOOST_OKAY = false ] ] ; then
DEP_STATUS[ boost] = 1 # Force boost to be "not okay" if previous check failed
fi
2025-07-29 09:05:47 -04:00
2025-07-29 14:36:23 -04:00
log " ${ BLUE } [Info] compiler status code: ${ DEP_STATUS [compiler] } ${ NC } "
log " ${ BLUE } [Info] pip status code: ${ DEP_STATUS [pip] } ${ NC } "
log " ${ BLUE } [Info] python-dev status code: ${ DEP_STATUS [python-dev] } ${ NC } "
2025-07-29 15:25:50 -04:00
log " ${ BLUE } [Info] python3-venv status code: ${ DEP_STATUS [python3-venv] } ${ NC } "
2025-07-29 14:36:23 -04:00
log " ${ BLUE } [Info] meson-python status code: ${ DEP_STATUS [meson-python] } ${ NC } "
log " ${ BLUE } [Info] cmake status code: ${ DEP_STATUS [cmake] } ${ NC } "
log " ${ BLUE } [Info] meson status code: ${ DEP_STATUS [meson] } ${ NC } "
log " ${ BLUE } [Info] ninja status code: ${ DEP_STATUS [ninja] } ${ NC } "
log " ${ BLUE } [Info] boost status code: ${ DEP_STATUS [boost] } ${ NC } "
2025-07-29 09:05:47 -04:00
local choices
choices = $( dialog --clear --backtitle "Project Dependency Installer" \
2025-07-29 09:25:44 -04:00
--title "Install System Dependencies" \
2025-07-29 13:44:43 -04:00
--checklist "Select dependencies to install. Already found dependencies are unchecked." 20 70 7 \
2025-07-29 09:44:29 -04:00
"compiler" "C++ Compilers (g++, clang++)" " $( [ [ ${ DEP_STATUS [compiler] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 13:44:43 -04:00
"pip" "Python Package Installer (pip)" " $( [ [ ${ DEP_STATUS [pip] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 09:25:44 -04:00
"python-dev" "Python 3 Dev Headers" " $( [ [ ${ DEP_STATUS [python-dev] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 15:25:50 -04:00
"python3-venv" "Python 3 Virtual Environment (venv)" " $( [ [ ${ DEP_STATUS [python3-venv] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 09:44:29 -04:00
"meson-python" "meson-python (for Python bindings)" " $( [ [ ${ DEP_STATUS [meson-python] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 09:25:44 -04:00
"cmake" "CMake" " $( [ [ ${ DEP_STATUS [cmake] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 10:54:49 -04:00
"meson" " Meson Build System (>= ${ MIN_MESON_VER } ) " " $( [ [ ${ DEP_STATUS [meson] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 14:36:23 -04:00
"ninja" "Ninja Build System" " $( [ [ ${ DEP_STATUS [ninja] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 11:40:01 -04:00
"boost" "Boost Libraries (system package)" " $( [ [ ${ DEP_STATUS [boost] } -ne 0 ] ] && echo "on" || echo "off" ) " \
2025-07-29 09:05:47 -04:00
3>& 1 1>& 2 2>& 3)
clear
2025-07-29 09:25:44 -04:00
if [ -z " $choices " ] ; then log " ${ YELLOW } [Info] No dependencies selected. ${ NC } " ; return ; fi
2025-07-29 09:05:47 -04:00
for choice in $choices ; do
2025-07-29 09:25:44 -04:00
local dep; dep = $( echo " $choice " | tr -d '"' )
2025-07-29 09:05:47 -04:00
log " \n ${ BLUE } --- Installing ${ dep } --- ${ NC } "
2025-07-29 13:44:43 -04:00
# Handle python packages specially
if [ [ " $dep " = = "meson-python" || " $dep " = = "meson" ] ] ; then
if is_externally_managed; then
if ! ensure_venv; then
log " ${ YELLOW } [Skip] User cancelled venv creation. Skipping ${ dep } installation. ${ NC } "
continue
fi
fi
local pip_cmd; pip_cmd = $( get_pip_cmd)
eval " $pip_cmd install --upgrade $dep " 2>& 1 | tee -a " $LOGFILE "
2025-07-29 09:05:47 -04:00
else
2025-07-29 13:44:43 -04:00
local install_cmd; install_cmd = $( get_install_cmd " $dep " )
if [ -n " $install_cmd " ] ; then
eval " $install_cmd " 2>& 1 | tee -a " $LOGFILE "
else
log " ${ RED } [Error] No automatic installation command for ' ${ dep } '. Please install manually. ${ NC } "
dialog --msgbox " Could not find an automatic installation command for ' ${ dep } ' on your system. Please install it manually. " 8 60
fi
2025-07-29 09:05:47 -04:00
fi
done
2025-07-29 09:44:29 -04:00
# Re-run check to update status
check_compiler
2025-07-29 13:44:43 -04:00
BOOST_CHECKED = false # Force re-check of boost
2025-07-29 09:05:47 -04:00
}
2025-07-29 09:25:44 -04:00
run_python_bindings_tui( ) {
2025-07-29 09:44:29 -04:00
if ! check_meson_python; then
dialog --msgbox "The 'meson-python' package is required to build Python bindings. Please install it from the 'Install System Dependencies' menu first." 10 70
return
fi
if [ -z " $CC_COMPILER " ] ; then
dialog --msgbox "No C++ compiler is selected. Please configure one from the 'Configure Build Options' menu before building the Python bindings." 10 70
return
fi
2025-07-29 09:25:44 -04:00
local python_exec
python_exec = $( command -v python3)
if [ -z " $python_exec " ] ; then
dialog --msgbox "Could not find 'python3' executable. Please ensure Python 3 is installed and in your PATH." 8 60
return
fi
2025-07-29 13:44:43 -04:00
local pip_cmd = "python3 -m pip"
local pip_opts = ""
if is_externally_managed; then
local env_choice
env_choice = $( dialog --clear --backtitle "Python Environment" \
--title "Externally Managed Environment Detected" \
--menu "This OS protects its system Python. How would you like to install the bindings?" 15 78 3 \
"1" "Use a Virtual Environment (Recommended)" \
"2" "Install to System with --break-system-packages (Advanced)" \
"3" "Cancel" \
3>& 1 1>& 2 2>& 3)
case " $env_choice " in
1)
if ! ensure_venv; then return ; fi
pip_cmd = " $VENV_DIR /bin/pip "
; ;
2)
pip_opts = "--break-system-packages"
; ;
*)
return
; ;
esac
fi
2025-07-29 09:25:44 -04:00
local choice
choice = $( dialog --clear --backtitle "Python Bindings Installer" \
--title "Install Python Bindings" \
2025-07-29 09:44:29 -04:00
--menu " Using Python: ${ python_exec } \nUsing C++ Compiler: ${ CC_COMPILER } \n\nSelect installation mode: " 15 70 2 \
2025-07-29 09:25:44 -04:00
"1" "Developer Mode (pip install -e .)" \
"2" "User Mode (pip install .)" \
3>& 1 1>& 2 2>& 3)
clear
case " $choice " in
1)
log " ${ BLUE } [Info] Installing Python bindings in Developer Mode... ${ NC } "
2025-07-29 13:44:43 -04:00
if ! CC = " ${ C_COMPILER } " CXX = " ${ CC_COMPILER } " FC = " ${ FC_COMPILER } " $pip_cmd install $pip_opts -e . --no-build-isolation -vv; then
2025-07-29 09:25:44 -04:00
log " ${ RED } [Error] Failed to install Python bindings in developer mode. ${ NC } "
dialog --msgbox "Developer mode installation failed. Check the log for details." 8 60
else
log " ${ GREEN } [Success] Python bindings installed in developer mode. ${ NC } "
dialog --msgbox "Successfully installed Python bindings in developer mode." 8 60
fi
; ;
2)
log " ${ BLUE } [Info] Installing Python bindings in User Mode... ${ NC } "
2025-07-29 13:44:43 -04:00
if ! CC = " ${ C_COMPILER } " CXX = " ${ CC_COMPILER } " FC = " ${ FC_COMPILER } " $pip_cmd install $pip_opts .; then
2025-07-29 09:25:44 -04:00
log " ${ RED } [Error] Failed to install Python bindings in user mode. ${ NC } "
dialog --msgbox "User mode installation failed. Check the log for details." 8 60
else
log " ${ GREEN } [Success] Python bindings installed in user mode. ${ NC } "
dialog --msgbox "Successfully installed Python bindings in user mode." 8 60
fi
; ;
*)
log " ${ YELLOW } [Info] Python binding installation cancelled. ${ NC } "
; ;
esac
}
2025-07-29 12:23:43 -04:00
run_compiler_help_tui( ) {
local compiler_name = " $1 "
local req_ver = ""
local help_text = ""
if [ [ " $compiler_name " = = "g++" ] ] ; then
req_ver = $MIN_GCC_VER
help_text = " The installer could not automatically install GCC >= ${ req_ver } .\n\n "
help_text += "This can happen on older Linux distributions.\n\n"
help_text += "Recommended Solutions:\n"
help_text += "1. (Ubuntu/Debian) Add a PPA with newer compilers:\n"
help_text += " sudo add-apt-repository ppa:ubuntu-toolchain-r/test\n"
help_text += " sudo apt-get update\n"
help_text += " sudo apt-get install g++-13\n\n"
help_text += "2. Download pre-built binaries from a trusted source.\n\n"
help_text += "3. Build GCC from source (advanced)."
elif [ [ " $compiler_name " = = "clang++" ] ] ; then
req_ver = $MIN_CLANG_VER
help_text = " The installer could not automatically install Clang >= ${ req_ver } .\n\n "
help_text += "This is common on systems like Ubuntu 22.04.\n\n"
help_text += "Recommended Solution (Ubuntu/Debian):\n"
help_text += "Use the official LLVM APT repository. Run this command in your terminal:\n\n"
help_text += ' bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"'
help_text += "\n\nThis script will set up the repository and install the latest version of Clang. After running it, re-run this installer."
fi
dialog --title "Compiler Installation Failed" --msgbox " $help_text " 25 78
}
2025-07-29 09:44:29 -04:00
run_compiler_selection_tui( ) {
2025-07-29 10:54:49 -04:00
local gpp_ver; gpp_ver = $( g++ -dumpversion 2>/dev/null | grep -oE '[0-9]+(\.[0-9]+)*' | head -n1)
local clang_ver; clang_ver = $( clang++ --version 2>/dev/null | head -n1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
local gpp_ok = false
local clang_ok = false
if [ [ -n " $gpp_ver " ] ] ; then vercomp " $gpp_ver " " $MIN_GCC_VER " ; [ [ $? -ne 2 ] ] && gpp_ok = true; fi
if [ [ -n " $clang_ver " ] ] ; then vercomp " $clang_ver " " $MIN_CLANG_VER " ; [ [ $? -ne 2 ] ] && clang_ok = true; fi
2025-07-29 09:44:29 -04:00
2025-07-29 10:54:49 -04:00
if ! $gpp_ok && ! $clang_ok ; then
# No valid compilers found
2025-07-29 09:44:29 -04:00
local choices
2025-07-29 10:54:49 -04:00
choices = $( dialog --title "Compiler Installation" --checklist "No valid C++ compiler found. Please select which to install:" 15 70 2 \
"g++" " GNU C++ Compiler (>= ${ MIN_GCC_VER } ) " "on" \
"clang++" " Clang C++ Compiler (>= ${ MIN_CLANG_VER } , often faster) " "off" 3>& 1 1>& 2 2>& 3)
2025-07-29 09:44:29 -04:00
if [ -n " $choices " ] ; then
for choice in $choices ; do
local compiler_to_install; compiler_to_install = $( echo " $choice " | tr -d '"' )
local install_cmd; install_cmd = $( get_compiler_install_cmd " $compiler_to_install " )
2025-07-29 12:23:43 -04:00
if [ -n " $install_cmd " ] ; then
eval " $install_cmd " 2>& 1 | tee -a " $LOGFILE "
# Post-install check
check_compiler
if ! check_command " ${ VALID_COMPILERS [g++*] } " && [ [ " $compiler_to_install " = = "g++" ] ] ; then run_compiler_help_tui "g++" ; fi
if ! check_command " ${ VALID_COMPILERS [clang++*] } " && [ [ " $compiler_to_install " = = "clang++" ] ] ; then run_compiler_help_tui "clang++" ; fi
fi
2025-07-29 09:44:29 -04:00
done
fi
2025-07-29 10:54:49 -04:00
elif ! $gpp_ok && [ [ -n " $gpp_ver " ] ] ; then
# g++ found but too old
if dialog --title "Compiler Update" --yesno " Found g++ version ${ gpp_ver } , but require >= ${ MIN_GCC_VER } .\n\nAttempt to install a compatible version? " 10 70; then
local install_cmd; install_cmd = $( get_compiler_install_cmd "g++" )
2025-07-29 12:23:43 -04:00
if [ -n " $install_cmd " ] ; then
eval " $install_cmd " 2>& 1 | tee -a " $LOGFILE "
check_compiler
if ! $gpp_ok ; then run_compiler_help_tui "g++" ; fi
fi
2025-07-29 09:44:29 -04:00
fi
2025-07-29 10:54:49 -04:00
elif ! $clang_ok && [ [ -n " $clang_ver " ] ] ; then
# clang++ found but too old
if dialog --title "Compiler Update" --yesno " Found clang++ version ${ clang_ver } , but require >= ${ MIN_CLANG_VER } .\n\nAttempt to install a compatible version? " 10 70; then
local install_cmd; install_cmd = $( get_compiler_install_cmd "clang++" )
2025-07-29 12:23:43 -04:00
if [ -n " $install_cmd " ] ; then
eval " $install_cmd " 2>& 1 | tee -a " $LOGFILE "
check_compiler
if ! $clang_ok ; then run_compiler_help_tui "clang++" ; fi
fi
2025-07-29 09:44:29 -04:00
fi
fi
# Re-check compilers and let user choose if multiple are available
check_compiler
2025-07-29 10:54:49 -04:00
if [ ${# VALID_COMPILERS [@] } -gt 0 ] ; then
2025-07-29 09:44:29 -04:00
local menu_items = ( )
2025-07-29 10:54:49 -04:00
for name in " ${ !VALID_COMPILERS[@] } " ; do
menu_items += ( " $name " "" )
done
local compiler_choice_key
compiler_choice_key = $( dialog --title "Select C++ Compiler" --menu "Select the C++ compiler to use:" 15 70 ${# VALID_COMPILERS [@] } " ${ menu_items [@] } " 3>& 1 1>& 2 2>& 3)
if [ -n " $compiler_choice_key " ] ; then
CC_COMPILER = " ${ VALID_COMPILERS [ $compiler_choice_key ] } "
set_compilers
log " ${ BLUE } [Config] Set C compiler to: ${ C_COMPILER } ${ NC } "
2025-07-29 09:44:29 -04:00
log " ${ BLUE } [Config] Set C++ compiler to: ${ CC_COMPILER } ${ NC } "
2025-07-29 10:54:49 -04:00
log " ${ BLUE } [Config] Set Fortran compiler to: ${ FC_COMPILER } ${ NC } "
2025-07-29 09:44:29 -04:00
fi
2025-07-29 10:54:49 -04:00
else
dialog --msgbox "No valid C++ compiler could be found or installed. Please install one manually that meets the version requirements." 8 70
2025-07-29 09:44:29 -04:00
fi
}
2025-07-29 11:22:39 -04:00
run_advanced_options_tui( ) {
while true; do
local choice
choice = $( dialog --clear --backtitle "Advanced Build Options" \
--title "Advanced Meson Core & Base Options" \
--menu "Select an option to configure:" 20 78 10 \
"1" " Backend (current: ${ MESON_ADVANCED_OPTS [backend] } ) " \
"2" " Default Library (current: ${ MESON_ADVANCED_OPTS [default_library] } ) " \
"3" " LTO (Link-Time Opt) (current: ${ MESON_ADVANCED_OPTS [b_lto] } ) " \
"4" " PCH (Precompiled H) (current: ${ MESON_ADVANCED_OPTS [b_pch] } ) " \
"5" " Coverage (current: ${ MESON_ADVANCED_OPTS [b_coverage] } ) " \
"6" " Strip on install (current: ${ MESON_ADVANCED_OPTS [strip] } ) " \
"7" " Unity build (current: ${ MESON_ADVANCED_OPTS [unity] } ) " \
"8" " Warning Level (current: ${ MESON_ADVANCED_OPTS [warning_level] } ) " \
"9" " Warnings as Errors (current: ${ MESON_ADVANCED_OPTS [werror] } ) " \
2025-07-29 15:25:50 -04:00
"O" " Optimization Level (current: ${ MESON_ADVANCED_OPTS [optimization] } ) " \
"Q" "Back to main config" \
2025-07-29 11:22:39 -04:00
3>& 1 1>& 2 2>& 3)
case " $choice " in
1)
local backend_choice
backend_choice = $( dialog --title "Select Backend" --menu "" 15 70 4 \
"ninja" "Ninja build system" \
"vs" "Visual Studio" \
"xcode" "Xcode" \
"none" "No backend" 3>& 1 1>& 2 2>& 3)
if [ -n " $backend_choice " ] ; then MESON_ADVANCED_OPTS[ "backend" ] = " $backend_choice " ; fi
; ;
2)
local lib_choice
lib_choice = $( dialog --title "Default Library Type" --menu "" 15 70 3 \
"shared" "Shared (.so, .dylib)" \
"static" "Static (.a)" \
"both" "Build both types" 3>& 1 1>& 2 2>& 3)
if [ -n " $lib_choice " ] ; then MESON_ADVANCED_OPTS[ "default_library" ] = " $lib_choice " ; fi
; ;
3)
if dialog --title "LTO (Link-Time Optimization)" --yesno "Enable Link-Time Optimization?\n(Can improve performance but increases link time)" 8 70; then
MESON_ADVANCED_OPTS[ "b_lto" ] = "true"
else
MESON_ADVANCED_OPTS[ "b_lto" ] = "false"
fi
; ;
4)
if dialog --title "PCH (Precompiled Headers)" --yesno "Use precompiled headers?\n(Can speed up compilation)" 8 70; then
MESON_ADVANCED_OPTS[ "b_pch" ] = "true"
else
MESON_ADVANCED_OPTS[ "b_pch" ] = "false"
fi
; ;
5)
if dialog --title "Enable Coverage Tracking" --yesno "Enable code coverage tracking?\n(For generating coverage reports)" 8 70; then
MESON_ADVANCED_OPTS[ "b_coverage" ] = "true"
else
MESON_ADVANCED_OPTS[ "b_coverage" ] = "false"
fi
; ;
6)
if dialog --title "Strip on Install" --yesno "Strip binaries on install?\n(Reduces size, removes debug symbols)" 8 70; then
MESON_ADVANCED_OPTS[ "strip" ] = "true"
else
MESON_ADVANCED_OPTS[ "strip" ] = "false"
fi
; ;
7)
local unity_choice
unity_choice = $( dialog --title "Unity Build" --menu "" 15 70 3 \
"on" "Enable for all targets" \
"subprojects" "Enable for subprojects only" \
"off" "Disable unity builds" 3>& 1 1>& 2 2>& 3)
if [ -n " $unity_choice " ] ; then MESON_ADVANCED_OPTS[ "unity" ] = " $unity_choice " ; fi
; ;
8)
local warn_choice
warn_choice = $( dialog --title "Compiler Warning Level" --menu "" 15 70 5 \
"0" "No warnings" \
"1" "Normal warnings" \
"2" "More warnings" \
"3" "All warnings" \
"everything" "Pedantic warnings" 3>& 1 1>& 2 2>& 3)
if [ -n " $warn_choice " ] ; then MESON_ADVANCED_OPTS[ "warning_level" ] = " $warn_choice " ; fi
; ;
9)
if dialog --title "Treat Warnings as Errors" --yesno "Enable -Werror?\n(Build will fail on any compiler warning)" 8 70; then
MESON_ADVANCED_OPTS[ "werror" ] = "true"
else
MESON_ADVANCED_OPTS[ "werror" ] = "false"
fi
; ;
2025-07-29 15:25:50 -04:00
O)
if dialog --title "Optimization Level" --yesno "Set optimization level?\n(affects performance and debug info)" 8 70; then
local opt_choice
opt_choice = $( dialog --title "Select Optimization Level" --menu "" 15 70 5 \
"plain" "No optimization at all (no meson flags)" \
"0" "No optimization (debug)" \
"g" "optimization for debugging" \
"1" "Basic optimization (default)" \
"2" "More optimization" \
"3" "Full optimization" \
"s" "Size optimization (strip debug symbols)" 3>& 1 1>& 2 2>& 3)
if [ -n " $opt_choice " ] ; then MESON_ADVANCED_OPTS[ "optimization" ] = " $opt_choice " ; fi
else
MESON_ADVANCED_OPTS[ "optimization" ] = "0"
fi
; ;
Q) break ; ;
2025-07-29 11:22:39 -04:00
*) break ; ;
esac
done
}
2025-07-29 09:25:44 -04:00
run_build_config_tui( ) {
local choice
choice = $( dialog --clear --backtitle "Build Configuration" \
--title "Configure Build Options" \
2025-07-29 11:22:39 -04:00
--menu "Select an option to configure:" 20 70 8 \
2025-07-29 09:25:44 -04:00
"1" " Build Directory (current: ${ BUILD_DIR } ) " \
"2" " Install Prefix (current: ${ INSTALL_PREFIX } ) " \
2025-07-29 10:54:49 -04:00
"3" "Manage & Select C/C++/Fortran Compiler" \
2025-07-29 09:44:29 -04:00
"4" " Build Type (current: ${ MESON_BUILD_TYPE } ) " \
"5" " Log Level (current: ${ MESON_LOG_LEVEL } ) " \
"6" " Generate pkg-config (current: ${ MESON_PKG_CONFIG } ) " \
"7" " Number of Cores (current: ${ MESON_NUM_CORES } ) " \
2025-07-29 11:22:39 -04:00
"8" "Advanced Build Options" \
2025-07-29 09:25:44 -04:00
3>& 1 1>& 2 2>& 3)
clear
case " $choice " in
1)
local new_dir
new_dir = $( dialog --title "Set Build Directory" --inputbox "Enter new build directory name:" 10 60 " ${ BUILD_DIR } " 3>& 1 1>& 2 2>& 3)
if [ -n " $new_dir " ] ; then
BUILD_DIR = " $new_dir "
log " ${ BLUE } [Config] Set build directory to: ${ BUILD_DIR } ${ NC } "
fi
; ;
2)
local new_prefix
new_prefix = $( dialog --title "Set Install Prefix" --inputbox "Enter absolute path for installation prefix:" 10 60 " ${ INSTALL_PREFIX } " 3>& 1 1>& 2 2>& 3)
if [ -n " $new_prefix " ] ; then
INSTALL_PREFIX = " $new_prefix "
log " ${ BLUE } [Config] Set install prefix to: ${ INSTALL_PREFIX } ${ NC } "
fi
; ;
3)
2025-07-29 09:44:29 -04:00
run_compiler_selection_tui
; ;
4)
2025-07-29 09:25:44 -04:00
local build_type_choice
2025-07-29 10:54:49 -04:00
build_type_choice = $( dialog --title "Select Build Type" --menu "" 15 70 4 \
"debug" "No optimizations, with debug symbols" \
2025-07-29 09:25:44 -04:00
"release" "Optimized for performance" \
"debugoptimized" "With debug symbols and optimization" \
2025-07-29 10:54:49 -04:00
"plain" "Custom flags only" \
2025-07-29 09:25:44 -04:00
3>& 1 1>& 2 2>& 3)
if [ -n " $build_type_choice " ] ; then
MESON_BUILD_TYPE = " $build_type_choice "
log " ${ BLUE } [Config] Set build type to: ${ MESON_BUILD_TYPE } ${ NC } "
fi
; ;
2025-07-29 09:44:29 -04:00
5)
2025-07-29 09:25:44 -04:00
local log_level_choice
log_level_choice = $( dialog --title "Select Log Level" --menu "" 15 70 8 \
"traceL3" "" "traceL2" "" "traceL1" "" "debug" "" "info" "" "warning" "" "error" "" "critical" "" \
3>& 1 1>& 2 2>& 3)
if [ -n " $log_level_choice " ] ; then
MESON_LOG_LEVEL = " $log_level_choice "
log " ${ BLUE } [Config] Set log level to: ${ MESON_LOG_LEVEL } ${ NC } "
fi
; ;
2025-07-29 09:44:29 -04:00
6)
2025-07-29 09:25:44 -04:00
if dialog --title "Generate pkg-config" --yesno "Generate gridfire.pc file?" 7 60; then
MESON_PKG_CONFIG = "true"
else
MESON_PKG_CONFIG = "false"
fi
log " ${ BLUE } [Config] Set pkg-config generation to: ${ MESON_PKG_CONFIG } ${ NC } "
; ;
2025-07-29 09:44:29 -04:00
7)
2025-07-29 09:25:44 -04:00
local max_cores; max_cores = $( getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1)
local core_choice
core_choice = $( dialog --title "Set Number of Cores" --inputbox " Enter number of cores for compilation.\nAvailable: ${ max_cores } " 10 60 " ${ MESON_NUM_CORES } " 3>& 1 1>& 2 2>& 3)
if [ [ " $core_choice " = ~ ^[ 0-9] +$ ] ] && [ " $core_choice " -gt 0 ] ; then
MESON_NUM_CORES = " $core_choice "
log " ${ BLUE } [Config] Set number of cores to: ${ MESON_NUM_CORES } ${ NC } "
elif [ -n " $core_choice " ] ; then
dialog --msgbox "Invalid input. Please enter a positive number." 6 40
fi
; ;
2025-07-29 11:22:39 -04:00
8)
run_advanced_options_tui
; ;
2025-07-29 09:25:44 -04:00
esac
}
2025-07-29 10:54:49 -04:00
run_notes_tui( ) {
if [ ! -f " $NOTES_FILE " ] ; then
dialog --msgbox " Notes file ' ${ NOTES_FILE } ' not found. " 8 50
return
fi
local notes_content = ""
local counter = 1
# Read file, filter comments, and process non-empty lines
while IFS = read -r line; do
# Skip empty or comment lines
if [ [ -z " $line " || " $line " = ~ ^[ [ :space:] ] *# ] ] ; then
continue
fi
notes_content += " ${ counter } . ${ line } \n\n "
( ( counter++) )
done < " $NOTES_FILE "
if [ -z " $notes_content " ] ; then
dialog --msgbox " No notes found in ' ${ NOTES_FILE } '. " 8 50
else
dialog --title "Installer Notes" --msgbox " $notes_content " 20 70
fi
}
2025-07-29 11:22:39 -04:00
run_save_config_tui( ) {
local file_to_save
file_to_save = $( dialog --title "Save Configuration" --inputbox "Enter filename to save configuration:" 10 60 " $CONFIG_FILE " 3>& 1 1>& 2 2>& 3)
if [ -z " $file_to_save " ] ; then
dialog --msgbox "Save cancelled." 8 50
return
fi
# Write main settings
{
echo "# GridFire Build Configuration"
echo " BUILD_DIR=\" $BUILD_DIR \" "
echo " INSTALL_PREFIX=\" $INSTALL_PREFIX \" "
echo " MESON_BUILD_TYPE=\" $MESON_BUILD_TYPE \" "
echo " MESON_LOG_LEVEL=\" $MESON_LOG_LEVEL \" "
echo " MESON_PKG_CONFIG=\" $MESON_PKG_CONFIG \" "
echo " MESON_NUM_CORES=\" $MESON_NUM_CORES \" "
echo " C_COMPILER=\" $C_COMPILER \" "
echo " CC_COMPILER=\" $CC_COMPILER \" "
echo " FC_COMPILER=\" $FC_COMPILER \" "
echo ""
echo "# Advanced Meson Options"
for key in " ${ !MESON_ADVANCED_OPTS[@] } " ; do
echo " MESON_ADVANCED_OPTS[\" $key \"]=\" ${ MESON_ADVANCED_OPTS [ $key ] } \" "
done
} > " $file_to_save "
dialog --title "Success" --msgbox " Configuration saved to:\n ${ file_to_save } " 8 60
}
run_load_config_tui( ) {
local file_to_load
file_to_load = $( dialog --title "Load Configuration" --inputbox "Enter filename to load configuration:" 10 60 " $CONFIG_FILE " 3>& 1 1>& 2 2>& 3)
if [ -z " $file_to_load " ] ; then
dialog --msgbox "Load cancelled." 8 50
return
fi
if [ ! -f " $file_to_load " ] ; then
dialog --msgbox " Error: File not found:\n ${ file_to_load } " 8 60
return
fi
# Source the file to load the variables
# We need to re-declare the associative array for it to be populated by source
declare -A MESON_ADVANCED_OPTS
# shellcheck source=/dev/null
. " $file_to_load "
# Re-validate the compiler
check_compiler
if ! check_command " $CC_COMPILER " ; then
dialog --title "Warning" --msgbox " Compiler ' ${ CC_COMPILER } ' from config file not found.\nRe-detecting a valid compiler. " 10 60
check_compiler
fi
dialog --title "Success" --msgbox " Configuration loaded from:\n ${ file_to_load } " 8 60
}
2025-07-29 11:40:01 -04:00
run_boost_help_tui( ) {
local help_text = "The version of the Boost library found on your system is not compatible with the selected C++ compiler and the C++23 standard. This is a common issue on distributions like Ubuntu that may have older versions of Boost in their package repositories.\n\n"
help_text += "To resolve this, you need to manually download, build, and install a newer version of Boost (e.g., 1.83.0 or newer).\n\n"
help_text += "Recommended Steps:\n"
help_text += "1. Download the latest Boost source from boost.org.\n"
help_text += "2. Follow their instructions to build it. A typical sequence is:\n"
help_text += " ./bootstrap.sh\n"
2025-07-29 12:29:02 -04:00
help_text += " sudo ./b2 install\n"
2025-07-29 11:40:01 -04:00
help_text += "Meson should then automatically find and use your manually installed version."
dialog --title "Boost Compatibility Issue" --msgbox " $help_text " 25 78
}
2025-07-29 11:22:39 -04:00
2025-07-29 09:25:44 -04:00
run_main_tui( ) {
if ! check_dialog_installed; then return 1; fi
2025-07-29 09:44:29 -04:00
# Initial check to populate compiler list and set a default
check_compiler
local sudo_status = "User Mode"
if [ " $EUID " -eq 0 ] ; then
sudo_status = "Root/Sudo Mode"
fi
2025-07-29 09:25:44 -04:00
2025-07-29 09:44:29 -04:00
while true; do
2025-07-29 11:40:01 -04:00
# Re-check boost status to update menu dynamically
if [ [ $BOOST_CHECKED = false ] ] ; then
2025-07-29 14:36:23 -04:00
BOOST_OKAY = true
2025-07-29 11:46:50 -04:00
log " ${ BLUE } [Info] Checking Boost library status (this may take a minute)... ${ NC } "
2025-07-29 11:40:01 -04:00
# If BOOST_CHECKED is set, we assume Boost was checked previously
2025-07-29 11:41:58 -04:00
check_boost >/dev/null 2>& 1 || BOOST_OKAY = false
2025-07-29 11:40:01 -04:00
BOOST_CHECKED = true
fi
local menu_items = (
"1" "Install System Dependencies"
"2" "Configure Build Options"
"3" "Install Python Bindings"
)
2025-07-29 11:41:58 -04:00
if $BOOST_OKAY ; then
2025-07-29 11:40:01 -04:00
menu_items += (
"4" "Run Full Build (Setup + Compile)"
"5" "Run Meson Setup/Reconfigure"
"6" "Run Meson Compile"
"7" "Run Meson Install (requires sudo)"
"8" "Run Tests"
"S" "Save Configuration"
"L" "Load Configuration"
)
fi
2025-07-29 11:41:58 -04:00
if ! $BOOST_OKAY ; then
2025-07-29 11:40:01 -04:00
menu_items += ( "B" "Boost Error Detected! Help with Boost Issues" )
fi
2025-07-29 15:25:50 -04:00
menu_items += (
"N" "View Notes"
"Q" "Exit"
)
2025-07-29 11:40:01 -04:00
2025-07-29 09:25:44 -04:00
local choice
2025-07-29 09:44:29 -04:00
choice = $( dialog --clear --backtitle " GridFire Installer - [ ${ sudo_status } ] " \
2025-07-29 09:25:44 -04:00
--title "Main Menu" \
2025-07-29 11:40:01 -04:00
--menu " C: ${ C_COMPILER :- N /A } C++: ${ CC_COMPILER :- N /A } FC: ${ FC_COMPILER :- N /A } \nDIR: ${ BUILD_DIR } | TYPE: ${ MESON_BUILD_TYPE } | CORES: ${ MESON_NUM_CORES } \nPREFIX: ${ INSTALL_PREFIX } \nLOG: ${ MESON_LOG_LEVEL } | PKG-CONFIG: ${ MESON_PKG_CONFIG } " 24 78 14 \
" ${ menu_items [@] } " \
2025-07-29 09:25:44 -04:00
3>& 1 1>& 2 2>& 3)
clear
case " $choice " in
2025-07-29 13:44:43 -04:00
1)
run_dependency_installer_tui
BOOST_CHECKED = false # Force re-check after installing
; ;
2025-07-29 09:25:44 -04:00
2) run_build_config_tui ; ;
3) run_python_bindings_tui ; ;
4) run_meson_setup && run_meson_compile ; ;
5) run_meson_setup ; ;
6) run_meson_compile ; ;
7) run_meson_install ; ;
8) run_meson_tests ; ;
2025-07-29 11:40:01 -04:00
N) run_notes_tui ; ;
S) run_save_config_tui ; ;
L) run_load_config_tui ; ;
B) run_boost_help_tui ; ;
Q) break ; ;
2025-07-29 09:25:44 -04:00
*) log " ${ YELLOW } [Info] TUI cancelled. ${ NC } " ; break ; ;
esac
done
clear
}
2025-07-29 09:05:47 -04:00
# --- Script Entry Point ---
main( ) {
2025-07-29 09:25:44 -04:00
if [ [ " $@ " = ~ " --help " ] ] || [ [ " $@ " = ~ " -h " ] ] ; then show_help; exit 0; fi
if [ [ " $@ " = ~ " --clean " ] ] ; then log " ${ BLUE } [Info] Cleaning up... ${ NC } " ; rm -rf " $BUILD_DIR " " $LOGFILE " ; fi
2025-07-29 09:05:47 -04:00
2025-07-29 11:40:01 -04:00
local useTUI = 0
2025-07-29 09:25:44 -04:00
if [ [ " $@ " = ~ " --tui " ] ] ; then
2025-07-29 11:40:01 -04:00
useTUI = 1
log " ${ BLUE } [Info] Using TUI mode... ${ NC } "
2025-07-29 09:05:47 -04:00
fi
2025-07-29 11:22:39 -04:00
# Handle --config argument
while [ $# -gt 0 ] ; do
case " $1 " in
--config)
if [ -f " $2 " ] ; then
log " ${ BLUE } [Info] Loading configuration from $2 ... ${ NC } "
declare -A MESON_ADVANCED_OPTS
# shellcheck source=/dev/null
. " $2 "
else
log " ${ RED } [Error] Configuration file not found: $2 ${ NC } "
exit 1
fi
shift 2
; ;
*)
shift
; ;
esac
done
2025-07-29 11:40:01 -04:00
if [ [ $useTUI -eq 1 ] ] ; then
run_main_tui
log " ${ GREEN } Exited TUI mode. ${ NC } "
exit 0
fi
echo "" > " $LOGFILE " # Clear log file
log "--- GridFire Installation Log ---"
log " Date: $( date) "
log " OS: ${ OS_NAME } , Distro: ${ DISTRO_ID } "
2025-07-29 11:22:39 -04:00
2025-07-29 09:25:44 -04:00
# --- Non-TUI path ---
log " \n ${ BLUE } --- Checking System Dependencies (CLI Mode) --- ${ NC } "
2025-07-29 09:44:29 -04:00
# Run check_compiler first to set the default
check_compiler
2025-07-29 09:25:44 -04:00
declare -A CHECKS = (
2025-07-29 09:44:29 -04:00
[ python-dev] = "check_python_dev" [ meson-python] = "check_meson_python" [ cmake] = "check_cmake"
[ meson] = "check_meson" [ boost] = "check_boost"
2025-07-29 09:25:44 -04:00
)
2025-07-29 09:44:29 -04:00
if ! check_compiler; then
# Handle case where no compiler is found
local install_cmd; install_cmd = $( get_install_cmd "compiler" )
if [ -n " $install_cmd " ] ; then
if prompt_yes_no "Dependency 'compiler' is missing. Attempt to install? (y/n):" ; then
eval " $install_cmd " 2>& 1 | tee -a " $LOGFILE "
fi
else
log " ${ RED } [Error] No automatic installation for 'compiler'. Please install manually. ${ NC } "
fi
fi
2025-07-29 09:25:44 -04:00
for dep in " ${ !CHECKS[@] } " ; do
if ! ${ CHECKS [ $dep ] } ; 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? (y/n): " ; then
2025-07-29 09:44:29 -04:00
eval " $install_cmd " 2>& 1 | tee -a " $LOGFILE "
2025-07-29 09:25:44 -04:00
fi
else
log " ${ RED } [Error] No automatic installation for ' ${ dep } '. Please install manually. ${ NC } "
2025-07-29 09:05:47 -04:00
fi
fi
2025-07-29 09:25:44 -04:00
done
2025-07-29 09:05:47 -04:00
2025-07-29 09:25:44 -04:00
log " \n ${ BLUE } --- Re-checking all dependencies --- ${ NC } "
local final_fail = false
2025-07-29 09:44:29 -04:00
# Re-add compiler check to the list for final verification
CHECKS[ compiler] = "check_compiler"
2025-07-29 09:25:44 -04:00
for dep in " ${ !CHECKS[@] } " ; do
if ! ${ CHECKS [ $dep ] } ; then
log " ${ RED } [FATAL] Dependency still missing: ${ dep } ${ NC } "
final_fail = true
fi
2025-07-29 09:05:47 -04:00
done
2025-07-29 09:25:44 -04:00
if $final_fail ; then
log " ${ RED } Please install missing dependencies and re-run. ${ NC } "
exit 1
2025-07-29 09:05:47 -04:00
fi
2025-07-29 09:25:44 -04:00
log " \n ${ GREEN } --- All dependencies met. Proceeding with build. --- ${ NC } "
run_meson_setup && run_meson_compile
2025-07-29 09:05:47 -04:00
}
main " $@ "