Build Packages / build:rugnux:windows (push) Failing after 2s
Build Packages / build:rugnux-tgz (x86_64) (push) Failing after 14s
Build Packages / build:rugnux:aarch64 (cross) (push) Failing after 30s
Build Packages / Unit tests (push) Canceled after 2m33s
Build Packages / build:rpm (rocky8) (push) Canceled after 0s
Build Packages / build:rpm (rocky9_sls9) (push) Canceled after 0s
Build Packages / build:rpm (rocky9) (push) Canceled after 0s
Build Packages / build:rpm (ubuntu2204) (push) Canceled after 0s
Build Packages / build:rpm (ubuntu2404) (push) Canceled after 0s
Build Packages / DIALS test (push) Canceled after 0s
Build Packages / XDS test (durin plugin) (push) Canceled after 0s
Build Packages / XDS test (JFJoch plugin) (push) Canceled after 0s
Build Packages / XDS test (neggia plugin) (push) Canceled after 0s
Build Packages / Generate python client (push) Canceled after 0s
Build Packages / build:viewer-tgz:cuda (push) Canceled after 2m29s
Build Packages / Build documentation (push) Canceled after 0s
Build Packages / Create release (push) Canceled after 0s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Canceled after 2m19s
Build Packages / build:viewer-tgz:cpu (push) Canceled after 2m31s
Build Packages / build:rpm (rocky8_sls9) (push) Canceled after 1m54s
Build Packages / build:rpm (rocky9_nocuda) (push) Canceled after 2m21s
Build Packages / build:rpm (rocky8_nocuda) (push) Canceled after 2m23s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Canceled after 2m13s
Build Packages / build:windows:cuda (push) Canceled after 2m42s
Build Packages / build:windows:nocuda (push) Canceled after 2m45s
The viewer tarball also carried rugnux, jfjoch_extract_hkl and jfjoch_recompress. A GUI download that contains a batch processor is confusing on its own, and it forced anyone who only wanted rugnux to take Qt with it. JFJOCH_RUGNUX_ONLY is the viewer-only subtree minus viewer/ and tools/, so it needs no Qt at all, and each of the two options now yields one artifact holding one program: JFJOCH_VIEWER_ONLY jfjoch_viewer .tar.gz / installer / .dmg JFJOCH_RUGNUX_ONLY rugnux .tar.gz / .zip The two CLI tools are still built and no longer installed anywhere. rugnux gets a CPack component of its own, so its notices land in share/doc/jfjoch_rugnux. What makes the split possible is linking cuFFT statically in both products. It was the only CUDA component still dynamic - cudart and the fast-feedback indexer were already static - and shipping it as a .so meant each self-contained archive had to carry the library beside its executables and find it again through an $ORIGIN rpath. That rpath was set on jfjoch_viewer alone, while the same tarball installed three more executables, so those shipped with no runpath at all (cmake strips the build-tree one, which points at the build host's CUDA directory) and could not load the libcufft lying next to them. Static, an artifact is one file that runs: the x86_64 rugnux tarball needs only libc, libstdc++, libgcc_s, libm, libpthread, librt and libdl. The bundling code and the rpath both go away. libcufft_static.a carries a relocatable-device-code object, so a consuming executable needs a CUDA device link; CUDA 13 no longer ships the libcufft_static_nocallback.a that used to avoid this. CUDA_RESOLVE_DEVICE_SYMBOLS emits that step while leaving the host link driver alone, so the -march and -flto flags CI passes still apply. The server build keeps the shared library: its .deb/.rpm take CUDA from the distro, and every executable there would otherwise need the same device link. The guards that exclude server-side targets keyed on NOT JFJOCH_VIEWER_ONLY, which a rugnux-only build does not satisfy - it failed on jfjoch_writer pulling in JFJochImagePuller. They now key on JFJOCH_PORTABLE_ONLY, true for either product, rather than on one product's option in five places. docker/ubuntu2404 additionally cross-compiles rugnux for arm64 SBSA, which is both DGX Spark (GB10, sm_121) and Grace Hopper (GH200, sm_90); one binary with both fatbins runs on either. It needed three things beyond a cross gcc. arm64 is published on ports.ubuntu.com and Noble's deb822 sources carry no Architectures: field, so adding the architecture without splitting the entries 404s on every index. The CUDA cross packages are in neither the x86_64 repo nor the sbsa one but in cross-linux-sbsa, whose fatbinary_section.h ships only in the x86_64 target tree even though it is architecture-neutral. And HDF5 has two try_run probes, so qemu-user-static is needed as CMAKE_CROSSCOMPILING_EMULATOR; every other fetched dependency either guards its run-checks or has none. The cross-built tarball is one ELF aarch64 binary carrying all 17 GPU modules for both sm_90 and sm_121, needing no cuFFT and no CUDA runtime at run time. It is untested on hardware: XDS is x86-64 only, so CI can show it links but only a Spark or a GH200 can show it works. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQjneRUssfhi1k9rq8Ts3h
249 lines
11 KiB
Docker
249 lines
11 KiB
Docker
# Ubuntu 24.04 (Noble) base with CUDA 13 devel toolchain
|
|
FROM nvidia/cuda:13.3.0-devel-ubuntu24.04
|
|
LABEL authors="leonarski_f"
|
|
|
|
ENV DEBIAN_FRONTEND=noninteractive
|
|
|
|
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). nasm is required by the
|
|
# project's libjpeg-turbo ExternalProject for SIMD-accelerated JPEG.
|
|
|
|
# Update base and install toolchain + static-Qt build dependencies
|
|
# (XCB/X11/OpenGL/EGL/DBus/fontconfig/freetype/zlib headers needed to build static Qt).
|
|
#
|
|
# arm64 is enabled as a second dpkg architecture here so this one image can also CROSS-COMPILE the
|
|
# rugnux CLI for aarch64 (DGX Spark GB10 / Grace Hopper GH200 -- both arm64 SBSA). Noble's deb822
|
|
# ubuntu.sources carries no Architectures: field, so a bare `dpkg --add-architecture arm64` sends apt
|
|
# to archive.ubuntu.com for arm64 indexes and 404s on every one; arm64 is published on
|
|
# ports.ubuntu.com instead. Pin the stock entries to amd64 and add a ports entry for arm64.
|
|
RUN set -eux; \
|
|
dpkg --add-architecture arm64; \
|
|
sed -i 's/^Components: main/Architectures: amd64\nComponents: main/' /etc/apt/sources.list.d/ubuntu.sources; \
|
|
printf '\nTypes: deb\nURIs: http://ports.ubuntu.com/ubuntu-ports\nSuites: noble noble-updates noble-security\nComponents: main restricted universe multiverse\nArchitectures: arm64\nSigned-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n' \
|
|
>> /etc/apt/sources.list.d/ubuntu.sources
|
|
|
|
RUN set -eux; \
|
|
apt-get update; \
|
|
apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
curl \
|
|
wget \
|
|
git \
|
|
which \
|
|
tar \
|
|
xz-utils \
|
|
build-essential \
|
|
cmake \
|
|
ninja-build \
|
|
python3 \
|
|
python3-venv \
|
|
python3-requests \
|
|
python3.12 \
|
|
python3.12-venv \
|
|
perl \
|
|
pkg-config \
|
|
gdb \
|
|
file \
|
|
nasm \
|
|
dpkg-dev \
|
|
fakeroot \
|
|
libnuma-dev \
|
|
libkrb5-dev \
|
|
libxcb1-dev \
|
|
libx11-dev \
|
|
libxext-dev \
|
|
libxrender-dev \
|
|
libxi-dev \
|
|
libxrandr-dev \
|
|
libxcursor-dev \
|
|
libxfixes-dev \
|
|
libxinerama-dev \
|
|
libxkbcommon-dev \
|
|
libxkbcommon-x11-dev \
|
|
libx11-xcb-dev \
|
|
libxcb-shape0-dev \
|
|
libxcb-sync-dev \
|
|
libxcb-xfixes0-dev \
|
|
libxcb-image0-dev \
|
|
libxcb-icccm4-dev \
|
|
libxcb-keysyms1-dev \
|
|
libxcb-render-util0-dev \
|
|
libxcb-util-dev \
|
|
libxcb-randr0-dev \
|
|
libxcb-xkb-dev \
|
|
libxcb-shm0-dev \
|
|
libxcb-cursor0 \
|
|
libxcb-cursor-dev \
|
|
libxcb-glx0-dev \
|
|
libgl1-mesa-dev \
|
|
libglx-dev \
|
|
libegl1-mesa-dev \
|
|
libexpat1-dev \
|
|
zlib1g-dev \
|
|
libfontconfig1-dev \
|
|
libdrm-dev \
|
|
libglvnd-dev \
|
|
libassimp-dev \
|
|
libfreetype6-dev; \
|
|
apt-get clean; \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Use the default GCC/G++ (gcc-13 on Noble, supported by CUDA 13.3)
|
|
ENV CC=/usr/bin/gcc
|
|
ENV CXX=/usr/bin/g++
|
|
|
|
# Build a static OpenSSL
|
|
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}
|
|
ENV PKG_CONFIG_PATH=${OPENSSL_ROOT_DIR}/lib/pkgconfig:${OPENSSL_ROOT_DIR}/lib64/pkgconfig
|
|
|
|
# Install Node.js (NodeSource)
|
|
RUN set -eux; \
|
|
curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash -; \
|
|
apt-get update; \
|
|
apt-get install -y --no-install-recommends nodejs; \
|
|
apt-get clean; \
|
|
rm -rf /var/lib/apt/lists/*; \
|
|
node --version; npm --version; (corepack enable || true)
|
|
|
|
# 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}
|
|
|
|
# Build and install static Qt with Core, Gui, Widgets, Charts, DBus
|
|
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
|
|
|
|
# ---------------------------------------------------------------------------------------------
|
|
# aarch64 cross-compilation support (rugnux only -- the viewer is not cross-built).
|
|
#
|
|
# crossbuild-essential-arm64 the aarch64 gcc/g++.
|
|
# qemu-user-static HDF5 runs two try_run() probes (config/ConfigureChecks.cmake) that
|
|
# need CMAKE_CROSSCOMPILING_EMULATOR. libzmq guards its own run-checks
|
|
# with NOT CMAKE_CROSSCOMPILING; Ceres, libtiff, zstd, Catch2, spdlog,
|
|
# cpp-httplib, FFTW and ffbidx have no run-checks at all.
|
|
# binutils-aarch64-linux-gnu reading aarch64 ELF on the build host.
|
|
# :arm64 libraries ZLIB is one of the project's two external dependencies (Eigen, the
|
|
# other, is header-only and installed above); OpenSSL is needed by the
|
|
# libcurl the build fetches.
|
|
# ---------------------------------------------------------------------------------------------
|
|
RUN set -eux; \
|
|
apt-get update; \
|
|
apt-get install -y --no-install-recommends \
|
|
crossbuild-essential-arm64 binutils-aarch64-linux-gnu qemu-user-static \
|
|
zlib1g-dev:arm64 libssl-dev:arm64; \
|
|
apt-get clean; \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# CUDA cross target tree -> /usr/local/cuda/targets/sbsa-linux, beside the image's x86_64 tree.
|
|
# These packages are NOT in the x86_64 CUDA repo (it publishes none) and NOT in the sbsa repo (that
|
|
# is the NATIVE arm64 one a Spark or GH200 installs locally). They have their own repo and keyring:
|
|
# repos/ubuntu2404/cross-linux-sbsa/
|
|
# repos/ubuntu2404/cross-linux-aarch64/ also exists -- that is the Tegra/Jetson tree, not this one.
|
|
RUN set -eux; \
|
|
cd /tmp; \
|
|
wget -q https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/cross-linux-sbsa/cuda-keyring_1.1-1_all.deb; \
|
|
dpkg -i cuda-keyring_1.1-1_all.deb; rm cuda-keyring_1.1-1_all.deb; \
|
|
apt-get update; \
|
|
V=$(nvcc --version | sed -nE 's/.*release ([0-9]+)\.([0-9]+).*/\1-\2/p'); \
|
|
apt-get install -y --no-install-recommends \
|
|
cuda-cudart-cross-sbsa-$V cuda-crt-cross-sbsa-$V \
|
|
cuda-culibos-cross-sbsa-$V libcufft-cross-sbsa-$V; \
|
|
test -f /usr/local/cuda/targets/sbsa-linux/lib/libcufft_static.a; \
|
|
apt-get clean; \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
COPY aarch64-sbsa.cmake /opt/cross/aarch64-sbsa.cmake
|
|
|
|
# Set workdir for your project
|
|
WORKDIR /workspace
|
|
|
|
# Default entrypoint: interactive shell
|
|
CMD ["/bin/bash", "-l"]
|