#!/usr/bin/env bash

# BSD 2-Clause License
#
# Copyright (c) 2021-2025, Christoph Neuhauser
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Conda crashes with "set -euo pipefail".
set -eo pipefail

scriptpath="$( cd "$(dirname "$0")" ; pwd -P )"
projectpath="$scriptpath"
pushd $scriptpath > /dev/null

if [[ "$(uname -s)" =~ ^MSYS_NT.* ]] || [[ "$(uname -s)" =~ ^MINGW.* ]]; then
    use_msys=true
    if [[ -z "${MINGW_PACKAGE_PREFIX+x}" ]]; then
        pkg_prefix="mingw-w64-x86_64"
    else
        pkg_prefix="$MINGW_PACKAGE_PREFIX"
    fi
else
    use_msys=false
fi
if [[ "$(uname -s)" =~ ^Darwin.* ]]; then
    use_macos=true
else
    use_macos=false
fi
os_arch="$(uname -m)"

run_program=true
debug=false
glibcxx_debug=false
clean=false
build_dir_debug=".build_debug"
build_dir_release=".build_release"
install_dir="install"
if $use_msys; then
    msystem_lower=$(echo "$MSYSTEM" | tr '[:upper:]' '[:lower:]')
    build_dir_debug="${build_dir_debug}-${msystem_lower}"
    build_dir_release="${build_dir_release}-${msystem_lower}"
    install_dir="${install_dir}-${msystem_lower}"
fi
use_vcpkg=false
use_conda=false
conda_env_name="linevis"
link_dynamic=false
use_custom_vcpkg_triplet=false
custom_glslang=false
use_open_image_denoise=true
use_download_swapchain=false
if [ $use_msys = false ] && command -v pacman &> /dev/null; then
    is_embree_installed=true
    is_ospray_installed=true
else
    is_embree_installed=false
    is_ospray_installed=false
fi
use_ospray3=false
if [ $use_msys = false ] && ([ $use_macos = false ] || [[ $(uname -m) == 'x86_64' ]]); then
    use_ospray2=true
else
    use_ospray2=false
fi
# Optionally, the program can be built on Windows with MSYS2 with Direct3D 12 support for some renderers.
use_d3d=false

# Check if a conda environment is already active.
if $use_conda; then
    if [ ! -z "${CONDA_DEFAULT_ENV+x}" ]; then
        conda_env_name="$CONDA_DEFAULT_ENV"
    fi
fi

