# vim: set expandtab sts=4 ts=4 sw=4:

create_links() {
    # FIXME: libglxserver_nvidia.so has no soname so this function won't create a symlink for it
    find "$PKGDIR" -type f -name '*.so*' ! -path '*xorg/*' -print0 | while read -d $'\0' _lib; do
        _soname=$(dirname "${_lib}")/$(readelf -d "${_lib}" | grep -Po 'SONAME.*: \[\K[^]]*' || true)
        _base=$(echo ${_soname} | sed -r 's/(.*).so.*/\1.so/')
        if [[ -e "${_soname}" ]]; then
            abwarn "${_lib} does not have soname! Not creating symlink for it"
        else
            ln -sv $(basename "${_lib}") "${_soname}"
        fi
        [[ -e "${_base}" ]] || ln -sv $(basename "${_soname}") "${_base}"
    done
}

install_for_all() {
    MOD="$1"
    SRC="$2"
    DESTDIR="$3"
    install -Dvm${MOD} "$SRC" "$DESTDIR/$(basename ${SRC})"
    return $?
}

NEED_FIX=0

install_if_amd64() {
    MOD="$1"
    SRC="$2"
    DESTDIR="$3"
    if [[ $NV_ARCH = x86_64 ]]; then
        install -Dvm${MOD} "$SRC" "$DESTDIR/$(basename ${SRC})"
        return $?
    elif [[ -f "${SRC}" ]]; then
        # Make sure the file really doesn't exist
        aberr "File $SRC exists for non-amd64. Fix build scripts!"
        # Set fail flag. Catch all errors in one go
        NEED_FIX=1
    fi
    return 0
}

sanity_check() {
    # where the check should commmence in $PKGDIR
    LOCATION="$1"
    # The regex glob matching so that should not be installed, due to
    #  - Incompatibility with with GLVND, or
    #  - A separate package containing this so.
    BLACKLIST="(EGL|GL|GLESv1_CM|GLESv2|GLX|OpenGL|OpenCL|GLdispatch|nvidia-egl-wayland|libnvidia-gtk2|libnvidia-gtk3|libnvidia-wayland-client).so."
    # Assuming pwd is in NVIDIA-Linux-${NV_ARCH}
    abinfo "Checking whether all the .so provided has been installed"
    _PROVIDED=$(find -maxdepth 1 -name "*.so.*" -exec basename {} \; | sort | sed -E "/${BLACKLIST}/d")
    _INSTALLED=$(find ${LOCATION} -name "*.so.*" -exec basename {} \; | sort | sed -E "/${BLACKLIST}/d")
    diff -a <(echo -e "${_PROVIDED}") <(echo -e "${_INSTALLED}") --suppress-common-lines
    if (($?)); then
        aberr "There are files provided but not installed! See the diff stat above."
        abdie "Fix the build scripts!"
    fi
}

NV_ARCH="undefined"

case "$ABHOST" in
    amd64)
        NV_ARCH="x86_64"
        ;;
    arm64)
        NV_ARCH="aarch64"
        ;;
    *)
        abdie "Unsupported architecture"
esac

pushd "$SRCDIR"/NVIDIA-Linux-${NV_ARCH}-${PKGVER}

abinfo "Processing and installing OpenCL runtime..."
install_for_all 644 nvidia.icd "$PKGDIR"/etc/OpenCL/vendors
install_for_all 755 "libnvidia-opencl.so.$PKGVER" "$PKGDIR"/usr/lib

abinfo "NVIDIA Xorg driver..."
install_for_all 755 nvidia_drv.so "$PKGDIR"/usr/lib/xorg/modules/drivers

abinfo "GLX extension modules..."
install_for_all 755 "libglxserver_nvidia.so.$PKGVER" "$PKGDIR"/usr/lib/nvidia/xorg
install_for_all 755 "libGLX_nvidia.so.$PKGVER" "$PKGDIR"/usr/lib

abinfo 'OpenGL libraries (for LibGLVND)...'
install -Dvm755 "libEGL_nvidia.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libEGL_nvidia.so.$PKGVER
install -Dvm755 "libGLESv1_CM_nvidia.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libGLESv1_CM_nvidia.so.$PKGVER
install -Dvm755 "libGLESv2_nvidia.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libGLESv2_nvidia.so.$PKGVER
install -Dvm644 "10_nvidia.json" \
    "$PKGDIR"/usr/share/glvnd/egl_vendor.d/10_nvidia.json

abinfo "NVIDIA OpenGL core libraries..."
install -Dvm755 "libnvidia-glcore.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-glcore.so.$PKGVER
install -Dvm755 "libnvidia-eglcore.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-eglcore.so.$PKGVER
install -Dvm755 "libnvidia-glsi.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-glsi.so.$PKGVER

