diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f109d12..a3795b3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/docker/ubuntu2404/aarch64-sbsa.cmake b/docker/ubuntu2404/aarch64-sbsa.cmake index 13ae8b14..5c94e3d8 100644 --- a/docker/ubuntu2404/aarch64-sbsa.cmake +++ b/docker/ubuntu2404/aarch64-sbsa.cmake @@ -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) diff --git a/image_analysis/indexing/CMakeLists.txt b/image_analysis/indexing/CMakeLists.txt index 227b58ae..e79dc456 100644 --- a/image_analysis/indexing/CMakeLists.txt +++ b/image_analysis/indexing/CMakeLists.txt @@ -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) diff --git a/rugnux/CMakeLists.txt b/rugnux/CMakeLists.txt index 9d859bfb..56de8481 100644 --- a/rugnux/CMakeLists.txt +++ b/rugnux/CMakeLists.txt @@ -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() diff --git a/viewer/CMakeLists.txt b/viewer/CMakeLists.txt index 7035fb8e..a56b719f 100644 --- a/viewer/CMakeLists.txt +++ b/viewer/CMakeLists.txt @@ -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()