# Process command line arguments.
for ((i=1;i<=$#;i++));
do
    if [ ${!i} = "--do-not-run" ]; then
        run_program=false
    elif [ ${!i} = "--debug" ] || [ ${!i} = "debug" ]; then
        debug=true
    elif [ ${!i} = "--glibcxx-debug" ]; then
        glibcxx_debug=true
    elif [ ${!i} = "--clean" ] || [ ${!i} = "clean" ]; then
        clean=true
    elif [ ${!i} = "--vcpkg" ] || [ ${!i} = "--use-vcpkg" ]; then
        use_vcpkg=true
    elif [ ${!i} = "--conda" ] || [ ${!i} = "--use-conda" ]; then
        use_conda=true
    elif [ ${!i} = "--conda-env-name" ]; then
        ((i++))
        conda_env_name=${!i}
    elif [ ${!i} = "--link-static" ]; then
        link_dynamic=false
    elif [ ${!i} = "--link-dynamic" ]; then
        link_dynamic=true
    elif [ ${!i} = "--vcpkg-triplet" ]; then
        ((i++))
        vcpkg_triplet=${!i}
        use_custom_vcpkg_triplet=true
    elif [ ${!i} = "--custom-glslang" ]; then
        custom_glslang=true
    elif [ ${!i} = "--dlswap" ]; then
        use_download_swapchain=true
        build_with_vkvg_support=true
    elif [ ${!i} = "--d3d" ]; then
        use_d3d=true
    elif [ ${!i} = "--ospray2" ]; then
        use_ospray2=true
        use_ospray3=false
    elif [ ${!i} = "--ospray3" ]; then
        use_ospray2=false
        use_ospray3=true
    fi
done

if [ $clean = true ]; then
    echo "------------------------"
    echo " cleaning up old files  "
    echo "------------------------"
    rm -rf third_party/vcpkg/ $build_dir_debug/ $build_dir_release/ Shipping/
    if grep -wq "sgl" .gitmodules; then
        rm -rf third_party/sgl/$install_dir/ third_party/sgl/$build_dir_debug/ third_party/sgl/$build_dir_release/
    else
        rm -rf third_party/sgl/
    fi
    git submodule update --init --recursive
fi

if [ $debug = true ]; then
    cmake_config="Debug"
    build_dir=$build_dir_debug
else
    cmake_config="Release"
    build_dir=$build_dir_release
fi
destination_dir="Shipping"
if $use_macos; then
    binaries_dest_dir="$destination_dir/LineVis.app/Contents/MacOS"
    if ! command -v brew &> /dev/null; then
        if [ ! -d "/opt/homebrew/bin" ]; then
            /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
        fi
        if [ -d "/opt/homebrew/bin" ]; then
            #echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/$USER/.zprofile
            eval "$(/opt/homebrew/bin/brew shellenv)"
        fi
    fi
fi

params_link=()
params_vcpkg=()
build_sgl_release_only=false
if [ $use_custom_vcpkg_triplet = true ]; then
    params_link+=(-DVCPKG_TARGET_TRIPLET=$vcpkg_triplet)
    if [ -f "$projectpath/third_party/vcpkg/triplets/$vcpkg_triplet.cmake" ]; then
        triplet_file_path="$projectpath/third_party/vcpkg/triplets/$vcpkg_triplet.cmake"
    elif [ -f "$projectpath/third_party/vcpkg/triplets/community/$vcpkg_triplet.cmake" ]; then
        triplet_file_path="$projectpath/third_party/vcpkg/triplets/community/$vcpkg_triplet.cmake"
    else
        echo "Custom vcpkg triplet set, but file not found."
        exit 1
    fi
    if grep -q "VCPKG_BUILD_TYPE release" "$triplet_file_path"; then
        build_sgl_release_only=true
    fi
elif [ $use_vcpkg = true ] && [ $use_macos = false ] && [ $link_dynamic = true ]; then
    params_link+=(-DVCPKG_TARGET_TRIPLET=x64-linux-dynamic)
fi
if [ $use_vcpkg = true ] && [ $use_macos = false ]; then
    params_vcpkg+=(-DUSE_STATIC_STD_LIBRARIES=On)
fi
if [ $use_vcpkg = true ]; then
    params_vcpkg+=(-DCMAKE_TOOLCHAIN_FILE="$projectpath/third_party/vcpkg/scripts/buildsystems/vcpkg.cmake")
fi

is_installed_apt() {
    local pkg_name="$1"
    if [ "$(dpkg -l | awk '/'"$pkg_name"'/ {print }'|wc -l)" -ge 1 ]; then
        return 0
    else
        return 1
    fi
}
is_available_apt() {
    local pkg_name="$1"
    if [ -z "$(apt-cache search --names-only $pkg_name)" ]; then
        return 1
    else
        return 0
    fi
}

is_installed_pacman() {
    local pkg_name="$1"
    if pacman -Qs $pkg_name > /dev/null; then
        return 0
    else
        return 1
    fi
}
is_available_pacman() {
    local pkg_name="$1"
    if pacman -Ss $pkg_name > /dev/null; then
        return 0
    else
        return 1
    fi
}

is_installed_yay() {
    local pkg_name="$1"
    if yay -Ss $pkg_name > /dev/null | grep -q 'instal'; then
        return 1
    else
        return 0
    fi
}

is_installed_yum() {
    local pkg_name="$1"
    if yum list installed "$pkg_name" > /dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}
is_available_yum() {
    local pkg_name="$1"
    if yum list "$pkg_name" > /dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

# is_installed_rpm is supposedly faster than is_installed_yum.
is_installed_rpm() {
    local pkg_name="$1"
    if rpm -q "$pkg_name" > /dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

is_installed_brew() {
    local pkg_name="$1"
    if brew list $pkg_name > /dev/null; then
        return 0
    else
        return 1
    fi
}

# https://stackoverflow.com/questions/8063228/check-if-a-variable-exists-in-a-list-in-bash
list_contains() {
    if [[ "$1" =~ (^|[[:space:]])"$2"($|[[:space:]]) ]]; then
        return 0
    else
        return 1
    fi
}

if $use_msys && command -v pacman &> /dev/null && [ ! -d $build_dir_debug ] && [ ! -d $build_dir_release ]; then
    if ! command -v cmake &> /dev/null || ! command -v git &> /dev/null || ! command -v rsync &> /dev/null \
            || ! command -v curl &> /dev/null || ! command -v wget &> /dev/null || ! command -v unzip &> /dev/null \
            || ! command -v pkg-config &> /dev/null || ! command -v ntldd &> /dev/null; then
        echo "------------------------"
        echo "installing build essentials"
        echo "------------------------"
        pacman --noconfirm -S --needed make git rsync curl wget unzip ${pkg_prefix}-cmake ${pkg_prefix}-ntldd
    fi
    if [[ "$msystem_lower" =~ ^clang.* ]]; then
        if ! command -v clang++ &> /dev/null; then
            # https://packages.msys2.org/groups/mingw-w64-clang-x86_64-toolchain
            echo "------------------------"
            echo "  installing compiler   "
            echo "------------------------"
            pacman --noconfirm -S --needed ${pkg_prefix}-toolchain
        fi
    else
        if ! command -v g++ &> /dev/null; then
            # https://packages.msys2.org/groups/mingw-w64-x86_64-toolchain
            echo "------------------------"
            echo "  installing compiler   "
            echo "------------------------"
            pacman --noconfirm -S --needed ${pkg_prefix}-toolchain
        fi
    fi

    # Dependencies of sgl and the application.
    if ! is_installed_pacman "${pkg_prefix}-boost" || ! is_installed_pacman "${pkg_prefix}-icu" \
            || ! is_installed_pacman "${pkg_prefix}-glm" || ! is_installed_pacman "${pkg_prefix}-libarchive" \
            || ! is_installed_pacman "${pkg_prefix}-tinyxml2" || ! is_installed_pacman "${pkg_prefix}-libpng" \
            || ! is_installed_pacman "${pkg_prefix}-sdl3" || ! is_installed_pacman "${pkg_prefix}-sdl3-image" \
            || ! is_installed_pacman "${pkg_prefix}-glew" || ! is_installed_pacman "${pkg_prefix}-vulkan-headers" \
            || ! is_installed_pacman "${pkg_prefix}-vulkan-loader" \
            || ! is_installed_pacman "${pkg_prefix}-vulkan-validation-layers" \
            || ! is_installed_pacman "${pkg_prefix}-shaderc" || ! is_installed_pacman "${pkg_prefix}-directx-headers" \
            || ! is_installed_pacman "${pkg_prefix}-opencl-headers" || ! is_installed_pacman "${pkg_prefix}-opencl-icd" \
            || ! is_installed_pacman "${pkg_prefix}-jsoncpp" || ! is_installed_pacman "${pkg_prefix}-eigen3" \
            || ! is_installed_pacman "${pkg_prefix}-python" || ! is_installed_pacman "${pkg_prefix}-zeromq" \
            || ! is_installed_pacman "${pkg_prefix}-cppzmq" || ! is_installed_pacman "${pkg_prefix}-netcdf" \
            || ! is_installed_pacman "${pkg_prefix}-openexr" || ! is_installed_pacman "${pkg_prefix}-eccodes"; then
        echo "------------------------"
        echo "installing dependencies "
        echo "------------------------"
        pacman --noconfirm --needed -S ${pkg_prefix}-boost ${pkg_prefix}-icu ${pkg_prefix}-glm ${pkg_prefix}-libarchive \
        ${pkg_prefix}-tinyxml2 ${pkg_prefix}-libpng ${pkg_prefix}-sdl3 ${pkg_prefix}-sdl3-image ${pkg_prefix}-glew \
        ${pkg_prefix}-vulkan-headers ${pkg_prefix}-vulkan-loader ${pkg_prefix}-vulkan-validation-layers \
        ${pkg_prefix}-shaderc ${pkg_prefix}-directx-headers ${pkg_prefix}-opencl-headers ${pkg_prefix}-opencl-icd \
        ${pkg_prefix}-jsoncpp ${pkg_prefix}-eigen3 ${pkg_prefix}-python ${pkg_prefix}-zeromq ${pkg_prefix}-cppzmq \
        ${pkg_prefix}-netcdf ${pkg_prefix}-openexr ${pkg_prefix}-eccodes
    fi
elif $use_msys && command -v pacman &> /dev/null; then
    :
elif [ ! -z "${BUILD_USE_NIX+x}" ]; then
    echo "------------------------"
    echo "   building using Nix"
    echo "------------------------"
elif $use_macos && command -v brew &> /dev/null && [ ! -d $build_dir_debug ] && [ ! -d $build_dir_release ]; then
    if ! is_installed_brew "git"; then
        brew install git
    fi
    if ! is_installed_brew "cmake"; then
        brew install cmake
    fi
    if ! is_installed_brew "curl"; then
        brew install curl
    fi
    if ! is_installed_brew "wget"; then
        brew install wget
    fi
    if ! is_installed_brew "pkg-config"; then
        brew install pkg-config
    fi
    if ! is_installed_brew "llvm@20"; then
        brew install llvm@20
    fi
    if ! is_installed_brew "libomp"; then
        brew install libomp
    fi
    if ! is_installed_brew "make"; then
        brew install make
    fi
    if ! is_installed_brew "autoconf"; then
        brew install autoconf
    fi
    if ! is_installed_brew "automake"; then
        brew install automake
    fi
    if ! is_installed_brew "autoconf-archive"; then
        brew install autoconf-archive
    fi

    # Homebrew MoltenVK does not contain script for setting environment variables, unfortunately.
    #if ! is_installed_brew "molten-vk"; then
    #    brew install molten-vk
    #fi

    # Dependencies of sgl and the application.
    if [ $use_vcpkg = false ]; then
        if ! is_installed_brew "boost"; then
            brew install boost
        fi
        if ! is_installed_brew "icu4c"; then
            brew install icu4c
        fi
        if ! is_installed_brew "glm"; then
            brew install glm
        fi
        if ! is_installed_brew "libarchive"; then
            brew install libarchive
        fi
        if ! is_installed_brew "tinyxml2"; then
            brew install tinyxml2
        fi
        if ! is_installed_brew "zlib"; then
            brew install zlib
        fi
        if ! is_installed_brew "libpng"; then
            brew install libpng
        fi
        if ! is_installed_brew "sdl3"; then
            brew install sdl3
        fi
        if ! is_installed_brew "sdl3_image"; then
            brew install sdl3_image
        fi
        if ! is_installed_brew "glew"; then
            brew install glew
        fi
        if ! is_installed_brew "opencl-headers"; then
            brew install opencl-headers
        fi
        if ! is_installed_brew "jsoncpp"; then
            brew install jsoncpp
        fi
        if ! is_installed_brew "eigen"; then
            brew install eigen
        fi
        if ! is_installed_brew "python@3.12"; then
            brew install python@3.12
        fi
        if ! is_installed_brew "zeromq"; then
            brew install zeromq
        fi
        if ! is_installed_brew "cppzmq"; then
            brew install cppzmq
        fi
        if ! is_installed_brew "netcdf"; then
            brew install netcdf
        fi
        if ! is_installed_brew "openexr"; then
            brew install openexr
        fi
    fi
elif $use_macos && command -v brew &> /dev/null; then
    :
elif command -v apt &> /dev/null && ! $use_conda; then
    if ! command -v cmake &> /dev/null || ! command -v git &> /dev/null || ! command -v curl &> /dev/null \
            || ! command -v pkg-config &> /dev/null || ! command -v g++ &> /dev/null \
            || ! command -v patchelf &> /dev/null; then
        echo "------------------------"
        echo "installing build essentials"
        echo "------------------------"
        sudo apt install -y cmake git curl pkg-config build-essential patchelf
    fi

    # Dependencies of sgl and the application.
    if $use_vcpkg; then
        if ! is_installed_apt "libgl-dev" || ! is_installed_apt "libxmu-dev" || ! is_installed_apt "libxi-dev" \
                || ! is_installed_apt "libx11-dev" || ! is_installed_apt "libxft-dev" \
                || ! is_installed_apt "libxext-dev" || ! is_installed_apt "libxrandr-dev" \
                || ! is_installed_apt "libwayland-dev" || ! is_installed_apt "libxkbcommon-dev" \
                || ! is_installed_apt "libxxf86vm-dev" || ! is_installed_apt "libegl1-mesa-dev" \
                || ! is_installed_apt "libglu1-mesa-dev" || ! is_installed_apt "mesa-common-dev" \
                || ! is_installed_apt "libibus-1.0-dev" || ! is_installed_apt "autoconf" \
                || ! is_installed_apt "automake" || ! is_installed_apt "autoconf-archive" \
                || ! is_installed_apt "libxinerama-dev" || ! is_installed_apt "libxcursor-dev" \
                || ! is_installed_apt "xorg-dev" || ! is_installed_apt "pkg-config" \
                || ! is_installed_apt "wayland-protocols" || ! is_installed_apt "extra-cmake-modules"; then
            echo "------------------------"
            echo "installing dependencies "
            echo "------------------------"
            sudo apt install -y libgl-dev libxmu-dev libxi-dev libx11-dev libxft-dev libxext-dev libxrandr-dev \
            libwayland-dev libxkbcommon-dev libxxf86vm-dev libegl1-mesa-dev libglu1-mesa-dev mesa-common-dev \
            libibus-1.0-dev autoconf automake autoconf-archive libxinerama-dev libxcursor-dev xorg-dev pkg-config \
            wayland-protocols extra-cmake-modules
        fi
    else
        if ! is_installed_apt "libboost-filesystem-dev" || ! is_installed_apt "libicu-dev" \
                || ! is_installed_apt "libglm-dev" || ! is_installed_apt "libarchive-dev" \
                || ! is_installed_apt "libtinyxml2-dev" || ! is_installed_apt "libpng-dev" \
                || ! is_installed_apt "libglew-dev" || ! is_installed_apt "opencl-c-headers" \
                || ! is_installed_apt "ocl-icd-opencl-dev" || ! is_installed_apt "libjsoncpp-dev" \
                || ! is_installed_apt "libeigen3-dev" || ! is_installed_apt "python3-dev" \
                || ! is_installed_apt "libzmq3-dev" || ! is_installed_apt "libnetcdf-dev" \
                || ! is_installed_apt "libopenexr-dev" || ! is_installed_apt "libeccodes-dev" \
                || ! is_installed_apt "libeccodes-tools" || ! is_installed_apt "libopenjp2-7-dev"; then
            echo "------------------------"
            echo "installing dependencies "
            echo "------------------------"
            sudo apt install -y libboost-filesystem-dev libicu-dev libglm-dev libarchive-dev libtinyxml2-dev libpng-dev \
            libglew-dev opencl-c-headers ocl-icd-opencl-dev libjsoncpp-dev libeigen3-dev python3-dev libzmq3-dev \
            libnetcdf-dev libopenexr-dev libeccodes-dev libeccodes-tools libopenjp2-7-dev
        fi
        if is_available_apt "libsdl3-dev"; then
            if ! is_installed_apt "libsdl3-dev"; then
                sudo apt install -y libsdl3-dev
            fi
        else
            if ! is_installed_apt "libsdl2-dev"; then
                sudo apt install -y libsdl2-dev
            fi
        fi
        if is_available_apt "libsdl3-image-dev"; then
            if ! is_installed_apt "libsdl3-image-dev"; then
                sudo apt install -y libsdl3-image-dev
            fi
        else
            if ! is_installed_apt "libsdl2-image-dev"; then
                sudo apt install -y libsdl2-image-dev
            fi
        fi
    fi
elif command -v pacman &> /dev/null && ! $use_conda; then
    if ! command -v cmake &> /dev/null || ! command -v git &> /dev/null || ! command -v curl &> /dev/null \
            || ! command -v pkg-config &> /dev/null || ! command -v g++ &> /dev/null \
            || ! command -v patchelf &> /dev/null; then
        echo "------------------------"
        echo "installing build essentials"
        echo "------------------------"
        sudo pacman --noconfirm --needed -S cmake git curl pkgconf base-devel patchelf
    fi

    # Dependencies of sgl and the application.
    if $use_vcpkg; then
        if ! is_installed_pacman "libgl" || ! is_installed_pacman "glu" || ! is_installed_pacman "vulkan-devel" \
                || ! is_installed_pacman "shaderc" || ! is_installed_pacman "openssl" \
                || ! is_installed_pacman "autoconf" || ! is_installed_pacman "automake" \
                || ! is_installed_pacman "autoconf-archive" || ! is_installed_pacman "libxinerama" \
                || ! is_installed_pacman "libxcursor" || ! is_installed_pacman "pkgconf" \
                || ! is_installed_pacman "libxkbcommon" || ! is_installed_pacman "wayland-protocols" \
                || ! is_installed_pacman "wayland" || ! is_installed_pacman "extra-cmake-modules"; then
            echo "------------------------"
            echo "installing dependencies "
            echo "------------------------"
            sudo pacman --noconfirm --needed -S libgl glu vulkan-devel shaderc openssl autoconf automake \
            autoconf-archive libxinerama libxcursor pkgconf libxkbcommon wayland-protocols wayland extra-cmake-modules
        fi
    else
        if ! is_installed_pacman "boost" || ! is_installed_pacman "icu" || ! is_installed_pacman "glm" \
                || ! is_installed_pacman "libarchive" || ! is_installed_pacman "tinyxml2" \
                || ! is_installed_pacman "libpng" || ! is_installed_pacman "glew" \
                || ! is_installed_pacman "vulkan-devel" || ! is_installed_pacman "shaderc" \
                || ! is_installed_pacman "opencl-headers" || ! is_installed_pacman "ocl-icd" \
                || ! is_installed_pacman "jsoncpp" || ! is_installed_pacman "eigen" || ! is_installed_pacman "python3" \
                || ! is_installed_pacman "zeromq" || ! is_installed_pacman "cppzmq" || ! is_installed_pacman "netcdf" \
                || ! is_installed_pacman "openexr" || ! is_installed_pacman "ospray"; then
            echo "------------------------"
            echo "installing dependencies "
            echo "------------------------"
            sudo pacman --noconfirm --needed -S boost icu glm libarchive tinyxml2 libpng glew vulkan-devel shaderc \
            opencl-headers ocl-icd jsoncpp eigen python3 zeromq cppzmq netcdf openexr ospray
        fi
        if is_available_pacman "sdl3"; then
            if ! is_installed_pacman "sdl3"; then
                sudo pacman --noconfirm --needed -S sdl3
            fi
        else
            if ! is_installed_pacman "sdl2"; then
                sudo pacman --noconfirm --needed -S sdl2
            fi
        fi
        if ! command -v yay &> /dev/null && ! is_installed_yay "eccodes"; then
            echo "------------------------"
            echo "installing dependencies "
            echo "------------------------"
            yay -S eccodes
        fi
    fi
elif command -v yum &> /dev/null && ! $use_conda; then
    if ! command -v cmake &> /dev/null || ! command -v git &> /dev/null || ! command -v curl &> /dev/null \
            || ! command -v pkg-config &> /dev/null || ! command -v g++ &> /dev/null \
            || ! command -v patchelf &> /dev/null || ! command -v awk &> /dev/null \
            || ! command -v wget &> /dev/null; then
        echo "------------------------"
        echo "installing build essentials"
        echo "------------------------"
        sudo yum install -y cmake git curl pkgconf gcc gcc-c++ patchelf gawk wget
    fi

    # Dependencies of sgl and the application.
    if $use_vcpkg; then
        if ! is_installed_rpm "perl" || ! is_installed_rpm "libstdc++-devel" || ! is_installed_rpm "libstdc++-static" \
                || ! is_installed_rpm "autoconf" || ! is_installed_rpm "automake" \
                || ! is_installed_rpm "autoconf-archive" || ! is_installed_rpm "mesa-libGLU-devel" \
                || ! is_installed_rpm "glew-devel" || ! is_installed_rpm "libXext-devel" \
                || ! is_installed_rpm "vulkan-headers" || ! is_installed_rpm "vulkan-loader" \
                || ! is_installed_rpm "vulkan-tools" || ! is_installed_rpm "vulkan-validation-layers" \
                || ! is_installed_rpm "libshaderc-devel" || ! is_installed_rpm "libXinerama-devel" \
                || ! is_installed_rpm "libXrandr-devel" || ! is_installed_rpm "libXcursor-devel" \
                || ! is_installed_rpm "libXi-devel" || ! is_installed_rpm "wayland-devel" \
                || ! is_installed_rpm "libxkbcommon-devel" || ! is_installed_rpm "wayland-protocols-devel" \
                || ! is_installed_rpm "extra-cmake-modules"; then
            echo "------------------------"
            echo "installing dependencies "
            echo "------------------------"
            sudo yum install -y perl libstdc++-devel libstdc++-static autoconf automake autoconf-archive \
            mesa-libGLU-devel glew-devel libXext-devel vulkan-headers vulkan-loader vulkan-tools \
            vulkan-validation-layers libshaderc-devel libXinerama-devel libXrandr-devel libXcursor-devel libXi-devel \
            wayland-devel libxkbcommon-devel wayland-protocols-devel extra-cmake-modules
        fi
    else
        if ! is_installed_rpm "boost-devel" || ! is_installed_rpm "libicu-devel" || ! is_installed_rpm "glm-devel" \
                || ! is_installed_rpm "libarchive-devel" || ! is_installed_rpm "tinyxml2-devel" \
                || ! is_installed_rpm "libpng-devel" || ! is_installed_rpm "glew-devel" \
                || ! is_installed_rpm "vulkan-headers" || ! is_installed_rpm "libshaderc-devel" \
                || ! is_installed_rpm "opencl-headers" || ! is_installed_rpm "ocl-icd" \
                || ! is_installed_rpm "jsoncpp-devel" || ! is_installed_rpm "eigen3-devel" \
                || ! is_installed_rpm "python3-devel" || ! is_installed_rpm "zeromq-devel" \
                || ! is_installed_rpm "cppzmq-devel" || ! is_installed_rpm "netcdf-devel" \
                || ! is_installed_rpm "openexr-devel" || ! is_installed_rpm "eccodes-devel"; then
            echo "------------------------"
            echo "installing dependencies "
            echo "------------------------"
            sudo yum install -y boost-devel libicu-devel glm-devel libarchive-devel tinyxml2-devel libpng-devel \
            glew-devel vulkan-headers libshaderc-devel opencl-headers ocl-icd jsoncpp-devel eigen3-devel python3-devel \
            zeromq-devel cppzmq-devel netcdf-devel openexr-devel eccodes-devel
        fi
        if is_available_yum "SDL3-devel"; then
            if ! is_installed_rpm "SDL3-devel"; then
                sudo yum install -y SDL3-devel
            fi
        else
            if ! is_installed_rpm "SDL2-devel"; then
                sudo yum install -y SDL2-devel
            fi
        fi
        if is_available_yum "SDL3_image-devel"; then
            if ! is_installed_rpm "SDL3_image-devel"; then
                sudo yum install -y SDL3_image-devel
            fi
        else
            if ! is_installed_rpm "SDL2_image-devel"; then
                sudo yum install -y SDL2_image-devel
            fi
        fi
    fi
elif $use_conda && ! $use_macos; then
    if [ -f "$HOME/miniconda3/etc/profile.d/conda.sh" ]; then
        . "$HOME/miniconda3/etc/profile.d/conda.sh" shell.bash hook
    elif [ -f "/opt/anaconda3/etc/profile.d/conda.sh" ]; then
        . "/opt/anaconda3/etc/profile.d/conda.sh" shell.bash hook
    elif [ ! -z "${CONDA_PREFIX+x}" ]; then
        . "$CONDA_PREFIX/etc/profile.d/conda.sh" shell.bash hook
    fi

    if ! command -v conda &> /dev/null; then
        echo "------------------------"
        echo "  installing Miniconda  "
        echo "------------------------"
        if [ "$os_arch" = "x86_64" ]; then
            wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
            chmod +x Miniconda3-latest-Linux-x86_64.sh
            bash ./Miniconda3-latest-Linux-x86_64.sh
            . "$HOME/miniconda3/etc/profile.d/conda.sh" shell.bash hook
            rm ./Miniconda3-latest-Linux-x86_64.sh
        else
            wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh
            chmod +x Miniconda3-latest-Linux-aarch64.sh
            bash ./Miniconda3-latest-Linux-aarch64.sh
            . "$HOME/miniconda3/etc/profile.d/conda.sh" shell.bash hook
            rm ./Miniconda3-latest-Linux-aarch64.sh
        fi
    fi

    if ! conda env list | grep ".*${conda_env_name}.*" >/dev/null 2>&1; then
        echo "------------------------"
        echo "creating conda environment"
        echo "------------------------"
        conda create -n "${conda_env_name}" -y
        conda init bash
        conda activate "${conda_env_name}"
    elif [ "${var+CONDA_DEFAULT_ENV}" != "${conda_env_name}" ]; then
        conda activate "${conda_env_name}"
    fi

    conda_pkg_list="$(conda list)"
    if ! list_contains "$conda_pkg_list" "boost" || ! list_contains "$conda_pkg_list" "conda-forge::icu" \
            || ! list_contains "$conda_pkg_list" "glm" || ! list_contains "$conda_pkg_list" "libarchive" \
            || ! list_contains "$conda_pkg_list" "tinyxml2" || ! list_contains "$conda_pkg_list" "libpng" \
            || ! list_contains "$conda_pkg_list" "sdl3" || ! list_contains "$conda_pkg_list" "glew" \
            || ! list_contains "$conda_pkg_list" "cxx-compiler" || ! list_contains "$conda_pkg_list" "make" \
            || ! list_contains "$conda_pkg_list" "cmake" || ! list_contains "$conda_pkg_list" "pkg-config" \
            || ! list_contains "$conda_pkg_list" "gdb" || ! list_contains "$conda_pkg_list" "git" \
            || ! list_contains "$conda_pkg_list" "mesa-libgl-devel-cos7-x86_64" \
            || ! list_contains "$conda_pkg_list" "libglvnd-glx-cos7-x86_64" \
            || ! list_contains "$conda_pkg_list" "mesa-dri-drivers-cos7-aarch64" \
            || ! list_contains "$conda_pkg_list" "libxau-devel-cos7-aarch64" \
            || ! list_contains "$conda_pkg_list" "libselinux-devel-cos7-aarch64" \
            || ! list_contains "$conda_pkg_list" "libxdamage-devel-cos7-aarch64" \
            || ! list_contains "$conda_pkg_list" "libxxf86vm-devel-cos7-aarch64" \
            || ! list_contains "$conda_pkg_list" "libxext-devel-cos7-aarch64" \
            || ! list_contains "$conda_pkg_list" "xorg-libxfixes" || ! list_contains "$conda_pkg_list" "xorg-libxau" \
            || ! list_contains "$conda_pkg_list" "xorg-libxrandr" || ! list_contains "$conda_pkg_list" "patchelf" \
            || ! list_contains "$conda_pkg_list" "libvulkan-headers" || ! list_contains "$conda_pkg_list" "shaderc" \
            || ! list_contains "$conda_pkg_list" "jsoncpp" || ! list_contains "$conda_pkg_list" "eigen" \
            || ! list_contains "$conda_pkg_list" "zeromq" || ! list_contains "$conda_pkg_list" "cppzmq" \
            || ! list_contains "$conda_pkg_list" "netcdf4" || ! list_contains "$conda_pkg_list" "openexr" \
            || ! list_contains "$conda_pkg_list" "eccodes"; then
        echo "------------------------"
        echo "installing dependencies "
        echo "------------------------"
        conda install -y -c conda-forge boost conda-forge::icu glm libarchive tinyxml2 libpng sdl3 glew cxx-compiler \
        make cmake pkg-config gdb git mesa-libgl-devel-cos7-x86_64 libglvnd-glx-cos7-x86_64 \
        mesa-dri-drivers-cos7-aarch64 libxau-devel-cos7-aarch64 libselinux-devel-cos7-aarch64 \
        libxdamage-devel-cos7-aarch64 libxxf86vm-devel-cos7-aarch64 libxext-devel-cos7-aarch64 xorg-libxfixes \
        xorg-libxau xorg-libxrandr patchelf libvulkan-headers shaderc jsoncpp eigen zeromq cppzmq netcdf4 openexr \
        eccodes
    fi
else
    echo "Warning: Unsupported system package manager detected." >&2
fi

if ! command -v cmake &> /dev/null; then
    echo "CMake was not found, but is required to build the program."
    exit 1
fi
if ! command -v git &> /dev/null; then
    echo "git was not found, but is required to build the program."
    exit 1
fi
if ! command -v curl &> /dev/null; then
    echo "curl was not found, but is required to build the program."
    exit 1
fi
if [ $use_macos = false ] && ! command -v pkg-config &> /dev/null; then
    echo "pkg-config was not found, but is required to build the program."
    exit 1
fi

if [ ! -d "submodules/IsosurfaceCpp/src" ]; then
    echo "------------------------"
    echo "initializing submodules "
    echo "------------------------"
    git submodule init
    git submodule update
fi

[ -d "./third_party/" ] || mkdir "./third_party/"
pushd third_party > /dev/null

params_sgl=()
params=()
params_run=()
params_gen=()

if [ $use_msys = true ]; then
    params_gen+=(-G "MSYS Makefiles")
    params_sgl+=(-G "MSYS Makefiles")
    params+=(-G "MSYS Makefiles")
fi

if [ $use_vcpkg = false ] && [ $use_macos = true ]; then
    brew_prefix="$(brew --prefix)"
    params_gen+=(-DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=False)
    params_gen+=(-DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=False)
    params_gen+=(-DCMAKE_FIND_FRAMEWORK=LAST)
    params_gen+=(-DCMAKE_FIND_APPBUNDLE=NEVER)
    params_gen+=(-DCMAKE_PREFIX_PATH="${brew_prefix}")
    params_gen+=(-DCMAKE_C_COMPILER="${brew_prefix}/opt/llvm@20/bin/clang")
    params_gen+=(-DCMAKE_CXX_COMPILER="${brew_prefix}/opt/llvm@20/bin/clang++")
    params_gen+=(-DCMAKE_LINKER="$(brew --prefix)/opt/llvm@20/bin/llvm-ld")
    params_gen+=(-DCMAKE_AR="$(brew --prefix)/opt/llvm@20/bin/llvm-ar")
    params_sgl+=(-DCMAKE_INSTALL_PREFIX="../$install_dir")
    params_sgl+=(-DZLIB_ROOT="${brew_prefix}/opt/zlib")
    params+=(-DZLIB_ROOT="${brew_prefix}/opt/zlib")
fi

if $glibcxx_debug; then
    params_sgl+=(-DUSE_GLIBCXX_DEBUG=On)
    params+=(-DUSE_GLIBCXX_DEBUG=On)
fi

cmake_version=$(cmake --version | head -n 1 | awk '{print $NF}')
cmake_version_major=$(echo $cmake_version | cut -d. -f1)
cmake_version_minor=$(echo $cmake_version | cut -d. -f2)
if [ $use_msys = false ] && [ $use_macos = false ] && [ $use_conda = false ] && [ $use_vcpkg = false ] && [[ $cmake_version_major -ge 4 ]]; then
    # Ubuntu 22.04 ships packages, such as libjsoncpp-dev, that are incompatible with CMake 4.0.
    if (lsb_release -a 2> /dev/null | grep -q 'Ubuntu' || lsb_release -a 2> /dev/null | grep -q 'Mint'); then
        if lsb_release -a 2> /dev/null | grep -q 'Ubuntu'; then
            distro_code_name=$(lsb_release -cs)
            distro_release=$(lsb_release -rs)
        else
            distro_code_name=$(cat /etc/upstream-release/lsb-release | grep "DISTRIB_CODENAME=" | sed 's/^.*=//')
            distro_release=$(cat /etc/upstream-release/lsb-release | grep "DISTRIB_RELEASE=" | sed 's/^.*=//')
        fi
        if dpkg --compare-versions "$distro_release" "lt" "24.04"; then
            params+=(-DCMAKE_POLICY_VERSION_MINIMUM=3.5)
        fi
    fi
fi

use_vulkan=false
vulkan_sdk_env_set=true
use_vulkan=true

search_for_vulkan_sdk=false
if [ $use_msys = false ] && [ -z "${VULKAN_SDK+1}" ]; then
    search_for_vulkan_sdk=true
fi

if [ $search_for_vulkan_sdk = true ]; then
    echo "------------------------"
    echo "searching for Vulkan SDK"
    echo "------------------------"

    found_vulkan=false
    use_local_vulkan_sdk=false

    if [ $use_macos = false ]; then
        if [ -d "VulkanSDK" ]; then
            VK_LAYER_PATH=""
            source "VulkanSDK/$(ls VulkanSDK)/setup-env.sh"
            use_local_vulkan_sdk=true
            pkgconfig_dir="$(realpath "VulkanSDK/$(ls VulkanSDK)/$os_arch/lib/pkgconfig")"
            if [ -d "$pkgconfig_dir" ]; then
                export PKG_CONFIG_PATH="$pkgconfig_dir"
            fi
            found_vulkan=true
        fi

        if ! $found_vulkan && (lsb_release -a 2> /dev/null | grep -q 'Ubuntu' || lsb_release -a 2> /dev/null | grep -q 'Mint') && ! $use_conda; then
            if lsb_release -a 2> /dev/null | grep -q 'Ubuntu'; then
                distro_code_name=$(lsb_release -cs)
                distro_release=$(lsb_release -rs)
            else
                distro_code_name=$(cat /etc/upstream-release/lsb-release | grep "DISTRIB_CODENAME=" | sed 's/^.*=//')
                distro_release=$(cat /etc/upstream-release/lsb-release | grep "DISTRIB_RELEASE=" | sed 's/^.*=//')
            fi
            if ! compgen -G "/etc/apt/sources.list.d/lunarg-vulkan-*" > /dev/null \
                    && ! curl -s -I "https://packages.lunarg.com/vulkan/dists/${distro_code_name}/" | grep "2 404" > /dev/null \
                    && [ "$os_arch" = "x86_64" ]; then
                echo "Setting up Vulkan SDK for $(lsb_release -ds)..."
                wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
                sudo curl --silent --show-error --fail \
                https://packages.lunarg.com/vulkan/lunarg-vulkan-${distro_code_name}.list \
                --output /etc/apt/sources.list.d/lunarg-vulkan-${distro_code_name}.list
                sudo apt update
                sudo apt install -y vulkan-sdk shaderc glslang-dev
            elif dpkg --compare-versions "$distro_release" "ge" "24.04"; then
                if ! is_installed_apt "libvulkan-dev" || ! is_installed_apt "libshaderc-dev" \
                        || ! is_installed_apt "glslang-dev" || ! is_installed_apt "glslang-tools"; then
                    # Optional: vulkan-validationlayers
                    sudo apt install -y libvulkan-dev libshaderc-dev glslang-dev glslang-tools
                fi
            fi
        fi

        if [ -d "/usr/include/vulkan" ] && [ -d "/usr/include/shaderc" ]; then
            if ! grep -q VULKAN_SDK ~/.bashrc; then
                echo 'export VULKAN_SDK="/usr"' >> ~/.bashrc
            fi
            export VULKAN_SDK="/usr"
            found_vulkan=true
        fi

        if ! $found_vulkan; then
            curl --silent --show-error --fail -O https://sdk.lunarg.com/sdk/download/latest/linux/vulkan-sdk.tar.gz
            mkdir -p VulkanSDK
            tar -xf vulkan-sdk.tar.gz -C VulkanSDK
            if [ "$os_arch" != "x86_64" ]; then
                pushd "VulkanSDK/$(ls VulkanSDK)" >/dev/null
                ./vulkansdk -j $(nproc) vulkan-loader glslang shaderc
                popd >/dev/null
            fi
            VK_LAYER_PATH=""
            source "VulkanSDK/$(ls VulkanSDK)/setup-env.sh"
            use_local_vulkan_sdk=true

            # Fix pkgconfig file.
            shaderc_pkgconfig_file="VulkanSDK/$(ls VulkanSDK)/$os_arch/lib/pkgconfig/shaderc.pc"
            if [ -f "$shaderc_pkgconfig_file" ]; then
                prefix_path=$(realpath "VulkanSDK/$(ls VulkanSDK)/$os_arch")
                sed -i '3s;.*;prefix=\"'$prefix_path'\";' "$shaderc_pkgconfig_file"
                sed -i '5s;.*;libdir=${prefix}/lib;' "$shaderc_pkgconfig_file"
                export PKG_CONFIG_PATH="$(realpath "VulkanSDK/$(ls VulkanSDK)/$os_arch/lib/pkgconfig")"
            fi
            found_vulkan=true
        fi
    else
        if [ -d "$HOME/VulkanSDK" ] && [ ! -z "$(ls -A "$HOME/VulkanSDK")" ]; then
            source "$HOME/VulkanSDK/$(ls $HOME/VulkanSDK)/setup-env.sh"
            found_vulkan=true
        else
            vulkansdk_filename=$(curl -sIkL https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.zip | sed -r '/filename=/!d;s/.*filename=(.*)$/\1/')
            VULKAN_SDK_VERSION=$(echo $vulkansdk_filename | sed -r 's/^.*vulkansdk-macos-(.*)\.zip.*$/\1/')
            curl -O https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.zip
            unzip vulkan-sdk.zip -d vulkan-sdk/
            vulkan_dir="$(pwd)/vulkan-sdk"
            if [ -d "${vulkan_dir}/vulkansdk-macOS-${VULKAN_SDK_VERSION}.app" ]; then
                # For some reason, this convention was introduced in version 1.4.313.0...
                sudo "${vulkan_dir}/vulkansdk-macOS-${VULKAN_SDK_VERSION}.app/Contents/MacOS/vulkansdk-macOS-${VULKAN_SDK_VERSION}" \
                --root ~/VulkanSDK/$VULKAN_SDK_VERSION --accept-licenses --default-answer --confirm-command install
            elif [ -d "${vulkan_dir}/InstallVulkan-${VULKAN_SDK_VERSION}.app" ]; then
                # For some reason, this convention was introduced in version 1.4.304.1...
                sudo "${vulkan_dir}/InstallVulkan-${VULKAN_SDK_VERSION}.app/Contents/MacOS/InstallVulkan-${VULKAN_SDK_VERSION}" \
                --root ~/VulkanSDK/$VULKAN_SDK_VERSION --accept-licenses --default-answer --confirm-command install
            else
                sudo "${vulkan_dir}/InstallVulkan.app/Contents/MacOS/InstallVulkan" \
                --root ~/VulkanSDK/$VULKAN_SDK_VERSION --accept-licenses --default-answer --confirm-command install
            fi
            pushd ~/VulkanSDK/$VULKAN_SDK_VERSION
            if [ $use_vcpkg = false ]; then
                if ! command -v python &> /dev/null; then
                    ln -s "$(brew --prefix)/bin/python"{3,}
                fi
            fi
            sudo python3 ./install_vulkan.py || true
            popd
            source "$HOME/VulkanSDK/$(ls $HOME/VulkanSDK)/setup-env.sh"
            found_vulkan=true
        fi
    fi

    if ! $found_vulkan; then
        if [ $use_macos = false ]; then
            os_name="linux"
        else
            os_name="mac"
        fi
        echo "The environment variable VULKAN_SDK is not set but is required in the installation process."
        echo "Please refer to https://vulkan.lunarg.com/sdk/home#${os_name} for instructions on how to install the Vulkan SDK."
        exit 1
    fi

    # On RHEL 8.6, I got the following errors when using the libvulkan.so provided by the SDK:
    # dlopen failed: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /home/u12458/Correrender/third_party/VulkanSDK/1.3.275.0/x86_64/lib/libvulkan.so)
    # Thus, we should remove it from the path if necessary.
    if $use_local_vulkan_sdk; then
        pushd VulkanSDK/$(ls VulkanSDK)/$os_arch/lib >/dev/null
        if ldd -r libvulkan.so | grep "undefined symbol"; then
            echo "Removing Vulkan SDK libvulkan.so from path..."
            export LD_LIBRARY_PATH=$(echo ${LD_LIBRARY_PATH} | awk -v RS=: -v ORS=: '/VulkanSDK/ {next} {print}' | sed 's/:*$//') && echo $OUTPATH
        fi
        popd >/dev/null
    fi
fi

if $custom_glslang; then
    if [ ! -d "./glslang" ]; then
        echo "------------------------"
        echo "  downloading glslang   "
        echo "------------------------"
        # Make sure we have no leftovers from a failed build attempt.
        if [ -d "./glslang-src" ]; then
            rm -rf "./glslang-src"
        fi
        git clone https://github.com/KhronosGroup/glslang.git glslang-src
        pushd glslang-src >/dev/null
        ./update_glslang_sources.py
        mkdir build
        pushd build >/dev/null
        cmake ${params_gen[@]+"${params_gen[@]}"} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="${projectpath}/third_party/glslang" ..
        make -j $(nproc)
        make install
        popd >/dev/null
        popd >/dev/null
    fi
    params_sgl+=(-Dglslang_DIR="${projectpath}/third_party/glslang" -DUSE_SHADERC=Off)
fi

if [ $use_msys = false ] && [ -z "${VULKAN_SDK+1}" ]; then
    vulkan_sdk_env_set=true
fi
if [ $use_d3d = true ] && [ $use_msys = true ]; then
    # As of 2024-08-18, MSYS2 does not have a package for the DirectX Shader Compiler yet.
    # For progress, see issue at: https://github.com/msys2/MINGW-packages/issues/20670
    # As a fix, we will use the pre-compiled binaries for now.
    if [ ! -d "./dxc" ]; then
        echo "------------------------"
        echo "downloading DX Shader Compiler"
        echo "------------------------"
        dxc_version="v1.8.2407"
        dxc_dir_name="dxc_2024_07_31"
        wget "https://github.com/microsoft/DirectXShaderCompiler/releases/download/${dxc_version}/${dxc_dir_name}.zip"
        unzip "${dxc_dir_name}.zip" -d "${dxc_dir_name}"
        rm "${dxc_dir_name}.zip"
        mkdir dxc
        mkdir dxc/tools
        mkdir dxc/bin
        mkdir dxc/lib
        mkdir dxc/include
        mkdir dxc/share
        pushd dxc/share >/dev/null
        wget "https://raw.githubusercontent.com/chrismile/CMakeSnippets/main/directx-dxc-config.cmake"
        popd >/dev/null
        os_arch="$(uname -m)"
        os_arch_win=${os_arch}
        if [ "$os_arch" = "x86_64" ]; then
            os_arch_win="x64"
        fi
        find "${dxc_dir_name}/bin/${os_arch_win}" -name "*.dll" -exec cp {} dxc/bin/ \;
        find "${dxc_dir_name}/bin/${os_arch_win}" -name "*.exe" -exec cp {} dxc/tools/ \;
        find "${dxc_dir_name}/lib/${os_arch_win}" -name "*.lib" -exec cp {} dxc/lib/ \;
        find "${dxc_dir_name}/inc" -name "*.h" -exec cp {} dxc/include/ \;
    fi

    params_sgl+=(-DSUPPORT_D3D12=ON -Ddirectx-dxc_DIR="${projectpath}/third_party/dxc/share")
fi

if [ $use_vcpkg = true ] && [ ! -d "./vcpkg" ]; then
    echo "------------------------"
    echo "    fetching vcpkg      "
    echo "------------------------"
    if $use_vulkan && [ $vulkan_sdk_env_set = false ]; then
        echo "The environment variable VULKAN_SDK is not set but is required in the installation process."
        exit 1
    fi
    git clone --depth 1 https://github.com/microsoft/vcpkg.git
    vcpkg/bootstrap-vcpkg.sh -disableMetrics
fi

if [ $use_vcpkg = true ] && [ $use_macos = false ] && [ $link_dynamic = false ]; then
    params_sgl+=(-DBUILD_STATIC_LIBRARY=On)
fi

if [ ! -d "./sgl" ]; then
    echo "------------------------"
    echo "     fetching sgl       "
    echo "------------------------"
    git clone --depth 1 https://github.com/chrismile/sgl.git
fi

if [ -f "./sgl/$build_dir/CMakeCache.txt" ]; then
    remove_build_cache_sgl=false
    if grep -q vcpkg_installed "./sgl/$build_dir/CMakeCache.txt"; then
        cache_uses_vcpkg=true
    else
        cache_uses_vcpkg=false
    fi
    if ([ $use_vcpkg = true ] && [ $cache_uses_vcpkg = false ]) || ([ $use_vcpkg = false ] && [ $cache_uses_vcpkg = true ]); then
        remove_build_cache_sgl=true
    fi
    if [ $remove_build_cache_sgl = true ]; then
        echo "Removing old sgl build cache..."
        if [ -d "./sgl/$build_dir_debug" ]; then
            rm -rf "./sgl/$build_dir_debug"
        fi
        if [ -d "./sgl/$build_dir_release" ]; then
            rm -rf "./sgl/$build_dir_release"
        fi
        if [ -d "./sgl/$install_dir" ]; then
            rm -rf "./sgl/$install_dir"
        fi
    fi
fi

if [ ! -d "./sgl/$install_dir" ]; then
    echo "------------------------"
    echo "     building sgl       "
    echo "------------------------"

    pushd "./sgl" >/dev/null
    if ! $build_sgl_release_only; then
        mkdir -p $build_dir_debug
    fi
    mkdir -p $build_dir_release

    if ! $build_sgl_release_only; then
        pushd "$build_dir_debug" >/dev/null
        cmake .. \
             -DCMAKE_BUILD_TYPE=Debug \
             -DCMAKE_INSTALL_PREFIX="../$install_dir" \
             ${params_gen[@]+"${params_gen[@]}"} ${params_link[@]+"${params_link[@]}"} \
             ${params_vcpkg[@]+"${params_vcpkg[@]}"} ${params_sgl[@]+"${params_sgl[@]}"}
        if [ $use_vcpkg = false ] && [ $use_macos = false ]; then
            make -j $(nproc)
            make install
        fi
        popd >/dev/null
    fi

    pushd $build_dir_release >/dev/null
    cmake .. \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX="../$install_dir" \
         ${params_gen[@]+"${params_gen[@]}"} ${params_link[@]+"${params_link[@]}"} \
         ${params_vcpkg[@]+"${params_vcpkg[@]}"} ${params_sgl[@]+"${params_sgl[@]}"}
    if [ $use_vcpkg = false ] && [ $use_macos = false ]; then
        make -j $(nproc)
        make install
    fi
    popd >/dev/null

    if [ $use_macos = true ]; then
        if ! $build_sgl_release_only; then
            cmake --build $build_dir_debug --parallel $(sysctl -n hw.ncpu)
            cmake --build $build_dir_debug --target install
        fi

        cmake --build $build_dir_release --parallel $(sysctl -n hw.ncpu)
        cmake --build $build_dir_release --target install
    elif [ $use_vcpkg = true ]; then
        if ! $build_sgl_release_only; then
            cmake --build $build_dir_debug --parallel $(nproc)
            cmake --build $build_dir_debug --target install
            if [ $link_dynamic = true ]; then
                cp $build_dir_debug/libsgld.so $install_dir/lib/libsgld.so
            fi
        fi

        cmake --build $build_dir_release --parallel $(nproc)
        cmake --build $build_dir_release --target install
        if [ $link_dynamic = true ]; then
            cp $build_dir_release/libsgl.so $install_dir/lib/libsgl.so
        fi
    fi

    popd >/dev/null
fi

if [ $use_vcpkg = true ]; then
    params+=(-DPYTHONHOME="./python3")
fi

if $use_msys; then
    Python3_VERSION="$(find "$MSYSTEM_PREFIX/lib/" -maxdepth 1 -type d -name 'python*' -printf "%f" -quit)"
    params+=(-DPython3_FIND_REGISTRY=NEVER -DPYTHONHOME="./python3" -DPYTHONPATH="./python3/lib/$Python3_VERSION")
fi
if $use_ospray2; then
    embree_version="3.13.3"
    ospray_version="2.9.0"
else
    embree_version="4.3.3"
    ospray_version="3.2.0"
fi

if ($use_ospray2 || $use_ospray3) && [ $use_macos = false ]; then
    if ! $is_embree_installed && [ $os_arch = "x86_64" ]; then
        if [ ! -d "./embree-${embree_version}.x86_64.linux" ]; then
            echo "------------------------"
            echo "   downloading Embree   "
            echo "------------------------"
            wget "https://github.com/embree/embree/releases/download/v${embree_version}/embree-${embree_version}.x86_64.linux.tar.gz"
            if $use_ospray2; then
                tar -xvzf "embree-${embree_version}.x86_64.linux.tar.gz"
            else
                mkdir "embree-${embree_version}.x86_64.linux"
                tar -xvzf "embree-${embree_version}.x86_64.linux.tar.gz" -C "embree-${embree_version}.x86_64.linux"
            fi
        fi
        params+=(-Dembree_DIR="${projectpath}/third_party/embree-${embree_version}.x86_64.linux/lib/cmake/embree-${embree_version}")
    fi
    if ! $is_ospray_installed && [ $os_arch = "x86_64" ]; then
        if [ ! -d "./ospray-${ospray_version}.x86_64.linux" ]; then
            echo "------------------------"
            echo "   downloading OSPRay   "
            echo "------------------------"
            wget "https://github.com/ospray/OSPRay/releases/download/v${ospray_version}/ospray-${ospray_version}.x86_64.linux.tar.gz"
            tar -xvzf "ospray-${ospray_version}.x86_64.linux.tar.gz"
        fi
        params+=(-Dospray_DIR="${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/cmake/ospray-${ospray_version}")
    fi
fi

if ($use_ospray2 || $use_ospray3) && [ $use_macos = true ]; then
    if [ ! -d "./ospray/ospray/lib/cmake" ]; then
        # Make sure we have no leftovers from a failed build attempt.
        if [ -d "./ospray-repo" ]; then
            rm -rf "./ospray-repo"
        fi
        if [ -d "./ospray-build" ]; then
            rm -rf "./ospray-build"
        fi
        if [ -d "./ospray" ]; then
            rm -rf "./ospray"
        fi

        params_ospray=()
        if [[ $(uname -m) == 'arm64' ]]; then
            params_ospray+=(-DBUILD_TBB_FROM_SOURCE=On)
        fi

        # Build OSPRay and its dependencies.
        git clone https://github.com/ospray/ospray.git ospray-repo
        if $use_ospray2; then
            pushd "./ospray-repo" >/dev/null
            git checkout v2.12.0
            popd >/dev/null
        fi
        mkdir ospray-build
        pushd "./ospray-build" >/dev/null
        cmake ../ospray-repo/scripts/superbuild -DCMAKE_INSTALL_PREFIX="$projectpath/third_party/ospray" \
        -DBUILD_JOBS=$(sysctl -n hw.ncpu) -DBUILD_OSPRAY_APPS=Off ${params_ospray[@]+"${params_ospray[@]}"} \
        ${params_link[@]+"${params_link[@]}"} ${params_vcpkg[@]+"${params_vcpkg[@]}"}
        CMAKE_POLICY_VERSION_MINIMUM=3.5 cmake --build . --parallel $(sysctl -n hw.ncpu)
        cmake --build . --parallel $(sysctl -n hw.ncpu)
        popd >/dev/null
    fi

    params+=(-Dembree_DIR="${projectpath}/third_party/ospray/embree/lib/cmake/$(ls "${projectpath}/third_party/ospray/embree/lib/cmake")")
    params+=(-Dospray_DIR="${projectpath}/third_party/ospray/ospray/lib/cmake/$(ls "${projectpath}/third_party/ospray/ospray/lib/cmake")")
fi

#if [ -d "./ospray/ospray/lib/cmake" ]; then
#    is_ospray_installed=true
#else
#    is_ospray_installed=false
#
#    # Make sure we have no leftovers from a failed build attempt.
#    if [ -d "./ospray-repo" ]; then
#        rm -rf "./ospray-repo"
#    fi
#    if [ -d "./ospray-build" ]; then
#        rm -rf "./ospray-build"
#    fi
#    if [ -d "./ospray" ]; then
#        rm -rf "./ospray"
#    fi
#
#    # Build OSPRay and its dependencies.
#    git clone https://github.com/ospray/ospray.git ospray-repo
#    mkdir ospray-build
#    pushd "./ospray-build" >/dev/null
#    cmake ../ospray-repo/scripts/superbuild -G "MSYS Makefiles" \
#    -DCMAKE_INSTALL_PREFIX="$projectpath/third_party/ospray" \
#    -DBUILD_JOBS=$(nproc) -DBUILD_OSPRAY_APPS=Off
#    cmake --build . --parallel $(nproc)
#    cmake --build . --parallel $(nproc)
#    popd >/dev/null
#
#    is_ospray_installed=true
#fi
#
#if $is_ospray_installed; then
#    params+=(-Dembree_DIR="${projectpath}/third_party/ospray/embree/lib/cmake/$(ls "${projectpath}/third_party/ospray/embree/lib/cmake")")
#    params+=(-Dospray_DIR="${projectpath}/third_party/ospray/ospray/lib/cmake/$(ls "${projectpath}/third_party/ospray/ospray/lib/cmake")")
#fi

if $use_open_image_denoise; then
    oidn_version="2.3.3"
    if $use_msys; then
        oidn_folder_name="oidn-${oidn_version}.x64.windows"
        oidn_archive_name="${oidn_folder_name}.zip"
    elif $use_macos; then
        oidn_folder_name="oidn-${oidn_version}.${os_arch}.macos"
        oidn_archive_name="${oidn_folder_name}.tar.gz"
    else
        oidn_folder_name="oidn-${oidn_version}.${os_arch}.linux"
        oidn_archive_name="${oidn_folder_name}.tar.gz"
    fi
    if [ ! -d "./${oidn_folder_name}" ]; then
        echo "------------------------"
        echo "downloading OpenImageDenoise"
        echo "------------------------"
        wget "https://github.com/OpenImageDenoise/oidn/releases/download/v${oidn_version}/${oidn_archive_name}"
        if $use_msys; then
            unzip "${oidn_archive_name}"
        else
            tar -xvzf "${oidn_archive_name}"
        fi
        rm "${oidn_archive_name}"
    fi
    params+=(-DOpenImageDenoise_DIR="${projectpath}/third_party/${oidn_folder_name}/lib/cmake/OpenImageDenoise-${oidn_version}")
fi

popd >/dev/null # back to project root

if [ $debug = true ]; then
    echo "------------------------"
    echo "  building in debug     "
    echo "------------------------"
else
    echo "------------------------"
    echo "  building in release   "
    echo "------------------------"
fi

if [ -f "./$build_dir/CMakeCache.txt" ]; then
    remove_build_cache=false
    if grep -q vcpkg_installed "./$build_dir/CMakeCache.txt"; then
        cache_uses_vcpkg=true
    else
        cache_uses_vcpkg=false
    fi
    if ([ $use_vcpkg = true ] && [ $cache_uses_vcpkg = false ]) || ([ $use_vcpkg = false ] && [ $cache_uses_vcpkg = true ]); then
        remove_build_cache=true
    fi
    if [ remove_build_cache = true ]; then
        echo "Removing old application build cache..."
        if [ -d "./$build_dir_debug" ]; then
            rm -rf "./$build_dir_debug"
        fi
        if [ -d "./$build_dir_release" ]; then
            rm -rf "./$build_dir_release"
        fi
        if [ -d "./$destination_dir" ]; then
            rm -rf "./$destination_dir"
        fi
    fi
fi

mkdir -p $build_dir

echo "------------------------"
echo "      generating        "
echo "------------------------"
pushd $build_dir >/dev/null
cmake .. \
    -DCMAKE_BUILD_TYPE=$cmake_config \
    -Dsgl_DIR="$projectpath/third_party/sgl/$install_dir/lib/cmake/sgl/" \
    ${params_gen[@]+"${params_gen[@]}"} ${params_link[@]+"${params_link[@]}"} \
    ${params_vcpkg[@]+"${params_vcpkg[@]}"} ${params[@]+"${params[@]}"}
if [ $use_vcpkg = true ] || [ $use_msys = true ] || [ $use_macos = true ]; then
    Python3_VERSION=$(cat pythonversion.txt)
fi
popd >/dev/null

echo "------------------------"
echo "      compiling         "
echo "------------------------"
if [ $use_macos = true ]; then
    cmake --build $build_dir --parallel $(sysctl -n hw.ncpu)
elif [ $use_vcpkg = true ]; then
    cmake --build $build_dir --parallel $(nproc)
else
    pushd "$build_dir" >/dev/null
    make -j $(nproc)
    popd >/dev/null
fi

echo "------------------------"
echo "   copying new files    "
echo "------------------------"

# https://stackoverflow.com/questions/2829613/how-do-you-tell-if-a-string-contains-another-string-in-posix-sh
contains() {
    string="$1"
    substring="$2"
    if test "${string#*$substring}" != "$string"
    then
        return 0
    else
        return 1
    fi
}
startswith() {
    string="$1"
    prefix="$2"
    if test "${string#$prefix}" != "$string"
    then
        return 0
    else
        return 1
    fi
}

if $use_msys; then
    if [[ -z "${PATH+x}" ]]; then
        export PATH="${projectpath}/third_party/sgl/$install_dir/bin"
    elif [[ ! "${PATH}" == *"${projectpath}/third_party/sgl/$install_dir/bin"* ]]; then
        export PATH="${projectpath}/third_party/sgl/$install_dir/bin:$PATH"
    fi
elif $use_macos; then
    if [ -z "${DYLD_LIBRARY_PATH+x}" ]; then
        export DYLD_LIBRARY_PATH="${projectpath}/third_party/sgl/$install_dir/lib"
    elif contains "${DYLD_LIBRARY_PATH}" "${projectpath}/third_party/sgl/$install_dir/lib"; then
        export DYLD_LIBRARY_PATH="DYLD_LIBRARY_PATH:${projectpath}/third_party/sgl/$install_dir/lib"
    fi
else
  if [[ -z "${LD_LIBRARY_PATH+x}" ]]; then
      export LD_LIBRARY_PATH="${projectpath}/third_party/sgl/$install_dir/lib"
  elif [[ ! "${LD_LIBRARY_PATH}" == *"${projectpath}/third_party/sgl/$install_dir/lib"* ]]; then
      export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${projectpath}/third_party/sgl/$install_dir/lib"
  fi
fi
if [ $use_macos = false ] && [ $use_msys = false ]; then
    if ! $is_ospray_installed && [ $os_arch = "x86_64" ]; then
        export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib"
    fi
fi
if $use_open_image_denoise; then
    if $use_msys; then
        if [[ -z "${PATH+x}" ]]; then
            export PATH="${projectpath}/third_party/${oidn_folder_name}/bin"
        elif [[ ! "${PATH}" == *"${projectpath}/third_party/${oidn_folder_name}/bin"* ]]; then
            export PATH="${projectpath}/third_party/${oidn_folder_name}/bin:$PATH"
        fi
    elif $use_macos; then
        if [ -z "${DYLD_LIBRARY_PATH+x}" ]; then
            export DYLD_LIBRARY_PATH="${projectpath}/third_party/${oidn_folder_name}/lib"
        elif contains "${DYLD_LIBRARY_PATH}" "${projectpath}/third_party/${oidn_folder_name}/lib"; then
            export DYLD_LIBRARY_PATH="DYLD_LIBRARY_PATH:${projectpath}/third_party/${oidn_folder_name}/lib"
        fi
    else
      if [[ -z "${LD_LIBRARY_PATH+x}" ]]; then
          export LD_LIBRARY_PATH="${projectpath}/third_party/${oidn_folder_name}/lib"
      elif [[ ! "${LD_LIBRARY_PATH}" == *"${projectpath}/third_party/${oidn_folder_name}/lib"* ]]; then
          export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${projectpath}/third_party/${oidn_folder_name}/lib"
      fi
    fi
fi

if $use_msys; then
    mkdir -p $destination_dir/bin

    # Copy sgl to the destination directory.
    if [ $debug = true ] ; then
        cp "./third_party/sgl/$install_dir/bin/libsgld.dll" "$destination_dir/bin"
    else
        cp "./third_party/sgl/$install_dir/bin/libsgl.dll" "$destination_dir/bin"
    fi

    # Copy the application to the destination directory.
    cp "$build_dir/LineVis.exe" "$destination_dir/bin"

    # Copy all dependencies of the application to the destination directory.
    ldd_output="$(ntldd -R $build_dir/LineVis.exe)"
    if $use_open_image_denoise; then
        # Copy OpenImageDenoise device libraries.
        for oidn_lib_file in "${projectpath}/third_party/${oidn_folder_name}/bin/OpenImageDenoise_device_"*; do
            ldd_output="$ldd_output ${oidn_lib_file}"
        done
        # Copy other dependencies.
        for oidn_lib_file in "${projectpath}/third_party/${oidn_folder_name}/bin/"*.dll; do
            oidn_lib_file_basename="$(basename ${oidn_lib_file})"
            if [[ ${oidn_lib_file_basename} != "OpenImageDenoise"* ]]; then
                ldd_output="$ldd_output ${oidn_lib_file}"
            fi
        done
    fi
    for library_abs in $ldd_output
    do
        if [[ $library_abs == "not found"* ]] || [[ $library_abs == "ext-ms-win"* ]] || [[ $library_abs == "=>" ]] \
                || [[ $library_abs == "(0x"* ]] || [[ $library_abs == "C:\\WINDOWS"* ]] \
                || [[ $library_abs == "not" ]] || [[ $library_abs == "found"* ]]; then
            continue
        fi
        library="$(cygpath "$library_abs")"
        if [[ $library == "$MSYSTEM_PREFIX"* ]] || [[ $library == "$projectpath"* ]];
        then
            cp "$library" "$destination_dir/bin"
        fi
        if [[ $library == libpython* ]];
        then
            tmp=${library#*lib}
            Python3_VERSION=${tmp%.dll}
        fi
    done
elif [ $use_macos = true ] && [ $use_vcpkg = true ]; then
    [ -d $destination_dir ] || mkdir $destination_dir
    rsync -a "$build_dir/LineVis.app/Contents/MacOS/LineVis" $destination_dir
elif [ $use_macos = true ] && [ $use_vcpkg = false ]; then
    mkdir -p $destination_dir

    if [ -d "$destination_dir/LineVis.app" ]; then
        rm -rf "$destination_dir/LineVis.app"
    fi

    # Copy the application to the destination directory.
    cp -a "$build_dir/LineVis.app" "$destination_dir"

    # Copy sgl to the destination directory.
    if [ $debug = true ] ; then
        cp "./third_party/sgl/$install_dir/lib/libsgld.dylib" "$binaries_dest_dir"
    else
        cp "./third_party/sgl/$install_dir/lib/libsgl.dylib" "$binaries_dest_dir"
    fi

    # Copy all dependencies of the application and sgl to the destination directory.
    rsync -a "$VULKAN_SDK/lib/libMoltenVK.dylib" "$binaries_dest_dir"
    copy_dependencies_recursive() {
        local binary_path="$1"
        local binary_source_folder=$(dirname "$binary_path")
        local binary_name=$(basename "$binary_path")
        local binary_target_path="$binaries_dest_dir/$binary_name"
        if contains "$(file "$binary_target_path")" "dynamically linked shared library"; then
            install_name_tool -id "@executable_path/$binary_name" "$binary_target_path" &> /dev/null
        fi
        local otool_output="$(otool -L "$binary_path")"
        local otool_output=${otool_output#*$'\n'}
        while read -r line
        do
            local stringarray=($line)
            local library=${stringarray[0]}
            local library_name=$(basename "$library")
            local library_target_path="$binaries_dest_dir/$library_name"
            if ! startswith "$library" "@rpath/" \
                && ! startswith "$library" "@loader_path/" \
                && ! startswith "$library" "/System/Library/Frameworks/" \
                && ! startswith "$library" "/usr/lib/"
            then
                install_name_tool -change "$library" "@executable_path/$library_name" "$binary_target_path" &> /dev/null

                if [ ! -f "$library_target_path" ]; then
                    cp "$library" "$binaries_dest_dir"
                    copy_dependencies_recursive "$library"
                fi
            elif startswith "$library" "@rpath/"; then
                install_name_tool -change "$library" "@executable_path/$library_name" "$binary_target_path" &> /dev/null

                local rpath_grep_string="$(otool -l "$binary_target_path" | grep RPATH -A2)"
                local counter=0
                while read -r grep_rpath_line
                do
                    if [ $(( counter % 4 )) -eq 2 ]; then
                        local stringarray_grep_rpath_line=($grep_rpath_line)
                        local rpath=${stringarray_grep_rpath_line[1]}
                        if startswith "$rpath" "@loader_path"; then
                            rpath="${rpath/@loader_path/$binary_source_folder}"
                        fi
                        local library_rpath="${rpath}${library#"@rpath"}"

                        if [ -f "$library_rpath" ]; then
                            if [ ! -f "$library_target_path" ]; then
                                cp "$library_rpath" "$binaries_dest_dir"
                                copy_dependencies_recursive "$library_rpath"
                            fi
                            break
                        fi
                    fi
                    counter=$((counter + 1))
                done < <(echo "$rpath_grep_string")
            fi
        done < <(echo "$otool_output")
    }
    copy_dependencies_recursive "$build_dir/LineVis.app/Contents/MacOS/LineVis"
    if [ $debug = true ]; then
        copy_dependencies_recursive "./third_party/sgl/$install_dir/lib/libsgld.dylib"
    else
        copy_dependencies_recursive "./third_party/sgl/$install_dir/lib/libsgl.dylib"
    fi
    copy_ospray_lib_symlinked() {
        local lib_name="$1"
        local lib_path_1="./third_party/ospray/ospray/lib/$lib_name"
        local lib_path_2="./third_party/ospray/ospray/lib/$(readlink $lib_path_1)"
        local lib_path_3="./third_party/ospray/ospray/lib/$(readlink $lib_path_2)"
        cp "$lib_path_1" "$binaries_dest_dir"
        cp "$lib_path_2" "$binaries_dest_dir"
        cp "$lib_path_3" "$binaries_dest_dir"
        copy_dependencies_recursive "$lib_path_1"
        copy_dependencies_recursive "$lib_path_2"
        copy_dependencies_recursive "$lib_path_3"
    }
    if $use_ospray2 || $use_ospray3; then
        copy_ospray_lib_symlinked "libopenvkl.dylib"
        copy_ospray_lib_symlinked "libopenvkl_module_cpu_device.dylib"
        copy_ospray_lib_symlinked "libopenvkl_module_cpu_device_4.dylib"
        copy_ospray_lib_symlinked "libospray_module_cpu.dylib"
    fi

    # Fix code signing for arm64.
    for filename in $binaries_dest_dir/*
    do
        if contains "$(file "$filename")" "arm64"; then
            codesign --force -s - "$filename" &> /dev/null
        fi
    done
else
    mkdir -p $destination_dir/bin

    # Copy the application to the destination directory.
    rsync -a "$build_dir/LineVis" "$destination_dir/bin"

    # Copy all dependencies of the application to the destination directory.
    ldd_output="$(ldd $build_dir/LineVis)"

    if ! $is_ospray_installed && ($use_ospray2 || $use_ospray3) && [ $os_arch = "x86_64" ]; then
        if $use_ospray2; then
            libembree3_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libembree3.so")"
            libospray_module_cpu_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libospray_module_cpu.so")"
            libopenvkl_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl.so")"
            libopenvkl_module_cpu_device_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device.so")"
            libopenvkl_module_cpu_device_4_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device_4.so")"
            libopenvkl_module_cpu_device_8_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device_8.so")"
            libopenvkl_module_cpu_device_16_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device_16.so")"
            ldd_output="$ldd_output $libembree3_so $libospray_module_cpu_so $libopenvkl_so $libopenvkl_module_cpu_device_so"
            ldd_output="$ldd_output $libopenvkl_module_cpu_device_4_so $libopenvkl_module_cpu_device_8_so $libopenvkl_module_cpu_device_16_so"
        else
            libembree4_so="${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libembree4.so.4"
            libospray_module_cpu_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libospray_module_cpu.so.3")"
            libopenvkl_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl.so.2")"
            libopenvkl_module_cpu_device_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device.so.2")"
            libopenvkl_module_cpu_device_4_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device_4.so.2")"
            libopenvkl_module_cpu_device_8_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device_8.so.2")"
            libopenvkl_module_cpu_device_16_so="$(readlink -f "${projectpath}/third_party/ospray-${ospray_version}.x86_64.linux/lib/libopenvkl_module_cpu_device_16.so.2")"
            ldd_output="$ldd_output $libembree4_so $libospray_module_cpu_so $libopenvkl_so $libopenvkl_module_cpu_device_so"
            ldd_output="$ldd_output $libopenvkl_module_cpu_device_4_so $libopenvkl_module_cpu_device_8_so $libopenvkl_module_cpu_device_16_so"
        fi
    fi
    if $use_open_image_denoise; then
        # Copy OpenImageDenoise device libraries.
        for oidn_lib_file in "${projectpath}/third_party/${oidn_folder_name}/lib/libOpenImageDenoise_device_"*; do
            ldd_output="$ldd_output ${oidn_lib_file}"
        done
        # Copy other dependencies.
        for oidn_lib_file in "${projectpath}/third_party/${oidn_folder_name}/lib/lib"*; do
            oidn_lib_file_basename="$(basename ${oidn_lib_file})"
            if [[ ${oidn_lib_file_basename} != "libOpenImageDenoise"* ]]; then
                ldd_output="$ldd_output ${oidn_lib_file}"
            fi
        done
    fi
    library_blacklist=(
        "libOpenGL" "libGLdispatch" "libGL.so" "libGLX.so"
        "libwayland" "libffi." "libX" "libxcb" "libxkbcommon"
        "ld-linux" "libdl." "libutil." "libm." "libc." "libpthread." "libbsd." "librt."
    )
    if [ $use_vcpkg = true ]; then
        # We build with libstdc++.so and libgcc_s.so statically. If we were to ship them, libraries opened with dlopen will
        # use our, potentially older, versions. Then, we will get errors like "version `GLIBCXX_3.4.29' not found" when
        # the Vulkan loader attempts to load a Vulkan driver that was built with a never version of libstdc++.so.
        # I tried to solve this by using "patchelf --replace-needed" to directly link to the patch version of libstdc++.so,
        # but that made no difference whatsoever for dlopen.
        library_blacklist+=("libstdc++.so")
        library_blacklist+=("libgcc_s.so")
    fi
    for library in $ldd_output
    do
        if [[ $library != "/"* ]]; then
            continue
        fi
        is_blacklisted=false
        for blacklisted_library in ${library_blacklist[@]+"${library_blacklist[@]}"}; do
            if [[ "$library" == *"$blacklisted_library"* ]]; then
                is_blacklisted=true
                break
            fi
        done
        if [ $is_blacklisted = true ]; then
            continue
        fi
        # TODO: Add blacklist entries for pulseaudio and dependencies when not using vcpkg.
        #cp "$library" "$destination_dir/bin"
        #patchelf --set-rpath '$ORIGIN' "$destination_dir/bin/$(basename "$library")"
        if [ $use_vcpkg = true ]; then
            cp "$library" "$destination_dir/bin"
            patchelf --set-rpath '$ORIGIN' "$destination_dir/bin/$(basename "$library")"
        fi
    done
    patchelf --set-rpath '$ORIGIN' "$destination_dir/bin/LineVis"
    if ! $is_ospray_installed && ($use_ospray2 || $use_ospray3); then
        if $use_ospray2; then
            ln -sf "./$(basename "$libembree3_so")" "$destination_dir/bin/libembree3.so"
            ln -sf "./$(basename "$libospray_module_cpu_so")" "$destination_dir/bin/libospray_module_cpu.so"
            ln -sf "./$(basename "$libopenvkl_so")" "$destination_dir/bin/libopenvkl.so"
            ln -sf "./$(basename "$libopenvkl_so")" "$destination_dir/bin/libopenvkl.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_so")" "$destination_dir/bin/libopenvkl_module_cpu_device.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_so")" "$destination_dir/bin/libopenvkl_module_cpu_device.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_4_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_4.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_4_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_4.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_8_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_8.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_8_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_8.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_16_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_16.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_16_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_16.so.1"
        else
            ln -sf "./$(basename "$libembree4_so")" "$destination_dir/bin/libembree4.so"
            ln -sf "./$(basename "$libospray_module_cpu_so")" "$destination_dir/bin/libospray_module_cpu.so"
            ln -sf "./$(basename "$libopenvkl_so")" "$destination_dir/bin/libopenvkl.so"
            ln -sf "./$(basename "$libopenvkl_so")" "$destination_dir/bin/libopenvkl.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_so")" "$destination_dir/bin/libopenvkl_module_cpu_device.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_so")" "$destination_dir/bin/libopenvkl_module_cpu_device.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_4_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_4.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_4_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_4.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_8_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_8.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_8_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_8.so.1"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_16_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_16.so"
            ln -sf "./$(basename "$libopenvkl_module_cpu_device_16_so")" "$destination_dir/bin/libopenvkl_module_cpu_device_16.so.1"
        fi
    fi
fi

# 2023-11-11: It seems like for LineVis, vcpkg_installed is in the root directory, but for HexVolumeRenderer
# it is in the build folder.
if [ $use_vcpkg = true ]; then
    if [ -d "vcpkg_installed" ]; then
        vcpkg_installed_dir="vcpkg_installed"
    elif [ -d "$build_dir/vcpkg_installed" ]; then
        vcpkg_installed_dir="$build_dir/vcpkg_installed"
    fi
    if [ $use_custom_vcpkg_triplet = true ]; then
        vcpkg_installed_dir_triplet="$vcpkg_installed_dir/$vcpkg_triplet"
    else
        if [ $use_macos = true ]; then
            vcpkg_installed_dir_triplet="$vcpkg_installed_dir/$(ls $vcpkg_installed_dir | grep -Ewv 'vcpkg')"
        else
            vcpkg_installed_dir_triplet="$vcpkg_installed_dir/$(ls --ignore=vcpkg $vcpkg_installed_dir)"
        fi
    fi
fi
# Copy python3 to the destination directory.
if $use_msys; then
    if [ ! -d "$destination_dir/bin/python3" ]; then
        mkdir -p "$destination_dir/bin/python3/lib"
        #cp -r "$MSYSTEM_PREFIX/lib/$Python3_VERSION" "$destination_dir/bin/python3/lib"
        rsync -qav "$MSYSTEM_PREFIX/lib/$Python3_VERSION" "$destination_dir/bin/python3/lib" --exclude site-packages --exclude dist-packages
    fi
elif [ $use_macos = true ] && [ $use_vcpkg = true ]; then
    [ -d $destination_dir/python3 ]     || mkdir $destination_dir/python3
    [ -d $destination_dir/python3/lib ] || mkdir $destination_dir/python3/lib
    rsync -a "$vcpkg_installed_dir_triplet/lib/$Python3_VERSION" $destination_dir/python3/lib
    #rsync -a "$(eval echo "$vcpkg_installed_dir_triplet/lib/python*")" $destination_dir/python3/lib
elif [ $use_macos = true ] && [ $use_vcpkg = false ]; then
    python_version=${Python3_VERSION#python}
    python_subdir="$brew_prefix/Cellar/python@${Python3_VERSION#python}"
    PYTHONHOME_global="$python_subdir/$(ls "$python_subdir")/Frameworks/Python.framework/Versions/$python_version"
    if [ ! -d "$binaries_dest_dir/python3" ]; then
        mkdir -p "$binaries_dest_dir/python3/lib"
        rsync -a "$PYTHONHOME_global/lib/$Python3_VERSION" "$binaries_dest_dir/python3/lib"
        rsync -a "$brew_prefix/lib/$Python3_VERSION" "$binaries_dest_dir/python3/lib"
        #rsync -a "$(eval echo "$brew_prefix/lib/python*")" $binaries_dest_dir/python3/lib
    fi
elif [ $use_vcpkg = true ]; then
    [ -d $destination_dir/bin/python3 ]     || mkdir $destination_dir/bin/python3
    [ -d $destination_dir/bin/python3/lib ] || mkdir $destination_dir/bin/python3/lib
    python_lib_dir="$vcpkg_installed_dir_triplet/lib/$Python3_VERSION"
    rsync -a "$python_lib_dir" $destination_dir/bin/python3/lib
    #rsync -a "$(eval echo "$vcpkg_installed_dir_triplet/lib/python*")" $destination_dir/python3/lib
fi
if [ $use_macos = true ] && [ $use_vcpkg = true ]; then
    export PYTHONHOME="../$destination_dir/python3"
elif [ $use_macos = true ] && [ $use_vcpkg = false ]; then
    export PYTHONHOME="$PYTHONHOME_global"
elif $use_msys; then
    export PYTHONHOME="$MSYSTEM_PREFIX"
else
    if [ $use_vcpkg = true ]; then
        export PYTHONHOME="../Shipping/bin/python3"
    fi
fi

# Copy the docs to the destination directory.
cp "README.md" "$destination_dir"
if [ ! -d "$destination_dir/LICENSE" ]; then
    mkdir -p "$destination_dir/LICENSE"
    cp -r "docs/license-libraries/." "$destination_dir/LICENSE/"
    cp -r "LICENSE" "$destination_dir/LICENSE/LICENSE-linevis.txt"
    cp -r "submodules/IsosurfaceCpp/LICENSE" "$destination_dir/LICENSE/graphics/LICENSE-isosurfacecpp.txt"
fi
if [ ! -d "$destination_dir/docs" ]; then
    cp -r "docs" "$destination_dir"
fi

# Create a run script.
if $use_msys; then
    printf "@echo off\npushd %%~dp0\npushd bin\nstart \"\" LineVis.exe\n" > "$destination_dir/run.bat"
elif [ $use_macos = true ] && [ $use_vcpkg = true ]; then
    printf "#!/bin/sh\npushd \"\$(dirname \"\$0\")\" >/dev/null\n./LineVis\npopd\n" > "$destination_dir/run.sh"
    chmod +x "$destination_dir/run.sh"
elif [ $use_macos = true ] && [ $use_vcpkg = false ]; then
    printf "#!/bin/sh\npushd \"\$(dirname \"\$0\")\" >/dev/null\n./LineVis.app/Contents/MacOS/LineVis\npopd\n" > "$destination_dir/run.sh"
    chmod +x "$destination_dir/run.sh"
else
    printf "#!/bin/bash\npushd \"\$(dirname \"\$0\")/bin\" >/dev/null\n./LineVis\npopd\n" > "$destination_dir/run.sh"
    chmod +x "$destination_dir/run.sh"
fi



# Run the program as the last step.
echo ""
echo "All done!"
pushd $build_dir >/dev/null

if [ $run_program = true ] && [ $use_macos = false ]; then
    ./LineVis ${params_run[@]+"${params_run[@]}"}
elif [ $run_program = true ] && [ $use_macos = true ]; then
    #open ./LineVis.app
    #open ./LineVis.app --args --perf
    ./LineVis.app/Contents/MacOS/LineVis ${params_run[@]+"${params_run[@]}"}
fi
