Build Packages / build:windows:nocuda (push) Successful in 14m38s
Build Packages / build:viewer-tgz:cpu (push) Successful in 18m34s
Build Packages / build:viewer-tgz:cuda (push) Successful in 21m44s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 23m0s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 23m41s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 28m36s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 28m38s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 28m54s
Build Packages / build:windows:cuda (push) Successful in 15m45s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m56s
Build Packages / XDS test (durin plugin) (push) Successful in 10m58s
Build Packages / build:rpm (rocky9) (push) Successful in 21m16s
Build Packages / Generate python client (push) Successful in 35s
Build Packages / Build documentation (push) Successful in 1m9s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky8) (push) Successful in 28m17s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 11m39s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 21m36s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 26m33s
Build Packages / DIALS test (push) Successful in 21m38s
Build Packages / XDS test (neggia plugin) (push) Successful in 10m42s
Build Packages / Unit tests (push) Successful in 2h33m11s
CMAKE_CUDA_ARCHITECTURES had no sm_70 entry, and PTX only ever JIT-compiles forwards, so a V100 had no runnable code in the fatbin at all - every kernel launch failed with "no kernel image is available for execution on the device". Append 70 only for a CUDA 12 toolkit: CUDA 13 removed offline compilation for Volta, so an unconditional entry would break the RHEL 9, Ubuntu and Windows builds. 12.8/12.9 still emit it but warn on every .cu, hence -Wno-deprecated-gpu-targets. The append goes after ENABLE_LANGUAGE(CUDA), where the nvcc version is known, matching the existing sm_121 handling. Verified: all 15 CUDA sources compile for sm_70 (including ffbidx, which already guards on __CUDA_ARCH__ >= 700/800), and cuobjdump shows an sm_70 cubin in the built rugnux binary. Consequence worth documenting: a V100 can only run the artefacts built with CUDA 12 - the RHEL 8 packages and the portable Linux .tgz. Document that alongside the minimum NVIDIA driver of every released artefact (525.60.13 for CUDA 12, 580.65.06 for CUDA 13), which applies because the CUDA runtime is linked statically and cuFFT is bundled, so the driver is the only NVIDIA component the target host must supply. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
585 lines
28 KiB
CMake
585 lines
28 KiB
CMake
CMAKE_MINIMUM_REQUIRED(VERSION 3.26)
|
|
|
|
# The VERSION file is the single source of truth for the version, and JFJOCH_VERSION carries it
|
|
# verbatim - including a pre-release suffix such as "-rc.161" - into the package names, the DKMS
|
|
# install path and the version every binary reports. PROJECT(VERSION) cannot hold that string: it
|
|
# only accepts numeric major.minor.patch, so the numeric part is cut out of the same file rather
|
|
# than written out a second time, and PROJECT_VERSION can never drift from VERSION.
|
|
FILE(STRINGS VERSION JFJOCH_VERSION)
|
|
STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" JFJOCH_VERSION_NUMERIC "${JFJOCH_VERSION}")
|
|
|
|
PROJECT(jfjoch VERSION ${JFJOCH_VERSION_NUMERIC} LANGUAGES C CXX)
|
|
SET(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
|
|
|
SET(CMAKE_CXX_STANDARD 20)
|
|
SET(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
|
|
SET(JFJOCH_WRITER_ONLY OFF CACHE BOOL "Compile HDF5 writer only")
|
|
SET(JFJOCH_INSTALL_DRIVER_SOURCE OFF CACHE BOOL "Install kernel driver source (ignored if building writer only; necessary for RPM building)")
|
|
SET(JFJOCH_USE_CUDA ON CACHE BOOL "Compile Jungfraujoch with CUDA")
|
|
SET(JFJOCH_VIEWER_BUILD OFF CACHE BOOL "Compile Jungfraujoch viewer")
|
|
|
|
# Only the viewer (and its portable dependency tree) is supported on Windows and macOS -- the
|
|
# broker/receiver/FPGA/writer server stack is Linux-only. Force viewer-only on those platforms so a
|
|
# plain configure builds the right subset; on Linux it remains a user-togglable option.
|
|
IF (WIN32 OR APPLE)
|
|
SET(JFJOCH_VIEWER_ONLY ON CACHE BOOL "Compile only jfjoch_viewer and its dependencies" FORCE)
|
|
ELSE()
|
|
SET(JFJOCH_VIEWER_ONLY OFF CACHE BOOL "Compile only jfjoch_viewer and its dependencies")
|
|
ENDIF()
|
|
|
|
SET (ZLIB_USE_STATIC_LIBS TRUE)
|
|
|
|
FIND_PACKAGE(ZLIB REQUIRED)
|
|
|
|
OPTION(SLS9 "Build with sls_detector_package v9.2.0" OFF)
|
|
|
|
SET(BUILD_SHARED_LIBS OFF)
|
|
SET(BUILD_TESTING OFF)
|
|
|
|
SET(ZSTD_LEGACY_SUPPORT OFF)
|
|
SET(ZSTD_MULTITHREAD_SUPPORT OFF)
|
|
SET(ZSTD_BUILD_PROGRAMS OFF)
|
|
SET(ZSTD_BUILD_SHARED OFF)
|
|
|
|
SET(SLS_USE_RECEIVER OFF)
|
|
SET(SLS_USE_RECEIVER_BINARIES OFF)
|
|
SET(SLS_BUILD_SHARED_LIBRARIES OFF)
|
|
|
|
SET(BUILD_FAST_INDEXER OFF)
|
|
SET(BUILD_FAST_INDEXER_STATIC ON)
|
|
|
|
INCLUDE(CheckLanguage)
|
|
INCLUDE(CheckIncludeFile)
|
|
|
|
# Locate nvcc ourselves when it isn't already pinned (-DCMAKE_CUDA_COMPILER / $CUDACXX). CHECK_LANGUAGE
|
|
# below only searches PATH, which is missed routinely on Windows and intermittently on Linux; the
|
|
# standard CUDA install locations (CUDA_PATH on Windows, /usr/local/cuda on Linux) cover both, so the
|
|
# compiler need not be passed by hand. Only set it when actually found, leaving CHECK_LANGUAGE to run
|
|
# its normal detection otherwise.
|
|
IF (JFJOCH_USE_CUDA AND NOT CMAKE_CUDA_COMPILER AND NOT DEFINED ENV{CUDACXX})
|
|
FIND_PROGRAM(_jfjoch_nvcc nvcc
|
|
HINTS ENV CUDA_PATH ENV CUDA_HOME ENV CUDA_ROOT /usr/local/cuda /opt/cuda
|
|
PATH_SUFFIXES bin)
|
|
IF (_jfjoch_nvcc)
|
|
SET(CMAKE_CUDA_COMPILER "${_jfjoch_nvcc}")
|
|
ENDIF()
|
|
ENDIF()
|
|
|
|
CHECK_LANGUAGE(CUDA)
|
|
|
|
# GPU architectures to generate device code for: Turing (T4), Ampere (A100; RTX A4000), Ada (L4),
|
|
# Hopper, and Blackwell in both its data-centre and consumer forms. A bare entry emits SASS *and*
|
|
# PTX for that architecture, so the newest one here also covers any future GPU: the driver
|
|
# JIT-compiles its PTX on first launch. Volta (V100) is added below, once the nvcc version is known.
|
|
SET(CMAKE_CUDA_ARCHITECTURES 75 80 86 89 90 100 120)
|
|
SET(CMAKE_CUDA_STANDARD 20)
|
|
SET(CMAKE_CUDA_STANDARD_REQUIRED True)
|
|
SET(CMAKE_CUDA_FLAGS_RELEASE "-O3 -lineinfo")
|
|
SET(CMAKE_CUDA_RUNTIME_LIBRARY Static)
|
|
|
|
SET(JFJOCH_CUDA_AVAILABLE OFF)
|
|
|
|
IF (CMAKE_CUDA_COMPILER)
|
|
IF (JFJOCH_USE_CUDA)
|
|
ENABLE_LANGUAGE(CUDA)
|
|
MESSAGE(STATUS "CUDA VERSION: ${CMAKE_CUDA_COMPILER_VERSION}")
|
|
IF (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.8")
|
|
FIND_PACKAGE(CUDAToolkit REQUIRED)
|
|
ADD_COMPILE_DEFINITIONS(JFJOCH_USE_CUDA)
|
|
SET(JFJOCH_CUDA_AVAILABLE ON)
|
|
# Blackwell GB10 (DGX Spark) is sm_121, only known to nvcc >= 12.9; add it there so the
|
|
# binary runs natively on Spark instead of having the driver JIT sm_120 PTX for it.
|
|
IF (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.9")
|
|
LIST(APPEND CMAKE_CUDA_ARCHITECTURES 121)
|
|
ENDIF()
|
|
# Volta (V100) is sm_70, and PTX only ever JITs *forwards* - without an sm_70 entry a
|
|
# V100 has no runnable code in the fatbin at all and every launch fails with "no kernel
|
|
# image is available for execution on the device". CUDA 13 removed offline compilation
|
|
# for Volta, so only a CUDA 12 toolkit can emit it; 12.8/12.9 still do, but warn on
|
|
# every .cu, hence -Wno-deprecated-gpu-targets. Volta is the floor - older GPUs are
|
|
# not in use here.
|
|
IF (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS "13.0")
|
|
LIST(APPEND CMAKE_CUDA_ARCHITECTURES 70)
|
|
SET(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets")
|
|
ENDIF()
|
|
ELSE()
|
|
MESSAGE(WARNING "CUDA older than 12.8 not supported")
|
|
ENDIF()
|
|
ELSE()
|
|
MESSAGE(WARNING "CUDA Available, but disabled by user")
|
|
ENDIF()
|
|
ENDIF()
|
|
|
|
INCLUDE_DIRECTORIES(include)
|
|
|
|
include(FetchContent)
|
|
|
|
SET(HDF5_ENABLE_SZIP_SUPPORT OFF CACHE BOOL "" FORCE)
|
|
SET(HDF5_ENABLE_SZIP_ENCODING OFF CACHE BOOL "" FORCE)
|
|
SET(HDF5_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|
SET(HDF5_BUILD_CPP_LIB OFF CACHE BOOL "" FORCE)
|
|
SET(HDF5_ENABLE_ZLIB_SUPPORT ON CACHE BOOL "" FORCE)
|
|
SET(HDF5_EXTERNALLY_CONFIGURED 1 CACHE BOOL "" FORCE)
|
|
|
|
SET(SPDLOG_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|
SET(SPDLOG_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
|
SET(SPDLOG_BUILD_BENCH OFF CACHE BOOL "" FORCE)
|
|
set(SPDLOG_BUILD_SHARED OFF CACHE BOOL "" FORCE)
|
|
SET(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
|
|
|
SET(HTTPLIB_USE_NON_BLOCKING_GETADDRINFO OFF CACHE BOOL "" FORCE)
|
|
SET(HTTPLIB_REQUIRE_ZLIB ON CACHE BOOL "" FORCE)
|
|
|
|
FetchContent_Declare(
|
|
spdlog
|
|
GIT_REPOSITORY https://github.com/gabime/spdlog.git
|
|
GIT_TAG v1.17.0
|
|
EXCLUDE_FROM_ALL
|
|
)
|
|
|
|
FetchContent_Declare(
|
|
zstd
|
|
GIT_REPOSITORY https://github.com/facebook/zstd
|
|
GIT_TAG 794ea1b0afca0f020f4e57b6732332231fb23c70
|
|
SOURCE_SUBDIR build/cmake
|
|
EXCLUDE_FROM_ALL
|
|
)
|
|
|
|
FetchContent_Declare(hdf5
|
|
GIT_REPOSITORY https://github.com/HDFGroup/hdf5/
|
|
GIT_TAG hdf5_2.1.0
|
|
GIT_SHALLOW 1
|
|
EXCLUDE_FROM_ALL)
|
|
|
|
SET(SLS_DETECTOR_GIT_TAG "8.0.2")
|
|
IF(SLS9)
|
|
SET(SLS_DETECTOR_GIT_TAG "9.2.0")
|
|
ENDIF()
|
|
|
|
FetchContent_Declare(
|
|
sls_detector_package
|
|
GIT_REPOSITORY https://github.com/slsdetectorgroup/slsDetectorPackage
|
|
GIT_TAG ${SLS_DETECTOR_GIT_TAG}
|
|
EXCLUDE_FROM_ALL
|
|
)
|
|
|
|
FetchContent_Declare(
|
|
catch2
|
|
GIT_REPOSITORY https://github.com/catchorg/Catch2
|
|
GIT_TAG v3.13.0
|
|
EXCLUDE_FROM_ALL
|
|
)
|
|
|
|
FetchContent_Declare(
|
|
httplib
|
|
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
|
|
GIT_TAG v0.39.0
|
|
EXCLUDE_FROM_ALL
|
|
)
|
|
# httplib enables Brotli content-encoding whenever it finds system Brotli; we don't use it
|
|
# (gzip/zlib is enough for the broker), so disable it to avoid linking libbrotli.
|
|
SET(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF CACHE BOOL "" FORCE)
|
|
|
|
# httplib auto-enables HTTPS by linking system OpenSSL whenever it finds it. The broker serves
|
|
# plain HTTP only (TLS, if ever wanted, is terminated by a front reverse proxy), so disable it --
|
|
# otherwise jfjoch_broker would pull in libssl/libcrypto for no reason.
|
|
SET(HTTPLIB_USE_OPENSSL_IF_AVAILABLE OFF CACHE BOOL "" FORCE)
|
|
|
|
# ZeroMQ (libzmq): fetch it here, at the top level, so that THIS project - not
|
|
# slsDetectorPackage - controls the version. slsDetectorPackage bundles its own libzmq
|
|
# archive, but only populates it behind `if(NOT libzmq_POPULATED)`; by making libzmq
|
|
# available before sls below, sls reuses this copy and a single libzmq-static target is
|
|
# built (no duplicate target / double-symbol clash). A future viewer-only / Windows build
|
|
# (which does not build sls) fetches the same libzmq standalone.
|
|
SET(BUILD_SHARED OFF CACHE BOOL "" FORCE) # libzmq: static only (matches sls)
|
|
SET(BUILD_TESTS OFF CACHE BOOL "" FORCE) # libzmq: no test build
|
|
SET(WITH_PERF_TOOL OFF CACHE BOOL "" FORCE) # libzmq: no perf tools
|
|
SET(WITH_DOCS OFF CACHE BOOL "" FORCE) # libzmq: no docs
|
|
SET(ENABLE_CPACK OFF CACHE BOOL "" FORCE) # libzmq: no CPack injection
|
|
FetchContent_Declare(
|
|
libzmq
|
|
GIT_REPOSITORY https://github.com/zeromq/libzmq.git
|
|
GIT_TAG v4.3.5
|
|
EXCLUDE_FROM_ALL
|
|
)
|
|
|
|
# CMake >= 4.0 (e.g. the 4.x bundled with Visual Studio 2026) makes any
|
|
# cmake_minimum_required(VERSION < 3.5) a fatal error. Some fetched dependencies still
|
|
# declare such old floors (libzmq: 3.0.2), so raise the policy-version floor for the
|
|
# FetchContent subprojects. Ignored (harmless) on CMake < 3.30, which lacks this variable.
|
|
SET(CMAKE_POLICY_VERSION_MINIMUM 3.5)
|
|
|
|
# libzmq must be made available BEFORE sls_detector_package for the override above to take effect.
|
|
FetchContent_MakeAvailable(libzmq)
|
|
IF (JFJOCH_VIEWER_ONLY)
|
|
# A viewer-only build still needs zstd/hdf5/spdlog/httplib (JFJochReader uses httplib).
|
|
# Only sls_detector_package (detector) and catch2 (tests) are not built here -- and sls
|
|
# in particular does not configure under MSVC -- so skip just those two.
|
|
FetchContent_MakeAvailable(zstd hdf5 spdlog httplib)
|
|
ELSE()
|
|
FetchContent_MakeAvailable(zstd sls_detector_package catch2 hdf5 spdlog httplib)
|
|
ENDIF()
|
|
|
|
# libtiff (used by JFJochPreview in every build mode): build it ourselves. Its C++ binding
|
|
# (tiffxx) is packaged inconsistently across distros (missing on Rocky 9) and absent on
|
|
# Windows. Library only; the SET()s below are libtiff's own codec/tool switches.
|
|
# We only need DEFLATE (zlib) + the internal LZW codec, matching what Python tifffile writes
|
|
# by default. The remaining codecs default to ON whenever their library is found on the build
|
|
# host, so each must be explicitly turned OFF to keep the dependency set minimal -- otherwise
|
|
# webp pulls in libwebp + libsharpyuv and lerc pulls in libLerc.
|
|
SET(jbig OFF)
|
|
SET(zstd OFF)
|
|
SET(lzma OFF)
|
|
SET(jpeg OFF)
|
|
SET(old-jpeg OFF)
|
|
SET(webp OFF)
|
|
SET(lerc OFF)
|
|
SET(tiff-tools OFF)
|
|
SET(tiff-tests OFF)
|
|
FetchContent_Declare(tiff
|
|
GIT_REPOSITORY https://gitlab.com/libtiff/libtiff.git
|
|
GIT_TAG v4.7.1
|
|
EXCLUDE_FROM_ALL)
|
|
FetchContent_MakeAvailable(tiff)
|
|
|
|
# FFTW single precision (target fftw3f): the CPU fallback indexer, enables JFJOCH_USE_FFTW.
|
|
# Built from the release tarball -- the git repo ships no pre-generated codelets (needs the
|
|
# OCaml genfft).
|
|
SET(ENABLE_FLOAT ON CACHE BOOL "" FORCE)
|
|
SET(BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
|
# SIMD codelets are runtime-dispatched (cpuid), so enabling AVX2 does NOT require an AVX2 CPU
|
|
# -- FFTW falls back at runtime. The codelet sets are arch-specific, so guard by processor:
|
|
# x86 gets SSE2/AVX/AVX2, aarch64 (e.g. Grace on DGX Spark) gets NEON; other arches build scalar.
|
|
IF (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
|
|
SET(ENABLE_SSE2 ON CACHE BOOL "" FORCE)
|
|
SET(ENABLE_AVX ON CACHE BOOL "" FORCE)
|
|
SET(ENABLE_AVX2 ON CACHE BOOL "" FORCE)
|
|
ELSEIF (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
|
|
SET(ENABLE_NEON ON CACHE BOOL "" FORCE)
|
|
ENDIF()
|
|
FetchContent_Declare(fftw
|
|
URL https://www.fftw.org/fftw-3.3.10.tar.gz
|
|
URL_HASH SHA256=56c932549852cddcfafdab3820b0200c7742675be92179e59e6215b340e26467
|
|
EXCLUDE_FROM_ALL)
|
|
FetchContent_MakeAvailable(fftw)
|
|
# FFTW exposes fftw3.h only via $<INSTALL_INTERFACE:include>, so consuming fftw3f straight from
|
|
# the build tree (FetchContent) leaves the header unreachable. On Linux a system-installed
|
|
# fftw3.h masks this; on Windows it does not. Add the source-tree api/ dir for build-tree use.
|
|
TARGET_INCLUDE_DIRECTORIES(fftw3f INTERFACE $<BUILD_INTERFACE:${fftw_SOURCE_DIR}/api>)
|
|
ADD_COMPILE_DEFINITIONS(JFJOCH_USE_FFTW)
|
|
|
|
# Eigen is an EXTERNAL dependency (like ZLIB), resolved by find_package(Eigen3) in the subdirectories
|
|
# that need it (image_analysis, and transitively Ceres and ffbidx). It is deliberately NOT vendored
|
|
# via FetchContent: declaring Eigen with OVERRIDE_FIND_PACKAGE makes the CMake bundled with Visual
|
|
# Studio (cmake 4.x "-msvc") intermittently SEGFAULT during configure. The fault is in CMake's own
|
|
# FetchContent variable-stack cleanup, reached when Ceres' find_package(Eigen3) resolves the override
|
|
# through a nested FetchContent_MakeAvailable -- ~1 in 3 fresh configures, and 100% with Ceres CUDA on.
|
|
# Stock Kitware CMake runs the identical scripts fine, so it is a bug in the VS-bundled cmake binary;
|
|
# providing Eigen externally avoids that code path entirely and is stable (verified, both Ceres CUDA
|
|
# on and off). Provide it via the system package on Linux (eigen3-devel / libeigen3-dev) or a build
|
|
# prefix on Windows (point CMAKE_PREFIX_PATH / Eigen3_DIR at it), exactly as for ZLIB.
|
|
|
|
# getopt/getopt_long shim for Windows: the MSVC CRT has no <getopt.h>. Vendored OpenBSD/NetBSD
|
|
# implementation (BSD-licensed). Built only on Windows and defined here, before the subdirectories,
|
|
# so the portable CLI tools in tools/ can link it. A no-op on Linux/macOS, where getopt lives in
|
|
# libc (macOS uses the system getopt even though it is also a forced viewer-only platform).
|
|
IF (WIN32)
|
|
ADD_LIBRARY(wingetopt STATIC tools/wingetopt/getopt.c tools/wingetopt/getopt.h)
|
|
TARGET_INCLUDE_DIRECTORIES(wingetopt PUBLIC tools/wingetopt)
|
|
ENDIF()
|
|
|
|
# libcurl: the jfjoch_viewer HTTP client (viewer/JFJochHttpReader). Fetched and STATICALLY linked
|
|
# ONLY for viewer builds, so the broker/writer never pull in a TLS/Kerberos stack. Backends are
|
|
# OS-native per platform to keep the Windows build self-contained: Schannel (TLS) + SSPI
|
|
# (Negotiate/Kerberos) on Windows -- no external OpenSSL/krb5 -- and system OpenSSL + GSSAPI (krb5)
|
|
# on Linux. Trimmed to HTTP(S) only, mirroring the libtiff codec pruning above.
|
|
IF (JFJOCH_VIEWER_BUILD OR JFJOCH_VIEWER_ONLY)
|
|
SET(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
|
SET(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) # static libcurl only, never a shared lib
|
|
SET(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE)
|
|
SET(BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
|
SET(CURL_DISABLE_INSTALL ON CACHE BOOL "" FORCE)
|
|
SET(HTTP_ONLY ON CACHE BOOL "" FORCE) # HTTP/HTTPS only; drop FTP/LDAP/SMTP/...
|
|
SET(CURL_USE_LIBPSL OFF CACHE BOOL "" FORCE) # avoid the libpsl dependency
|
|
SET(CURL_USE_LIBSSH2 OFF CACHE BOOL "" FORCE)
|
|
SET(CURL_ZLIB ON CACHE BOOL "" FORCE) # reuse the project's ZLIB
|
|
IF (WIN32)
|
|
SET(CURL_USE_SCHANNEL ON CACHE BOOL "" FORCE) # native Windows TLS (no OpenSSL)
|
|
SET(CURL_USE_SSPI ON CACHE BOOL "" FORCE) # native Negotiate/Kerberos (no krb5)
|
|
ELSE()
|
|
SET(CURL_USE_OPENSSL ON CACHE BOOL "" FORCE)
|
|
SET(CURL_USE_GSSAPI ON CACHE BOOL "" FORCE) # Kerberos via system krb5 (needs krb5-dev)
|
|
ENDIF()
|
|
FetchContent_Declare(curl
|
|
GIT_REPOSITORY https://github.com/curl/curl.git
|
|
GIT_TAG curl-8_11_1
|
|
EXCLUDE_FROM_ALL)
|
|
FetchContent_MakeAvailable(curl)
|
|
# The viewer links libcurl_static (curl's concrete static-lib target) directly rather than the
|
|
# CURL::libcurl alias: the alias can be shadowed by a system libcurl (find_package / dependency
|
|
# provider / a distro CURL config), silently linking the OS curl with the wrong TLS/Kerberos
|
|
# backend. libcurl_static is unambiguous; guard that FetchContent actually produced it.
|
|
IF (NOT TARGET libcurl_static)
|
|
MESSAGE(FATAL_ERROR "libcurl_static missing after FetchContent_MakeAvailable(curl) -- "
|
|
"the vendored static libcurl was not built.")
|
|
ENDIF()
|
|
ENDIF()
|
|
|
|
IF (JFJOCH_VIEWER_ONLY)
|
|
# Minimal subtree: jfjoch_viewer and only the libraries it transitively links.
|
|
# (broker here provides JFJochAPI only; its service targets are gated out.)
|
|
ADD_SUBDIRECTORY(jungfrau)
|
|
ADD_SUBDIRECTORY(compression)
|
|
ADD_SUBDIRECTORY(common)
|
|
ADD_SUBDIRECTORY(gemmi_gph)
|
|
ADD_SUBDIRECTORY(frame_serialize)
|
|
ADD_SUBDIRECTORY(preview)
|
|
ADD_SUBDIRECTORY(writer)
|
|
ADD_SUBDIRECTORY(image_analysis)
|
|
ADD_SUBDIRECTORY(broker)
|
|
ADD_SUBDIRECTORY(reader)
|
|
ADD_SUBDIRECTORY(rugnux)
|
|
ADD_SUBDIRECTORY(viewer)
|
|
ADD_SUBDIRECTORY(tools) # builds only the portable analysis tools (rugnux/extract_hkl)
|
|
ELSE()
|
|
ADD_SUBDIRECTORY(jungfrau)
|
|
ADD_SUBDIRECTORY(compression)
|
|
ADD_SUBDIRECTORY(common)
|
|
ADD_SUBDIRECTORY(writer)
|
|
ADD_SUBDIRECTORY(frame_serialize)
|
|
ADD_SUBDIRECTORY(reader)
|
|
ADD_SUBDIRECTORY(detector_control)
|
|
ADD_SUBDIRECTORY(image_puller)
|
|
ADD_SUBDIRECTORY(preview)
|
|
ADD_SUBDIRECTORY(gemmi_gph)
|
|
ADD_SUBDIRECTORY(xds-plugin)
|
|
|
|
IF (JFJOCH_WRITER_ONLY)
|
|
MESSAGE(STATUS "Compiling HDF5 writer only")
|
|
ELSE()
|
|
ADD_SUBDIRECTORY(image_pusher)
|
|
ADD_SUBDIRECTORY(broker)
|
|
ADD_SUBDIRECTORY(fpga)
|
|
ADD_SUBDIRECTORY(acquisition_device)
|
|
ADD_SUBDIRECTORY(receiver)
|
|
ADD_SUBDIRECTORY(image_analysis)
|
|
ADD_SUBDIRECTORY(rugnux)
|
|
ADD_SUBDIRECTORY(tests)
|
|
ADD_SUBDIRECTORY(tools)
|
|
ENDIF()
|
|
|
|
IF (JFJOCH_VIEWER_BUILD)
|
|
ADD_SUBDIRECTORY(viewer)
|
|
ENDIF()
|
|
ENDIF()
|
|
|
|
IF (NOT JFJOCH_WRITER_ONLY AND NOT JFJOCH_VIEWER_ONLY)
|
|
ADD_CUSTOM_COMMAND(OUTPUT frontend/dist/index.html
|
|
COMMAND npm ci
|
|
COMMAND npm run build
|
|
COMMAND npm run licenses # write dist/THIRD_PARTY_LICENSES.txt (npm deps attribution)
|
|
COMMAND npm run redocly
|
|
COMMAND npm run docs # bundle Sphinx docs into dist/docs (served at /frontend/docs)
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/frontend)
|
|
ADD_CUSTOM_TARGET(frontend DEPENDS frontend/dist/index.html)
|
|
|
|
ADD_CUSTOM_TARGET(update_version
|
|
COMMAND bash update_version.sh
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
|
|
|
IF (JFJOCH_INSTALL_DRIVER_SOURCE)
|
|
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/
|
|
DESTINATION /usr/src/jfjoch-${JFJOCH_VERSION}
|
|
COMPONENT driver-dkms
|
|
FILES_MATCHING PATTERN "dkms.conf")
|
|
|
|
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/
|
|
DESTINATION /usr/src/jfjoch-${JFJOCH_VERSION}/src
|
|
COMPONENT driver-dkms
|
|
FILES_MATCHING PATTERN "*.c" PATTERN "*.h" PATTERN "Makefile")
|
|
ENDIF()
|
|
FILE(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/frontend/dist/)
|
|
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/frontend/dist/ DESTINATION share/jfjoch/frontend COMPONENT jfjoch )
|
|
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)
|
|
|
|
# Set Package Name
|
|
SET(CPACK_PACKAGE_NAME "jfjoch")
|
|
|
|
# Select the components to package based on build mode
|
|
if (JFJOCH_VIEWER_ONLY)
|
|
set(CPACK_COMPONENTS_ALL viewer)
|
|
else()
|
|
set(CPACK_COMPONENTS_ALL jfjoch writer)
|
|
if (JFJOCH_INSTALL_DRIVER_SOURCE)
|
|
list(APPEND CPACK_COMPONENTS_ALL driver-dkms)
|
|
endif()
|
|
if (JFJOCH_VIEWER_BUILD)
|
|
list(APPEND CPACK_COMPONENTS_ALL viewer)
|
|
endif()
|
|
endif()
|
|
|
|
# Common metadata
|
|
set(CPACK_PACKAGE_CONTACT "Filip Leonarski <filip.leonarski@psi.ch>")
|
|
set(CPACK_PACKAGE_VENDOR "Paul Scherrer Institut")
|
|
set(CPACK_PACKAGE_VERSION ${JFJOCH_VERSION})
|
|
|
|
# OS-aware packaging: DragNDrop (.dmg) on macOS, NSIS installer on Windows, DEB on Debian/Ubuntu,
|
|
# RPM on RHEL/Rocky. macOS/Windows are checked first because the /etc/* probes below are Linux-only.
|
|
if (APPLE)
|
|
# .dmg containing jfjoch_viewer.app (Qt runtime already deployed into the bundle).
|
|
set(CPACK_GENERATOR "DragNDrop")
|
|
elseif (WIN32)
|
|
# NSIS installer .exe (Qt runtime deployed next to the binary by windeployqt).
|
|
set(CPACK_GENERATOR "NSIS")
|
|
|
|
# GPLv3 text shown as the click-through license page of the installer.
|
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
|
|
|
# Branding is split across three CPack knobs so the CUDA/CPU variant surfaces exactly where we
|
|
# want it and nowhere else:
|
|
# - Install folder + Start Menu group come from CPACK_PACKAGE_INSTALL_DIRECTORY and
|
|
# CPACK_NSIS_PACKAGE_NAME (the latter feeds $(^Name), the Start Menu group's default folder).
|
|
# Both stay plain "Jungfraujoch", so the Start Menu group carries no variant tag and the two
|
|
# builds install to the same place (CUDA is a strict superset -- they replace, not coexist).
|
|
# - CPACK_NSIS_DISPLAY_NAME is the Add/Remove Programs entry -- tagged "(CUDA)"/"(CPU)".
|
|
# - CPACK_PACKAGE_FILE_NAME is the installer .exe filename -- tagged "-cuda<major>"/"-cpu", so
|
|
# the (much larger) CUDA download is self-identifying, with the CUDA major version baked in.
|
|
# The tag follows JFJOCH_CUDA_AVAILABLE automatically; CUDAToolkit_VERSION_MAJOR is set whenever
|
|
# it is ON (find_package(CUDAToolkit) ran in the same guard above).
|
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Jungfraujoch")
|
|
set(CPACK_NSIS_PACKAGE_NAME "Jungfraujoch")
|
|
if (JFJOCH_CUDA_AVAILABLE)
|
|
set(CPACK_NSIS_DISPLAY_NAME "Jungfraujoch (CUDA)")
|
|
set(CPACK_PACKAGE_FILE_NAME "jfjoch-viewer-${JFJOCH_VERSION}-win64-cuda${CUDAToolkit_VERSION_MAJOR}")
|
|
else()
|
|
set(CPACK_NSIS_DISPLAY_NAME "Jungfraujoch (CPU)")
|
|
set(CPACK_PACKAGE_FILE_NAME "jfjoch-viewer-${JFJOCH_VERSION}-win64-cpu")
|
|
endif()
|
|
|
|
# Start Menu shortcut for the viewer ("<exe basename>;<label>"). The shortcut and the
|
|
# Add/Remove Programs entry both use the .exe's embedded icon.
|
|
set(CPACK_PACKAGE_EXECUTABLES "jfjoch_viewer;Jungfraujoch Viewer")
|
|
# Forward slash on purpose: CPack writes this value verbatim into CPackConfig.cmake, and a
|
|
# backslash there ("bin\jfjoch...") is an invalid escape that cmake 4.x (CMP0010 strict, e.g. the
|
|
# VS-bundled cmake) rejects when cpack re-parses it. Windows accepts the forward slash at runtime.
|
|
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin/jfjoch_viewer.exe")
|
|
elseif (JFJOCH_VIEWER_ONLY)
|
|
# Linux portable viewer: a single self-contained .tar.gz of jfjoch_viewer (Qt is linked
|
|
# statically here, so there is nothing external to ship alongside the binary). Built on the
|
|
# oldest supported distro (RHEL 8) for a low glibc floor, so the archive runs on any newer
|
|
# Linux -- unlike the per-distro .rpm/.deb this is meant to replace in the release. Named to
|
|
# mirror the Windows/macOS artifacts, with the same -cuda<major>/-cpu tag so the (larger) GPU
|
|
# build is self-identifying. CI renames the .tar.gz to .tgz before upload.
|
|
set(CPACK_GENERATOR "TGZ")
|
|
# Package only the components in CPACK_COMPONENTS_ALL (here: viewer). Without this the archive
|
|
# generator falls back to a monolithic install and walks every install() rule in the tree --
|
|
# including the fetched HDF5 command-line tools, abseil's EXCLUDE_FROM_ALL sub-libraries and the
|
|
# non-viewer components -- none of which the viewer-only build produces, so cpack aborts with
|
|
# "cannot find <artifact>". ALL_COMPONENTS_IN_ONE keeps the output a single tarball named
|
|
# CPACK_PACKAGE_FILE_NAME (no per-component suffix), matching the CI upload glob. This mirrors
|
|
# 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)
|
|
if (JFJOCH_CUDA_AVAILABLE)
|
|
set(CPACK_PACKAGE_FILE_NAME "jfjoch_viewer-${JFJOCH_VERSION}-linux-cuda${CUDAToolkit_VERSION_MAJOR}")
|
|
else()
|
|
set(CPACK_PACKAGE_FILE_NAME "jfjoch_viewer-${JFJOCH_VERSION}-linux-cpu")
|
|
endif()
|
|
elseif (EXISTS "/etc/debian_version")
|
|
set(CPACK_PACKAGE_LICENSE "GPL-3.0-only")
|
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
|
|
|
# Debian/Ubuntu: .deb with components
|
|
set(CPACK_GENERATOR "DEB")
|
|
set(CPACK_DEB_COMPONENT_INSTALL ON)
|
|
# Every component package is named "<CPACK_PACKAGE_NAME>-<component>" unless the component
|
|
# overrides it, so the broker component came out as "jfjoch-jfjoch". Name it plain "jfjoch", to
|
|
# match what the RPM generator produces for CPACK_RPM_MAIN_COMPONENT below. (There is no
|
|
# CPACK_DEBIAN_MAIN_COMPONENT: only CPackRPM.cmake has that variable, and the DEB spelling this
|
|
# used to set was silently ignored.)
|
|
set(CPACK_DEBIAN_JFJOCH_PACKAGE_NAME "jfjoch")
|
|
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
|
|
|
|
# Up to 1.0.0-rc.160 that package was "jfjoch-jfjoch". It owns the same files as "jfjoch" does
|
|
# now, so dpkg would refuse to unpack over it; declare the rename so an existing installation
|
|
# upgrades instead of conflicting.
|
|
set(CPACK_DEBIAN_JFJOCH_PACKAGE_REPLACES "jfjoch-jfjoch")
|
|
set(CPACK_DEBIAN_JFJOCH_PACKAGE_CONFLICTS "jfjoch-jfjoch")
|
|
|
|
# Enable automatic shlib dependency discovery
|
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
|
|
|
# Optional DEB metadata (tune as needed)
|
|
set(CPACK_DEBIAN_PACKAGE_SECTION "science")
|
|
# set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://example.org/jfjoch")
|
|
|
|
# DKMS component (maps from RPM settings)
|
|
if (JFJOCH_INSTALL_DRIVER_SOURCE)
|
|
# Dependencies and arch for the DKMS component
|
|
# Note: component name "driver-dkms" maps to variable suffix "DRIVER_DKMS"
|
|
set(CPACK_DEBIAN_DRIVER_DKMS_PACKAGE_DEPENDS "dkms, gcc, bash, sed")
|
|
set(CPACK_DEBIAN_DRIVER_DKMS_PACKAGE_ARCHITECTURE "all")
|
|
|
|
# Provide Debian control scripts (postinst/prerm).
|
|
# We rename existing scripts to Debian control names at configure time.
|
|
set(_dkms_ctrl_dir "${CMAKE_CURRENT_BINARY_DIR}/cpack-debian-driver-dkms")
|
|
file(MAKE_DIRECTORY "${_dkms_ctrl_dir}")
|
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/postinstall.sh
|
|
${_dkms_ctrl_dir}/postinst COPYONLY)
|
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/preuninstall.sh
|
|
${_dkms_ctrl_dir}/prerm COPYONLY)
|
|
set(CPACK_DEBIAN_DRIVER_DKMS_PACKAGE_CONTROL_EXTRA
|
|
"${_dkms_ctrl_dir}/postinst;${_dkms_ctrl_dir}/prerm")
|
|
endif()
|
|
|
|
elseif (EXISTS "/etc/redhat-release")
|
|
# RHEL/Rocky: .rpm with components (original behavior)
|
|
set(CPACK_GENERATOR "RPM")
|
|
set(CPACK_RPM_COMPONENT_INSTALL ON)
|
|
set(CPACK_RPM_MAIN_COMPONENT jfjoch)
|
|
set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
|
|
set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
|
|
set(CPACK_RPM_PACKAGE_VERSION ${JFJOCH_VERSION})
|
|
set(CPACK_RPM_PACKAGE_RELEASE 1)
|
|
set(CPACK_RPM_PACKAGE_SUMMARY "Jungfraujoch data acquisition system")
|
|
set(CPACK_RPM_PACKAGE_DESCRIPTION "Jungfraujoch")
|
|
set(CPACK_RPM_PACKAGE_LICENSE "GPLv3")
|
|
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
|
/usr/src /usr/share /usr/share/dbus-1 /usr/share/dbus-1/services /usr/share/pixmaps /usr/share/applications)
|
|
|
|
# DKMS component scripts and requirements for RPM
|
|
if (JFJOCH_INSTALL_DRIVER_SOURCE)
|
|
set(CPACK_RPM_DRIVER-DKMS_PACKAGE_REQUIRES "dkms, gcc, bash, sed")
|
|
set(CPACK_RPM_DRIVER-DKMS_PACKAGE_ARCHITECTURE "noarch")
|
|
set(CPACK_RPM_DRIVER-DKMS_POST_INSTALL_SCRIPT_FILE
|
|
${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/postinstall.sh)
|
|
set(CPACK_RPM_DRIVER-DKMS_PRE_UNINSTALL_SCRIPT_FILE
|
|
${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/preuninstall.sh)
|
|
endif()
|
|
else()
|
|
# Fallback if OS is unknown
|
|
set(CPACK_GENERATOR "TGZ")
|
|
endif()
|
|
|
|
|
|
# Ship the license notices (top-level LICENSE, the third-party manifest, and the verbatim
|
|
# license texts) with every package variant, under share/doc/jfjoch. Installed per component so
|
|
# the file lands in whichever component package(s) the current build mode produces.
|
|
SET(JFJOCH_NOTICE_FILES
|
|
${CMAKE_SOURCE_DIR}/LICENSE
|
|
${CMAKE_SOURCE_DIR}/THIRD_PARTY_NOTICES.md)
|
|
FOREACH(_component IN LISTS CPACK_COMPONENTS_ALL)
|
|
INSTALL(FILES ${JFJOCH_NOTICE_FILES}
|
|
DESTINATION share/doc/jfjoch COMPONENT ${_component})
|
|
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses/
|
|
DESTINATION share/doc/jfjoch/licenses COMPONENT ${_component}
|
|
PATTERN "COLLECT.sh" EXCLUDE)
|
|
ENDFOREACH()
|
|
|
|
INCLUDE(CPack)
|