FROM nvidia/cuda:12.9.1-devel-rockylinux8
LABEL authors="leonarski_f"

ARG OPENSSL_VERSION=3.5.4
ARG QT_VERSION=6.9.1
ARG DBUS_VERSION=1.14.10
ARG NODE_MAJOR=22
ARG EIGEN_VERSION=3.4.0
# HDF5, libtiff and libjpeg-turbo are built by the jungfraujoch CMake itself (FetchContent /
# ExternalProject). Eigen is an external find_package(Eigen3 3.4) dependency, installed from source
# below (3.4.x is required; Eigen's same-major-version rule rejects 5.x).

# Update base and install common utilities
RUN dnf -y install epel-release && \
    dnf -y install --enablerepo=devel \
      dnf-plugins-core \
      git \
      git-lfs \
      which \
      ca-certificates \
      wget \
      tar \
      xz \
      make \
      cmake \
      nasm \
      gcc-toolset-13 \
      gcc-toolset-13-gcc \
      gcc-toolset-13-gcc-c++ \
      gcc-toolset-13-gdb \
      rpm-build \
      rpmdevtools \
      numactl-devel \
      redhat-rpm-config \
      ninja-build \
      libxcb-devel \
      xcb-util-*-devel \
      xcb-util-devel \
      libxkbcommon-devel \
      libxkbcommon-x11-devel \
      libX11-devel \
      libXext-devel \
      libXrender-devel \
      libXi-devel \
      libXrandr-devel \
      libXcursor-devel \
      libXfixes-devel \
      libXinerama-devel \
      mesa-libGL-devel \
      mesa-libEGL-devel \
      expat-devel \
      krb5-devel \
      zlib-devel \
      zlib-static \
      fontconfig-devel \
      zlib-static \
      java-21-openjdk-headless \
      java-21-openjdk-devel \
      perl \
      perl-IPC-Cmd \
      python3 \
      python3-pip \
      python3-setuptools \
      python3-wheel \
      twine \
      libdrm-devel \
      libglvnd-core-devel \
      libglvnd-devel \
      freetype-devel && \
    dnf clean all && rm -rf /var/cache/dnf

RUN set -eux; \
    cd /tmp; \
    curl -LO https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz; \
    tar -xf openssl-${OPENSSL_VERSION}.tar.gz; \
    cd openssl-${OPENSSL_VERSION}; \
    ./Configure linux-x86_64 no-shared no-module no-tests --prefix=/opt/openssl-${OPENSSL_VERSION} --libdir=lib; \
    make -j"$(nproc)"; \
    make install_sw; \
    cd /; rm -rf /tmp/openssl-${OPENSSL_VERSION} /tmp/openssl-${OPENSSL_VERSION}.tar.gz

# Expose static OpenSSL to CMake/pkg-config
ENV OPENSSL_ROOT_DIR=/opt/openssl-${OPENSSL_VERSION}

# Install a recent Node.js (NodeSource). Change NODE_MAJOR if you want another major version.
RUN curl -fsSL https://rpm.nodesource.com/setup_${NODE_MAJOR}.x | bash - && \
    dnf -y install nodejs && \
    dnf clean all && rm -rf /var/cache/dnf && \
    node --version && npm --version && (corepack enable || true)

# Make GCC/G++ 13 the default for builds
ENV GCC_TOOLSET_ROOT=/opt/rh/gcc-toolset-13/root
ENV PATH=${GCC_TOOLSET_ROOT}/usr/bin:${PATH}
ENV CC=${GCC_TOOLSET_ROOT}/usr/bin/gcc
ENV CXX=${GCC_TOOLSET_ROOT}/usr/bin/g++

ENV PKG_CONFIG_PATH=${OPENSSL_ROOT_DIR}/lib/pkgconfig:${OPENSSL_ROOT_DIR}/lib64/pkgconfig