abinfo "Miscellaneous libraries for multimedia, framebuffer, etc..."
install -Dvm755 "libnvidia-allocator.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-allocator.so.$PKGVER
install -Dvm755 "libnvidia-encode.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-encode.so.$PKGVER
install -Dvm755 "libnvidia-cfg.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-cfg.so.$PKGVER
install -Dvm755 "libnvidia-ml.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-ml.so.$PKGVER
install -Dvm755 "libnvidia-sandboxutils.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-sandboxutils.so.$PKGVER
install -Dvm755 "libnvidia-egl-xlib.so.1.0.5" \
    "$PKGDIR"/usr/lib/libnvidia-egl-xlib.so.1.0.5
install -Dvm755 "libnvidia-egl-xcb.so.1.0.5" \
    "$PKGDIR"/usr/lib/libnvidia-egl-xcb.so.1.0.5
install -Dvm644 "20_nvidia_xlib.json" \
    "$PKGDIR"/usr/share/egl/egl_external_platform.d/20_nvidia_xlib.json
install -Dvm644 "20_nvidia_xcb.json" \
    "$PKGDIR"/usr/share/egl/egl_external_platform.d/20_nvidia_xcb.json
install -Dvm644 "10_nvidia.json" \
    "$PKGDIR"/usr/share/glvnd/egl_vendor.d/20_nvidia_xlib.json
install -Dvm644 "10_nvidia.json" \
    "$PKGDIR"/usr/share/glvnd/egl_vendor.d/20_nvidia_xcb.json

install_for_all 755 "libnvidia-fbc.so.$PKGVER" "$PKGDIR"/usr/lib

abinfo "NGX and wine support"
install_for_all 755 "nvidia-ngx-updater" "$PKGDIR"/usr/bin
install_for_all 755 "libnvidia-ngx.so.$PKGVER" "$PKGDIR"/usr/lib
install_if_amd64 755 _nvngx.dll "$PKGDIR"/usr/lib/nvidia/wine
install_if_amd64 755 nvngx.dll "$PKGDIR"/usr/lib/nvidia/wine

abinfo "Nvidia GPU control APIs"
install_for_all 755 "libnvidia-api.so.1" "$PKGDIR"/usr/lib

abinfo "Wayland support libraries and platform files..."
install_for_all 755 "libnvidia-egl-gbm.so.1.1.3" "$PKGDIR"/usr/lib
# libnvidia-wayland-client.so is open-source

install -Dvm644 "15_nvidia_gbm.json" \
    "$PKGDIR"/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json
mkdir -vp "$PKGDIR/usr/lib/gbm"
ln -svf "/usr/lib/libnvidia-allocator.so.${PKGVER}" \
    "$PKGDIR"/usr/lib/gbm/nvidia-drm_gbm.so

abinfo "Nvidia VM IR library..."
install_for_all 755 "libnvidia-nvvm.so.$PKGVER" "$PKGDIR"/usr/lib
install_for_all 755 "libnvidia-nvvm70.so.4" "$PKGDIR"/usr/lib

abinfo "Vulkan ICD data..."
install -Dvm644 "nvidia_icd.json" \
    "$PKGDIR"/usr/share/vulkan/icd.d/nvidia_icd.json
install -Dvm644 nvidia_layers.json \
    "$PKGDIR"/usr/share/vulkan/implicit_layer.d/nvidia_layers.json

abinfo "GPU shader compilation helper..."
install_for_all 755 "libnvidia-gpucomp.so.$PKGVER" "$PKGDIR"/usr/lib

abinfo "VDPAU runtime library..."
install -Dvm755 "libvdpau_nvidia.so.$PKGVER" \
    "$PKGDIR"/usr/lib/vdpau/libvdpau_nvidia.so.$PKGVER

abinfo "nvidia-tls libraries..."
install_for_all 755 "libnvidia-tls.so.$PKGVER" "$PKGDIR"/usr/lib
install_if_amd64 755 "libnvidia-pkcs11-openssl3.so.$PKGVER" "$PKGDIR"/usr/lib
install_if_amd64 755 "libnvidia-pkcs11.so.$PKGVER" "$PKGDIR"/usr/lib

abinfo "CUDA interface libraries..."
install_for_all 755 "libcuda.so.$PKGVER" "$PKGDIR"/usr/lib
install_for_all 755 "libnvcuvid.so.$PKGVER" "$PKGDIR"/usr/lib
install_for_all 755 "libcudadebugger.so.$PKGVER" "$PKGDIR"/usr/lib

abinfo "PTX JIT Compiler library..."
install -Dvm755 "libnvidia-ptxjitcompiler.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-ptxjitcompiler.so.$PKGVER

