build(install): added venv python managment
This commit is contained in:
19
README.md
19
README.md
@@ -31,7 +31,8 @@ GridFire is a part of the 4D-STAR collaboration.
|
|||||||
Work for this project is funded by the European Union. Views and opinions expressed are however those of the author(s)
|
Work for this project is funded by the European Union. Views and opinions expressed are however those of the author(s)
|
||||||
only and do not necessarily reflect those of the European Union or the European Research Council.
|
only and do not necessarily reflect those of the European Union or the European Research Council.
|
||||||
|
|
||||||
## Build and Installation Instructions
|
## Automatic Build and Installation
|
||||||
|
### Script Build and Installation Instructions
|
||||||
|
|
||||||
The easiest way to build GridFire is using the `install.sh` or `install-tui.sh` scripts in the root directory. To use
|
The easiest way to build GridFire is using the `install.sh` or `install-tui.sh` scripts in the root directory. To use
|
||||||
these scripts, simply run:
|
these scripts, simply run:
|
||||||
@@ -41,14 +42,28 @@ these scripts, simply run:
|
|||||||
# or
|
# or
|
||||||
./install-tui.sh
|
./install-tui.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
The regular installation script will select a standard "ideal" set of build options for you. If you want more control
|
The regular installation script will select a standard "ideal" set of build options for you. If you want more control
|
||||||
over the build options, you can use the `install-tui.sh` script, which will provide a text-based user interface to
|
over the build options, you can use the `install-tui.sh` script, which will provide a text-based user interface to
|
||||||
select the build options you want.
|
select the build options you want.
|
||||||
|
|
||||||
Generally, both are intended to be easy to use and will prompt you automatically to install any missing dependencies.
|
Generally, both are intended to be easy to use and will prompt you automatically to install any missing dependencies.
|
||||||
|
|
||||||
|
|
||||||
|
### Currently known good platforms
|
||||||
|
The installation script has been tested and found to work on clean installations of the following platforms:
|
||||||
|
- MacOS 15.3.2 (Apple Silicon + brew installed)
|
||||||
|
- Fedora 42.0 (aarch64)
|
||||||
|
- Ubuntu 25.04 (aarch64)
|
||||||
|
- Ubuntu 22.04 (X86_64)
|
||||||
|
|
||||||
|
> **Note:** On Ubuntu 22.04 the user needs to install boost libraries manually as the versions in the Ubuntu repositories
|
||||||
|
are too old. The installer automatically detects this and will instruct the user in how to do this.
|
||||||
|
|
||||||
|
## Manual Build Instructions
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
These only need to be manually installed if the user is not making use of the `install.sh` or `install-tui.sh`
|
||||||
|
|
||||||
- C++ compiler supporting C++23 standard
|
- C++ compiler supporting C++23 standard
|
||||||
- Meson build system (>= 1.5.0)
|
- Meson build system (>= 1.5.0)
|
||||||
- Python 3.10 or newer
|
- Python 3.10 or newer
|
||||||
|
|||||||
122
install.sh
122
install.sh
@@ -17,6 +17,7 @@ set -o pipefail
|
|||||||
LOGFILE="GridFire_Installer.log"
|
LOGFILE="GridFire_Installer.log"
|
||||||
NOTES_FILE="notes.txt"
|
NOTES_FILE="notes.txt"
|
||||||
CONFIG_FILE="gridfire_build.conf"
|
CONFIG_FILE="gridfire_build.conf"
|
||||||
|
VENV_DIR=".venv"
|
||||||
MIN_GCC_VER="13.0.0"
|
MIN_GCC_VER="13.0.0"
|
||||||
MIN_CLANG_VER="16.0.0"
|
MIN_CLANG_VER="16.0.0"
|
||||||
MIN_MESON_VER="1.5.0"
|
MIN_MESON_VER="1.5.0"
|
||||||
@@ -146,6 +147,25 @@ check_command() {
|
|||||||
command -v "$1" &>/dev/null
|
command -v "$1" &>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_externally_managed() {
|
||||||
|
# Check for the PEP 668 marker file
|
||||||
|
local py_prefix
|
||||||
|
py_prefix=$(python3 -c "import sys; print(sys.prefix)")
|
||||||
|
if [ -f "$py_prefix/EXTERNALLY-MANAGED" ]; then
|
||||||
|
return 0 # 0 means true in bash
|
||||||
|
else
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
set_compilers() {
|
set_compilers() {
|
||||||
if [[ "$CC_COMPILER" == *"clang++"* ]]; then
|
if [[ "$CC_COMPILER" == *"clang++"* ]]; then
|
||||||
C_COMPILER=$(echo "$CC_COMPILER" | sed 's/clang++/clang/')
|
C_COMPILER=$(echo "$CC_COMPILER" | sed 's/clang++/clang/')
|
||||||
@@ -227,6 +247,16 @@ check_compiler() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
check_python_dev() {
|
check_python_dev() {
|
||||||
if check_command python3 && python3-config --includes &>/dev/null; then
|
if check_command python3 && python3-config --includes &>/dev/null; then
|
||||||
log "${GREEN}[OK] Found Python 3 development headers.${NC}"
|
log "${GREEN}[OK] Found Python 3 development headers.${NC}"
|
||||||
@@ -238,6 +268,12 @@ check_python_dev() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_meson_python() {
|
check_meson_python() {
|
||||||
|
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
|
||||||
if python3 -c "import mesonpy" &>/dev/null; then
|
if python3 -c "import mesonpy" &>/dev/null; then
|
||||||
log "${GREEN}[OK] Found meson-python package.${NC}"
|
log "${GREEN}[OK] Found meson-python package.${NC}"
|
||||||
return 0
|
return 0
|
||||||
@@ -258,8 +294,13 @@ check_cmake() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_meson() {
|
check_meson() {
|
||||||
if check_command meson; then
|
local meson_cmd="meson"
|
||||||
local ver; ver=$(meson --version)
|
if [ -d "$VENV_DIR" ]; then
|
||||||
|
meson_cmd="$VENV_DIR/bin/meson"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_command "$meson_cmd"; then
|
||||||
|
local ver; ver=$($meson_cmd --version)
|
||||||
vercomp "$ver" "$MIN_MESON_VER"
|
vercomp "$ver" "$MIN_MESON_VER"
|
||||||
if [[ $? -ne 2 ]]; then
|
if [[ $? -ne 2 ]]; then
|
||||||
log "${GREEN}[OK] Found Meson ${ver}.${NC}"
|
log "${GREEN}[OK] Found Meson ${ver}.${NC}"
|
||||||
@@ -383,6 +424,7 @@ get_install_cmd() {
|
|||||||
case "$dep_name" in
|
case "$dep_name" in
|
||||||
"compiler") cmd="$brew_cmd install gcc llvm" ;; # Install both
|
"compiler") cmd="$brew_cmd install gcc llvm" ;; # Install both
|
||||||
"python-dev") cmd="$brew_cmd install python3" ;;
|
"python-dev") cmd="$brew_cmd install python3" ;;
|
||||||
|
"pip") cmd="python3 -m ensurepip --upgrade" ;;
|
||||||
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
||||||
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
||||||
"cmake") cmd="$brew_cmd install cmake" ;;
|
"cmake") cmd="$brew_cmd install cmake" ;;
|
||||||
@@ -396,6 +438,7 @@ get_install_cmd() {
|
|||||||
case "$dep_name" in
|
case "$dep_name" in
|
||||||
"compiler") cmd="sudo apt-get install -y g++-13 gfortran-13 clang-16" ;;
|
"compiler") cmd="sudo apt-get install -y g++-13 gfortran-13 clang-16" ;;
|
||||||
"python-dev") cmd="sudo apt-get install -y python3-dev" ;;
|
"python-dev") cmd="sudo apt-get install -y python3-dev" ;;
|
||||||
|
"pip") cmd="sudo apt-get install -y python3-pip" ;;
|
||||||
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
||||||
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
||||||
"cmake") cmd="sudo apt-get install -y cmake" ;;
|
"cmake") cmd="sudo apt-get install -y cmake" ;;
|
||||||
@@ -407,6 +450,7 @@ get_install_cmd() {
|
|||||||
case "$dep_name" in
|
case "$dep_name" in
|
||||||
"compiler") cmd="sudo dnf install -y gcc-c++ gcc-gfortran clang" ;;
|
"compiler") cmd="sudo dnf install -y gcc-c++ gcc-gfortran clang" ;;
|
||||||
"python-dev") cmd="sudo dnf install -y python3-devel" ;;
|
"python-dev") cmd="sudo dnf install -y python3-devel" ;;
|
||||||
|
"pip") cmd="sudo dnf install -y python3-pip" ;;
|
||||||
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
||||||
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
||||||
"cmake") cmd="sudo dnf install -y cmake" ;;
|
"cmake") cmd="sudo dnf install -y cmake" ;;
|
||||||
@@ -418,6 +462,7 @@ get_install_cmd() {
|
|||||||
case "$dep_name" in
|
case "$dep_name" in
|
||||||
"compiler") cmd="sudo pacman -S --noconfirm gcc gcc-fortran clang" ;;
|
"compiler") cmd="sudo pacman -S --noconfirm gcc gcc-fortran clang" ;;
|
||||||
"python-dev") cmd="sudo pacman -S --noconfirm python" ;;
|
"python-dev") cmd="sudo pacman -S --noconfirm python" ;;
|
||||||
|
"pip") cmd="sudo pacman -S --noconfirm python-pip" ;;
|
||||||
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
"meson-python") cmd="python3 -m pip install meson-python" ;;
|
||||||
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
"meson") cmd="python3 -m pip install --upgrade meson" ;;
|
||||||
"cmake") cmd="sudo pacman -S --noconfirm cmake" ;;
|
"cmake") cmd="sudo pacman -S --noconfirm cmake" ;;
|
||||||
@@ -533,10 +578,27 @@ check_dialog_installed() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
dialog --msgbox "Failed to create virtual environment. Please ensure 'python3-venv' is installed." 8 60
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
log "${GREEN}[Success] Virtual environment created.${NC}"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
run_dependency_installer_tui() {
|
run_dependency_installer_tui() {
|
||||||
# This function now just calls the check functions to populate status
|
# This function now just calls the check functions to populate status
|
||||||
declare -A DEP_STATUS
|
declare -A DEP_STATUS
|
||||||
check_compiler >/dev/null; DEP_STATUS[compiler]=$?
|
check_compiler >/dev/null; DEP_STATUS[compiler]=$?
|
||||||
|
check_pip >/dev/null; DEP_STATUS[pip]=$?
|
||||||
check_python_dev >/dev/null; DEP_STATUS[python-dev]=$?
|
check_python_dev >/dev/null; DEP_STATUS[python-dev]=$?
|
||||||
check_meson_python >/dev/null; DEP_STATUS[meson-python]=$?
|
check_meson_python >/dev/null; DEP_STATUS[meson-python]=$?
|
||||||
check_cmake >/dev/null; DEP_STATUS[cmake]=$?
|
check_cmake >/dev/null; DEP_STATUS[cmake]=$?
|
||||||
@@ -548,8 +610,9 @@ run_dependency_installer_tui() {
|
|||||||
local choices
|
local choices
|
||||||
choices=$(dialog --clear --backtitle "Project Dependency Installer" \
|
choices=$(dialog --clear --backtitle "Project Dependency Installer" \
|
||||||
--title "Install System Dependencies" \
|
--title "Install System Dependencies" \
|
||||||
--checklist "Select dependencies to install. Already found dependencies are unchecked." 20 70 6 \
|
--checklist "Select dependencies to install. Already found dependencies are unchecked." 20 70 7 \
|
||||||
"compiler" "C++ Compilers (g++, clang++)" "$([[ ${DEP_STATUS[compiler]} -ne 0 ]] && echo "on" || echo "off")" \
|
"compiler" "C++ Compilers (g++, clang++)" "$([[ ${DEP_STATUS[compiler]} -ne 0 ]] && echo "on" || echo "off")" \
|
||||||
|
"pip" "Python Package Installer (pip)" "$([[ ${DEP_STATUS[pip]} -ne 0 ]] && echo "on" || echo "off")" \
|
||||||
"python-dev" "Python 3 Dev Headers" "$([[ ${DEP_STATUS[python-dev]} -ne 0 ]] && echo "on" || echo "off")" \
|
"python-dev" "Python 3 Dev Headers" "$([[ ${DEP_STATUS[python-dev]} -ne 0 ]] && echo "on" || echo "off")" \
|
||||||
"meson-python" "meson-python (for Python bindings)" "$([[ ${DEP_STATUS[meson-python]} -ne 0 ]] && echo "on" || echo "off")" \
|
"meson-python" "meson-python (for Python bindings)" "$([[ ${DEP_STATUS[meson-python]} -ne 0 ]] && echo "on" || echo "off")" \
|
||||||
"cmake" "CMake" "$([[ ${DEP_STATUS[cmake]} -ne 0 ]] && echo "on" || echo "off")" \
|
"cmake" "CMake" "$([[ ${DEP_STATUS[cmake]} -ne 0 ]] && echo "on" || echo "off")" \
|
||||||
@@ -563,6 +626,18 @@ run_dependency_installer_tui() {
|
|||||||
for choice in $choices; do
|
for choice in $choices; do
|
||||||
local dep; dep=$(echo "$choice" | tr -d '"')
|
local dep; dep=$(echo "$choice" | tr -d '"')
|
||||||
log "\n${BLUE}--- Installing ${dep} ---${NC}"
|
log "\n${BLUE}--- Installing ${dep} ---${NC}"
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
else
|
||||||
local install_cmd; install_cmd=$(get_install_cmd "$dep")
|
local install_cmd; install_cmd=$(get_install_cmd "$dep")
|
||||||
if [ -n "$install_cmd" ]; then
|
if [ -n "$install_cmd" ]; then
|
||||||
eval "$install_cmd" 2>&1 | tee -a "$LOGFILE"
|
eval "$install_cmd" 2>&1 | tee -a "$LOGFILE"
|
||||||
@@ -570,12 +645,11 @@ run_dependency_installer_tui() {
|
|||||||
log "${RED}[Error] No automatic installation command for '${dep}'. Please install manually.${NC}"
|
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
|
dialog --msgbox "Could not find an automatic installation command for '${dep}' on your system. Please install it manually." 8 60
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
# Re-run check to update status
|
# Re-run check to update status
|
||||||
check_compiler
|
check_compiler
|
||||||
log "${BLUE}[Info] Checking Boost library status (this may take a minute)...${NC}"
|
BOOST_CHECKED=false # Force re-check of boost
|
||||||
# If BOOST_CHECKED is set, we assume Boost was checked previously
|
|
||||||
check_boost >/dev/null 2>&1 || BOOST_OKAY=false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run_python_bindings_tui() {
|
run_python_bindings_tui() {
|
||||||
@@ -595,6 +669,33 @@ run_python_bindings_tui() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
local choice
|
local choice
|
||||||
choice=$(dialog --clear --backtitle "Python Bindings Installer" \
|
choice=$(dialog --clear --backtitle "Python Bindings Installer" \
|
||||||
--title "Install Python Bindings" \
|
--title "Install Python Bindings" \
|
||||||
@@ -607,7 +708,7 @@ run_python_bindings_tui() {
|
|||||||
case "$choice" in
|
case "$choice" in
|
||||||
1)
|
1)
|
||||||
log "${BLUE}[Info] Installing Python bindings in Developer Mode...${NC}"
|
log "${BLUE}[Info] Installing Python bindings in Developer Mode...${NC}"
|
||||||
if ! CC="${C_COMPILER}" CXX="${CC_COMPILER}" FC="${FC_COMPILER}" pip install -e . --no-build-isolation -vv; then
|
if ! CC="${C_COMPILER}" CXX="${CC_COMPILER}" FC="${FC_COMPILER}" $pip_cmd install $pip_opts -e . --no-build-isolation -vv; then
|
||||||
log "${RED}[Error] Failed to install Python bindings in developer mode.${NC}"
|
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
|
dialog --msgbox "Developer mode installation failed. Check the log for details." 8 60
|
||||||
else
|
else
|
||||||
@@ -617,7 +718,7 @@ run_python_bindings_tui() {
|
|||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
log "${BLUE}[Info] Installing Python bindings in User Mode...${NC}"
|
log "${BLUE}[Info] Installing Python bindings in User Mode...${NC}"
|
||||||
if ! CC="${C_COMPILER}" CXX="${CC_COMPILER}" FC="${FC_COMPILER}" pip install .; then
|
if ! CC="${C_COMPILER}" CXX="${CC_COMPILER}" FC="${FC_COMPILER}" $pip_cmd install $pip_opts .; then
|
||||||
log "${RED}[Error] Failed to install Python bindings in user mode.${NC}"
|
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
|
dialog --msgbox "User mode installation failed. Check the log for details." 8 60
|
||||||
else
|
else
|
||||||
@@ -1062,7 +1163,10 @@ run_main_tui() {
|
|||||||
|
|
||||||
clear
|
clear
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
1) run_dependency_installer_tui ;;
|
1)
|
||||||
|
run_dependency_installer_tui
|
||||||
|
BOOST_CHECKED=false # Force re-check after installing
|
||||||
|
;;
|
||||||
2) run_build_config_tui ;;
|
2) run_build_config_tui ;;
|
||||||
3) run_python_bindings_tui ;;
|
3) run_python_bindings_tui ;;
|
||||||
4) run_meson_setup && run_meson_compile ;;
|
4) run_meson_setup && run_meson_compile ;;
|
||||||
|
|||||||
Reference in New Issue
Block a user