Fix the packaging split where it was only exercised on one configuration
Build Packages / build:rugnux:aarch64 (cross) (push) Failing after 2m8s
Build Packages / build:rugnux:windows (push) Successful in 14m6s
Build Packages / build:rugnux-tgz (x86_64) (push) Failing after 15m4s
Build Packages / build:windows:nocuda (push) Successful in 16m1s
Build Packages / build:windows:cuda (push) Successful in 18m48s
Build Packages / build:viewer-tgz:cpu (push) Successful in 20m9s
Build Packages / build:viewer-tgz:cuda (push) Successful in 23m1s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 22m54s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 24m23s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 27m45s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 27m49s
Build Packages / build:rpm (rocky8) (push) Canceled after 7m42s
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 documentation (push) Canceled after 0s
Build Packages / Create release (push) Canceled after 0s
Build Packages / build:rpm (ubuntu2204) (push) Canceled after 4m8s
Build Packages / build:rpm (ubuntu2404) (push) Canceled after 2m52s
Build Packages / build:rpm (rocky8_sls9) (push) Canceled after 15m38s
Build Packages / build:rpm (rocky9) (push) Canceled after 7m40s
Build Packages / build:rpm (rocky9_sls9) (push) Canceled after 10m37s
Build Packages / DIALS test (push) Canceled after 2m45s
Build Packages / Unit tests (push) Canceled after 30m48s

Three failures, all from validating the rugnux path alone and assuming the rest
followed.

viewer/CMakeLists.txt had an unbalanced ENDIF: removing the cuFFT bundling block
took its opening IF(JFJOCH_CUDA_AVAILABLE) with it and left the closer behind, so
every configuration that adds viewer/ died on "flow control statements are not
properly nested" -- both Windows jobs and the viewer tarball.

The cross toolchain could not find Eigen. CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY
confines find_package to the target roots, and the ubuntu2404 image installs Eigen
from source in /opt/eigen-3.4 rather than as libeigen3-dev, so it sat outside them.
It is header-only, so serving it from outside the target roots is safe; the root is
now listed explicitly.

Static cuFFT is not available everywhere. The Windows toolkit ships no
cufft_static.lib, so CUDA::cufft_static does not exist there and linking it fails
at generate time. Condition on the target rather than the platform, so a toolkit
that gains or loses the static library needs no further change, and restore the
Windows DLL bundling for both products -- now in the top-level CMakeLists, since
rugnux needs it too and does not add viewer/. rugnux.exe therefore ships beside
cufft64_*.dll rather than alone; the Linux and cross artifacts are still one file.

That condition also has to keep the JFJOCH_PORTABLE_ONLY half. Testing only for
the target quietly moved the SERVER build onto static cuFFT as well, where every
executable -- broker, tests, tools -- would then need the CUDA device-link step and
would fail on an undefined __cudaRegisterLinkedBinary_* at link. Configure still
succeeds, so nothing catches that until the link; the server build keeps libcufft.so
exactly as before.

Checked by configuring all four flavours in the image CI actually uses -- rugnux,
viewer and server on x86_64 plus the aarch64 cross -- and confirming each links the
cuFFT it should.