abinfo 'Vulkan Spir-V compiler library'
install -Dvm755 "libnvidia-glvkspirv.so.$PKGVER" \
    "$PKGDIR"/usr/lib/libnvidia-glvkspirv.so.$PKGVER

abinfo 'Vulkan Ray tracing extensions'
install_for_all 755 "libnvidia-rtcore.so.$PKGVER" "$PKGDIR"/usr/lib
install_for_all 755 "libnvoptix.so.$PKGVER" "$PKGDIR"/usr/lib
install_for_all 644 "nvoptix.bin" "$PKGDIR"/usr/share/nvidia

abinfo "Vulkan SC Core"
install_if_amd64 755 "libnvidia-vksc-core.so.$PKGVER" \
    "$PKGDIR"/usr/lib

abinfo 'Optical flow library'
install -Dvm755 "libnvidia-opticalflow.so.${PKGVER}" \
    "$PKGDIR"/usr/lib/libnvidia-opticalflow.so.${PKGVER}

abinfo 'NvPresent NVIDIA Smooth Motion Vulkan layer'
install_if_amd64 755 "libnvidia-present.so.$PKGVER" "$PKGDIR"/usr/lib

abinfo "Debug and core dump utility..."
install -Dvm755 nvidia-debugdump \
    "$PKGDIR"/usr/bin/nvidia-debugdump

abinfo "NVIDIA Bug Reporter..."
install -Dvm755 nvidia-bug-report.sh \
    "$PKGDIR"/usr/bin/nvidia-bug-report

abinfo "NVIDIA hardware status monitor..."
install -Dvm755 nvidia-smi \
    "$PKGDIR"/usr/bin/nvidia-smi
install -Dvm644 nvidia-smi.1.gz \
    "$PKGDIR"/usr/share/man/man1/nvidia-smi.1.gz

abinfo "NVIDIA CUDA Multi-Process Service..."
install -Dvm755 nvidia-cuda-mps-server \
    "$PKGDIR"/usr/bin/nvidia-cuda-mps-server
install -Dvm755 nvidia-cuda-mps-control \
    "$PKGDIR"/usr/bin/nvidia-cuda-mps-control
install -Dvm644 nvidia-cuda-mps-control.1.gz \
    "$PKGDIR"/usr/share/man/man1/nvidia-cuda-mps-control.1.gz

abinfo "nvidia-modprobe... This should be removed if nvidia fixed their uvm module!"
install -Dvm4755 nvidia-modprobe \
    "$PKGDIR"/usr/bin/nvidia-modprobe
install -Dvm644 nvidia-modprobe.1.gz \
    "$PKGDIR"/usr/share/man/man1/nvidia-modprobe.1.gz

abinfo "Application profiles..."
install -Dvm644 nvidia-application-profiles-$PKGVER-rc \
    "$PKGDIR"/usr/share/nvidia/nvidia-application-profiles-$PKGVER-rc
install -Dvm644 nvidia-application-profiles-$PKGVER-key-documentation \
    "$PKGDIR"/usr/share/nvidia/nvidia-application-profiles-$PKGVER-key-documentation

abinfo "Power management services"
for i in suspend hibernate resume; do
    install_for_all 644 systemd/system/nvidia-${i}.service \
        "$PKGDIR"/usr/lib/systemd/system
done
install_for_all 755 systemd/system-sleep/nvidia "$PKGDIR"/usr/lib/systemd/system-sleep
install_for_all 755 systemd/nvidia-sleep.sh "$PKGDIR"/usr/bin
install_for_all 755 nvidia-powerd "${PKGDIR}/usr/bin"
install_for_all 644 nvidia-dbus.conf "${PKGDIR}/usr/share/dbus-1/system.d"
install_for_all 644 systemd/system/nvidia-powerd.service "$PKGDIR"/usr/lib/systemd/system

if ((NEED_FIX)); then
    aberr "Additional files should be installed. See errors above."
    abdie
fi

sanity_check "${PKGDIR}/usr/"

abinfo "Creating symbolic links for shared objects"
create_links

abinfo "Manually symlinking glxserver_nvidia as it has no SONAME"
ln -sv "libglxserver_nvidia.so.$PKGVER" \
    "$PKGDIR"/usr/lib/nvidia/xorg/libglxserver_nvidia.so.1
ln -sv "libglxserver_nvidia.so.$PKGVER" \
    "$PKGDIR"/usr/lib/nvidia/xorg/libglxserver_nvidia.so

abinfo "License and help texts"
for i in README.txt LICENSE NVIDIA_Changelog; do
    install -Dvm644 $i "$PKGDIR"/usr/share/doc/nvidia-utils/$i
done

popd

if [[ $NV_ARCH == "x86_64" ]]; then
    abinfo "Installing optenv32 libraries"
    pushd "${SRCDIR}"
    source "${SRCDIR}/autobuild/build-optenv32"
    popd
fi