# Static libdbus: link D-Bus into the viewer (Qt6::DBus) instead of pulling libdbus-1.so.3 at runtime.
# A distro libdbus-1.so drags in libsystemd (-> libzstd/liblz4/libcap/libgcrypt/libgpg-error) and
# libselinux (-> libpcre2). Disabling those integrations makes libdbus-1.a depend on ~libc alone, so
# that whole runtime .so tail disappears while the viewer keeps its single-instance / remote-control
# D-Bus feature -- it is a pure session-bus client (registers a name + exports an adaptor), so the
# daemon-side systemd/selinux features are irrelevant. Static-only install (no .so); the Qt build
# finds it through find_package(DBus1) via the -DDBus1_DIR hint (the CMake package config dbus
# installs, which imports libdbus-1.a). Built -fPIC (--with-pic) so the archive links into Qt's PIE
# tools (qdbusxml2cpp). expat is only a configure-time dep of the dbus daemon; the client libdbus-1
# links neither expat nor systemd.
RUN set -eux; \
    cd /tmp; \
    curl -LO https://dbus.freedesktop.org/releases/dbus/dbus-${DBUS_VERSION}.tar.xz; \
    tar -xf dbus-${DBUS_VERSION}.tar.xz; \
    cd dbus-${DBUS_VERSION}; \
    ./configure --prefix=/opt/dbus-${DBUS_VERSION}-static \
      --enable-static --disable-shared --with-pic \
      --disable-systemd --without-systemdsystemunitdir \
      --disable-selinux --disable-apparmor --disable-libaudit \
      --disable-tests --disable-asserts \
      --disable-doxygen-docs --disable-xml-docs --disable-ducktype-docs \
      CFLAGS="-fPIC"; \
    make -j"$(nproc)"; \
    make install; \
    cd /; rm -rf /tmp/dbus-${DBUS_VERSION} /tmp/dbus-${DBUS_VERSION}.tar.xz

# Put the static libdbus pkgconfig ahead of the system one so Qt6::DBus resolves to the .a
ENV PKG_CONFIG_PATH=/opt/dbus-${DBUS_VERSION}-static/lib/pkgconfig:${PKG_CONFIG_PATH}

ARG QT_PREFIX=/opt/qt-${QT_VERSION}-static
RUN set -eux; \
    cd /tmp; \
    curl -LO https://download.qt.io/official_releases/qt/6.9/${QT_VERSION}/single/qt-everywhere-src-${QT_VERSION}.tar.xz; \
    tar -xf qt-everywhere-src-${QT_VERSION}.tar.xz; \
    mkdir -p qt-everywhere-src-${QT_VERSION}/build && cd qt-everywhere-src-${QT_VERSION}/build; \
    cmake -G Ninja \
      -DQT_BUILD_SUBMODULES="qtbase;qtshadertools;qtdeclarative;qtcharts;qt3d" \
      -DBUILD_SHARED_LIBS=OFF \
      -DQT_BUILD_TESTS=OFF \
      -DQT_BUILD_EXAMPLES=OFF \
      -DQT_FEATURE_dbus=ON \
      -DQT_FEATURE_dbus_linked=ON \
      -DDBus1_DIR=/opt/dbus-${DBUS_VERSION}-static/lib/cmake/DBus1 \
      -DQT_FEATURE_xcb=ON \
      -DQT_FEATURE_xcb_xlib=OFF \
      -DQT_FEATURE_xkbcommon_x11=ON \
      -DQT_FEATURE_opengl=ON \
      -DQT_FEATURE_opengl_desktop=ON \
      -DQT_FEATURE_opengl_dynamic=OFF \
      -DQT_FEATURE_vulkan=OFF \
      -DQT_FEATURE_glib=OFF \
      -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_INSTALL_PREFIX=${QT_PREFIX} \
      -DCMAKE_C_COMPILER=${CC} \
      -DCMAKE_CXX_COMPILER=${CXX} \
      -DQT_FEATURE_openssl=ON \
      -DQT_FEATURE_openssl_linked=ON \
      -DOPENSSL_USE_STATIC_LIBS=TRUE \
      ..; \
    cmake --build . -j"$(nproc)"; \
    cmake --install .; \
    cd /; rm -rf /tmp/qt-everywhere-src-${QT_VERSION} /tmp/qt-everywhere-src-${QT_VERSION}.tar.xz

# Eigen 3.4 (header-only) -- external find_package(Eigen3 3.4) dependency, installed to /opt/eigen-3.4.
RUN set -eux; \
    cd /tmp; \
    git clone --depth 1 --branch ${EIGEN_VERSION} https://gitlab.com/libeigen/eigen.git; \
    cmake -G Ninja -S eigen -B eigen-build -DCMAKE_INSTALL_PREFIX=/opt/eigen-3.4 \
      -DEIGEN_BUILD_BLAS=OFF -DEIGEN_BUILD_LAPACK=OFF -DEIGEN_BUILD_DOC=OFF -DBUILD_TESTING=OFF; \
    cmake --install eigen-build; \
    cd /; rm -rf /tmp/eigen /tmp/eigen-build

# Make Qt, the static libdbus, and Eigen discoverable by CMake. The static libdbus prefix is
# required here (not only at Qt build time): every Qt6::DBus consumer re-runs find_package(DBus1)
# through Qt's exported config, so DBus1Config.cmake must be on CMAKE_PREFIX_PATH for the viewer build.
ENV CMAKE_PREFIX_PATH=/opt/qt-${QT_VERSION}-static:/opt/dbus-${DBUS_VERSION}-static:/opt/eigen-3.4

# Set workdir for your project
WORKDIR /workspace

# Default entrypoint prints tool versions and hints.
CMD ["/bin/bash", "-l"]