The rugnux archives now also carry their target architecture, since that build
produces more than one: rugnux-<version>-linux-x86_64-cuda13.tar.gz beside the
aarch64 one. CMAKE_SYSTEM_PROCESSOR is the target's, never the build host's. The
viewer is x86_64-only and keeps its existing name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SQjneRUssfhi1k9rq8Ts3h
This commit is contained in:
2026-08-25 20:53:49 +02:00
co-authored by Claude Opus 5
parent fd9e7bce1f
commit 491312f263
5 changed files with 45 additions and 23 deletions
+23 -7
View File
@@ -453,6 +453,24 @@ IF (NOT JFJOCH_WRITER_ONLY AND NOT JFJOCH_PORTABLE_ONLY)
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/frontend/dist/ DESTINATION share/jfjoch/frontend COMPONENT jfjoch )
ENDIF()
# Windows has no static cuFFT (the toolkit ships no cufft_static.lib), so there the indexer links
# the import library and the self-contained products must carry the DLL beside the executable --
# the same idea the Linux builds no longer need, since they link libcufft_static.a. CUDA 13 keeps
# the redistributable DLLs in bin/x64, earlier toolkits in bin; glob both.
IF (WIN32 AND JFJOCH_CUDA_AVAILABLE AND JFJOCH_PORTABLE_ONLY AND NOT TARGET CUDA::cufft_static)
FILE(GLOB _cufft_dll
"${CUDAToolkit_BIN_DIR}/x64/cufft64_*.dll"
"${CUDAToolkit_BIN_DIR}/cufft64_*.dll")
IF (NOT _cufft_dll)
MESSAGE(FATAL_ERROR "cuFFT runtime DLL not found under ${CUDAToolkit_BIN_DIR}")
ENDIF()
IF (JFJOCH_RUGNUX_ONLY)
INSTALL(FILES ${_cufft_dll} DESTINATION bin COMPONENT rugnux)
ELSE()
INSTALL(FILES ${_cufft_dll} DESTINATION bin COMPONENT viewer)
ENDIF()
ENDIF()
IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
SET(CMAKE_INSTALL_PREFIX /opt/jfjoch CACHE PATH "Default directory" FORCE)
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
@@ -550,17 +568,15 @@ elseif (JFJOCH_VIEWER_ONLY OR JFJOCH_RUGNUX_ONLY)
# CPACK_DEB_COMPONENT_INSTALL / CPACK_RPM_COMPONENT_INSTALL in the DEB/RPM branches below.
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)
# The rugnux archive always carries its architecture, because it is built for more than one:
# x86_64 natively and aarch64 through the cross toolchain. CMAKE_SYSTEM_PROCESSOR is the TARGET
# architecture (the toolchain file declares it), never the build host's, so a cross-built tarball
# cannot be mistaken for a native one. The viewer is x86_64-only and keeps its existing name.
if (JFJOCH_RUGNUX_ONLY)
set(_jfjoch_tgz_name "rugnux")
else()
set(_jfjoch_tgz_name "jfjoch_viewer")
endif()
# A cross-built archive is named for the TARGET arch, never the build host's: CMAKE_SYSTEM_PROCESSOR
# is what the toolchain file declares, so an aarch64 tarball cannot be mistaken for an x86 one.
# Left off for a native build, so the existing x86 artifact names do not change.
if (CMAKE_CROSSCOMPILING)
set(_jfjoch_tgz_arch "-${CMAKE_SYSTEM_PROCESSOR}")
else()
set(_jfjoch_tgz_name "jfjoch_viewer")
set(_jfjoch_tgz_arch "")
endif()
if (JFJOCH_CUDA_AVAILABLE)
+5 -1
View File
@@ -13,7 +13,11 @@ set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu)
# Programs must come from the build host (nvcc, ninja); libraries and headers from the target.
set(CMAKE_FIND_ROOT_PATH /usr/lib/aarch64-linux-gnu /usr)
# /opt/eigen-3.4 is listed explicitly: this image installs Eigen from source there rather than as
# libeigen3-dev, and CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY confines find_package to these roots,
# so without it find_package(Eigen3 3.4 REQUIRED) fails even though the headers are present. Eigen
# is header-only, so serving it from outside the target roots is safe.
set(CMAKE_FIND_ROOT_PATH /usr/lib/aarch64-linux-gnu /usr /opt/eigen-3.4)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+15 -12
View File
@@ -34,19 +34,22 @@ IF (JFJOCH_CUDA_AVAILABLE)
CUDAMemHelpers.h
FFTIndexerGPU.cu FFTIndexerGPU.h
FFBIDXIndexer.cpp FFBIDXIndexer.h)
# The two shipped products (jfjoch_viewer, rugnux) link cuFFT STATICALLY on every platform.
# It is the only CUDA component that was ever dynamic -- cudart and the fast-feedback indexer are
# already static -- and shipping it as a .so meant each self-contained artifact had to carry the
# library beside its executables and find it again through an $ORIGIN rpath, machinery that
# silently failed for any executable that was not the one the rpath had been set on. Static, an
# artifact is one file that runs; it is also what lets rugnux ship as a bare rugnux.exe on
# Windows. A cross build has no alternative anyway: NVIDIA's cross-linux-sbsa packages carry
# libcufft_static.a and no libcufft.so at all.
# Link cuFFT statically where a static cuFFT exists. It is the only CUDA component that was
# ever dynamic (cudart and the fast-feedback indexer are already static), and as a .so it forced
# every self-contained artifact to carry the library beside its executables and find it again
# through an $ORIGIN rpath -- machinery that silently failed for any executable that was not the
# one the rpath had been set on. Static, a Linux artifact is one file that runs, and a cross
# build has no alternative anyway: NVIDIA's cross-linux-sbsa packages ship libcufft_static.a and
# no libcufft.so at all.
#
# The server stack keeps the shared library: its .deb/.rpm take CUDA from the distro, so there is
# nothing to bundle, and every executable in that build (broker, tests, tools) would otherwise
# need the device-link step below.
IF (JFJOCH_PORTABLE_ONLY)
# The Windows CUDA toolkit ships no cufft_static.lib, so CUDA::cufft_static does not exist there
# and the dynamic library is the only option; the top-level CMakeLists installs the DLL beside
# the executable for the self-contained builds. Test the target rather than the platform, so a
# toolkit that gains or loses the static library is handled without another special case.
# Both halves matter: the server build keeps the shared library (its .deb/.rpm take CUDA from the
# distro, and every executable there -- broker, tests, tools -- would otherwise need the device
# link below), and Windows has no static cuFFT to link even for the portable products.
IF (JFJOCH_PORTABLE_ONLY AND TARGET CUDA::cufft_static)
TARGET_LINK_LIBRARIES(JFJochIndexing fast_indexer_static CUDA::cufft_static)
ELSE()
TARGET_LINK_LIBRARIES(JFJochIndexing fast_indexer_static CUDA::cufft)
+1 -1
View File
@@ -29,7 +29,7 @@ INSTALL(TARGETS rugnux RUNTIME COMPONENT rugnux)
# __cudaRegisterLinkedBinary_* symbol. CUDA 13 no longer ships libcufft_static_nocallback.a, which
# used to be the way around it. CUDA_RESOLVE_DEVICE_SYMBOLS makes CMake emit that step while leaving
# the host link driver alone, so the -march/-flto flags CI passes still apply.
IF (JFJOCH_PORTABLE_ONLY AND JFJOCH_CUDA_AVAILABLE)
IF (JFJOCH_PORTABLE_ONLY AND JFJOCH_CUDA_AVAILABLE AND TARGET CUDA::cufft_static)
SET_TARGET_PROPERTIES(rugnux PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
ENDIF()
+1 -2
View File
@@ -146,7 +146,7 @@ INSTALL(TARGETS jfjoch_viewer
# __cudaRegisterLinkedBinary_* symbol. CUDA 13 no longer ships libcufft_static_nocallback.a, which
# used to be the way around it. CUDA_RESOLVE_DEVICE_SYMBOLS makes CMake emit that step while leaving
# the host link driver alone, so the -march/-flto flags CI passes still apply.
IF (JFJOCH_PORTABLE_ONLY AND JFJOCH_CUDA_AVAILABLE)
IF (JFJOCH_PORTABLE_ONLY AND JFJOCH_CUDA_AVAILABLE AND TARGET CUDA::cufft_static)
SET_TARGET_PROPERTIES(jfjoch_viewer PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
ENDIF()
@@ -204,4 +204,3 @@ ENDIF()
# cuFFT is linked statically (see image_analysis/indexing/CMakeLists.txt), so there is no CUDA
# runtime library to ship beside jfjoch_viewer on any platform.
ENDIF()