cmake_minimum_required(VERSION 3.24)

include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/xtbloom_version.cmake)
xtbloom_resolve_version(XTBLOOM_VERSION_RELEASE XTBLOOM_VERSION_FULL)

project(
  xtbloom
  VERSION ${XTBLOOM_VERSION_RELEASE}
  DESCRIPTION "Batched CPU and GPU inference for GFN-xTB"
  LANGUAGES C CXX
)

# The product version follows Git tags. ABI generation and SONAME changes are
# independent compatibility decisions and must remain manually reviewed.
set(XTBLOOM_ABI_SOVERSION 0)
set(XTBLOOM_GENERATED_INCLUDE_DIR
  ${CMAKE_CURRENT_BINARY_DIR}/generated/include
)
file(MAKE_DIRECTORY ${XTBLOOM_GENERATED_INCLUDE_DIR}/xtbloom)
configure_file(
  cmake/xtbloom_version.h.in
  ${XTBLOOM_GENERATED_INCLUDE_DIR}/xtbloom/version.h
  @ONLY
)
# Several provider-free ABI tests compile the public header without linking the
# library target. Make the one generated public header visible consistently.
include_directories(BEFORE ${XTBLOOM_GENERATED_INCLUDE_DIR})

include(CheckLanguage)
include(CheckLibraryExists)
include(CheckCXXCompilerFlag)
include(CheckCXXSourceCompiles)
include(CMakePushCheckState)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/xtbloom_cuda_toolkit.cmake)
find_package(Threads REQUIRED)

set(XTBLOOM_ENABLE_CUDA "AUTO" CACHE STRING "Build the CUDA backend: AUTO, ON, or OFF")
set_property(CACHE XTBLOOM_ENABLE_CUDA PROPERTY STRINGS AUTO ON OFF)
option(XTBLOOM_ENABLE_TORCH_EXT
  "Build the PyTorch stable-ABI integration extension (vendored headers + stub)" ON)
# ----------------------------------------------------------------------------#
# PyTorch integration extension (LibTorch Stable ABI).
#
# src/bindings/torch/xtbloom_torch_ext.cpp binds torch tensors directly to
# the public xtbloom C ABI.  It is compiled against the vendored stable-ABI
# headers (cmake/3rdparty/torch-stable, see its README) and linked against a
# build-time-only platform stub, so building the extension never downloads or
# depends on a torch install.
#
# The stub has the real runtime identity (ELF SONAME, Mach-O install name, or
# PE DLL/import-library name) and defines exactly the stable symbols the
# extension references.  The shipped binary therefore binds to the Torch
# runtime the Python layer imports first; the stub is never installed.  Each
# platform retains strict undefined-symbol linking so header/version drift
# that introduces an unstubbed symbol fails the build.
set(XTBLOOM_HAS_TORCH_EXT OFF)
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" XTBLOOM_SYSTEM_PROCESSOR_LOWER)
set(XTBLOOM_TORCH_PLATFORM_SUPPORTED OFF)
set(XTBLOOM_TORCH_RUNTIME_NAME "")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  set(XTBLOOM_TORCH_PLATFORM_SUPPORTED ON)
  set(XTBLOOM_TORCH_RUNTIME_NAME "libtorch_cpu.so")
elseif(APPLE AND XTBLOOM_SYSTEM_PROCESSOR_LOWER MATCHES "^(arm64|aarch64)$")
  # PyTorch 2.10+ publishes supported macOS wheels only for Apple Silicon.
  set(XTBLOOM_TORCH_PLATFORM_SUPPORTED ON)
  set(XTBLOOM_TORCH_RUNTIME_NAME "@rpath/libtorch_cpu.dylib")
elseif(WIN32 AND XTBLOOM_SYSTEM_PROCESSOR_LOWER MATCHES "^(amd64|x86_64|x64)$")
  # PyTorch 2.10+ publishes supported Windows wheels only for AMD64.
  set(XTBLOOM_TORCH_PLATFORM_SUPPORTED ON)
  set(XTBLOOM_TORCH_RUNTIME_NAME "torch_cpu.dll")
endif()

if(XTBLOOM_ENABLE_TORCH_EXT)
  if(NOT XTBLOOM_TORCH_PLATFORM_SUPPORTED)
    message(STATUS
      "xtbloom PyTorch extension disabled: no supported Torch >=2.10 runtime "
      "is published for ${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}")
  else()
    set(XTBLOOM_TORCH_STABLE_DIR
      "${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/torch-stable")
    set(XTBLOOM_TORCH_STABLE_INCLUDE "${XTBLOOM_TORCH_STABLE_DIR}/include")
    if(NOT EXISTS "${XTBLOOM_TORCH_STABLE_INCLUDE}/torch/csrc/stable/library.h")
      message(FATAL_ERROR
        "vendored torch stable headers missing; regenerate with "
        "tools/torch_stable_vendor.py")
    endif()
    if(NOT EXISTS "${XTBLOOM_TORCH_STABLE_DIR}/aoti_symbols.txt")
      message(FATAL_ERROR
        "missing ${XTBLOOM_TORCH_STABLE_DIR}/aoti_symbols.txt")
    endif()

    # Generate the build-time stub source: one C-linkage abort() per required
    # symbol.  Signatures are irrelevant because the stub is only consumed by
    # the linker (name-based C linkage); the real libtorch_cpu.so provides the
    # actual ABI at runtime.
    set(XTBLOOM_TORCH_STUB_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated/torch_stub")
    file(MAKE_DIRECTORY "${XTBLOOM_TORCH_STUB_DIR}")
    set(XTBLOOM_TORCH_STUB_C "${XTBLOOM_TORCH_STUB_DIR}/torch_cpu_stub.c")
    file(WRITE "${XTBLOOM_TORCH_STUB_C}"
      "/* Build-time-only stub for the LibTorch Stable ABI.\n"
      " * Provides the exact aoti_torch_* / torch_* stable symbols the\n"
      " * extension references so xtbloom_torch_ext can link without a torch\n"
      " * install. Never installed; the shipped extension binds to the real\n"
      " * ${XTBLOOM_TORCH_RUNTIME_NAME} at runtime. Generated from\n"
      " * cmake/3rdparty/torch-stable/aoti_symbols.txt.\n"
      " */\n"
      "#include <stdlib.h>\n"
    )
    file(STRINGS "${XTBLOOM_TORCH_STABLE_DIR}/aoti_symbols.txt"
      XTBLOOM_TORCH_SYMBOLS)
    foreach(_xtbloom_torch_symbol IN LISTS XTBLOOM_TORCH_SYMBOLS)
      string(STRIP "${_xtbloom_torch_symbol}" _xtbloom_torch_symbol)
      if(_xtbloom_torch_symbol STREQUAL "")
        continue()
      endif()
      file(APPEND "${XTBLOOM_TORCH_STUB_C}"
        "void ${_xtbloom_torch_symbol}(void) { abort(); }\n")
    endforeach()

    add_library(xtbloom_torch_stub SHARED "${XTBLOOM_TORCH_STUB_C}")
    set_target_properties(xtbloom_torch_stub PROPERTIES
      OUTPUT_NAME torch_cpu
      C_STANDARD 11
      ARCHIVE_OUTPUT_DIRECTORY "${XTBLOOM_TORCH_STUB_DIR}"
      LIBRARY_OUTPUT_DIRECTORY "${XTBLOOM_TORCH_STUB_DIR}"
      RUNTIME_OUTPUT_DIRECTORY "${XTBLOOM_TORCH_STUB_DIR}"
    )
    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
      set_target_properties(xtbloom_torch_stub PROPERTIES
        # Same SONAME as the real Torch library.
        LINK_FLAGS "-Wl,-soname,libtorch_cpu.so"
      )
    elseif(APPLE)
      set_target_properties(xtbloom_torch_stub PROPERTIES
        # Match the official wheel's LC_ID_DYLIB exactly.  The extension has
        # no LC_RPATH of its own and reuses Torch's already-loaded image.
        INSTALL_NAME_DIR "@rpath"
        BUILD_WITH_INSTALL_NAME_DIR TRUE
        MACOSX_RPATH TRUE
      )
    elseif(WIN32)
      # Generate torch_cpu.dll plus its architecture-correct torch_cpu.lib.
      # Only the import library participates in the extension link; neither
      # artifact is installed or copied into a distribution.
      set_target_properties(xtbloom_torch_stub PROPERTIES
        PREFIX ""
        WINDOWS_EXPORT_ALL_SYMBOLS TRUE
      )
    endif()

    add_library(xtbloom_torch_ext SHARED
      "${CMAKE_CURRENT_SOURCE_DIR}/src/bindings/torch/xtbloom_torch_ext.cpp"
    )
    set_target_properties(xtbloom_torch_ext PROPERTIES
      OUTPUT_NAME xtbloom_torch_ext
      CXX_VISIBILITY_PRESET hidden
      VISIBILITY_INLINES_HIDDEN YES
      # The stub lives next to the built extension in the build tree; never let
      # RPATH/RUNPATH discover it at runtime.
      SKIP_BUILD_RPATH TRUE
      INSTALL_RPATH ""
    )
    if(WIN32)
      # A Windows SHARED target needs one exported symbol; the existing anchor
      # is the only external definition and is also used to find the DLL's own
      # directory at runtime.
      set_target_properties(xtbloom_torch_ext PROPERTIES
        PREFIX ""
        WINDOWS_EXPORT_ALL_SYMBOLS TRUE
      )
    endif()
    target_include_directories(xtbloom_torch_ext PRIVATE
      "${CMAKE_CURRENT_SOURCE_DIR}/include"
      "${XTBLOOM_TORCH_STABLE_INCLUDE}"
    )
    target_link_libraries(xtbloom_torch_ext PRIVATE
      xtbloom_torch_stub
      ${CMAKE_DL_LIBS}
      Threads::Threads
    )
    target_compile_features(xtbloom_torch_ext PRIVATE cxx_std_17)
    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
      target_link_options(xtbloom_torch_ext PRIVATE "-Wl,-z,defs")
    elseif(APPLE)
      target_link_options(xtbloom_torch_ext PRIVATE "-Wl,-undefined,error")
    endif()
    install(TARGETS xtbloom_torch_ext
      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    )
    set(XTBLOOM_HAS_TORCH_EXT ON)
    message(STATUS
      "xtbloom PyTorch stable-ABI extension: enabled for "
      "${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR} "
      "(vendored headers + build-only ${XTBLOOM_TORCH_RUNTIME_NAME} stub)")
  endif()
else()
  message(STATUS "xtbloom PyTorch extension disabled: XTBLOOM_ENABLE_TORCH_EXT=OFF")
endif()
option(XTBLOOM_BUILD_TESTS "Build xtbloom tests" ${PROJECT_IS_TOP_LEVEL})
option(XTBLOOM_BUILD_WEB_DEMO
  "Build the GitHub Pages WebAssembly demo assets (requires the Emscripten toolchain)"
  OFF)
option(XTBLOOM_PYTHON_WHEEL
  "Install an unversioned single-copy shared library for a Python wheel" OFF)
option(XTBLOOM_BUNDLE_WHEEL_OPENBLAS
  "Build the private OpenBLAS shim whose dependencies auditwheel vendors" OFF)
option(XTBLOOM_ENABLE_AVX2_DISPATCH
  "Include runtime-selected AVX2/FMA CPU kernels in supported x86-64 builds" ON)
set(XTBLOOM_CPU_LINALG_LIBRARY "" CACHE FILEPATH
  "Optional monolithic shared LP64 LAPACKE+CBLAS runtime with local thread control for the CPU eigensolver (e.g. libscipy_openblas.so or libmkl_rt.so). When unset, compatible runtimes are auto-discovered with find_package(BLAS/LAPACK)."
)

# Linux provider isolation and its focused tests share one compile-time proof of
# the complete GNU namespace API. musl and other Linux libcs that do not expose
# dlmopen/dlinfo must not accidentally accept an MKL or wheel-isolation build.
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  cmake_push_check_state(RESET)
  set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
  check_cxx_source_compiles([=[
    #ifndef _GNU_SOURCE
    #define _GNU_SOURCE 1
    #endif
    #include <dlfcn.h>
    #include <link.h>
    int main() {
      void* handle = dlmopen(LM_ID_NEWLM, nullptr, RTLD_NOW | RTLD_LOCAL);
      Lmid_t namespace_id = LM_ID_BASE;
      return handle == nullptr ? 0 : dlinfo(handle, RTLD_DI_LMID, &namespace_id);
    }
  ]=] XTBLOOM_HAS_DLMOPEN_NAMESPACE)
  cmake_pop_check_state()
else()
  set(XTBLOOM_HAS_DLMOPEN_NAMESPACE OFF)
endif()

set(XTBLOOM_MKL_TSS_BRIDGE_COMPILER_SUPPORTED OFF)
if(CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang)$")
  set(XTBLOOM_MKL_TSS_BRIDGE_COMPILER_SUPPORTED ON)
endif()

function(xtbloom_add_mkl_pthread_tss_bridge target output_name)
  # This bridge must enter a new namespace before libc/libdl. Keep it free of
  # startup objects, compiler runtimes, sanitizers, and every DT_NEEDED edge.
  # The exact no-runtime link contract is currently proven only for these ELF
  # compiler drivers; rejecting other compilers is safer than silently adding
  # a libc/compiler-runtime dependency before private TSS is bridged.
  if(NOT XTBLOOM_MKL_TSS_BRIDGE_COMPILER_SUPPORTED)
    message(FATAL_ERROR
      "The MKL pthread TSS bridge requires a GNU- or Clang-compatible C compiler"
    )
  endif()
  add_library(${target} SHARED src/runtime/mkl_pthread_tss_bridge.c)
  target_compile_features(${target} PRIVATE c_std_11)
  target_include_directories(${target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
  target_compile_options(${target} PRIVATE
    -fno-stack-protector
    -fno-sanitize=all
    -fno-profile-arcs
    -fno-test-coverage
  )
  target_link_options(${target} PRIVATE
    -nostdlib
    -nodefaultlibs
    -nostartfiles
    -fno-sanitize=all
    -fno-profile-arcs
    -fno-test-coverage
    "LINKER:-z,defs"
  )
  set_target_properties(${target} PROPERTIES
    OUTPUT_NAME ${output_name}
    C_VISIBILITY_PRESET hidden
    POSITION_INDEPENDENT_CODE YES
  )
endfunction()

string(TOUPPER "${XTBLOOM_ENABLE_CUDA}" XTBLOOM_ENABLE_CUDA_NORMALIZED)
if(NOT XTBLOOM_ENABLE_CUDA_NORMALIZED MATCHES "^(AUTO|ON|OFF)$")
  message(FATAL_ERROR "XTBLOOM_ENABLE_CUDA must be AUTO, ON, or OFF")
endif()

set(XTBLOOM_HAS_CUDA OFF)
if(NOT XTBLOOM_ENABLE_CUDA_NORMALIZED STREQUAL "OFF")
  check_language(CUDA)
  if(CMAKE_CUDA_COMPILER)
    enable_language(CUDA)
    # FindCUDAToolkit is optional provider discovery: its required variable
    # set includes libcudart, while xtbloom can build without provider shared
    # libraries. The enabled compiler remains the authority for toolkit
    # version and the cudart header set.
    find_package(CUDAToolkit QUIET)
    xtbloom_resolve_cuda_toolkit_metadata(
      XTBLOOM_CUDA_TOOLKIT_VERSION
      XTBLOOM_CUDA_TOOLKIT_MAJOR
      XTBLOOM_CUDA_TOOLKIT_MINOR
      XTBLOOM_CUDA_TOOLKIT_INCLUDE_DIRS)
    xtbloom_validate_cuda_runtime_headers(${XTBLOOM_CUDA_TOOLKIT_INCLUDE_DIRS})
    set(XTBLOOM_HAS_CUDA ON)
  elseif(XTBLOOM_ENABLE_CUDA_NORMALIZED STREQUAL "ON")
    message(FATAL_ERROR "XTBLOOM_ENABLE_CUDA=ON, but no CUDA compiler was found")
  endif()
endif()

# The eigensolver requires one dlopen-able runtime that provides LAPACKE and
# CBLAS together. FindBLAS/FindLAPACK may also report split reference libraries
# (for example liblapack.so plus libblas.so), so validate every candidate as a
# self-contained runtime before baking its path into the library or enabling
# production-backend tests.
function(xtbloom_cpu_linalg_has_symbol_set candidate symbol_prefix result)
  set(symbol_set_complete ON)
  foreach(symbol IN ITEMS
      LAPACKE_dpotrf_work
      LAPACKE_dpocon_work
      LAPACKE_dsyevd_work
      cblas_dtrsm
      cblas_dgemm
  )
    unset(XTBLOOM_CPU_LINALG_SYMBOL_FOUND CACHE)
    check_library_exists(
      "${candidate}" "${symbol_prefix}${symbol}" ""
      XTBLOOM_CPU_LINALG_SYMBOL_FOUND
    )
    if(NOT XTBLOOM_CPU_LINALG_SYMBOL_FOUND)
      set(symbol_set_complete OFF)
      unset(XTBLOOM_CPU_LINALG_SYMBOL_FOUND CACHE)
      break()
    endif()
    unset(XTBLOOM_CPU_LINALG_SYMBOL_FOUND CACHE)
  endforeach()
  set(${result} ${symbol_set_complete} PARENT_SCOPE)
endfunction()

function(xtbloom_cpu_linalg_has_local_thread_control candidate result)
  # xtbloom parallelizes over systems. Accept a provider only when each worker
  # can suppress nested BLAS threads without mutating another worker's state.
  set(has_local_thread_control OFF)
  foreach(symbol IN ITEMS
      MKL_Set_Num_Threads_Local
      openblas_set_num_threads_local
      scipy_openblas_set_num_threads_local
  )
    unset(XTBLOOM_CPU_LINALG_THREAD_CONTROL_FOUND CACHE)
    check_library_exists(
      "${candidate}" "${symbol}" ""
      XTBLOOM_CPU_LINALG_THREAD_CONTROL_FOUND
    )
    if(XTBLOOM_CPU_LINALG_THREAD_CONTROL_FOUND)
      set(has_local_thread_control ON)
      unset(XTBLOOM_CPU_LINALG_THREAD_CONTROL_FOUND CACHE)
      break()
    endif()
    unset(XTBLOOM_CPU_LINALG_THREAD_CONTROL_FOUND CACHE)
  endforeach()
  set(${result} ${has_local_thread_control} PARENT_SCOPE)
endfunction()

function(xtbloom_validate_cpu_linalg_runtime candidate result symbol_prefix_result)
  if(NOT EXISTS "${candidate}" OR IS_DIRECTORY "${candidate}")
    set(${result} OFF PARENT_SCOPE)
    set(${symbol_prefix_result} "" PARENT_SCOPE)
    return()
  endif()

  # check_library_exists can successfully link a static archive, but the
  # production backend must be able to dlopen the exact configured path.
  get_filename_component(candidate_realpath "${candidate}" REALPATH)
  string(TOLOWER "${candidate}" candidate_lower)
  string(TOLOWER "${candidate_realpath}" candidate_realpath_lower)
  if(candidate_lower MATCHES "\\.a$" OR candidate_realpath_lower MATCHES "\\.a$")
    set(${result} OFF PARENT_SCOPE)
    set(${symbol_prefix_result} "" PARENT_SCOPE)
    return()
  endif()
  # OpenBLAS publishes its integer ABI in the get_config string embedded in
  # the shared object. Reject INTERFACE64 builds before tests link to them and
  # call the provider directly with xtbloom's 32-bit LapackInt declarations.
  file(STRINGS "${candidate_realpath}" ilp64_markers REGEX "USE64BITINT" LIMIT_COUNT 1)
  if(ilp64_markers)
    set(${result} OFF PARENT_SCOPE)
    set(${symbol_prefix_result} "" PARENT_SCOPE)
    return()
  endif()

  xtbloom_cpu_linalg_has_local_thread_control(
    "${candidate}" has_local_thread_control
  )
  if(NOT has_local_thread_control)
    set(${result} OFF PARENT_SCOPE)
    set(${symbol_prefix_result} "" PARENT_SCOPE)
    return()
  endif()

  xtbloom_cpu_linalg_has_symbol_set("${candidate}" "" has_standard_symbols)
  if(has_standard_symbols)
    set(${result} ON PARENT_SCOPE)
    set(${symbol_prefix_result} "" PARENT_SCOPE)
    return()
  endif()

  # scipy-openblas32 deliberately prefixes its public ABI with ``scipy_`` to
  # avoid interposing on another BLAS already loaded by NumPy or the host.
  xtbloom_cpu_linalg_has_symbol_set("${candidate}" "scipy_" has_scipy_symbols)
  set(${result} ${has_scipy_symbols} PARENT_SCOPE)
  if(has_scipy_symbols)
    set(${symbol_prefix_result} "scipy_" PARENT_SCOPE)
  else()
    set(${symbol_prefix_result} "" PARENT_SCOPE)
  endif()
endfunction()

# Wheels carry a reviewed private OpenBLAS cohort rather than requiring an end
# user provider. Native builds use scipy-openblas32 from the isolated PEP 517
# environment. Pyodide uses the exact official 314.0.4 WebAssembly artifact and
# a narrow LAPACKE adapter; its retained recipe and libf2c source closure are
# verified before CMake accepts the binary. Linux uses a private shim so
# auditwheel follows and collision-renames the ELF dependency closure. macOS
# and Windows copy the already self-contained native cohort under private names.
set(XTBLOOM_WHEEL_OPENBLAS OFF)
set(XTBLOOM_WHEEL_OPENBLAS_LINUX_SHIM OFF)
set(XTBLOOM_WHEEL_OPENBLAS_DESKTOP OFF)
set(XTBLOOM_WHEEL_OPENBLAS_PYODIDE OFF)
if(XTBLOOM_BUNDLE_WHEEL_OPENBLAS AND NOT XTBLOOM_PYTHON_WHEEL)
  message(FATAL_ERROR
    "XTBLOOM_BUNDLE_WHEEL_OPENBLAS requires XTBLOOM_PYTHON_WHEEL=ON")
endif()
if(XTBLOOM_BUNDLE_WHEEL_OPENBLAS)
  if(XTBLOOM_CPU_LINALG_LIBRARY)
    message(FATAL_ERROR
      "XTBLOOM_CPU_LINALG_LIBRARY cannot override the reviewed private provider "
      "in XTBLOOM_PYTHON_WHEEL builds")
  endif()

  string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" xtbloom_wheel_processor)
  if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
    set(XTBLOOM_WHEEL_OPENBLAS_PLATFORM pyodide)
    set(XTBLOOM_WHEEL_OPENBLAS_ARCH wasm32)
  elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    set(XTBLOOM_WHEEL_OPENBLAS_PLATFORM linux)
    if(xtbloom_wheel_processor MATCHES "^(x86_64|amd64)$")
      set(XTBLOOM_WHEEL_OPENBLAS_ARCH x86_64)
    elseif(xtbloom_wheel_processor MATCHES "^(aarch64|arm64)$")
      set(XTBLOOM_WHEEL_OPENBLAS_ARCH aarch64)
    else()
      message(FATAL_ERROR
        "Python wheels support private OpenBLAS on Linux x86_64/aarch64, not "
        "'${CMAKE_SYSTEM_PROCESSOR}'")
    endif()
  elseif(APPLE)
    set(XTBLOOM_WHEEL_OPENBLAS_PLATFORM macos)
    if(xtbloom_wheel_processor MATCHES "^(x86_64|amd64)$")
      set(XTBLOOM_WHEEL_OPENBLAS_ARCH x86_64)
    elseif(xtbloom_wheel_processor MATCHES "^(aarch64|arm64)$")
      set(XTBLOOM_WHEEL_OPENBLAS_ARCH arm64)
    else()
      message(FATAL_ERROR
        "Python wheels support private OpenBLAS on macOS x86_64/arm64, not "
        "'${CMAKE_SYSTEM_PROCESSOR}'")
    endif()
  elseif(WIN32)
    set(XTBLOOM_WHEEL_OPENBLAS_PLATFORM windows)
    if(xtbloom_wheel_processor MATCHES "^(x86_64|amd64)$")
      set(XTBLOOM_WHEEL_OPENBLAS_ARCH amd64)
    elseif(xtbloom_wheel_processor MATCHES "^(aarch64|arm64)$")
      set(XTBLOOM_WHEEL_OPENBLAS_ARCH arm64)
    else()
      message(FATAL_ERROR
        "Python wheels support private OpenBLAS on Windows AMD64/ARM64, not "
        "'${CMAKE_SYSTEM_PROCESSOR}'")
    endif()
  else()
    message(FATAL_ERROR
      "Python wheels do not have a reviewed private OpenBLAS provider for "
      "${CMAKE_SYSTEM_NAME}")
  endif()

  if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    # dlmopen is part of the Linux wheel's host-isolation contract, not an
    # optional optimization. Prove namespace creation and inspection before
    # accepting the build input.
    if(NOT XTBLOOM_HAS_DLMOPEN_NAMESPACE)
      message(FATAL_ERROR
        "XTBLOOM_PYTHON_WHEEL requires glibc dlmopen/dlinfo namespace isolation")
    endif()
  endif()

  find_package(Python3 COMPONENTS Interpreter REQUIRED)
  if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
    set(XTBLOOM_OPENBLAS_PROVENANCE
      "${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/pyodide_openblas_manifest.json")
    execute_process(
      COMMAND "${Python3_EXECUTABLE}"
        "${CMAKE_CURRENT_SOURCE_DIR}/python/ci/resolve-pyodide-openblas.py"
        --manifest "${XTBLOOM_OPENBLAS_PROVENANCE}"
        --cache-dir "${CMAKE_CURRENT_SOURCE_DIR}/build/pyodide-openblas-provider"
        --require-existing
      RESULT_VARIABLE xtbloom_openblas_resolve_status
      OUTPUT_VARIABLE xtbloom_openblas_resolve_output
      ERROR_VARIABLE xtbloom_openblas_resolve_error
      OUTPUT_STRIP_TRAILING_WHITESPACE
    )
  else()
    set(XTBLOOM_OPENBLAS_PROVENANCE
      "${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/scipy_openblas32_manifest.json")
    execute_process(
      COMMAND "${Python3_EXECUTABLE}"
        "${CMAKE_CURRENT_SOURCE_DIR}/python/ci/resolve-openblas-wheel.py"
        --manifest "${XTBLOOM_OPENBLAS_PROVENANCE}"
        --platform "${XTBLOOM_WHEEL_OPENBLAS_PLATFORM}"
        --architecture "${XTBLOOM_WHEEL_OPENBLAS_ARCH}"
      RESULT_VARIABLE xtbloom_openblas_resolve_status
      OUTPUT_VARIABLE xtbloom_openblas_resolve_output
      ERROR_VARIABLE xtbloom_openblas_resolve_error
      OUTPUT_STRIP_TRAILING_WHITESPACE
    )
  endif()
  if(NOT xtbloom_openblas_resolve_status EQUAL 0)
    message(FATAL_ERROR
      "failed to resolve the reviewed wheel OpenBLAS build input:\n"
      "${xtbloom_openblas_resolve_error}")
  endif()
  string(JSON XTBLOOM_WHEEL_OPENBLAS_LIBRARY GET
    "${xtbloom_openblas_resolve_output}" provider_path)
  string(JSON XTBLOOM_WHEEL_OPENBLAS_CONFIG_PREFIX GET
    "${xtbloom_openblas_resolve_output}" expected_config_prefix)
  string(JSON XTBLOOM_WHEEL_OPENBLAS_INSTALL_NAME GET
    "${xtbloom_openblas_resolve_output}" provider_install_name)
  if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
    string(JSON XTBLOOM_WHEEL_OPENBLAS_ADAPTER_NAME GET
      "${xtbloom_openblas_resolve_output}" adapter_install_name)
  endif()
  get_filename_component(XTBLOOM_WHEEL_OPENBLAS_DIRECTORY
    "${XTBLOOM_WHEEL_OPENBLAS_LIBRARY}" DIRECTORY)
  set(XTBLOOM_WHEEL_OPENBLAS ON)
  if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
    set(XTBLOOM_WHEEL_OPENBLAS_PYODIDE ON)
  elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    set(XTBLOOM_WHEEL_OPENBLAS_LINUX_SHIM ON)
  else()
    set(XTBLOOM_WHEEL_OPENBLAS_DESKTOP ON)
  endif()
  message(STATUS
    "xtbloom wheel OpenBLAS build input (${XTBLOOM_WHEEL_OPENBLAS_PLATFORM}-"
    "${XTBLOOM_WHEEL_OPENBLAS_ARCH}): ${XTBLOOM_WHEEL_OPENBLAS_LIBRARY}")
endif()

# Bake a verified absolute path into the library so a non-system LP64 runtime
# can be found without LD_LIBRARY_PATH. This remains a lazy dlopen: libxtbloom
# never gains a hard DT_NEEDED dependency that would make the CUDA backend
# unloadable when no BLAS is installed.
set(XTBLOOM_CPU_LINALG_RUNTIME "")
set(XTBLOOM_CPU_LINALG_SYMBOL_PREFIX "")
if(XTBLOOM_CPU_LINALG_LIBRARY)
  set(XTBLOOM_CONFIGURED_CPU_LINALG_LIBRARY "${XTBLOOM_CPU_LINALG_LIBRARY}")
else()
  set(XTBLOOM_CONFIGURED_CPU_LINALG_LIBRARY "")
endif()

if(XTBLOOM_CONFIGURED_CPU_LINALG_LIBRARY)
  xtbloom_validate_cpu_linalg_runtime(
    "${XTBLOOM_CONFIGURED_CPU_LINALG_LIBRARY}"
    configured_runtime_is_compatible
    configured_runtime_symbol_prefix
  )
  if(NOT configured_runtime_is_compatible)
    message(FATAL_ERROR
      "XTBLOOM_CPU_LINALG_LIBRARY=${XTBLOOM_CONFIGURED_CPU_LINALG_LIBRARY} does not provide a "
      "complete LP64 LAPACKE+CBLAS runtime with local thread control"
    )
  endif()
  set(XTBLOOM_CPU_LINALG_RUNTIME "${XTBLOOM_CONFIGURED_CPU_LINALG_LIBRARY}")
  set(XTBLOOM_CPU_LINALG_SYMBOL_PREFIX "${configured_runtime_symbol_prefix}")
elseif(NOT XTBLOOM_WHEEL_OPENBLAS)
  if(DEFINED BLA_SIZEOF_INTEGER)
    set(XTBLOOM_SAVED_BLA_SIZEOF_INTEGER "${BLA_SIZEOF_INTEGER}")
    set(XTBLOOM_HAD_BLA_SIZEOF_INTEGER ON)
  else()
    set(XTBLOOM_HAD_BLA_SIZEOF_INTEGER OFF)
  endif()
  # xtbloom's public and internal eigensolver ABI uses 32-bit LAPACK integers;
  # prevent FindBLAS/FindLAPACK from selecting an ILP64 provider automatically.
  set(BLA_SIZEOF_INTEGER 4)
  find_package(BLAS QUIET)
  if(BLAS_FOUND)
    find_package(LAPACK QUIET)
  endif()
  if(XTBLOOM_HAD_BLA_SIZEOF_INTEGER)
    set(BLA_SIZEOF_INTEGER "${XTBLOOM_SAVED_BLA_SIZEOF_INTEGER}")
  else()
    unset(BLA_SIZEOF_INTEGER)
  endif()
  set(XTBLOOM_CPU_LINALG_CANDIDATES "")
  foreach(candidate IN LISTS LAPACK_LIBRARIES BLAS_LIBRARIES)
    if(NOT IS_ABSOLUTE "${candidate}")
      continue()
    endif()
    string(TOLOWER "${candidate}" candidate_lower)
    if(candidate_lower MATCHES "intel|mkl_rt|openblas|scipy_openblas")
      list(APPEND XTBLOOM_CPU_LINALG_CANDIDATES "${candidate}")
    endif()
  endforeach()
  list(REMOVE_DUPLICATES XTBLOOM_CPU_LINALG_CANDIDATES)
  foreach(candidate IN LISTS XTBLOOM_CPU_LINALG_CANDIDATES)
    xtbloom_validate_cpu_linalg_runtime(
      "${candidate}" candidate_is_compatible candidate_symbol_prefix
    )
    if(candidate_is_compatible)
      set(XTBLOOM_CPU_LINALG_RUNTIME "${candidate}")
      set(XTBLOOM_CPU_LINALG_SYMBOL_PREFIX "${candidate_symbol_prefix}")
      break()
    endif()
    message(STATUS
      "xtbloom ignored incomplete CPU linear-algebra runtime: ${candidate}"
    )
  endforeach()
endif()
if(XTBLOOM_CPU_LINALG_RUNTIME)
  message(STATUS "xtbloom CPU eigensolver BLAS/LAPACK runtime: ${XTBLOOM_CPU_LINALG_RUNTIME}")
endif()

# Host-isolated MKL provider shim.
#
# libmkl_rt is an interface-layer dispatcher: loading it and calling
# MKL_Set_Interface_Layer mutates process-global MKL state that an embedding
# application may already own, and MKL_INTERFACE_LAYER can make xtbloom depend on
# the host's MKL lifecycle. When the selected runtime is MKL, build a tiny
# private shim with fixed DT_NEEDED dependencies on libmkl_intel_lp64,
# libmkl_sequential, and libmkl_core. Loading those components directly (never
# libmkl_rt) yields an LP64 + sequential provider. The factory loads the sibling
# shim in a new glibc link-map namespace with RTLD_LOCAL: RTLD_LOCAL by itself
# still permits a globally loaded host libmkl_rt to interpose on dependencies.
# The shim is lazy and never adds a hard DT_NEEDED dependency to libxtbloom.
set(XTBLOOM_CPU_LINALG_SHIM OFF)
set(XTBLOOM_CPU_LINALG_RUNTIME_IS_MKL OFF)
if(XTBLOOM_CPU_LINALG_RUNTIME)
  get_filename_component(xtbloom_linalg_runtime_name
    "${XTBLOOM_CPU_LINALG_RUNTIME}" NAME
  )
  if(xtbloom_linalg_runtime_name MATCHES "mkl_rt")
    set(XTBLOOM_CPU_LINALG_RUNTIME_IS_MKL ON)

    get_filename_component(xtbloom_linalg_runtime_realpath
      "${XTBLOOM_CPU_LINALG_RUNTIME}" REALPATH
    )
    get_filename_component(xtbloom_mkl_component_dir
      "${xtbloom_linalg_runtime_realpath}" DIRECTORY
    )
    get_filename_component(xtbloom_linalg_runtime_realname
      "${xtbloom_linalg_runtime_realpath}" NAME
    )
    get_filename_component(xtbloom_mkl_runtime_suffix
      "${xtbloom_linalg_runtime_realname}" EXT
    )

    # All three components must be the exact SONAME cohort adjacent to the
    # selected runtime. Mixing files across MKLROOT or unrelated installations
    # can bind an ABI-incoherent provider even when every filename exists.
    set(XTBLOOM_HAS_MKL_COMPONENTS ON)
    foreach(component IN ITEMS intel_lp64 sequential core)
      set(component_path
        "${xtbloom_mkl_component_dir}/libmkl_${component}${xtbloom_mkl_runtime_suffix}"
      )
      if(NOT EXISTS "${component_path}" OR IS_DIRECTORY "${component_path}")
        set(XTBLOOM_HAS_MKL_COMPONENTS OFF)
      endif()
      set("XTBLOOM_MKL_${component}_LIB" "${component_path}")
    endforeach()

    if(XTBLOOM_HAS_MKL_COMPONENTS AND XTBLOOM_HAS_DLMOPEN_NAMESPACE)
      xtbloom_add_mkl_pthread_tss_bridge(
        xtbloom_mkl_pthread_tss_bridge xtbloom_mkl_pthread_tss_bridge
      )
      set_target_properties(xtbloom_mkl_pthread_tss_bridge PROPERTIES
        EXPORT_NAME mkl_pthread_tss_bridge
      )
      add_library(xtbloom_mkl_lp64_shim SHARED
        src/runtime/mkl_lp64_shim.cpp
      )
      target_compile_features(xtbloom_mkl_lp64_shim PRIVATE cxx_std_17)
      # Sanitizer runtimes commonly claim pthread key 0 and can be injected as
      # the first DT_NEEDED entry. The bridge must remain first in every build.
      target_compile_options(xtbloom_mkl_lp64_shim PRIVATE -fno-sanitize=all)
      set_target_properties(xtbloom_mkl_lp64_shim PROPERTIES
        EXPORT_NAME mkl_lp64_shim
        OUTPUT_NAME xtbloom_mkl_lp64_shim
        CXX_VISIBILITY_PRESET hidden
        VISIBILITY_INLINES_HIDDEN YES
      )
      get_filename_component(xtbloom_mkl_component_dir
        "${XTBLOOM_MKL_intel_lp64_LIB}" DIRECTORY
      )
      target_link_libraries(xtbloom_mkl_lp64_shim PRIVATE
        # The initialized bridge must precede every provider/runtime DSO in
        # DT_NEEDED order so public and weak internal pthread TSS references
        # bind to it before private libc/libdl constructors can execute.
        xtbloom_mkl_pthread_tss_bridge
        "${XTBLOOM_MKL_intel_lp64_LIB}"
        "${XTBLOOM_MKL_sequential_LIB}"
        "${XTBLOOM_MKL_core_LIB}"
      )
      # The shim itself references none of the MKL symbols directly; its ELF
      # NEEDED records are what make dlopen resolve the whole LP64/sequential
      # component scope together. Force the records even on --as-needed hosts.
      # Emit DT_RPATH deliberately: DT_RUNPATH is searched after LD_LIBRARY_PATH
      # and would allow a same-SONAME component from another MKL installation to
      # replace one member of the configure-time cohort.
      target_link_options(xtbloom_mkl_lp64_shim PRIVATE
        -fno-sanitize=all
        "LINKER:--no-as-needed"
        "LINKER:--disable-new-dtags"
      )
      set_target_properties(xtbloom_mkl_lp64_shim PROPERTIES
        BUILD_RPATH "$ORIGIN;${xtbloom_mkl_component_dir}"
        INSTALL_RPATH "$ORIGIN;${xtbloom_mkl_component_dir}"
        # The runtime resolves only a sibling shim. Keep build-tree tests and
        # installed shared libraries on the same relocation-safe contract.
        LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
      )
      install(TARGETS
        xtbloom_mkl_pthread_tss_bridge
        xtbloom_mkl_lp64_shim
        EXPORT xtbloomTargets
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
      )
      set(XTBLOOM_CPU_LINALG_SHIM ON)
      message(STATUS
        "xtbloom host-isolated MKL LP64 provider shim: enabled"
      )
    else()
      set(mkl_isolation_error
        "XTBLOOM CPU MKL isolation requires dlmopen/dlinfo namespace support "
        "and the exact adjacent libmkl_intel_lp64, libmkl_sequential, and "
        "libmkl_core SONAME cohort"
      )
      if(XTBLOOM_CONFIGURED_CPU_LINALG_LIBRARY)
        message(FATAL_ERROR "${mkl_isolation_error}")
      endif()
      message(STATUS "${mkl_isolation_error}; disabling the auto-discovered runtime")
      set(XTBLOOM_CPU_LINALG_RUNTIME "")
      set(XTBLOOM_CPU_LINALG_SYMBOL_PREFIX "")
      set(XTBLOOM_CPU_LINALG_RUNTIME_IS_MKL OFF)
    endif()
  endif()
endif()

if(XTBLOOM_WHEEL_OPENBLAS_PYODIDE)
  if(NOT XTBLOOM_WHEEL_OPENBLAS_ADAPTER_NAME STREQUAL
      "libxtbloom_pyodide_lapacke.so")
    message(FATAL_ERROR "reviewed Pyodide LAPACKE adapter name differs")
  endif()
  add_library(xtbloom_pyodide_lapacke SHARED
    src/runtime/pyodide_lapacke_lp64_shim.c
  )
  target_compile_definitions(xtbloom_pyodide_lapacke PRIVATE
    "XTBLOOM_PYODIDE_OPENBLAS_FILENAME=\"${XTBLOOM_WHEEL_OPENBLAS_INSTALL_NAME}\""
  )
  # The exported dependency anchor preserves a unique dylink NEEDED edge so
  # pyodide auditwheel can vendor the reviewed provider. Actual dispatch uses
  # dlsym on the exact absolute provider path supplied by the wheel loader.
  target_link_libraries(xtbloom_pyodide_lapacke PRIVATE
    "${XTBLOOM_WHEEL_OPENBLAS_LIBRARY}"
  )
  set_target_properties(xtbloom_pyodide_lapacke PROPERTIES
    OUTPUT_NAME xtbloom_pyodide_lapacke
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
    INSTALL_RPATH ""
  )
  install(TARGETS xtbloom_pyodide_lapacke
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )
endif()

if(XTBLOOM_WHEEL_OPENBLAS_LINUX_SHIM)
  add_library(xtbloom_openblas_lp64_shim SHARED
    src/runtime/openblas_lp64_shim.c
  )
  target_link_libraries(xtbloom_openblas_lp64_shim PRIVATE
    "${XTBLOOM_WHEEL_OPENBLAS_LIBRARY}"
  )
  target_link_options(xtbloom_openblas_lp64_shim PRIVATE
    "LINKER:--no-as-needed"
  )
  set_target_properties(xtbloom_openblas_lp64_shim PROPERTIES
    OUTPUT_NAME xtbloom_openblas_lp64_shim
    CXX_VISIBILITY_PRESET hidden
    VISIBILITY_INLINES_HIDDEN YES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
    BUILD_RPATH "${XTBLOOM_WHEEL_OPENBLAS_DIRECTORY}"
    # repair-wheel.sh supplies the reviewed directory through LD_LIBRARY_PATH;
    # never record a temporary build-environment path in the unrepaired wheel.
    INSTALL_RPATH ""
  )
  install(TARGETS xtbloom_openblas_lp64_shim
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )
endif()

if(XTBLOOM_WHEEL_OPENBLAS_DESKTOP)
  string(JSON xtbloom_openblas_file_count LENGTH
    "${xtbloom_openblas_resolve_output}" files)
  math(EXPR xtbloom_openblas_file_last "${xtbloom_openblas_file_count} - 1")

  if(APPLE)
    find_program(XTBLOOM_INSTALL_NAME_TOOL install_name_tool REQUIRED)
    find_program(XTBLOOM_CODESIGN codesign REQUIRED)
    set(XTBLOOM_WHEEL_OPENBLAS_MACOS_OUTPUTS "")
  endif()

  foreach(xtbloom_openblas_file_index RANGE 0 ${xtbloom_openblas_file_last})
    string(JSON xtbloom_openblas_file_path GET
      "${xtbloom_openblas_resolve_output}" files
      ${xtbloom_openblas_file_index} path)
    # JSON preserves Windows native backslashes, but install(FILES) writes its
    # arguments into a generated CMake script where sequences such as ``\U``
    # would be parsed as escapes. Normalize every resolved payload path before
    # it enters build or install rules.
    cmake_path(CONVERT "${xtbloom_openblas_file_path}"
      TO_CMAKE_PATH_LIST xtbloom_openblas_file_path NORMALIZE)
    string(JSON xtbloom_openblas_file_role GET
      "${xtbloom_openblas_resolve_output}" files
      ${xtbloom_openblas_file_index} role)
    string(JSON xtbloom_openblas_install_destination GET
      "${xtbloom_openblas_resolve_output}" files
      ${xtbloom_openblas_file_index} install_destination)
    string(JSON xtbloom_openblas_install_name GET
      "${xtbloom_openblas_resolve_output}" files
      ${xtbloom_openblas_file_index} install_name)

    if(APPLE)
      string(JSON xtbloom_openblas_install_id GET
        "${xtbloom_openblas_resolve_output}" files
        ${xtbloom_openblas_file_index} install_id)
      set(xtbloom_openblas_output
        "${CMAKE_CURRENT_BINARY_DIR}/private-openblas/${xtbloom_openblas_install_name}")

      # Every Mach-O image gets a content-derived xTBloom-private ID and every
      # intra-cohort load command is rewritten to the matching private name.
      # Privateizing only the OpenBLAS image is insufficient: dyld may reuse a
      # previously loaded libgfortran/libquadmath image with the same LC_ID.
      add_custom_command(
        OUTPUT "${xtbloom_openblas_output}"
        COMMAND "${CMAKE_COMMAND}" -E make_directory
          "${CMAKE_CURRENT_BINARY_DIR}/private-openblas"
        COMMAND "${CMAKE_COMMAND}" -E copy
          "${xtbloom_openblas_file_path}"
          "${xtbloom_openblas_output}"
        COMMAND "${XTBLOOM_INSTALL_NAME_TOOL}" -id
          "${xtbloom_openblas_install_id}"
          "${xtbloom_openblas_output}"
        DEPENDS "${xtbloom_openblas_file_path}"
        VERBATIM
        COMMENT "Preparing private scipy-openblas32 image ${xtbloom_openblas_install_name}"
      )

      string(JSON xtbloom_openblas_rewrite_count LENGTH
        "${xtbloom_openblas_resolve_output}" files
        ${xtbloom_openblas_file_index} load_rewrites)
      if(xtbloom_openblas_rewrite_count GREATER 0)
        math(EXPR xtbloom_openblas_rewrite_last
          "${xtbloom_openblas_rewrite_count} - 1")
        foreach(xtbloom_openblas_rewrite_index RANGE 0
            ${xtbloom_openblas_rewrite_last})
          string(JSON xtbloom_openblas_rewrite_from GET
            "${xtbloom_openblas_resolve_output}" files
            ${xtbloom_openblas_file_index} load_rewrites
            ${xtbloom_openblas_rewrite_index} from)
          string(JSON xtbloom_openblas_rewrite_to GET
            "${xtbloom_openblas_resolve_output}" files
            ${xtbloom_openblas_file_index} load_rewrites
            ${xtbloom_openblas_rewrite_index} to)
          add_custom_command(
            OUTPUT "${xtbloom_openblas_output}"
            APPEND
            COMMAND "${XTBLOOM_INSTALL_NAME_TOOL}" -change
              "${xtbloom_openblas_rewrite_from}"
              "${xtbloom_openblas_rewrite_to}"
              "${xtbloom_openblas_output}"
          )
        endforeach()
      endif()
      add_custom_command(
        OUTPUT "${xtbloom_openblas_output}"
        APPEND
        COMMAND "${XTBLOOM_CODESIGN}" --force --sign -
          "${xtbloom_openblas_output}"
      )
      list(APPEND XTBLOOM_WHEEL_OPENBLAS_MACOS_OUTPUTS
        "${xtbloom_openblas_output}")
      install(FILES "${xtbloom_openblas_output}"
        DESTINATION "${xtbloom_openblas_install_destination}"
        RENAME "${xtbloom_openblas_install_name}"
      )
    else()
      # Windows provider DLLs have no ELF/Mach-O install name and can be safely
      # content-renamed while copying.
      install(FILES "${xtbloom_openblas_file_path}"
        DESTINATION "${xtbloom_openblas_install_destination}"
        RENAME "${xtbloom_openblas_install_name}"
      )
    endif()
  endforeach()
  if(APPLE)
    add_custom_target(xtbloom_wheel_openblas_provider ALL
      DEPENDS ${XTBLOOM_WHEEL_OPENBLAS_MACOS_OUTPUTS}
    )
  endif()
endif()

add_library(xtbloom_cpu_dispatch_objects OBJECT
  src/cpu_dispatch/features.cpp
)
target_compile_features(xtbloom_cpu_dispatch_objects PUBLIC cxx_std_17)
target_include_directories(xtbloom_cpu_dispatch_objects PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)
set_target_properties(xtbloom_cpu_dispatch_objects PROPERTIES
  CXX_VISIBILITY_PRESET hidden
  INTERPROCEDURAL_OPTIMIZATION OFF
  POSITION_INDEPENDENT_CODE ON
  VISIBILITY_INLINES_HIDDEN YES
)

add_library(xtbloom_gfn2_mulliken_baseline_objects OBJECT
  src/model/gfn2/mulliken_kernels_baseline.cpp
)
target_compile_features(xtbloom_gfn2_mulliken_baseline_objects PUBLIC cxx_std_17)
target_include_directories(xtbloom_gfn2_mulliken_baseline_objects PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)
set_target_properties(xtbloom_gfn2_mulliken_baseline_objects PROPERTIES
  CXX_VISIBILITY_PRESET hidden
  INTERPROCEDURAL_OPTIMIZATION OFF
  POSITION_INDEPENDENT_CODE ON
  VISIBILITY_INLINES_HIDDEN YES
)

# A single shared library carries the baseline kernels on every architecture.
# Add the AVX2/FMA object only for a single x86-64 target whose compiler accepts
# both flags; universal Apple builds, ARM, and WebAssembly remain baseline-only.
set(XTBLOOM_BUILD_AVX2_FMA_KERNELS OFF)
set(XTBLOOM_AVX2_FMA_COMPILE_OPTIONS "")
set(XTBLOOM_SINGLE_X86_64_TARGET OFF)
if(XTBLOOM_SYSTEM_PROCESSOR_LOWER MATCHES "^(x86_64|amd64|x64)$" AND NOT EMSCRIPTEN)
  set(XTBLOOM_SINGLE_X86_64_TARGET ON)
  if(APPLE AND CMAKE_OSX_ARCHITECTURES)
    list(LENGTH CMAKE_OSX_ARCHITECTURES XTBLOOM_OSX_ARCH_COUNT)
    list(GET CMAKE_OSX_ARCHITECTURES 0 XTBLOOM_OSX_FIRST_ARCH)
    if(NOT XTBLOOM_OSX_ARCH_COUNT EQUAL 1 OR NOT XTBLOOM_OSX_FIRST_ARCH STREQUAL "x86_64")
      set(XTBLOOM_SINGLE_X86_64_TARGET OFF)
    endif()
  endif()
endif()
if(XTBLOOM_ENABLE_AVX2_DISPATCH AND XTBLOOM_SINGLE_X86_64_TARGET)
  if(MSVC)
    # MSVC x64 has no supported option that resets a global /arch setting back
    # to the baseline ISA. Reject one before creating multiversioned objects so
    # generic detection and baseline leaves cannot inherit /arch:AVX2.
    get_cmake_property(XTBLOOM_CMAKE_VARIABLES VARIABLES)
    foreach(XTBLOOM_CMAKE_VARIABLE IN LISTS XTBLOOM_CMAKE_VARIABLES)
      if(XTBLOOM_CMAKE_VARIABLE MATCHES "^CMAKE_CXX_FLAGS($|_)")
        string(TOLOWER "${${XTBLOOM_CMAKE_VARIABLE}}"
          XTBLOOM_MSVC_GLOBAL_FLAGS_LOWER)
        if(XTBLOOM_MSVC_GLOBAL_FLAGS_LOWER MATCHES "[-/]arch:")
          message(FATAL_ERROR
            "${XTBLOOM_CMAKE_VARIABLE} contains a global /arch option; "
            "xTBloom CPU dispatch requires baseline-safe generic objects and "
            "adds /arch:AVX2 only to the dedicated AVX2 target")
        endif()
      endif()
    endforeach()
    foreach(XTBLOOM_MSVC_ENVIRONMENT_NAME IN ITEMS CL _CL_)
      if(XTBLOOM_MSVC_ENVIRONMENT_NAME STREQUAL "CL")
        set(XTBLOOM_MSVC_ENVIRONMENT_VALUE "$ENV{CL}")
      else()
        set(XTBLOOM_MSVC_ENVIRONMENT_VALUE "$ENV{_CL_}")
      endif()
      string(TOLOWER "${XTBLOOM_MSVC_ENVIRONMENT_VALUE}"
        XTBLOOM_MSVC_GLOBAL_FLAGS_LOWER)
      if(XTBLOOM_MSVC_GLOBAL_FLAGS_LOWER MATCHES "[-/]arch:")
        message(FATAL_ERROR
          "the ${XTBLOOM_MSVC_ENVIRONMENT_NAME} environment variable contains "
          "a global /arch option; xTBloom CPU dispatch requires baseline-safe "
          "generic objects and adds /arch:AVX2 only to the dedicated AVX2 target")
      endif()
    endforeach()
    unset(XTBLOOM_MSVC_ENVIRONMENT_NAME)
    unset(XTBLOOM_MSVC_ENVIRONMENT_VALUE)
    unset(XTBLOOM_MSVC_GLOBAL_FLAGS_LOWER)
    unset(XTBLOOM_CMAKE_VARIABLE)
    unset(XTBLOOM_CMAKE_VARIABLES)
    check_cxx_compiler_flag("/arch:AVX2" XTBLOOM_CXX_HAS_ARCH_AVX2)
    if(XTBLOOM_CXX_HAS_ARCH_AVX2)
      set(XTBLOOM_BUILD_AVX2_FMA_KERNELS ON)
      set(XTBLOOM_AVX2_FMA_COMPILE_OPTIONS "/arch:AVX2")
      # These objects are dispatch boundaries. /GL- prevents whole-program
      # optimization from merging ISA-specific code into generic code. On x64,
      # omitting /arch is MSVC's supported baseline; /arch:SSE2 is unsupported.
      target_compile_options(xtbloom_cpu_dispatch_objects PRIVATE /GL-)
      target_compile_options(xtbloom_gfn2_mulliken_baseline_objects PRIVATE
        /GL-)
    endif()
  elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
    check_cxx_compiler_flag("-mavx2" XTBLOOM_CXX_HAS_MAVX2)
    check_cxx_compiler_flag("-mfma" XTBLOOM_CXX_HAS_MFMA)
    if(XTBLOOM_CXX_HAS_MAVX2 AND XTBLOOM_CXX_HAS_MFMA)
      set(XTBLOOM_BUILD_AVX2_FMA_KERNELS ON)
      set(XTBLOOM_AVX2_FMA_COMPILE_OPTIONS
        "-march=x86-64;-mtune=generic;-mavx2;-mfma;-fno-lto")
      # Ensure generic detection and baseline leaves stay load-safe even when a
      # surrounding build environment supplies -march=native or LTO.
      target_compile_options(xtbloom_cpu_dispatch_objects PRIVATE
        -march=x86-64 -mtune=generic -mno-avx -mno-avx2 -mno-fma -fno-lto)
      target_compile_options(xtbloom_gfn2_mulliken_baseline_objects PRIVATE
        -march=x86-64 -mtune=generic -mno-avx -mno-avx2 -mno-fma -fno-lto)
    endif()
  endif()
endif()

set(XTBLOOM_GFN2_DISPATCH_OBJECT_TARGETS
  xtbloom_cpu_dispatch_objects
  xtbloom_gfn2_mulliken_baseline_objects
)
set(XTBLOOM_GFN2_DISPATCH_OBJECTS
  $<TARGET_OBJECTS:xtbloom_cpu_dispatch_objects>
  $<TARGET_OBJECTS:xtbloom_gfn2_mulliken_baseline_objects>
)
if(XTBLOOM_BUILD_AVX2_FMA_KERNELS)
  add_library(xtbloom_gfn2_mulliken_avx2_objects OBJECT
    src/model/gfn2/mulliken_kernels_avx2.cpp
  )
  target_compile_features(xtbloom_gfn2_mulliken_avx2_objects PUBLIC cxx_std_17)
  target_include_directories(xtbloom_gfn2_mulliken_avx2_objects PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/src
  )
  target_compile_options(xtbloom_gfn2_mulliken_avx2_objects PRIVATE
    ${XTBLOOM_AVX2_FMA_COMPILE_OPTIONS})
  if(MSVC)
    target_compile_options(xtbloom_gfn2_mulliken_avx2_objects PRIVATE /GL-)
  endif()
  set_target_properties(xtbloom_gfn2_mulliken_avx2_objects PROPERTIES
    CXX_VISIBILITY_PRESET hidden
    INTERPROCEDURAL_OPTIMIZATION OFF
    POSITION_INDEPENDENT_CODE ON
    VISIBILITY_INLINES_HIDDEN YES
  )
  target_compile_definitions(xtbloom_cpu_dispatch_objects PRIVATE
    XTBLOOM_HAS_AVX2_FMA_KERNELS=1)
  list(APPEND XTBLOOM_GFN2_DISPATCH_OBJECT_TARGETS
    xtbloom_gfn2_mulliken_avx2_objects)
  list(APPEND XTBLOOM_GFN2_DISPATCH_OBJECTS
    $<TARGET_OBJECTS:xtbloom_gfn2_mulliken_avx2_objects>)
  message(STATUS "xtbloom CPU ISA dispatch: baseline + AVX2/FMA Mulliken kernels")
else()
  message(STATUS "xtbloom CPU ISA dispatch: baseline Mulliken kernels only")
endif()

add_library(xtbloom_model_common_cpu_objects OBJECT
  src/model/common/sto.cpp
  src/model/common/integrals.cpp
  src/model/common/scc_mixer.cpp
  # The generalized eigensolver and fixed periodic charge-response algebra
  # are model-neutral even though their established internal namespace is
  # retained for source compatibility. Both GFN1 and GFN2 consume them.
  src/model/gfn2/eigensolver.cpp
  src/model/gfn2/periodic_embedding.cpp
  # The sealed ES2 implementation is shared by GFN2 arithmetic and GFN1
  # harmonic plan builders. Its legacy namespace remains internal and does
  # not make the rest of the GFN2 physics target a GFN1 dependency.
  src/model/gfn2/es2.cpp
)
target_compile_features(xtbloom_model_common_cpu_objects PUBLIC cxx_std_17)
target_include_directories(xtbloom_model_common_cpu_objects PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)
set_target_properties(xtbloom_model_common_cpu_objects PROPERTIES
  CXX_VISIBILITY_PRESET hidden
  POSITION_INDEPENDENT_CODE ON
  VISIBILITY_INLINES_HIDDEN YES
)
if(CMAKE_DL_LIBS)
  target_link_libraries(xtbloom_model_common_cpu_objects PUBLIC ${CMAKE_DL_LIBS})
endif()

if(XTBLOOM_CPU_LINALG_RUNTIME)
  target_compile_definitions(xtbloom_model_common_cpu_objects PRIVATE
    "XTBLOOM_CONFIGURED_CPU_LINALG_RUNTIME=\"${XTBLOOM_CPU_LINALG_RUNTIME}\""
  )
endif()
if(XTBLOOM_CPU_LINALG_RUNTIME_IS_MKL)
  target_compile_definitions(xtbloom_model_common_cpu_objects PRIVATE
    XTBLOOM_CONFIGURED_CPU_LINALG_MKL=1
  )
endif()
if(XTBLOOM_CPU_LINALG_SHIM)
  target_compile_definitions(xtbloom_model_common_cpu_objects PRIVATE
    XTBLOOM_CONFIGURED_CPU_LINALG_SHIM=1
  )
  add_dependencies(xtbloom_model_common_cpu_objects xtbloom_mkl_lp64_shim)
endif()
if(XTBLOOM_WHEEL_OPENBLAS)
  if(XTBLOOM_WHEEL_OPENBLAS_PYODIDE)
    target_compile_definitions(xtbloom_model_common_cpu_objects PRIVATE
      XTBLOOM_CONFIGURED_PYODIDE_OPENBLAS=1
      "XTBLOOM_CONFIGURED_PYODIDE_OPENBLAS_CONFIG_PREFIX=\"${XTBLOOM_WHEEL_OPENBLAS_CONFIG_PREFIX}\""
      "XTBLOOM_CONFIGURED_PYODIDE_OPENBLAS_ADAPTER=\"${XTBLOOM_WHEEL_OPENBLAS_ADAPTER_NAME}\""
    )
    add_dependencies(xtbloom_model_common_cpu_objects xtbloom_pyodide_lapacke)
  else()
    target_compile_definitions(xtbloom_model_common_cpu_objects PRIVATE
      XTBLOOM_CONFIGURED_WHEEL_OPENBLAS=1
      "XTBLOOM_CONFIGURED_WHEEL_OPENBLAS_CONFIG_PREFIX=\"${XTBLOOM_WHEEL_OPENBLAS_CONFIG_PREFIX}\""
    )
    if(XTBLOOM_WHEEL_OPENBLAS_DESKTOP)
      target_compile_definitions(xtbloom_model_common_cpu_objects PRIVATE
        "XTBLOOM_CONFIGURED_WHEEL_OPENBLAS_FILENAME=\"${XTBLOOM_WHEEL_OPENBLAS_INSTALL_NAME}\""
      )
    endif()
    if(XTBLOOM_WHEEL_OPENBLAS_LINUX_SHIM)
      add_dependencies(xtbloom_model_common_cpu_objects xtbloom_openblas_lp64_shim)
    elseif(APPLE)
      add_dependencies(xtbloom_model_common_cpu_objects xtbloom_wheel_openblas_provider)
    endif()
  endif()
endif()

add_library(xtbloom_gfn2_cpu_objects OBJECT
  src/backends/common/gfn2_plan_schema.cpp
  src/model/gfn2/aes2.cpp
  src/model/gfn2/alpb.cpp
  src/model/gfn2/basis.cpp
  src/model/gfn2/coordination.cpp
  src/model/gfn2/d4.cpp
  src/model/gfn2/es3.cpp
  src/model/gfn2/external_point_charges.cpp
  src/model/gfn2/force.cpp
  src/model/gfn2/h0.cpp
  src/model/gfn2/lattice.cpp
  src/model/gfn2/mulliken.cpp
  src/model/gfn2/mulliken_kernels.cpp
  src/model/gfn2/repulsion.cpp
  src/model/gfn2/scc_driver.cpp
  src/model/gfn2/scc_mixer.cpp
  src/model/gfn2/spin.cpp
  src/model/gfn2/wavefunction.cpp
)

target_compile_features(xtbloom_gfn2_cpu_objects PUBLIC cxx_std_17)
target_include_directories(xtbloom_gfn2_cpu_objects PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)
set_target_properties(xtbloom_gfn2_cpu_objects PROPERTIES
  CXX_VISIBILITY_PRESET hidden
  POSITION_INDEPENDENT_CODE ON
  VISIBILITY_INLINES_HIDDEN YES
)
if(XTBLOOM_BUILD_AVX2_FMA_KERNELS)
  target_compile_definitions(xtbloom_gfn2_cpu_objects PRIVATE
    XTBLOOM_HAS_AVX2_FMA_KERNELS=1)
endif()
# Keep the complete CPU GFN1 implementation in its own object target so the
# public library can publish the already-reserved model tag without merging
# the model-owned source graph into GFN2. Both models share only the reviewed
# CPU linear-algebra/provider boundary above.
add_library(xtbloom_gfn1_cpu_objects OBJECT
  src/model/gfn1/basis.cpp
  src/model/gfn1/coordination.cpp
  src/model/gfn1/d3.cpp
  src/model/gfn1/es2.cpp
  src/model/gfn1/es3.cpp
  src/model/gfn1/external_point_charges.cpp
  src/model/gfn1/force.cpp
  src/model/gfn1/h0.cpp
  src/model/gfn1/halogen.cpp
  src/model/gfn1/mulliken.cpp
  src/model/gfn1/repulsion.cpp
  src/model/gfn1/scc_driver.cpp
  src/model/gfn1/scc_mixer.cpp
  src/model/gfn1/spin.cpp
  src/model/gfn1/wavefunction.cpp
  src/runtime/gfn1_cpu_execution.cpp
)
target_compile_features(xtbloom_gfn1_cpu_objects PUBLIC cxx_std_17)
target_include_directories(xtbloom_gfn1_cpu_objects PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)
set_target_properties(xtbloom_gfn1_cpu_objects PROPERTIES
  CXX_VISIBILITY_PRESET hidden
  POSITION_INDEPENDENT_CODE ON
  VISIBILITY_INLINES_HIDDEN YES
)

# Interface wrappers include object files as link inputs while propagating the
# object targets' include paths and provider requirements. GFN1 deliberately
# receives only its own terms plus the small shared-model target.
add_library(xtbloom_gfn2_cpu INTERFACE)
target_link_libraries(xtbloom_gfn2_cpu INTERFACE
  ${XTBLOOM_GFN2_DISPATCH_OBJECT_TARGETS}
  xtbloom_model_common_cpu_objects
  xtbloom_gfn2_cpu_objects
  ${XTBLOOM_GFN2_DISPATCH_OBJECTS}
  $<TARGET_OBJECTS:xtbloom_model_common_cpu_objects>
  $<TARGET_OBJECTS:xtbloom_gfn2_cpu_objects>
)

add_library(xtbloom_gfn1_cpu INTERFACE)
target_link_libraries(xtbloom_gfn1_cpu INTERFACE
  xtbloom_model_common_cpu_objects
  xtbloom_gfn1_cpu_objects
  $<TARGET_OBJECTS:xtbloom_model_common_cpu_objects>
  $<TARGET_OBJECTS:xtbloom_gfn1_cpu_objects>
)

add_library(xtbloom
  src/api.cpp
  src/runtime/backend.cpp
  src/runtime/gfn2_cpu_execution.cpp
  src/runtime/gfn2_plan.cpp
  src/runtime/model_plan.cpp
  src/runtime/model_registry.cpp
  src/runtime/request.cpp
  src/runtime/result_owner.cpp
  src/runtime/validation.cpp
  ${XTBLOOM_GFN2_DISPATCH_OBJECTS}
  $<TARGET_OBJECTS:xtbloom_model_common_cpu_objects>
  $<TARGET_OBJECTS:xtbloom_gfn1_cpu_objects>
  $<TARGET_OBJECTS:xtbloom_gfn2_cpu_objects>
)
add_library(xtbloom::xtbloom ALIAS xtbloom)

target_compile_features(xtbloom PUBLIC cxx_std_17)
target_include_directories(xtbloom
  PUBLIC
    $<BUILD_INTERFACE:${XTBLOOM_GENERATED_INCLUDE_DIR}>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
  PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_compile_definitions(xtbloom PRIVATE XTBLOOM_BUILDING_LIBRARY)
target_link_libraries(xtbloom PRIVATE Threads::Threads)
if(CMAKE_DL_LIBS)
  target_link_libraries(xtbloom PRIVATE ${CMAKE_DL_LIBS})
endif()
set_target_properties(xtbloom PROPERTIES
  CUDA_VISIBILITY_PRESET hidden
  CXX_VISIBILITY_PRESET hidden
  VISIBILITY_INLINES_HIDDEN YES
)
if(NOT XTBLOOM_PYTHON_WHEEL)
  # Native SDK installs retain the normal SONAME chain.  Wheel archives often
  # dereference those symlinks and would otherwise store the large CUDA shared
  # object three times, so wheel builds deliberately install one unversioned
  # library instead.
  set_target_properties(xtbloom PROPERTIES
    VERSION ${PROJECT_VERSION}
    SOVERSION ${XTBLOOM_ABI_SOVERSION}
  )
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  target_link_options(xtbloom PRIVATE
    "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/cmake/xtbloom.map"
  )
  set_property(TARGET xtbloom APPEND PROPERTY
    LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/xtbloom.map
  )
endif()

if(XTBLOOM_HAS_CUDA)
  # implib's hand-written trampolines are GNU ELF assembly for Linux.  Keep the
  # accepted architecture aliases explicit so an unsupported wheel cannot
  # configure successfully and then fail at load time.
  if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
    message(FATAL_ERROR "the CUDA dlopen backend currently requires Linux ELF")
  endif()
  string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _xtbloom_cuda_processor)
  if(_xtbloom_cuda_processor MATCHES "^(x86_64|amd64)$")
    set(XTBLOOM_CUDA_IMPLIB_TARGET x86_64)
  elseif(_xtbloom_cuda_processor MATCHES "^(aarch64|arm64)$")
    set(XTBLOOM_CUDA_IMPLIB_TARGET aarch64)
  else()
    message(FATAL_ERROR
      "the CUDA dlopen backend supports only Linux x86_64 and aarch64, not "
      "'${CMAKE_SYSTEM_PROCESSOR}'")
  endif()

  # The generated shims contain all CUDA-facing host definitions needed by the
  # backend. Neither the host nor device link may silently reintroduce a static
  # CUDA runtime.
  set(CMAKE_CUDA_RUNTIME_LIBRARY None)
  enable_language(C ASM)
  find_package(Python3 COMPONENTS Interpreter REQUIRED)

  set(XTBLOOM_CUDA_IMPLIB_GEN
      "${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/implib/implib-gen.py")
  set(XTBLOOM_CUDA_STUBLIB_GEN
      "${CMAKE_CURRENT_SOURCE_DIR}/tools/implib_stubgen.py")
  set(XTBLOOM_CUDA_IMPLIB_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated/cuda_implib")
  file(MAKE_DIRECTORY "${XTBLOOM_CUDA_IMPLIB_DIR}")

  # Curate the object-level names actually referenced by xtbloom.  CUDA headers
  # normalize several source API names to versioned ELF aliases; listing those
  # aliases here keeps -z defs useful and prevents a full-library catch-all from
  # masking a new dependency or an ABI-unsafe fallback category.
  set(XTBLOOM_CUDART_SYMBOLS
    __cudaInitModule
    __cudaPopCallConfiguration
    __cudaPushCallConfiguration
    __cudaRegisterFatBinary
    __cudaRegisterFatBinaryEnd
    __cudaRegisterFunction
    __cudaRegisterVar
    __cudaUnregisterFatBinary
    cudaDeviceGetAttribute
    cudaDeviceSynchronize
    cudaEventCreate
    cudaEventCreateWithFlags
    cudaEventDestroy
    cudaEventElapsedTime
    cudaEventQuery
    cudaEventRecord
    cudaEventSynchronize
    cudaFree
    cudaFreeHost
    cudaGetDevice
    cudaGetDeviceCount
    cudaGetErrorName
    cudaGetErrorString
    cudaGetLastError
    cudaGraphAddNode
    cudaGraphChildGraphNodeGetGraph
    cudaGraphConditionalHandleCreate
    cudaGraphCreate
    cudaGraphDestroy
    cudaGraphExecDestroy
    cudaGraphGetNodes
    cudaGraphInstantiate
    cudaGraphKernelNodeGetParams
    cudaGraphLaunch
    cudaGraphMemcpyNodeGetParams
    cudaGraphNodeGetType
    cudaGraphUpload
    cudaHostGetFlags
    cudaHostRegister
    cudaHostUnregister
    cudaLaunchHostFunc
    cudaLaunchKernel
    cudaMalloc
    cudaMallocHost
    cudaMallocManaged
    cudaMemcpy
    cudaMemcpyAsync
    cudaMemcpyFromSymbol
    cudaMemcpyToSymbol
    cudaMemset
    cudaMemsetAsync
    cudaPeekAtLastError
    cudaPointerGetAttributes
    cudaRuntimeGetVersion
    cudaSetDevice
    cudaStreamBeginCapture
    cudaStreamBeginCaptureToGraph
    cudaStreamCreate
    cudaStreamCreateWithFlags
    cudaStreamDestroy
    cudaStreamEndCapture
    cudaStreamGetCaptureInfo_v2
    cudaStreamGetDevice
    cudaStreamIsCapturing
    cudaStreamQuery
    cudaStreamSynchronize
    cudaStreamUpdateCaptureDependencies
    cudaStreamWaitEvent
  )
  set(XTBLOOM_CUBLAS_SYMBOLS
    cublasCreate_v2
    cublasDestroy_v2
    cublasDtrsmBatched
    cublasGetMathMode
    cublasGetPointerMode_v2
    cublasGetStream_v2
    cublasGetVersion_v2
    cublasSetMathMode
    cublasSetPointerMode_v2
    cublasSetStream_v2
    cublasSetWorkspace_v2
  )
  set(XTBLOOM_CUSOLVER_SYMBOLS
    cusolverDnCreate
    cusolverDnCreateParams
    cusolverDnCreateSyevjInfo
    cusolverDnDestroy
    cusolverDnDestroyParams
    cusolverDnDestroySyevjInfo
    cusolverDnDormtr
    cusolverDnDormtr_bufferSize
    cusolverDnDpotrfBatched
    cusolverDnDsytrd
    cusolverDnDsytrd_bufferSize
    cusolverDnDsyevjBatched
    cusolverDnDsyevjBatched_bufferSize
    cusolverDnGetStream
    cusolverDnSetStream
    cusolverDnXsyevjSetMaxSweeps
    cusolverDnXsyevjSetSortEig
    cusolverDnXsyevjSetTolerance
    cusolverDnXsyevBatched
    cusolverDnXsyevBatched_bufferSize
    cusolverGetProperty
  )
  set(XTBLOOM_CUDA_DRIVER_SYMBOLS
    cuGetErrorString
    cuMemGetAddressRange_v2
  )

  function(xtbloom_write_implib_symbol_file output_path)
    file(WRITE "${output_path}" "")
    foreach(_xtbloom_symbol IN LISTS ARGN)
      file(APPEND "${output_path}" "${_xtbloom_symbol}\n")
    endforeach()
  endfunction()

  function(xtbloom_read_elf_soname library_path output_variable)
    execute_process(
      COMMAND "${XTBLOOM_READELF}" -dW "${library_path}"
      RESULT_VARIABLE _xtbloom_readelf_status
      OUTPUT_VARIABLE _xtbloom_readelf_output
      ERROR_VARIABLE _xtbloom_readelf_error)
    if(NOT _xtbloom_readelf_status EQUAL 0)
      message(FATAL_ERROR
        "failed to read CUDA library SONAME from '${library_path}': "
        "${_xtbloom_readelf_error}")
    endif()
    string(REGEX MATCH "\\(SONAME\\)[^[]*\\[([^]]+)\\]"
      _xtbloom_soname_match "${_xtbloom_readelf_output}")
    if(NOT _xtbloom_soname_match)
      message(FATAL_ERROR "CUDA library '${library_path}' has no ELF SONAME")
    endif()
    set(${output_variable} "${CMAKE_MATCH_1}" PARENT_SCOPE)
  endfunction()

  # The CUDA provider shared libraries are dlopen'd lazily at runtime and are
  # never linked. When the build environment ships them (the usual toolkit
  # layout), the vendored implib scanner derives each shim and SONAME from the
  # real ELF so the artifacts adapt to the exact toolchain version. When they
  # are absent, xtbloom generates byte-identical shims from the curated symbol
  # lists with pinned SONAMEs (overridable cache variables), so configuring
  # and building the CUDA backend requires no provider shared libraries;
  # nvcc's compiler-support files and the cudart headers still come from the
  # CUDA compiler installation.
  # The runtime cohort preflight in cuda_dlopen.c enforces the deployed names
  # and symbol set either way.
  xtbloom_cuda_default_provider_sonames(
    "${XTBLOOM_CUDA_TOOLKIT_MAJOR}"
    _xtbloom_cuda_default_cudart_soname
    _xtbloom_cuda_default_cublas_soname
    _xtbloom_cuda_default_cusolver_soname
    _xtbloom_cuda_default_driver_soname)
  xtbloom_cache_cuda_provider_soname(
    XTBLOOM_CUDA_CUDART_SONAME "${_xtbloom_cuda_default_cudart_soname}"
    "dlopen'd CUDA runtime SONAME used when the build toolkit ships no CUDA libraries")
  xtbloom_cache_cuda_provider_soname(
    XTBLOOM_CUDA_CUBLAS_SONAME "${_xtbloom_cuda_default_cublas_soname}"
    "dlopen'd cuBLAS SONAME used when the build toolkit ships no CUDA libraries")
  xtbloom_cache_cuda_provider_soname(
    XTBLOOM_CUDA_CUSOLVER_SONAME "${_xtbloom_cuda_default_cusolver_soname}"
    "dlopen'd cuSOLVER SONAME used when the build toolkit ships no CUDA libraries")
  xtbloom_cache_cuda_provider_soname(
    XTBLOOM_CUDA_DRIVER_SONAME "${_xtbloom_cuda_default_driver_soname}"
    "dlopen'd CUDA driver SONAME used when the build toolkit ships no CUDA libraries")
  set(_xtbloom_cuda_providers_present ON)
  foreach(_xtbloom_cuda_target IN ITEMS CUDA::cudart CUDA::cublas CUDA::cusolver)
    if(NOT TARGET ${_xtbloom_cuda_target})
      set(_xtbloom_cuda_providers_present OFF)
    endif()
  endforeach()
  if(NOT CUDA_cuda_driver_LIBRARY)
    set(_xtbloom_cuda_providers_present OFF)
  endif()
  if(_xtbloom_cuda_providers_present)
    message(STATUS
      "xtbloom CUDA provider shims: scanning the complete toolkit library cohort")
  else()
    foreach(_xtbloom_cuda_required_soname_var IN ITEMS
        XTBLOOM_CUDA_CUDART_SONAME
        XTBLOOM_CUDA_CUBLAS_SONAME
        XTBLOOM_CUDA_CUSOLVER_SONAME)
      if("${${_xtbloom_cuda_required_soname_var}}" STREQUAL "")
        message(FATAL_ERROR
          "CUDA ${XTBLOOM_CUDA_TOOLKIT_VERSION} has no curated fallback provider "
          "SONAME mapping; set XTBLOOM_CUDA_CUDART_SONAME, "
          "XTBLOOM_CUDA_CUBLAS_SONAME, and XTBLOOM_CUDA_CUSOLVER_SONAME explicitly")
      endif()
    endforeach()
    message(STATUS
      "xtbloom CUDA provider shims: curated symbols with toolkit-major SONAMEs")
  endif()

  set(_xtbloom_cuda_implib_bases
    libcudart.so libcublas.so libcusolver.so libcuda.so)
  set(_xtbloom_cuda_implib_soname_vars
    XTBLOOM_CUDA_CUDART_SONAME
    XTBLOOM_CUDA_CUBLAS_SONAME
    XTBLOOM_CUDA_CUSOLVER_SONAME
    XTBLOOM_CUDA_DRIVER_SONAME)
  set(_xtbloom_cuda_symbol_sets
    XTBLOOM_CUDART_SYMBOLS
    XTBLOOM_CUBLAS_SYMBOLS
    XTBLOOM_CUSOLVER_SYMBOLS
    XTBLOOM_CUDA_DRIVER_SYMBOLS)

  set(_xtbloom_cuda_implib_inputs "")
  if(_xtbloom_cuda_providers_present)
    find_program(XTBLOOM_READELF NAMES readelf REQUIRED)
    foreach(_xtbloom_cuda_target IN ITEMS CUDA::cudart CUDA::cublas CUDA::cusolver)
      get_target_property(_xtbloom_cuda_location
        "${_xtbloom_cuda_target}" IMPORTED_LOCATION)
      if(NOT _xtbloom_cuda_location)
        message(FATAL_ERROR
          "cannot locate ${_xtbloom_cuda_target} for dlopen shim generation")
      endif()
      list(APPEND _xtbloom_cuda_implib_inputs "${_xtbloom_cuda_location}")
    endforeach()
    list(APPEND _xtbloom_cuda_implib_inputs "${CUDA_cuda_driver_LIBRARY}")
  endif()

  set(XTBLOOM_CUDA_DYNLOADER_SOURCES
    "${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/cuda_dlopen.c")
  set(_xtbloom_cuda_sonames "")
  set(_xtbloom_cuda_index 0)
  foreach(_xtbloom_cuda_base _xtbloom_cuda_soname_var _xtbloom_cuda_symbol_set
      IN ZIP_LISTS
        _xtbloom_cuda_implib_bases
        _xtbloom_cuda_implib_soname_vars
        _xtbloom_cuda_symbol_sets)
    set(_xtbloom_cuda_symbol_file
      "${XTBLOOM_CUDA_IMPLIB_DIR}/${_xtbloom_cuda_base}.symbols")
    xtbloom_write_implib_symbol_file(
      "${_xtbloom_cuda_symbol_file}" ${${_xtbloom_cuda_symbol_set}})
    if(_xtbloom_cuda_providers_present)
      list(GET _xtbloom_cuda_implib_inputs ${_xtbloom_cuda_index} _xtbloom_cuda_input)
      get_filename_component(_xtbloom_cuda_input_base "${_xtbloom_cuda_input}" NAME)
      if(NOT _xtbloom_cuda_input_base STREQUAL _xtbloom_cuda_base)
        message(FATAL_ERROR
          "expected ${_xtbloom_cuda_base} from FindCUDAToolkit, got "
          "'${_xtbloom_cuda_input_base}'")
      endif()
      if(_xtbloom_cuda_base STREQUAL "libcuda.so")
        # The driver library may live outside the toolkit tree; its pinned
        # default applies and the runtime preflight still verifies the name.
        set(_xtbloom_cuda_soname "${XTBLOOM_CUDA_DRIVER_SONAME}")
      else()
        xtbloom_read_elf_soname("${_xtbloom_cuda_input}" _xtbloom_cuda_soname)
      endif()
      execute_process(
        COMMAND "${Python3_EXECUTABLE}" "${XTBLOOM_CUDA_IMPLIB_GEN}"
                "${_xtbloom_cuda_input}"
                --target "${XTBLOOM_CUDA_IMPLIB_TARGET}"
                --no-dlopen
                --lazy-load
                --library-load-name "${_xtbloom_cuda_soname}"
                --dlsym-callback xtbloom_cuda_dlsym
                --symbol-list "${_xtbloom_cuda_symbol_file}"
                --outdir "${XTBLOOM_CUDA_IMPLIB_DIR}"
        RESULT_VARIABLE _xtbloom_cuda_implib_result
        OUTPUT_VARIABLE _xtbloom_cuda_implib_output
        ERROR_VARIABLE _xtbloom_cuda_implib_error
        COMMAND_ERROR_IS_FATAL ANY)
    else()
      set(_xtbloom_cuda_soname "${${_xtbloom_cuda_soname_var}}")
      execute_process(
        COMMAND "${Python3_EXECUTABLE}" "${XTBLOOM_CUDA_STUBLIB_GEN}"
                --base-name "${_xtbloom_cuda_base}"
                --symbol-list "${_xtbloom_cuda_symbol_file}"
                --load-name "${_xtbloom_cuda_soname}"
                --target "${XTBLOOM_CUDA_IMPLIB_TARGET}"
                --implib-root "${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/implib"
                --outdir "${XTBLOOM_CUDA_IMPLIB_DIR}"
        RESULT_VARIABLE _xtbloom_cuda_stublib_result
        OUTPUT_VARIABLE _xtbloom_cuda_stublib_output
        ERROR_VARIABLE _xtbloom_cuda_stublib_error
        COMMAND_ERROR_IS_FATAL ANY)
    endif()
    list(APPEND _xtbloom_cuda_sonames "${_xtbloom_cuda_soname}")
    list(APPEND XTBLOOM_CUDA_DYNLOADER_SOURCES
      "${XTBLOOM_CUDA_IMPLIB_DIR}/${_xtbloom_cuda_base}.tramp.S"
      "${XTBLOOM_CUDA_IMPLIB_DIR}/${_xtbloom_cuda_base}.init.c")
    math(EXPR _xtbloom_cuda_index "${_xtbloom_cuda_index} + 1")
  endforeach()
  list(GET _xtbloom_cuda_sonames 0 XTBLOOM_CUDART_SONAME)
  list(GET _xtbloom_cuda_sonames 1 XTBLOOM_CUBLAS_SONAME)
  list(GET _xtbloom_cuda_sonames 2 XTBLOOM_CUSOLVER_SONAME)
  list(GET _xtbloom_cuda_sonames 3 XTBLOOM_CUDA_DRIVER_SONAME)

  # Runtime bootstrap consumes the same configure-time list used to generate
  # the trampolines, so cohort preflight cannot drift from the link closure.
  set(XTBLOOM_CUDA_DLOPEN_SYMBOLS_HEADER
    "${XTBLOOM_CUDA_IMPLIB_DIR}/cuda_dlopen_symbols.h")
  file(WRITE "${XTBLOOM_CUDA_DLOPEN_SYMBOLS_HEADER}"
    "/* Generated by CMake; do not edit. */\n#pragma once\n")
  foreach(_xtbloom_cuda_name IN ITEMS CUDART CUBLAS CUSOLVER CUDA_DRIVER)
    string(TOLOWER "${_xtbloom_cuda_name}" _xtbloom_cuda_name_lower)
    file(APPEND "${XTBLOOM_CUDA_DLOPEN_SYMBOLS_HEADER}"
      "static const char* const xtbloom_${_xtbloom_cuda_name_lower}_required_symbols[] = {\n")
    foreach(_xtbloom_symbol IN LISTS XTBLOOM_${_xtbloom_cuda_name}_SYMBOLS)
      file(APPEND "${XTBLOOM_CUDA_DLOPEN_SYMBOLS_HEADER}"
        "    \"${_xtbloom_symbol}\",\n")
    endforeach()
    file(APPEND "${XTBLOOM_CUDA_DLOPEN_SYMBOLS_HEADER}"
      "    (const char*)0,\n};\n")
  endforeach()

  add_library(xtbloom_cuda_backend OBJECT
    ${XTBLOOM_CUDA_DYNLOADER_SOURCES}
    src/backends/cuda/cuda_runtime.cu
    src/runtime/cuda_descriptor_validation.cu
    src/runtime/gfn2_cuda_topology_staging.cu
    src/runtime/gfn2_cuda_execution.cu
    src/runtime/result_owner_cuda.cu
    src/backends/cuda/gfn1_classical_corrections.cu
    src/backends/cuda/gfn2_aes2.cu
    src/backends/cuda/gfn2_classical_force.cu
    src/backends/cuda/gfn2_d4.cu
    src/backends/cuda/gfn2_density.cu
    src/backends/cuda/gfn2_electric_field.cu
    src/backends/cuda/gfn2_electronic_gradient.cu
    src/backends/cuda/gfn2_energy_force_execution.cu
    src/backends/cuda/gfn2_eigensolver.cu
    src/backends/cuda/gfn2_es2.cu
    src/backends/cuda/gfn2_es3.cu
    src/backends/cuda/gfn2_external_point_charges.cu
    src/backends/cuda/gfn2_force_composition.cu
    src/backends/cuda/gfn2_geometry.cu
    src/backends/cuda/gfn2_preprocessing.cu
    src/backends/cuda/gfn2_public_result_bridge.cu
    src/backends/cuda/gfn2_h0_force.cu
    src/backends/cuda/gfn2_hamiltonian.cu
    src/backends/cuda/gfn2_hamiltonian_force.cu
    src/backends/cuda/gfn2_inference_publication.cu
    src/backends/cuda/gfn2_integrals.cu
    src/backends/cuda/gfn2_mulliken.cu
    src/backends/cuda/gfn2_occupations.cu
    src/backends/cuda/gfn2_pairlist.cu
    src/backends/cuda/gfn2_parameters.cu
    src/backends/cuda/gfn2_plan_schema.cu
    src/backends/cuda/gfn2_periodic_embedding.cu
    src/backends/cuda/gfn2_post_scc_potential.cu
    src/backends/cuda/gfn2_repulsion.cu
    src/backends/cuda/gfn2_scc.cu
    src/backends/cuda/gfn2_scc_bridge.cu
    src/backends/cuda/gfn2_scc_classical_energy.cu
    src/backends/cuda/gfn2_scc_energy.cu
    src/backends/cuda/gfn2_scc_free_energy.cu
    src/backends/cuda/gfn2_scc_iteration.cu
    src/backends/cuda/gfn2_scc_loop.cu
    src/backends/cuda/gfn2_scc_iteration_arena.cu
    src/backends/cuda/gfn2_scc_iteration_control.cu
    src/backends/cuda/gfn2_scc_iteration_initialize.cu
    src/backends/cuda/gfn2_scc_iteration_reports.cu
    src/backends/cuda/gfn2_scc_mixer.cu
    src/backends/cuda/gfn2_scc_potential.cu
    src/backends/cuda/gfn2_scc_publication.cu
    src/backends/cuda/gfn2_scc_setup_eigensolver.cu
    src/backends/cuda/gfn2_scc_setup_inputs.cu
    src/backends/cuda/gfn2_scc_setup_topology.cu
    src/backends/cuda/gfn2_spin.cu
    src/backends/cuda/gfn2_terminal_classical_energy.cu
    src/backends/cuda/gfn2_total_energy.cu
  )
  target_include_directories(xtbloom_cuda_backend PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/src
    ${XTBLOOM_CUDA_TOOLKIT_INCLUDE_DIRS}
  )
  target_include_directories(xtbloom_cuda_backend PRIVATE
    ${XTBLOOM_CUDA_IMPLIB_DIR}
  )
  # The startup bootstrap uses pthread_once and a diagnostic mutex. Preserve
  # that dependency for every executable that consumes the backend objects,
  # not just for the final xtbloom library target.
  target_link_libraries(xtbloom_cuda_backend PUBLIC
    Threads::Threads
    # CUDA host planning reuses the canonical CPU GFN1 plan builders. Expose
    # their object closure to white-box CUDA executables, which link the
    # backend objects directly rather than resolving hidden symbols through
    # libxtbloom.
    xtbloom_gfn1_cpu
  )
  # The CUDA runtime/math/driver shared libraries are deliberately NOT linked.
  # The priority-101 bootstrap pre-resolves the complete shim cohort before
  # ordinary NVCC registration constructors run.
  target_compile_definitions(xtbloom_cuda_backend PRIVATE
    XTBLOOM_HAS_CUDA=1
    XTBLOOM_CUDART_SONAME="${XTBLOOM_CUDART_SONAME}"
    XTBLOOM_CUBLAS_SONAME="${XTBLOOM_CUBLAS_SONAME}"
    XTBLOOM_CUSOLVER_SONAME="${XTBLOOM_CUSOLVER_SONAME}"
    XTBLOOM_CUDA_DRIVER_SONAME="${XTBLOOM_CUDA_DRIVER_SONAME}"
  )
  if(XTBLOOM_BUILD_TESTS)
    # White-box CUDA kernels exercise otherwise unreachable transactional
    # failure and overflow boundaries without shipping test entry points in
    # release builds.
    target_compile_definitions(xtbloom_cuda_backend PRIVATE XTBLOOM_CUDA_TEST_HOOKS=1)
  endif()
  set_target_properties(xtbloom_cuda_backend PROPERTIES
    CUDA_SEPARABLE_COMPILATION ON
    CUDA_STANDARD 17
    CUDA_STANDARD_REQUIRED YES
    CUDA_VISIBILITY_PRESET hidden
    CUDA_RUNTIME_LIBRARY None
    C_VISIBILITY_PRESET hidden
    POSITION_INDEPENDENT_CODE ON
    VISIBILITY_INLINES_HIDDEN YES
  )
  # The committed sparse pair-list CN consumer (gfn2_pairlist.cu) recomputes
  # coordination pair values from live positions while the dense reference
  # (gfn2_geometry.cu) reads the geometry cache.  The sparse candidate is
  # parity-gated bit-for-bit against dense, which only holds when both files
  # compile the pair evaluation with the same FMA contraction; otherwise every
  # >40-atom CUDA force call is rejected by the gate with 1-ulp differences.
  # Pin both translation units to -fmad=false so the two paths agree exactly.
  set_source_files_properties(
    src/backends/cuda/gfn2_pairlist.cu
    src/backends/cuda/gfn2_geometry.cu
    PROPERTIES COMPILE_OPTIONS "-fmad=false"
  )

  target_sources(xtbloom PRIVATE
    $<TARGET_OBJECTS:xtbloom_cuda_backend>
  )
  # The NVIDIA runtime/math/driver libraries are intentionally not linked or
  # exported transitively; startup pre-resolution fills hidden trampoline
  # tables and the installed library does not demand them at load time.
  target_compile_definitions(xtbloom PRIVATE XTBLOOM_HAS_CUDA=1)
  set_target_properties(xtbloom PROPERTIES
    CUDA_STANDARD 17
    CUDA_STANDARD_REQUIRED YES
    CUDA_SEPARABLE_COMPILATION ON
    CUDA_RESOLVE_DEVICE_SYMBOLS ON
    CUDA_RUNTIME_LIBRARY None
  )
  # xtbloom uses relocatable device code for cross-translation-unit constants,
  # but it does not launch child kernels through CUDA Dynamic Parallelism.
  # Exclude nvcc's otherwise-default static device-runtime input explicitly.
  target_link_options(xtbloom PRIVATE
    "$<DEVICE_LINK:--cudadevrt=none>"
    "LINKER:-z,defs"
  )
endif()

if(XTBLOOM_BUILD_TESTS)
  enable_testing()
  find_package(Threads REQUIRED)
  find_package(Python3 3.11 REQUIRED COMPONENTS Interpreter)

  if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND
     XTBLOOM_HAS_DLMOPEN_NAMESPACE AND
     XTBLOOM_MKL_TSS_BRIDGE_COMPILER_SUPPORTED)
    # This provider-independent fixture preserves the glibc <=2.33 bootstrap
    # shape even when CI selects OpenBLAS instead of MKL: bridge first, then
    # private libdl/libpthread, followed by a private dlsym call.
    if(TARGET xtbloom_mkl_pthread_tss_bridge)
      set(xtbloom_mkl_tss_test_bridge xtbloom_mkl_pthread_tss_bridge)
    else()
      set(xtbloom_mkl_tss_test_bridge xtbloom_mkl_pthread_tss_bridge_test)
      xtbloom_add_mkl_pthread_tss_bridge(
        ${xtbloom_mkl_tss_test_bridge} xtbloom_mkl_pthread_tss_bridge_test
      )
    endif()

    add_library(xtbloom_mkl_tss_bootstrap_fixture SHARED
      tests/mkl_tss_bootstrap_fixture.c
    )
    target_compile_features(xtbloom_mkl_tss_bootstrap_fixture PRIVATE c_std_11)
    target_compile_options(xtbloom_mkl_tss_bootstrap_fixture PRIVATE -fno-sanitize=all)
    target_link_options(xtbloom_mkl_tss_bootstrap_fixture PRIVATE
      -fno-sanitize=all
      "LINKER:--no-as-needed"
      "LINKER:--disable-new-dtags"
      "LINKER:-z,defs"
    )
    target_link_libraries(xtbloom_mkl_tss_bootstrap_fixture PRIVATE
      ${xtbloom_mkl_tss_test_bridge}
      "-l:libdl.so.2"
      "-l:libpthread.so.0"
    )
    set_target_properties(xtbloom_mkl_tss_bootstrap_fixture PROPERTIES
      OUTPUT_NAME xtbloom_mkl_tss_bootstrap_fixture
      C_VISIBILITY_PRESET hidden
      BUILD_RPATH "$ORIGIN"
      BUILD_RPATH_USE_ORIGIN TRUE
    )

    add_executable(xtbloom_mkl_tss_bootstrap_test
      tests/mkl_tss_bootstrap_test.c
    )
    target_compile_features(xtbloom_mkl_tss_bootstrap_test PRIVATE c_std_11)
    # ASan and similar runtimes allocate TSS before main. Keep the launcher
    # uninstrumented so its hostile sentinel deterministically owns key 0.
    target_compile_options(xtbloom_mkl_tss_bootstrap_test PRIVATE -fno-sanitize=all)
    target_link_options(xtbloom_mkl_tss_bootstrap_test PRIVATE -fno-sanitize=all)
    target_include_directories(xtbloom_mkl_tss_bootstrap_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_link_libraries(xtbloom_mkl_tss_bootstrap_test PRIVATE
      Threads::Threads
      ${CMAKE_DL_LIBS}
    )
    add_test(
      NAME xtbloom.cpu.mkl_tss_bootstrap
      COMMAND xtbloom_mkl_tss_bootstrap_test
        $<TARGET_FILE:${xtbloom_mkl_tss_test_bridge}>
        $<TARGET_FILE:xtbloom_mkl_tss_bootstrap_fixture>
    )
    find_program(XTBLOOM_MKL_TSS_READELF NAMES readelf llvm-readelf REQUIRED)
    add_test(
      NAME xtbloom.cpu.mkl_tss_bridge_elf
      COMMAND ${Python3_EXECUTABLE}
        ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_mkl_tss_bridge.py
        --readelf ${XTBLOOM_MKL_TSS_READELF}
        --nm ${CMAKE_NM}
        --bridge $<TARGET_FILE:${xtbloom_mkl_tss_test_bridge}>
        --fixture $<TARGET_FILE:xtbloom_mkl_tss_bootstrap_fixture>
    )
    if(TARGET xtbloom_mkl_pthread_tss_bridge)
      add_test(
        NAME xtbloom.cpu.mkl_tss_provider_elf
        COMMAND ${Python3_EXECUTABLE}
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_mkl_tss_bridge.py
          --readelf ${XTBLOOM_MKL_TSS_READELF}
          --nm ${CMAKE_NM}
          --bridge $<TARGET_FILE:xtbloom_mkl_pthread_tss_bridge>
          --provider $<TARGET_FILE:xtbloom_mkl_lp64_shim>
      )
    endif()
  endif()

  add_test(
    NAME xtbloom.benchmarks.self_test
    COMMAND ${Python3_EXECUTABLE} -m unittest -v
      benchmarks.test_run benchmarks.test_natoms_scaling
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  )
  add_test(
    NAME xtbloom.cmake.cuda_toolkit_metadata
    COMMAND ${CMAKE_COMMAND} -P
            ${CMAKE_CURRENT_SOURCE_DIR}/tests/cmake/cuda_toolkit_metadata_test.cmake
  )
  add_test(
    NAME xtbloom.cmake.version_resolution
    COMMAND ${CMAKE_COMMAND} -P
            ${CMAKE_CURRENT_SOURCE_DIR}/tests/cmake/version_resolution_test.cmake
  )
  # This source-only guard must run in ordinary CPU PR configurations as well
  # as CUDA builds; hosted wheel jobs compile CUDA with tests disabled.
  add_test(
    NAME xtbloom.cuda.kernel_signature_audit
    COMMAND ${Python3_EXECUTABLE}
            ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_cuda_kernel_signatures.py
            --source-root ${CMAKE_CURRENT_SOURCE_DIR}
  )

  if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    # The production adapter is platform-neutral C. A tiny fake provider gives
    # native CI deterministic coverage of LAPACKE argument translation and the
    # exact-handle CBLAS path without committing any upstream WebAssembly bytes.
    add_library(xtbloom_pyodide_openblas_fake SHARED
      tests/pyodide_openblas_fake_provider.c
    )
    set_target_properties(xtbloom_pyodide_openblas_fake PROPERTIES
      OUTPUT_NAME xtbloom_pyodide_openblas_fake
    )
    add_executable(xtbloom_pyodide_lapacke_lp64_shim_test
      src/runtime/pyodide_lapacke_lp64_shim.c
      tests/pyodide_lapacke_lp64_shim_test.c
    )
    target_compile_definitions(xtbloom_pyodide_lapacke_lp64_shim_test PRIVATE
      XTBLOOM_PYODIDE_OPENBLAS_FILENAME="libxtbloom_pyodide_openblas_fake.so"
    )
    target_link_libraries(xtbloom_pyodide_lapacke_lp64_shim_test PRIVATE
      xtbloom_pyodide_openblas_fake
      ${CMAKE_DL_LIBS}
    )
    add_test(
      NAME xtbloom.cpu.pyodide_lapacke_lp64_shim
      COMMAND xtbloom_pyodide_lapacke_lp64_shim_test
    )
    set_tests_properties(xtbloom.cpu.pyodide_lapacke_lp64_shim PROPERTIES
      ENVIRONMENT
        "XTBLOOM_PYODIDE_OPENBLAS=$<TARGET_FILE:xtbloom_pyodide_openblas_fake>"
    )
    add_test(
      NAME xtbloom.cpu.pyodide_lapacke_lp64_shim_rejects_relative_provider
      COMMAND xtbloom_pyodide_lapacke_lp64_shim_test
    )
    set_tests_properties(
      xtbloom.cpu.pyodide_lapacke_lp64_shim_rejects_relative_provider
      PROPERTIES ENVIRONMENT
        "XTBLOOM_PYODIDE_OPENBLAS=libxtbloom_pyodide_openblas_fake.so;XTBLOOM_EXPECT_PYODIDE_PROVIDER_UNAVAILABLE=1"
    )
  endif()

  if(XTBLOOM_CPU_LINALG_RUNTIME)
    get_filename_component(XTBLOOM_CPU_LINALG_DIRECTORY
      "${XTBLOOM_CPU_LINALG_RUNTIME}" DIRECTORY
    )
    if(WIN32)
      set(XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE PATH)
    elseif(APPLE)
      set(XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE DYLD_LIBRARY_PATH)
    else()
      set(XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE LD_LIBRARY_PATH)
    endif()

    function(xtbloom_configure_linalg_runtime_test target_name test_name)
      # The production eigensolver dlopens the BLAS/LAPACK runtime by path and
      # soname. Give CTest (including sanitizer builds) an explicit loader path
      # instead of relying only on the executable's build RPATH being inherited
      # by dlopen. The MKL env vars are harmless for OpenBLAS runtimes.
      set_target_properties(${target_name} PROPERTIES
        BUILD_RPATH "${XTBLOOM_CPU_LINALG_DIRECTORY}"
      )
      set_tests_properties(${test_name} PROPERTIES
        ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
        ENVIRONMENT_MODIFICATION
          "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
      )
    endfunction()
  endif()

  add_executable(xtbloom_c_api_test tests/c_api_test.c)
  target_link_libraries(xtbloom_c_api_test PRIVATE xtbloom::xtbloom)
  set_target_properties(xtbloom_c_api_test PROPERTIES C_STANDARD 11 C_STANDARD_REQUIRED YES)
  add_test(NAME xtbloom.c_api COMMAND xtbloom_c_api_test)

  add_executable(xtbloom_request_test
    tests/request_test.cpp
    src/runtime/request.cpp
  )
  target_include_directories(xtbloom_request_test PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/src
  )
  target_link_libraries(xtbloom_request_test PRIVATE Threads::Threads)
  target_compile_features(xtbloom_request_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.request COMMAND xtbloom_request_test)

  # The browser adapter test supplies a fake public C ABI so failure
  # publication and optimizer math remain testable without a WASM toolchain or
  # an external BLAS/LAPACK runtime.
  add_executable(xtbloom_web_adapter_test tests/web_adapter_test.c)
  target_include_directories(xtbloom_web_adapter_test PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
  )
  if(NOT WIN32)
    target_link_libraries(xtbloom_web_adapter_test PRIVATE m)
  endif()
  set_target_properties(xtbloom_web_adapter_test PROPERTIES
    C_STANDARD 11
    C_STANDARD_REQUIRED YES
  )
  add_test(NAME xtbloom.web.adapter COMMAND xtbloom_web_adapter_test)

  add_executable(xtbloom_result_owner_test tests/result_owner_test.cpp)
  target_link_libraries(xtbloom_result_owner_test PRIVATE xtbloom::xtbloom)
  target_compile_features(xtbloom_result_owner_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.result_owner COMMAND xtbloom_result_owner_test)

  add_executable(xtbloom_runtime_test tests/runtime_test.cpp)
  target_link_libraries(xtbloom_runtime_test PRIVATE xtbloom::xtbloom)
  target_compile_features(xtbloom_runtime_test PRIVATE cxx_std_17)
  if(XTBLOOM_HAS_CUDA)
    target_compile_definitions(xtbloom_runtime_test PRIVATE XTBLOOM_TEST_HAS_CUDA=1)
  endif()
  add_test(NAME xtbloom.runtime COMMAND xtbloom_runtime_test)
  if(XTBLOOM_CPU_LINALG_RUNTIME)
    xtbloom_configure_linalg_runtime_test(xtbloom_runtime_test xtbloom.runtime)
  endif()

  add_executable(xtbloom_cpu_isa_dispatch_test tests/cpu_isa_dispatch_test.cpp)
  target_link_libraries(xtbloom_cpu_isa_dispatch_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_cpu_isa_dispatch_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.cpu.isa_dispatch COMMAND xtbloom_cpu_isa_dispatch_test)

  add_executable(xtbloom_model_registry_test
    tests/model_registry_test.cpp
    src/runtime/model_registry.cpp
  )
  target_include_directories(xtbloom_model_registry_test PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/src
  )
  target_compile_features(xtbloom_model_registry_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.model_registry COMMAND xtbloom_model_registry_test)

  add_executable(xtbloom_gfn1_cpu_execution_header_test
    tests/gfn1_cpu_execution_header_test.cpp
  )
  target_include_directories(xtbloom_gfn1_cpu_execution_header_test PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/src
  )
  target_compile_features(xtbloom_gfn1_cpu_execution_header_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.execution_header COMMAND xtbloom_gfn1_cpu_execution_header_test)

  if(XTBLOOM_HAS_CUDA)
    # This host-only test must compile in the provider-free configuration. It
    # verifies that provider status returns remain fixed-width integer domains
    # even when compilers are asked to shorten ordinary enum types.
    add_executable(xtbloom_nvidia_host_api_test tests/nvidia_host_api_test.cpp)
    target_include_directories(xtbloom_nvidia_host_api_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}/src
      ${XTBLOOM_CUDA_TOOLKIT_INCLUDE_DIRS}
    )
    target_compile_features(xtbloom_nvidia_host_api_test PRIVATE cxx_std_17)
    target_compile_options(xtbloom_nvidia_host_api_test PRIVATE
      $<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang>:-fshort-enums>
    )
    add_test(NAME xtbloom.cuda.nvidia_host_api COMMAND xtbloom_nvidia_host_api_test)
  endif()

  if(XTBLOOM_CPU_LINALG_RUNTIME)
    add_executable(xtbloom_cpu_public_inference_test
      tests/cpu_public_inference_test.cpp
    )
    target_link_libraries(xtbloom_cpu_public_inference_test PRIVATE
      xtbloom::xtbloom
      Threads::Threads
    )
    target_compile_features(xtbloom_cpu_public_inference_test PRIVATE cxx_std_17)
    add_test(NAME xtbloom.cpu.public_inference COMMAND xtbloom_cpu_public_inference_test)
    # Keep a stable acceptance-gate name for the GFN1 cases hosted by the
    # combined public CPU inference executable.
    add_test(NAME xtbloom.gfn1.public_inference COMMAND xtbloom_cpu_public_inference_test)
    xtbloom_configure_linalg_runtime_test(
      xtbloom_cpu_public_inference_test xtbloom.cpu.public_inference
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_cpu_public_inference_test xtbloom.gfn1.public_inference
    )

    # Issue #360 regression: compile the public CPU runtime into a standalone
    # test binary with deterministic worker observability. The production
    # shared library remains free of test hooks, while this binary still calls
    # the real public C API and the configured production LP64 provider.
    add_executable(xtbloom_cpu_worker_teardown_test
      tests/cpu_worker_teardown_test.cpp
      src/api.cpp
      src/runtime/backend.cpp
      src/runtime/gfn2_cpu_execution.cpp
      src/runtime/gfn2_plan.cpp
      src/runtime/model_plan.cpp
      src/runtime/model_registry.cpp
      src/runtime/request.cpp
      src/runtime/result_owner.cpp
      src/runtime/validation.cpp
      ${XTBLOOM_GFN2_DISPATCH_OBJECTS}
      $<TARGET_OBJECTS:xtbloom_model_common_cpu_objects>
      $<TARGET_OBJECTS:xtbloom_gfn1_cpu_objects>
      $<TARGET_OBJECTS:xtbloom_gfn2_cpu_objects>
    )
    target_include_directories(xtbloom_cpu_worker_teardown_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/include
      ${CMAKE_CURRENT_SOURCE_DIR}/src
      ${XTBLOOM_GENERATED_INCLUDE_DIR}
    )
    target_compile_definitions(xtbloom_cpu_worker_teardown_test PRIVATE
      XTBLOOM_BUILDING_LIBRARY
      XTBLOOM_CPU_WORKER_TEARDOWN_TESTING=1
    )
    target_compile_features(xtbloom_cpu_worker_teardown_test PRIVATE cxx_std_17)
    target_link_libraries(xtbloom_cpu_worker_teardown_test PRIVATE
      Threads::Threads
      ${CMAKE_DL_LIBS}
    )
    add_test(NAME xtbloom.cpu.worker_teardown COMMAND xtbloom_cpu_worker_teardown_test)
    xtbloom_configure_linalg_runtime_test(
      xtbloom_cpu_worker_teardown_test xtbloom.cpu.worker_teardown
    )
    set_property(TEST xtbloom.cpu.worker_teardown APPEND PROPERTY ENVIRONMENT
      "MALLOC_CHECK_=3"
      "GLIBC_TUNABLES=glibc.malloc.tcache_count=0"
    )
  endif()

  if(BUILD_SHARED_LIBS AND UNIX AND NOT APPLE)
    add_test(
      NAME xtbloom.abi_symbols
      COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_symbols.py
              --nm ${CMAKE_NM} --library $<TARGET_FILE:xtbloom>
    )
    if(XTBLOOM_HAS_CUDA)
      find_program(XTBLOOM_READELF NAMES readelf REQUIRED)
      add_test(
        NAME xtbloom.abi_cuda_no_proprietary_needed
        COMMAND ${Python3_EXECUTABLE}
                ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_cuda_dependencies.py
                --readelf ${XTBLOOM_READELF} --library $<TARGET_FILE:xtbloom>
      )
      add_test(
        NAME xtbloom.abi_cuda_dependency_checker
        COMMAND ${Python3_EXECUTABLE} -m unittest discover
                -s ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi
                -p test_check_cuda_dependencies.py -v
      )
      add_test(
        NAME xtbloom.abi_cuda_direct_dso_load
        COMMAND ${Python3_EXECUTABLE}
                ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_cuda_dlopen_runtime.py
                --library $<TARGET_FILE:xtbloom> --mode load
      )
      add_test(
        NAME xtbloom.abi_cuda_no_runtime_concurrent
        COMMAND ${Python3_EXECUTABLE}
                ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_cuda_dlopen_runtime.py
                --library $<TARGET_FILE:xtbloom>
                --mode concurrent-unavailable --threads 16 --calls-per-thread 16
      )
      set_tests_properties(xtbloom.abi_cuda_no_runtime_concurrent PROPERTIES
        ENVIRONMENT "XTBLOOM_CUDA_FORCE_FALLBACK=1"
      )
    endif()
    if(XTBLOOM_HAS_TORCH_EXT)
      set(XTBLOOM_TORCH_LINKAGE_ARGS
        --symbol-list
        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/torch-stable/aoti_symbols.txt
        --library $<TARGET_FILE:xtbloom_torch_ext>
      )
      if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
        find_program(XTBLOOM_READELF NAMES readelf REQUIRED)
        list(APPEND XTBLOOM_TORCH_LINKAGE_ARGS
          --readelf ${XTBLOOM_READELF} --nm ${CMAKE_NM}
        )
      endif()
      add_test(
        NAME xtbloom.abi_torch_extension_linkage
        COMMAND ${Python3_EXECUTABLE}
                ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_torch_extension_linkage.py
                ${XTBLOOM_TORCH_LINKAGE_ARGS}
      )
      set_tests_properties(xtbloom.abi_torch_extension_linkage PROPERTIES
        LABELS "abi;torch"
      )
    endif()
  endif()

  add_executable(xtbloom_batch_validation_test
    tests/batch_validation_test.cpp
    src/runtime/model_registry.cpp
    src/runtime/validation.cpp
    src/model/gfn2/lattice.cpp
  )
  target_include_directories(xtbloom_batch_validation_test PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/src
  )
  target_compile_features(xtbloom_batch_validation_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.batch_validation COMMAND xtbloom_batch_validation_test)

  add_executable(xtbloom_plan_schema_test tests/plan_schema_test.cpp)
  target_link_libraries(xtbloom_plan_schema_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_plan_schema_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.plan_schema COMMAND xtbloom_plan_schema_test)

  # CUDA runtime tests link CUDA::cudart and run on a real GPU. They are
  # built only when the build environment actually provides the provider
  # libraries; a stub-generation build (nvcc support files plus cudart
  # headers, but no provider shared objects) still
  # compiles and publishes the CUDA backend but cannot exercise it here.
  if(XTBLOOM_HAS_CUDA AND _xtbloom_cuda_providers_present)
    add_executable(xtbloom_cuda_descriptor_validation_test
      tests/cuda_descriptor_validation_test.cu
    )
    target_link_libraries(xtbloom_cuda_descriptor_validation_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_descriptor_validation_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/include
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_descriptor_validation_test PRIVATE
      XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_descriptor_validation_test PROPERTIES
      CUDA_SEPARABLE_COMPILATION ON
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
    )
    add_test(NAME xtbloom.cuda.descriptor_validation
      COMMAND xtbloom_cuda_descriptor_validation_test
    )

    add_executable(xtbloom_cuda_gfn2_topology_staging_test
      tests/cuda_gfn2_topology_staging_test.cu
    )
    target_link_libraries(xtbloom_cuda_gfn2_topology_staging_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_gfn2_topology_staging_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/include
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_topology_staging_test PRIVATE
      XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn2_topology_staging_test PROPERTIES
      CUDA_SEPARABLE_COMPILATION ON
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
    )
    add_test(NAME xtbloom.cuda.gfn2_topology_staging
      COMMAND xtbloom_cuda_gfn2_topology_staging_test
    )

    add_executable(xtbloom_cuda_gfn2_public_result_bridge_test
      tests/cuda_gfn2_public_result_bridge_test.cu
    )
    target_link_libraries(xtbloom_cuda_gfn2_public_result_bridge_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_gfn2_public_result_bridge_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/include
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_public_result_bridge_test PRIVATE
      XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn2_public_result_bridge_test PROPERTIES
      CUDA_SEPARABLE_COMPILATION ON
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
    )
    add_test(NAME xtbloom.cuda.gfn2_public_result_bridge
      COMMAND xtbloom_cuda_gfn2_public_result_bridge_test
    )

    add_executable(xtbloom_cuda_public_api_test
      tests/cuda_public_api_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_public_api_test PRIVATE
      xtbloom::xtbloom
      xtbloom_gfn2_cpu
      CUDA::cudart
      Threads::Threads
    )
    target_include_directories(xtbloom_cuda_public_api_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/include
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_public_api_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_public_api_test PROPERTIES
      CUDA_SEPARABLE_COMPILATION ON
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
    )
    add_test(NAME xtbloom.cuda.public_api COMMAND xtbloom_cuda_public_api_test)
    if(XTBLOOM_CPU_LINALG_RUNTIME)
      xtbloom_configure_linalg_runtime_test(
        xtbloom_cuda_public_api_test xtbloom.cuda.public_api
      )
    endif()

    add_executable(xtbloom_cuda_public_unrestricted_test
      tests/cuda_public_unrestricted_test.cu
    )
    target_link_libraries(xtbloom_cuda_public_unrestricted_test PRIVATE
      xtbloom::xtbloom
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_public_unrestricted_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/include
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_public_unrestricted_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_public_unrestricted_test PROPERTIES
      CUDA_SEPARABLE_COMPILATION ON
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      # Shared-library builds must load the cudart paired with the selected
      # CUDA compiler, even when another toolkit is the system default.
      BUILD_RPATH "$<TARGET_FILE_DIR:CUDA::cudart>"
    )
    add_test(NAME xtbloom.cuda.public_unrestricted
      COMMAND xtbloom_cuda_public_unrestricted_test
    )

    add_executable(xtbloom_cuda_result_owner_test
      tests/cuda_result_owner_test.cu
    )
    target_link_libraries(xtbloom_cuda_result_owner_test PRIVATE
      xtbloom::xtbloom
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_result_owner_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/include
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_result_owner_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_result_owner_test PROPERTIES
      CUDA_SEPARABLE_COMPILATION ON
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      BUILD_RPATH "$<TARGET_FILE_DIR:CUDA::cudart>"
    )
    add_test(NAME xtbloom.cuda.result_owner
      COMMAND xtbloom_cuda_result_owner_test
    )

    add_executable(xtbloom_cuda_atomics_test tests/cuda_atomics_test.cu)
    target_link_libraries(xtbloom_cuda_atomics_test PRIVATE CUDA::cudart)
    target_include_directories(xtbloom_cuda_atomics_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_atomics_test PRIVATE
      XTBLOOM_FORCE_FP64_ATOMIC_CAS=1
    )
    set_target_properties(xtbloom_cuda_atomics_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
    )
    add_test(NAME xtbloom.cuda.atomics COMMAND xtbloom_cuda_atomics_test)

    add_executable(xtbloom_cuda_parameters_test tests/cuda_parameters_test.cu)
    target_link_libraries(xtbloom_cuda_parameters_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_parameters_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_parameters_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_parameters_test PROPERTIES
      CUDA_SEPARABLE_COMPILATION ON
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
    )
    add_test(NAME xtbloom.cuda.parameters COMMAND xtbloom_cuda_parameters_test)

    add_executable(xtbloom_cuda_repulsion_test tests/cuda_repulsion_test.cu)
    target_link_libraries(xtbloom_cuda_repulsion_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_repulsion_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_repulsion_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_repulsion_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.repulsion COMMAND xtbloom_cuda_repulsion_test)

    add_executable(xtbloom_cuda_external_point_charges_test
      tests/cuda_external_point_charges_test.cu
    )
    target_link_libraries(xtbloom_cuda_external_point_charges_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_external_point_charges_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_external_point_charges_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_external_point_charges_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.external_point_charges
      COMMAND xtbloom_cuda_external_point_charges_test
    )

    add_executable(xtbloom_cuda_classical_force_test
      tests/cuda_classical_force_test.cu
    )
    target_link_libraries(xtbloom_cuda_classical_force_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_classical_force_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_classical_force_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_classical_force_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.classical_force
      COMMAND xtbloom_cuda_classical_force_test
    )

    add_executable(xtbloom_cuda_force_composition_test
      tests/cuda_force_composition_test.cu
    )
    target_link_libraries(xtbloom_cuda_force_composition_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_force_composition_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_force_composition_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_force_composition_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.force_composition
      COMMAND xtbloom_cuda_force_composition_test
    )

    add_executable(xtbloom_cuda_electric_field_test
      tests/cuda_electric_field_test.cu
    )
    target_link_libraries(xtbloom_cuda_electric_field_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_electric_field_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_electric_field_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_electric_field_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.electric_field
      COMMAND xtbloom_cuda_electric_field_test
    )

    add_executable(xtbloom_cuda_geometry_test tests/cuda_geometry_test.cu)
    target_link_libraries(xtbloom_cuda_geometry_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_geometry_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_geometry_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_geometry_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.geometry COMMAND xtbloom_cuda_geometry_test)

    add_executable(xtbloom_cuda_pairlist_test tests/cuda_pairlist_test.cu)
    target_link_libraries(xtbloom_cuda_pairlist_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_pairlist_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_pairlist_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_pairlist_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.pairlist COMMAND xtbloom_cuda_pairlist_test)

    # Focused #70 benchmark.  It measures the sparse bucket build, the dense
    # fallback build, and the coordination reuse cost at batch 1/8/32/128 so
    # the dispatch crossover is anchored by reproducible profiling.
    add_executable(xtbloom_cuda_pairlist_benchmark tests/cuda_pairlist_test.cu)
    target_link_libraries(xtbloom_cuda_pairlist_benchmark PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_pairlist_benchmark PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_pairlist_benchmark PRIVATE
      XTBLOOM_HAS_CUDA=1
      XTBLOOM_PAIRLIST_BENCHMARK_ONLY=1
    )
    set_target_properties(xtbloom_cuda_pairlist_benchmark PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )

    add_executable(xtbloom_cuda_integrals_test tests/cuda_integrals_test.cu)
    target_link_libraries(xtbloom_cuda_integrals_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_integrals_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_integrals_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_integrals_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.integrals COMMAND xtbloom_cuda_integrals_test)

    add_executable(xtbloom_cuda_integral_force_test tests/cuda_integral_force_test.cu)
    target_link_libraries(xtbloom_cuda_integral_force_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_integral_force_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_integral_force_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_integral_force_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.integral_force COMMAND xtbloom_cuda_integral_force_test)

    add_executable(xtbloom_cuda_h0_force_test tests/cuda_h0_force_test.cu)
    target_link_libraries(xtbloom_cuda_h0_force_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_h0_force_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_h0_force_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_h0_force_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.h0_force COMMAND xtbloom_cuda_h0_force_test)

    add_executable(xtbloom_cuda_hamiltonian_force_test tests/cuda_hamiltonian_force_test.cu)
    target_link_libraries(xtbloom_cuda_hamiltonian_force_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_hamiltonian_force_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_hamiltonian_force_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_hamiltonian_force_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.hamiltonian_force COMMAND xtbloom_cuda_hamiltonian_force_test)

    add_executable(xtbloom_cuda_hamiltonian_test tests/cuda_hamiltonian_test.cu)
    target_link_libraries(xtbloom_cuda_hamiltonian_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_hamiltonian_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_hamiltonian_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_hamiltonian_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.hamiltonian COMMAND xtbloom_cuda_hamiltonian_test)

    add_executable(xtbloom_cuda_mulliken_test tests/cuda_mulliken_test.cu)
    target_link_libraries(xtbloom_cuda_mulliken_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_mulliken_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_mulliken_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_mulliken_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.mulliken COMMAND xtbloom_cuda_mulliken_test)

    add_executable(xtbloom_cuda_spin_test tests/cuda_spin_test.cu)
    target_link_libraries(xtbloom_cuda_spin_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_spin_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_spin_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_spin_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.spin COMMAND xtbloom_cuda_spin_test)

    add_executable(xtbloom_cuda_occupations_test tests/cuda_occupations_test.cu)
    target_link_libraries(xtbloom_cuda_occupations_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_occupations_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_occupations_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_occupations_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.occupations COMMAND xtbloom_cuda_occupations_test)

    add_executable(xtbloom_cuda_density_test tests/cuda_density_test.cu)
    target_link_libraries(xtbloom_cuda_density_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_density_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_density_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_density_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.density COMMAND xtbloom_cuda_density_test)

    add_executable(xtbloom_cuda_electronic_gradient_test
      tests/cuda_electronic_gradient_test.cu
    )
    target_link_libraries(xtbloom_cuda_electronic_gradient_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_electronic_gradient_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_electronic_gradient_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_electronic_gradient_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.electronic_gradient COMMAND xtbloom_cuda_electronic_gradient_test)

    add_executable(xtbloom_cuda_energy_force_execution_test
      tests/cuda_energy_force_execution_test.cu
    )
    target_link_libraries(xtbloom_cuda_energy_force_execution_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_energy_force_execution_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_energy_force_execution_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_energy_force_execution_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.energy_force_execution
      COMMAND xtbloom_cuda_energy_force_execution_test
    )

    add_executable(xtbloom_cuda_gfn2_terminal_execution_test
      tests/cuda_gfn2_terminal_execution_test.cu
    )
    target_link_libraries(xtbloom_cuda_gfn2_terminal_execution_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn2_terminal_execution_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_terminal_execution_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn2_terminal_execution_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn2_terminal_execution
      COMMAND xtbloom_cuda_gfn2_terminal_execution_test
    )

    add_executable(xtbloom_cuda_gfn2_runtime_owner_test
      tests/cuda_gfn2_runtime_owner_test.cu
      tests/support/gfn2_scc_test_case.cpp
      # This white-box test exercises the internal context owner directly.
      # Shared-library builds hide that implementation symbol by design, so
      # compile the owner into the test instead of weakening the public ABI.
      src/runtime/backend.cpp
      src/runtime/gfn2_cpu_execution.cpp
    )
    target_link_libraries(xtbloom_cuda_gfn2_runtime_owner_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn2_runtime_owner_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_runtime_owner_test
      PRIVATE
        XTBLOOM_HAS_CUDA=1
        XTBLOOM_CUDA_TEST_HOOKS=1
    )
    set_target_properties(xtbloom_cuda_gfn2_runtime_owner_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_owner
      COMMAND xtbloom_cuda_gfn2_runtime_owner_test
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_owner_native_lattice_lifecycle
      COMMAND xtbloom_cuda_gfn2_runtime_owner_test --native-lattice-lifecycle
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_owner_bounded_fallback
      COMMAND xtbloom_cuda_gfn2_runtime_owner_test --bounded-fallback
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_owner_request_state
      COMMAND xtbloom_cuda_gfn2_runtime_owner_test --request-state
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_owner_refresh_chain
      COMMAND xtbloom_cuda_gfn2_runtime_owner_test --refresh-chain
    )
    add_test(NAME xtbloom.cuda.gfn1_host_plan_accounting
      COMMAND xtbloom_cuda_gfn2_runtime_owner_test --gfn1-host-plan-accounting
    )

    add_executable(xtbloom_cuda_gfn2_runtime_parity_test
      tests/cuda_gfn2_runtime_parity_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_gfn2_runtime_parity_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn2_runtime_parity_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_runtime_parity_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn2_runtime_parity_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_parity
      COMMAND xtbloom_cuda_gfn2_runtime_parity_test
    )
    if(XTBLOOM_CPU_LINALG_RUNTIME)
      xtbloom_configure_linalg_runtime_test(
        xtbloom_cuda_gfn2_runtime_parity_test xtbloom.cuda.gfn2_runtime_parity
      )
    endif()

    add_executable(xtbloom_cuda_gfn2_runtime_graph_test
      tests/cuda_gfn2_runtime_graph_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_gfn2_runtime_graph_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn2_runtime_graph_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_runtime_graph_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn2_runtime_graph_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_graph
      COMMAND xtbloom_cuda_gfn2_runtime_graph_test
    )

    add_executable(xtbloom_cuda_gfn2_runtime_cache_diagnostics_test
      tests/cuda_gfn2_runtime_cache_diagnostics_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_gfn2_runtime_cache_diagnostics_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn2_runtime_cache_diagnostics_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_runtime_cache_diagnostics_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn2_runtime_cache_diagnostics_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn2_runtime_cache_diagnostics
      COMMAND xtbloom_cuda_gfn2_runtime_cache_diagnostics_test
    )

    add_executable(xtbloom_cuda_gfn2_preprocessing_test
      tests/cuda_gfn2_preprocessing_test.cu
    )
    target_link_libraries(xtbloom_cuda_gfn2_preprocessing_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn2_preprocessing_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn2_preprocessing_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn2_preprocessing_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn2_preprocessing
      COMMAND xtbloom_cuda_gfn2_preprocessing_test
    )

    add_executable(xtbloom_cuda_eigensolver_test tests/cuda_eigensolver_test.cu)
    target_link_libraries(xtbloom_cuda_eigensolver_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_eigensolver_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_eigensolver_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_eigensolver_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.eigensolver COMMAND xtbloom_cuda_eigensolver_test)

    # Focused #80/#131 compaction benchmark. Builds homogeneous and
    # heterogeneous restricted eigensolver buckets, drives canonical
    # active-count tier sweeps, and reports exact-capacity bucket activity
    # (active vs submitted vs completed) with compacted/uncompacted latency
    # crossover for batch sizes 1/8/32/128. Not a CTest test: it is a
    # measurement runner like xtbloom_cuda_scc_loop_benchmark.
    add_executable(xtbloom_cuda_compaction_benchmark tests/cuda_eigensolver_test.cu)
    target_link_libraries(xtbloom_cuda_compaction_benchmark PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_compaction_benchmark PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_compaction_benchmark PRIVATE
      XTBLOOM_HAS_CUDA=1
      XTBLOOM_COMPACTION_BENCHMARK_ONLY=1
    )
    set_target_properties(xtbloom_cuda_compaction_benchmark PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )

    add_executable(xtbloom_cuda_es3_test tests/cuda_es3_test.cu)
    target_link_libraries(xtbloom_cuda_es3_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_es3_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_es3_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_es3_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.es3 COMMAND xtbloom_cuda_es3_test)

    add_executable(xtbloom_cuda_es2_test tests/cuda_es2_test.cu)
    target_link_libraries(xtbloom_cuda_es2_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_es2_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_es2_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_es2_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.es2 COMMAND xtbloom_cuda_es2_test)

    add_executable(xtbloom_cuda_aes2_test tests/cuda_aes2_test.cu)
    target_link_libraries(xtbloom_cuda_aes2_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_aes2_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_aes2_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_aes2_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.aes2 COMMAND xtbloom_cuda_aes2_test)

    # Focused #220 benchmark-only executable.  It reuses the scientific AES2
    # fixture but times individual production leaves with CUDA events; it is
    # intentionally not registered as a CTest and never changes the test main.
    add_executable(xtbloom_cuda_aes2_term_benchmark tests/cuda_aes2_test.cu)
    target_link_libraries(xtbloom_cuda_aes2_term_benchmark PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_aes2_term_benchmark PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_aes2_term_benchmark PRIVATE
      XTBLOOM_HAS_CUDA=1
      XTBLOOM_AES2_TERM_BENCHMARK_ONLY=1
    )
    set_target_properties(xtbloom_cuda_aes2_term_benchmark PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )

    add_executable(xtbloom_cuda_d4_test tests/cuda_d4_test.cu)
    target_link_libraries(xtbloom_cuda_d4_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_d4_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_d4_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_d4_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.d4 COMMAND xtbloom_cuda_d4_test)

    # Focused #220 committed-pair-list D4 term benchmark. Compact and open
    # topologies share the production entry points; error reset, output seeds,
    # and CPU-parity downloads stay outside every measured event range.
    add_executable(xtbloom_cuda_d4_term_benchmark tests/cuda_d4_test.cu)
    target_link_libraries(xtbloom_cuda_d4_term_benchmark PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
      CUDA::cudart
    )
    target_include_directories(xtbloom_cuda_d4_term_benchmark PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_d4_term_benchmark PRIVATE
      XTBLOOM_HAS_CUDA=1
      XTBLOOM_D4_TERM_BENCHMARK_ONLY=1
    )
    set_target_properties(xtbloom_cuda_d4_term_benchmark PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )

    add_executable(xtbloom_cuda_periodic_embedding_test
      tests/cuda_periodic_embedding_test.cu
    )
    target_link_libraries(xtbloom_cuda_periodic_embedding_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_periodic_embedding_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_periodic_embedding_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_periodic_embedding_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.periodic_embedding
      COMMAND xtbloom_cuda_periodic_embedding_test
    )

    add_executable(xtbloom_cuda_scc_test tests/cuda_scc_test.cu)
    target_link_libraries(xtbloom_cuda_scc_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_scc_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc COMMAND xtbloom_cuda_scc_test)

    add_executable(xtbloom_cuda_plan_schema_test tests/cuda_plan_schema_test.cu)
    target_link_libraries(xtbloom_cuda_plan_schema_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_plan_schema_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_plan_schema_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_plan_schema_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.plan_schema COMMAND xtbloom_cuda_plan_schema_test)

    add_executable(xtbloom_cuda_scc_bridge_test tests/cuda_scc_bridge_test.cu)
    target_link_libraries(xtbloom_cuda_scc_bridge_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_bridge_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_bridge_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_scc_bridge_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_bridge COMMAND xtbloom_cuda_scc_bridge_test)

    add_executable(xtbloom_cuda_scc_iteration_control_test
      tests/cuda_scc_iteration_control_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_control_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_control_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_control_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_control_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_control
      COMMAND xtbloom_cuda_scc_iteration_control_test
    )

    add_executable(xtbloom_cuda_scc_iteration_binding_test
      tests/cuda_scc_iteration_binding_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_binding_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_binding_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_binding_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_binding_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_binding
      COMMAND xtbloom_cuda_scc_iteration_binding_test
    )

    add_executable(xtbloom_cuda_scc_publication_test
      tests/cuda_scc_publication_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_publication_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_publication_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_publication_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_publication_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_publication
      COMMAND xtbloom_cuda_scc_publication_test
    )

    add_executable(xtbloom_cuda_scc_iteration_composer_test
      tests/cuda_scc_iteration_composer_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_composer_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_composer_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_composer_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_composer_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_composer
      COMMAND xtbloom_cuda_scc_iteration_composer_test
    )

    add_executable(xtbloom_cuda_scc_iteration_arena_test
      tests/cuda_scc_iteration_arena_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_arena_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_arena_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_arena_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_arena_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_arena
      COMMAND xtbloom_cuda_scc_iteration_arena_test
    )

    add_executable(xtbloom_cuda_gfn1_scalar_contract_test
      tests/cuda_gfn1_scalar_contract_test.cu
    )
    target_link_libraries(xtbloom_cuda_gfn1_scalar_contract_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn1_cpu
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn1_scalar_contract_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn1_scalar_contract_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn1_scalar_contract_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn1_scalar_contract
      COMMAND xtbloom_cuda_gfn1_scalar_contract_test
    )

    add_executable(xtbloom_cuda_gfn1_classical_corrections_test
      tests/cuda_gfn1_classical_corrections_test.cu
    )
    target_link_libraries(xtbloom_cuda_gfn1_classical_corrections_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn1_cpu
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_gfn1_classical_corrections_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_gfn1_classical_corrections_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_gfn1_classical_corrections_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.gfn1_classical_corrections
      COMMAND xtbloom_cuda_gfn1_classical_corrections_test
    )

    add_executable(xtbloom_cuda_scc_iteration_initialize_test
      tests/cuda_scc_iteration_initialize_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_initialize_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_initialize_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_initialize_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_initialize_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_initialize
      COMMAND xtbloom_cuda_scc_iteration_initialize_test
    )

    add_executable(xtbloom_cuda_scc_iteration_reports_test
      tests/cuda_scc_iteration_reports_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_reports_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_reports_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_reports_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_reports_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_reports
      COMMAND xtbloom_cuda_scc_iteration_reports_test
    )

    add_executable(xtbloom_cuda_scc_setup_topology_test
      tests/cuda_scc_setup_topology_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_setup_topology_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_setup_topology_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_setup_topology_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_setup_topology_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_setup_topology
      COMMAND xtbloom_cuda_scc_setup_topology_test
    )

    add_executable(xtbloom_cuda_scc_setup_eigensolver_test
      tests/cuda_scc_setup_eigensolver_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_scc_setup_eigensolver_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_setup_eigensolver_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_setup_eigensolver_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_setup_eigensolver_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_setup_eigensolver
      COMMAND xtbloom_cuda_scc_setup_eigensolver_test
    )

    add_executable(xtbloom_cuda_scc_setup_inputs_test
      tests/cuda_scc_setup_inputs_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_scc_setup_inputs_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_setup_inputs_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_setup_inputs_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_setup_inputs_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_setup_inputs
      COMMAND xtbloom_cuda_scc_setup_inputs_test
    )

    add_executable(xtbloom_cuda_scc_iteration_production_test
      tests/cuda_scc_iteration_production_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_production_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_production_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_production_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_production_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_production
      COMMAND xtbloom_cuda_scc_iteration_production_test
    )
    add_test(NAME xtbloom.cuda.scc_iteration_large_singleton
      COMMAND xtbloom_cuda_scc_iteration_production_test --large-singleton-tridiagonal
    )
    add_test(NAME xtbloom.cuda.scc_iteration_deterministic_debug
      COMMAND xtbloom_cuda_scc_iteration_production_test --deterministic-debug
    )

    # Focused #130 benchmark. It reuses the production SCC fixture but runs a
    # one-remaining-iteration state so the conditional WHILE body count and
    # latency can be compared directly with the bounded fallback.
    add_executable(xtbloom_cuda_scc_loop_benchmark
      tests/cuda_scc_iteration_production_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_scc_loop_benchmark PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_loop_benchmark PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_loop_benchmark PRIVATE
      XTBLOOM_HAS_CUDA=1
      XTBLOOM_SCC_LOOP_BENCHMARK_ONLY=1
    )
    set_target_properties(xtbloom_cuda_scc_loop_benchmark PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )

    add_executable(xtbloom_cuda_scc_iteration_failure_matrix_test
      tests/cuda_scc_iteration_failure_matrix_test.cu
      tests/support/gfn2_scc_test_case.cpp
    )
    target_link_libraries(xtbloom_cuda_scc_iteration_failure_matrix_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_iteration_failure_matrix_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_iteration_failure_matrix_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_iteration_failure_matrix_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_iteration_failure_matrix
      COMMAND xtbloom_cuda_scc_iteration_failure_matrix_test
    )

    add_executable(xtbloom_cuda_scc_electrostatic_components_test
      tests/cuda_scc_electrostatic_components_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_electrostatic_components_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_electrostatic_components_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_electrostatic_components_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_electrostatic_components_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_electrostatic_components
      COMMAND xtbloom_cuda_scc_electrostatic_components_test
    )

    add_executable(xtbloom_cuda_scc_d4_periodic_test
      tests/cuda_scc_d4_periodic_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_d4_periodic_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_d4_periodic_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_d4_periodic_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_d4_periodic_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_d4_periodic
      COMMAND xtbloom_cuda_scc_d4_periodic_test
    )

    add_executable(xtbloom_cuda_scc_free_energy_test
      tests/cuda_scc_free_energy_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_free_energy_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_free_energy_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_free_energy_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_scc_free_energy_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_free_energy COMMAND xtbloom_cuda_scc_free_energy_test)

    add_executable(xtbloom_cuda_total_energy_test tests/cuda_total_energy_test.cu)
    target_link_libraries(xtbloom_cuda_total_energy_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_total_energy_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_total_energy_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_total_energy_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.total_energy COMMAND xtbloom_cuda_total_energy_test)

    add_executable(xtbloom_cuda_post_scc_potential_test
      tests/cuda_post_scc_potential_test.cu
    )
    target_link_libraries(xtbloom_cuda_post_scc_potential_test PRIVATE
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_post_scc_potential_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_post_scc_potential_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_post_scc_potential_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.post_scc_potential
      COMMAND xtbloom_cuda_post_scc_potential_test
    )

    add_executable(xtbloom_cuda_scc_energy_test tests/cuda_scc_energy_test.cu)
    target_link_libraries(xtbloom_cuda_scc_energy_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_energy_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_energy_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_scc_energy_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_energy COMMAND xtbloom_cuda_scc_energy_test)

    add_executable(xtbloom_cuda_scc_classical_energy_test
      tests/cuda_scc_classical_energy_test.cu
    )
    target_link_libraries(xtbloom_cuda_scc_classical_energy_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_classical_energy_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_classical_energy_test
      PRIVATE XTBLOOM_HAS_CUDA=1
    )
    set_target_properties(xtbloom_cuda_scc_classical_energy_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_classical_energy
      COMMAND xtbloom_cuda_scc_classical_energy_test
    )

    add_executable(xtbloom_cuda_scc_potential_test tests/cuda_scc_potential_test.cu)
    target_link_libraries(xtbloom_cuda_scc_potential_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_potential_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_potential_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_scc_potential_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_potential COMMAND xtbloom_cuda_scc_potential_test)

    add_executable(xtbloom_cuda_scc_mixer_test tests/cuda_scc_mixer_test.cu)
    target_link_libraries(xtbloom_cuda_scc_mixer_test PRIVATE
      xtbloom::xtbloom
      xtbloom_cuda_backend
      xtbloom_gfn2_cpu
    )
    target_include_directories(xtbloom_cuda_scc_mixer_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}
      ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(xtbloom_cuda_scc_mixer_test PRIVATE XTBLOOM_HAS_CUDA=1)
    set_target_properties(xtbloom_cuda_scc_mixer_test PROPERTIES
      CUDA_STANDARD 17
      CUDA_STANDARD_REQUIRED YES
      CUDA_SEPARABLE_COMPILATION ON
    )
    add_test(NAME xtbloom.cuda.scc_mixer COMMAND xtbloom_cuda_scc_mixer_test)
  endif()

  add_executable(xtbloom_repulsion_test tests/repulsion_test.cpp)
  target_link_libraries(xtbloom_repulsion_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_repulsion_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.repulsion COMMAND xtbloom_repulsion_test)

  add_executable(xtbloom_alpb_test tests/alpb_test.cpp)
  target_link_libraries(xtbloom_alpb_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_alpb_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.alpb COMMAND xtbloom_alpb_test)

  add_executable(xtbloom_coordination_test tests/coordination_test.cpp)
  target_link_libraries(xtbloom_coordination_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_coordination_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.coordination COMMAND xtbloom_coordination_test)

  add_executable(xtbloom_lattice_test tests/lattice_test.cpp)
  target_link_libraries(xtbloom_lattice_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_lattice_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.lattice COMMAND xtbloom_lattice_test)

  add_executable(xtbloom_gfn1_coordination_test tests/gfn1_coordination_test.cpp)
  target_link_libraries(xtbloom_gfn1_coordination_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_coordination_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.coordination COMMAND xtbloom_gfn1_coordination_test)

  add_executable(xtbloom_gfn1_repulsion_test tests/gfn1_repulsion_test.cpp)
  target_link_libraries(xtbloom_gfn1_repulsion_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_repulsion_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.repulsion COMMAND xtbloom_gfn1_repulsion_test)

  add_executable(xtbloom_gfn1_d3_test tests/gfn1_d3_test.cpp)
  target_link_libraries(xtbloom_gfn1_d3_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_d3_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.d3 COMMAND xtbloom_gfn1_d3_test)

  add_executable(xtbloom_gfn1_halogen_test tests/gfn1_halogen_test.cpp)
  target_link_libraries(xtbloom_gfn1_halogen_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_halogen_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.halogen COMMAND xtbloom_gfn1_halogen_test)

  add_executable(xtbloom_gfn1_external_point_charges_test
    tests/gfn1_external_point_charges_test.cpp)
  target_link_libraries(xtbloom_gfn1_external_point_charges_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_external_point_charges_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.external_point_charges
    COMMAND xtbloom_gfn1_external_point_charges_test)

  add_executable(xtbloom_d4_test tests/d4_test.cpp)
  target_link_libraries(xtbloom_d4_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_d4_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.d4 COMMAND xtbloom_d4_test)

  add_executable(xtbloom_basis_test tests/basis_test.cpp)
  target_link_libraries(xtbloom_basis_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_basis_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.basis COMMAND xtbloom_basis_test)

  add_executable(xtbloom_integrals_test tests/integrals_test.cpp)
  target_link_libraries(xtbloom_integrals_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_integrals_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.integrals COMMAND xtbloom_integrals_test)

  add_executable(xtbloom_gfn1_basis_test tests/gfn1_basis_test.cpp)
  target_link_libraries(xtbloom_gfn1_basis_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_basis_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.basis COMMAND xtbloom_gfn1_basis_test)

  add_executable(xtbloom_gfn1_integrals_test tests/gfn1_integrals_test.cpp)
  target_link_libraries(xtbloom_gfn1_integrals_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_integrals_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.integrals COMMAND xtbloom_gfn1_integrals_test)

  add_executable(xtbloom_multipole_integrals_test tests/multipole_integrals_test.cpp)
  target_link_libraries(xtbloom_multipole_integrals_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_multipole_integrals_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.multipole_integrals COMMAND xtbloom_multipole_integrals_test)

  add_executable(xtbloom_h0_test tests/h0_test.cpp)
  target_link_libraries(xtbloom_h0_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_h0_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.h0 COMMAND xtbloom_h0_test)

  add_executable(xtbloom_gfn1_h0_test tests/gfn1_h0_test.cpp)
  target_link_libraries(xtbloom_gfn1_h0_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_h0_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.h0 COMMAND xtbloom_gfn1_h0_test)

  add_executable(xtbloom_force_test tests/force_test.cpp)
  target_link_libraries(xtbloom_force_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_force_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.force COMMAND xtbloom_force_test)

  add_executable(xtbloom_external_point_charges_test tests/external_point_charges_test.cpp)
  target_link_libraries(xtbloom_external_point_charges_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_external_point_charges_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.external_point_charges COMMAND xtbloom_external_point_charges_test)

  add_executable(xtbloom_periodic_embedding_test tests/periodic_embedding_test.cpp)
  target_link_libraries(xtbloom_periodic_embedding_test PRIVATE xtbloom_gfn2_cpu Threads::Threads)
  target_compile_features(xtbloom_periodic_embedding_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.periodic_embedding COMMAND xtbloom_periodic_embedding_test)

  add_executable(xtbloom_es3_test tests/es3_test.cpp)
  target_link_libraries(xtbloom_es3_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_es3_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.es3 COMMAND xtbloom_es3_test)

  add_executable(xtbloom_gfn1_es_spin_test tests/gfn1_es_spin_test.cpp)
  target_link_libraries(xtbloom_gfn1_es_spin_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_es_spin_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.es_spin COMMAND xtbloom_gfn1_es_spin_test)

  add_executable(xtbloom_spin_test tests/spin_test.cpp)
  target_link_libraries(xtbloom_spin_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_spin_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.spin COMMAND xtbloom_spin_test)

  add_executable(xtbloom_es2_test tests/es2_test.cpp)
  target_link_libraries(xtbloom_es2_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_es2_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.es2 COMMAND xtbloom_es2_test)

  add_executable(xtbloom_aes2_test tests/aes2_test.cpp)
  target_link_libraries(xtbloom_aes2_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_aes2_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.aes2 COMMAND xtbloom_aes2_test)

  add_executable(xtbloom_wavefunction_test tests/wavefunction_test.cpp)
  target_link_libraries(xtbloom_wavefunction_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_wavefunction_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.wavefunction COMMAND xtbloom_wavefunction_test)

  add_executable(xtbloom_gfn1_wavefunction_test tests/gfn1_wavefunction_test.cpp)
  target_link_libraries(xtbloom_gfn1_wavefunction_test PRIVATE xtbloom_gfn1_cpu)
  if(XTBLOOM_CPU_LINALG_RUNTIME)
    target_link_libraries(xtbloom_gfn1_wavefunction_test PRIVATE ${XTBLOOM_CPU_LINALG_RUNTIME})
    target_compile_definitions(
      xtbloom_gfn1_wavefunction_test PRIVATE XTBLOOM_TEST_HAS_CPU_LINALG=1
    )
    if(XTBLOOM_CPU_LINALG_SYMBOL_PREFIX STREQUAL "scipy_")
      target_compile_definitions(
        xtbloom_gfn1_wavefunction_test PRIVATE XTBLOOM_TEST_SCIPY_PREFIXED_BLAS=1
      )
    endif()
  endif()
  target_compile_features(xtbloom_gfn1_wavefunction_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.wavefunction COMMAND xtbloom_gfn1_wavefunction_test)
  if(XTBLOOM_CPU_LINALG_RUNTIME)
    xtbloom_configure_linalg_runtime_test(
      xtbloom_gfn1_wavefunction_test xtbloom.gfn1.wavefunction
    )
  endif()

  add_executable(xtbloom_common_scc_mixer_test tests/common_scc_mixer_test.cpp)
  target_link_libraries(xtbloom_common_scc_mixer_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_common_scc_mixer_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.common.scc_mixer COMMAND xtbloom_common_scc_mixer_test)

  add_executable(xtbloom_gfn1_scc_mixer_test tests/gfn1_scc_mixer_test.cpp)
  target_link_libraries(xtbloom_gfn1_scc_mixer_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_scc_mixer_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.scc_mixer COMMAND xtbloom_gfn1_scc_mixer_test)

  add_executable(xtbloom_gfn1_mulliken_test tests/gfn1_mulliken_test.cpp)
  target_link_libraries(xtbloom_gfn1_mulliken_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_mulliken_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.mulliken COMMAND xtbloom_gfn1_mulliken_test)

  add_executable(xtbloom_gfn1_force_test tests/gfn1_force_test.cpp)
  target_link_libraries(xtbloom_gfn1_force_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_force_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.force COMMAND xtbloom_gfn1_force_test)

  add_executable(xtbloom_gfn1_scc_driver_test tests/gfn1_scc_driver_test.cpp)
  target_link_libraries(xtbloom_gfn1_scc_driver_test PRIVATE xtbloom_gfn1_cpu)
  target_compile_features(xtbloom_gfn1_scc_driver_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn1.scc_driver COMMAND xtbloom_gfn1_scc_driver_test)

  if(XTBLOOM_CPU_LINALG_RUNTIME)
    add_executable(xtbloom_gfn1_cpu_execution_test tests/gfn1_cpu_execution_test.cpp)
    target_link_libraries(xtbloom_gfn1_cpu_execution_test PRIVATE
      xtbloom_gfn1_cpu
      ${XTBLOOM_CPU_LINALG_RUNTIME}
    )
    if(XTBLOOM_CPU_LINALG_SYMBOL_PREFIX STREQUAL "scipy_")
      target_compile_definitions(
        xtbloom_gfn1_cpu_execution_test PRIVATE XTBLOOM_TEST_SCIPY_PREFIXED_BLAS=1
      )
    endif()
    target_compile_features(xtbloom_gfn1_cpu_execution_test PRIVATE cxx_std_17)
    add_test(NAME xtbloom.gfn1.cpu_execution COMMAND xtbloom_gfn1_cpu_execution_test)
    xtbloom_configure_linalg_runtime_test(
      xtbloom_gfn1_cpu_execution_test xtbloom.gfn1.cpu_execution
    )

    # Drive the hidden executor from the immutable GFN1 corpus without adding
    # a production JSON dependency or copying canonical fixture bytes into C++.
    add_executable(xtbloom_gfn1_cpu_probe tests/gfn1_cpu_probe.cpp)
    target_link_libraries(xtbloom_gfn1_cpu_probe PRIVATE
      xtbloom_gfn1_cpu
      ${XTBLOOM_CPU_LINALG_RUNTIME}
    )
    target_compile_features(xtbloom_gfn1_cpu_probe PRIVATE cxx_std_17)
    add_test(
      NAME xtbloom.gfn1.conformance_cpu
      COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/gfn1_cpu_conformance.py
        --probe $<TARGET_FILE:xtbloom_gfn1_cpu_probe>
        --source-root ${CMAKE_CURRENT_SOURCE_DIR}
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_gfn1_cpu_probe xtbloom.gfn1.conformance_cpu
    )
  endif()

  add_executable(xtbloom_mulliken_test tests/mulliken_test.cpp)
  target_link_libraries(xtbloom_mulliken_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_mulliken_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.mulliken COMMAND xtbloom_mulliken_test)

  add_executable(xtbloom_scc_mixer_test tests/scc_mixer_test.cpp)
  target_link_libraries(xtbloom_scc_mixer_test PRIVATE xtbloom_gfn2_cpu Threads::Threads)
  target_compile_features(xtbloom_scc_mixer_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.scc_mixer COMMAND xtbloom_scc_mixer_test)

  add_executable(xtbloom_scc_driver_test tests/scc_driver_test.cpp)
  target_link_libraries(xtbloom_scc_driver_test PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_scc_driver_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.gfn2.scc_driver COMMAND xtbloom_scc_driver_test)

  # Focused #41 benchmark: per-iteration mixer history transactions must scale
  # with active-system history rather than the total batch history. Not a CTest
  # gate; run standalone to produce issue-scoped evidence.
  add_executable(xtbloom_scc_mixer_transaction_benchmark benchmarks/scc_mixer_transaction.cpp)
  target_link_libraries(xtbloom_scc_mixer_transaction_benchmark PRIVATE xtbloom_gfn2_cpu)
  target_compile_features(xtbloom_scc_mixer_transaction_benchmark PRIVATE cxx_std_17)

  if(XTBLOOM_CPU_LINALG_RUNTIME)
    add_executable(xtbloom_eigensolver_test tests/eigensolver_test.cpp)
    target_link_libraries(xtbloom_eigensolver_test PRIVATE
      xtbloom_gfn2_cpu
      ${XTBLOOM_CPU_LINALG_RUNTIME}
      Threads::Threads
    )
    target_compile_features(xtbloom_eigensolver_test PRIVATE cxx_std_17)
    if(XTBLOOM_CPU_LINALG_SYMBOL_PREFIX STREQUAL "scipy_")
      # The test spies call through to the configured provider directly; use
      # scipy-openblas32's collision-avoiding ABI names when applicable.
      target_compile_definitions(
        xtbloom_eigensolver_test PRIVATE XTBLOOM_TEST_SCIPY_PREFIXED_BLAS=1
      )
    endif()
    add_test(NAME xtbloom.gfn2.eigensolver COMMAND xtbloom_eigensolver_test)
    xtbloom_configure_linalg_runtime_test(
      xtbloom_eigensolver_test xtbloom.gfn2.eigensolver
    )

    if(XTBLOOM_CPU_LINALG_SHIM)
      # Host-isolated LP64 provider evidence (issue #30). This binary links only
      # xtbloom_gfn2_cpu, never a BLAS/MKL runtime, so it can prove that provider
      # libraries stay outside RTLD_DEFAULT and that xtbloom coexists with a
      # globally loaded ILP64 host before and after backend creation.
      add_executable(xtbloom_cpu_linalg_isolation_test
        tests/cpu_linalg_isolation_test.cpp
      )
      target_link_libraries(xtbloom_cpu_linalg_isolation_test PRIVATE
        xtbloom_gfn2_cpu
        ${CMAKE_DL_LIBS}
      )
      target_compile_features(xtbloom_cpu_linalg_isolation_test PRIVATE cxx_std_17)
      target_compile_definitions(
        xtbloom_cpu_linalg_isolation_test PRIVATE XTBLOOM_TEST_HAS_MKL_SHIM=1
      )
      add_test(
        NAME xtbloom.cpu.linalg_isolation
        COMMAND xtbloom_cpu_linalg_isolation_test
      )
      xtbloom_configure_linalg_runtime_test(
        xtbloom_cpu_linalg_isolation_test xtbloom.cpu.linalg_isolation
      )
      # The test itself selects the host interface in fresh children. Do not
      # preselect LP64 through the generic provider-test environment.
      set_tests_properties(xtbloom.cpu.linalg_isolation PROPERTIES
        ENVIRONMENT "MKL_THREADING_LAYER=SEQUENTIAL"
      )

      # Build deliberately unusable libraries with the same MKL component
      # SONAMEs. The adversarial test puts them first in LD_LIBRARY_PATH; only
      # the shim's configure-time DT_RPATH may select the verified cohort.
      set(xtbloom_mkl_decoy_targets "")
      foreach(component IN ITEMS intel_lp64 sequential core)
        set(decoy_target "xtbloom_mkl_${component}_decoy")
        add_library(${decoy_target} SHARED src/runtime/mkl_lp64_shim.cpp)
        target_compile_features(${decoy_target} PRIVATE cxx_std_17)
        set_target_properties(${decoy_target} PROPERTIES
          OUTPUT_NAME "mkl_${component}"
          SUFFIX "${xtbloom_mkl_runtime_suffix}"
          CXX_VISIBILITY_PRESET hidden
          VISIBILITY_INLINES_HIDDEN YES
          LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mkl-decoy"
        )
        list(APPEND xtbloom_mkl_decoy_targets ${decoy_target})
      endforeach()
      add_dependencies(
        xtbloom_cpu_linalg_isolation_test ${xtbloom_mkl_decoy_targets}
      )
      add_test(
        NAME xtbloom.cpu.linalg_isolation_search_path
        COMMAND xtbloom_cpu_linalg_isolation_test --correctness
      )
      set_tests_properties(xtbloom.cpu.linalg_isolation_search_path PROPERTIES
        ENVIRONMENT
          "MKL_THREADING_LAYER=SEQUENTIAL;LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}/mkl-decoy:${XTBLOOM_CPU_LINALG_DIRECTORY}"
      )

      # A provider can register a base-registry pthread key in its constructor
      # before symbol verification fails. Its key destructor remains private
      # code, so the failure path must retain the entire namespace until process
      # exit rather than dlclosing it before the calling worker terminates.
      set(xtbloom_mkl_tss_failure_dir
        "${CMAKE_CURRENT_BINARY_DIR}/mkl-tss-failure"
      )
      add_library(xtbloom_mkl_tss_failure_provider SHARED
        tests/mkl_tss_failure_provider.c
      )
      target_compile_features(xtbloom_mkl_tss_failure_provider PRIVATE c_std_11)
      target_compile_options(xtbloom_mkl_tss_failure_provider PRIVATE -fno-sanitize=all)
      target_link_options(xtbloom_mkl_tss_failure_provider PRIVATE
        -fno-sanitize=all
        "LINKER:--no-as-needed"
        "LINKER:--disable-new-dtags"
        "LINKER:-z,defs"
      )
      target_link_libraries(xtbloom_mkl_tss_failure_provider PRIVATE
        xtbloom_mkl_pthread_tss_bridge
      )
      set_target_properties(xtbloom_mkl_tss_failure_provider PROPERTIES
        OUTPUT_NAME xtbloom_mkl_lp64_shim
        C_VISIBILITY_PRESET hidden
        BUILD_RPATH "$ORIGIN"
        LIBRARY_OUTPUT_DIRECTORY "${xtbloom_mkl_tss_failure_dir}"
      )

      add_executable(xtbloom_mkl_tss_failure_retention_test
        tests/mkl_tss_failure_retention_test.cpp
      )
      target_link_libraries(xtbloom_mkl_tss_failure_retention_test PRIVATE
        xtbloom_gfn2_cpu
        Threads::Threads
        ${CMAKE_DL_LIBS}
      )
      target_compile_features(
        xtbloom_mkl_tss_failure_retention_test PRIVATE cxx_std_17
      )
      set_target_properties(xtbloom_mkl_tss_failure_retention_test PROPERTIES
        RUNTIME_OUTPUT_DIRECTORY "${xtbloom_mkl_tss_failure_dir}"
      )
      add_dependencies(
        xtbloom_mkl_tss_failure_retention_test
        xtbloom_mkl_tss_failure_provider
        xtbloom_mkl_pthread_tss_bridge
      )
      add_custom_command(TARGET xtbloom_mkl_tss_failure_retention_test POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
          "$<TARGET_FILE:xtbloom_mkl_pthread_tss_bridge>"
          "${xtbloom_mkl_tss_failure_dir}"
        COMMENT "Staging the MKL pthread bridge beside the failure-path fixture"
      )
      add_test(
        NAME xtbloom.cpu.mkl_tss_failure_retention
        COMMAND xtbloom_mkl_tss_failure_retention_test
      )
      add_test(
        NAME xtbloom.cpu.mkl_tss_failure_provider_elf
        COMMAND ${Python3_EXECUTABLE}
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/abi/check_mkl_tss_bridge.py
          --readelf ${XTBLOOM_MKL_TSS_READELF}
          --nm ${CMAKE_NM}
          --bridge $<TARGET_FILE:xtbloom_mkl_pthread_tss_bridge>
          --provider $<TARGET_FILE:xtbloom_mkl_tss_failure_provider>
      )
    endif()
  elseif(NOT XTBLOOM_WHEEL_OPENBLAS)
    message(STATUS
      "xtbloom eigensolver test: disabled (set XTBLOOM_CPU_LINALG_LIBRARY or provide a system BLAS to enable)"
    )
  endif()

  if(XTBLOOM_WHEEL_OPENBLAS_LINUX_SHIM)
    # Prove the wheel provider is loaded through the sibling shim in a fresh
    # link-map namespace. The process-global decoy deliberately has the
    # provider's original SONAME but none of its symbols; successful inference
    # therefore proves base-namespace interposition cannot satisfy the shim.
    add_library(xtbloom_openblas_decoy SHARED
      src/runtime/openblas_lp64_shim.c
    )
    set_target_properties(xtbloom_openblas_decoy PROPERTIES
      OUTPUT_NAME scipy_openblas
      LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/openblas-decoy"
    )
    add_executable(xtbloom_wheel_openblas_isolation_test
      tests/cpu_linalg_isolation_test.cpp
    )
    target_link_libraries(xtbloom_wheel_openblas_isolation_test PRIVATE
      xtbloom_gfn2_cpu
      ${CMAKE_DL_LIBS}
    )
    target_compile_features(
      xtbloom_wheel_openblas_isolation_test PRIVATE cxx_std_17
    )
    target_compile_definitions(
      xtbloom_wheel_openblas_isolation_test
      PRIVATE XTBLOOM_TEST_HAS_WHEEL_OPENBLAS=1
    )
    add_dependencies(
      xtbloom_wheel_openblas_isolation_test
      xtbloom_openblas_lp64_shim
      xtbloom_openblas_decoy
    )
    add_test(
      NAME xtbloom.cpu.wheel_openblas_isolation
      COMMAND xtbloom_wheel_openblas_isolation_test
    )
    set_tests_properties(xtbloom.cpu.wheel_openblas_isolation PROPERTIES
      ENVIRONMENT
        "XTBLOOM_TEST_OPENBLAS_DECOY=$<TARGET_FILE:xtbloom_openblas_decoy>"
    )
  endif()

  if(XTBLOOM_CPU_LINALG_RUNTIME)
    # Issue #217 investigation gate: pinned temperature-continuation evidence
    # for the separated Me4N+ / Cl- ion pair on the committed tmacl fixture.
    # Requires the real LP64 eigensolver because tmacl has 42 orbitals.
    add_executable(xtbloom_scc_temperature_continuation_test
      tests/scc_temperature_continuation_test.cpp
    )
    target_compile_definitions(xtbloom_scc_temperature_continuation_test PRIVATE
      XTBLOOM_TMACL_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/inputs/tmacl.xyz"
    )
    target_link_libraries(xtbloom_scc_temperature_continuation_test PRIVATE
      xtbloom_gfn2_cpu
      Threads::Threads
    )
    target_compile_features(xtbloom_scc_temperature_continuation_test PRIVATE cxx_std_17)
    add_test(NAME xtbloom.gfn2.scc_temperature_continuation
      COMMAND xtbloom_scc_temperature_continuation_test
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_temperature_continuation_test xtbloom.gfn2.scc_temperature_continuation
    )

    # Issues #49/#50/#51: harnesses that drive the production CPU GFN2 SCC
    # driver through the pinned restricted and unrestricted corpora.
    # These are now passing acceptance gates:
    #   * xtbloom_scc_trace_capture drives one case sequentially and compares the
    #     complete closed-loop trajectory with the cpu_closed_loop_v1 profile;
    #   * xtbloom_scc_trace_batch_capture runs several cases in one ragged batch
    #     and proves each lane equals its sequential trajectory, with early
    #     convergence and an optional controlled per-system failure lane;
    #   * xtbloom_scc_trace_replay injects one golden mixed state and compares a
    #     single independently executed iteration (cuda/cpu replay profile).
    # They require the host-isolated LP64 runtime for the eigensolver, so they
    # are only registered when that runtime is present.
    add_executable(xtbloom_scc_trace_capture
      tests/scc_trace_capture.cpp
    )
    target_include_directories(xtbloom_scc_trace_capture PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
    target_link_libraries(xtbloom_scc_trace_capture PRIVATE
      xtbloom_gfn2_cpu
      Threads::Threads
    )
    target_compile_features(xtbloom_scc_trace_capture PRIVATE cxx_std_17)

    add_executable(xtbloom_scc_trace_batch_capture
      tests/scc_trace_batch_capture.cpp
    )
    target_include_directories(xtbloom_scc_trace_batch_capture PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
    target_link_libraries(xtbloom_scc_trace_batch_capture PRIVATE
      xtbloom_gfn2_cpu
      Threads::Threads
    )
    target_compile_features(xtbloom_scc_trace_batch_capture PRIVATE cxx_std_17)

    add_executable(xtbloom_scc_trace_replay
      tests/scc_trace_replay.cpp
    )
    target_include_directories(xtbloom_scc_trace_replay PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
    target_link_libraries(xtbloom_scc_trace_replay PRIVATE
      xtbloom_gfn2_cpu
      Threads::Threads
    )
    target_compile_features(xtbloom_scc_trace_replay PRIVATE cxx_std_17)

    add_executable(xtbloom_scc_trace_mixer
      tests/scc_trace_mixer_replay.cpp
    )
    target_include_directories(xtbloom_scc_trace_mixer PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
    target_link_libraries(xtbloom_scc_trace_mixer PRIVATE
      xtbloom_gfn2_cpu
      Threads::Threads
    )
    target_compile_features(xtbloom_scc_trace_mixer PRIVATE cxx_std_17)

    # Native ragged-batch structure test: early-convergence freezing, per-lane
    # status/iteration/flags, controlled per-system failure isolation, and
    # disjoint per-system output placement under the CPU driver.  Registered
    # in every CPU configuration so sanitizer builds cover ragged execution.
    add_executable(xtbloom_scc_trace_harness_native_test
      tests/scc_trace_harness_native_test.cpp
    )
    target_compile_definitions(xtbloom_scc_trace_harness_native_test PRIVATE
      XTBLOOM_SCC_TRACE_SPEC_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces/specs"
    )
    target_include_directories(xtbloom_scc_trace_harness_native_test PRIVATE
      ${CMAKE_CURRENT_SOURCE_DIR}/tests
    )
    target_link_libraries(xtbloom_scc_trace_harness_native_test PRIVATE
      xtbloom_gfn2_cpu
      Threads::Threads
    )
    target_compile_features(xtbloom_scc_trace_harness_native_test PRIVATE cxx_std_17)
    add_test(NAME xtbloom.gfn2.scc_trace_ragged_batch_native
      COMMAND xtbloom_scc_trace_harness_native_test
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_harness_native_test xtbloom.gfn2.scc_trace_ragged_batch_native
    )

    # Sequential closed-loop gates keep the versioned restricted and
    # unrestricted contracts independently visible in CTest output.
    add_test(
      NAME xtbloom.gfn2.scc_trace_cpu_closed_loop
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --capture $<TARGET_FILE:xtbloom_scc_trace_capture>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-capture
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_capture xtbloom.gfn2.scc_trace_cpu_closed_loop
    )
    add_test(
      NAME xtbloom.gfn2.scc_trace_unrestricted_cpu_closed_loop
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --capture $<TARGET_FILE:xtbloom_scc_trace_capture>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-unrestricted-capture
              --cases oh_radical
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_capture xtbloom.gfn2.scc_trace_unrestricted_cpu_closed_loop
    )

    # Ragged batch gate: h3_plus (converges early), nenacl (slowest), and the
    # six-point-charge water dimer run in one heterogeneous batch and each lane
    # must equal its pinned sequential trajectory.  --poison 3 adds a controlled
    # preparation-failure lane that must not corrupt or suppress the peers.
    add_test(
      NAME xtbloom.gfn2.scc_trace_ragged_batch
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --batch-capture $<TARGET_FILE:xtbloom_scc_trace_batch_capture>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-batch
              --batch-cases h3_plus nenacl water_dimer_6pc_hardness
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_batch_capture xtbloom.gfn2.scc_trace_ragged_batch
    )
    add_test(
      NAME xtbloom.gfn2.scc_trace_mixed_spin_ragged_batch
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --batch-capture $<TARGET_FILE:xtbloom_scc_trace_batch_capture>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-mixed-spin-batch
              --batch-cases h3_plus oh_radical nenacl
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_batch_capture xtbloom.gfn2.scc_trace_mixed_spin_ragged_batch
    )

    # Single-iteration replay gate: every golden iteration replayed from its
    # injected mixed state must equal the pinned iteration snapshot.
    add_test(
      NAME xtbloom.gfn2.scc_trace_cpu_replay
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --replay $<TARGET_FILE:xtbloom_scc_trace_replay>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-replay
              --replay-cases h3_plus nenacl water_dimer_6pc_hardness
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_replay xtbloom.gfn2.scc_trace_cpu_replay
    )
    add_test(
      NAME xtbloom.gfn2.scc_trace_unrestricted_cpu_replay
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --replay $<TARGET_FILE:xtbloom_scc_trace_replay>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-unrestricted-replay
              --replay-cases oh_radical
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_replay xtbloom.gfn2.scc_trace_unrestricted_cpu_replay
    )

    # Independent Broyden mixer gate: replay the pinned golden residual
    # sequence through xtbloom's production mixer alone and check every state
    # transition reproduces the golden next mixed state.
    add_test(
      NAME xtbloom.gfn2.scc_trace_mixer_replay
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --mixer $<TARGET_FILE:xtbloom_scc_trace_mixer>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-mixer
              --mixer-cases h3_plus nenacl water_dimer_6pc_hardness
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_mixer xtbloom.gfn2.scc_trace_mixer_replay
    )
    add_test(
      NAME xtbloom.gfn2.scc_trace_unrestricted_mixer_replay
      COMMAND ${Python3_EXECUTABLE}
              ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/xtbloom_scc_cpu_trace.py
              --mixer $<TARGET_FILE:xtbloom_scc_trace_mixer>
              --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
              --work-dir ${CMAKE_CURRENT_BINARY_DIR}/scc-trace-unrestricted-mixer
              --mixer-cases oh_radical
    )
    xtbloom_configure_linalg_runtime_test(
      xtbloom_scc_trace_mixer xtbloom.gfn2.scc_trace_unrestricted_mixer_replay
    )

    # Issue #343 Phase 1: experimental SCC subspace-reuse diagnostic. Builds
    # the internal capture executable that drives the production CPU driver
    # and streams per-iteration H, C, eps, occupations, density, and timing.
    # tools/scc_reuse/scc_reuse_analyze.py consumes the stream. This is
    # investigation tooling, not a conformance gate.
    add_executable(xtbloom_scc_reuse_capture
      tools/scc_reuse/scc_reuse_capture.cpp
    )
    target_link_libraries(xtbloom_scc_reuse_capture PRIVATE
      xtbloom_gfn2_cpu
      Threads::Threads
    )
    target_compile_features(xtbloom_scc_reuse_capture PRIVATE cxx_std_17)
    # The analyzer intentionally uses NumPy for stable dense linear algebra.
    # A bare native CMake environment guarantees only an interpreter, so never
    # register a test that will fail later merely because that interpreter has
    # no project dependencies. Required CI selects the locked project Python.
    execute_process(
      COMMAND "${Python3_EXECUTABLE}" -c "import numpy"
      RESULT_VARIABLE xtbloom_scc_reuse_numpy_status
      OUTPUT_QUIET
      ERROR_QUIET
    )
    if(xtbloom_scc_reuse_numpy_status EQUAL 0)
      add_test(
        NAME xtbloom.gfn2.scc_reuse_smoke
        COMMAND ${Python3_EXECUTABLE}
                ${CMAKE_CURRENT_SOURCE_DIR}/tools/scc_reuse/smoke_test.py
                --capture $<TARGET_FILE:xtbloom_scc_reuse_capture>
                --spec ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces/specs/h3_plus.spec
                --analyzer ${CMAKE_CURRENT_SOURCE_DIR}/tools/scc_reuse/scc_reuse_analyze.py
      )
      xtbloom_configure_linalg_runtime_test(
        xtbloom_scc_reuse_capture xtbloom.gfn2.scc_reuse_smoke
      )
    else()
      message(STATUS
        "Skipping xtbloom.gfn2.scc_reuse_smoke: ${Python3_EXECUTABLE} cannot import NumPy"
      )
    endif()
  endif()

  add_executable(xtbloom_parameters_header_test tests/parameters/gfn2_header_test.cpp)
  target_include_directories(xtbloom_parameters_header_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
  target_compile_features(xtbloom_parameters_header_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.parameters.header COMMAND xtbloom_parameters_header_test)

  add_executable(xtbloom_gfn1_parameters_header_test
    tests/parameters/gfn1_header_test.cpp
  )
  target_include_directories(xtbloom_gfn1_parameters_header_test
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
  )
  target_compile_features(xtbloom_gfn1_parameters_header_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.parameters.gfn1_header
    COMMAND xtbloom_gfn1_parameters_header_test
  )

  add_executable(xtbloom_gfn1_d3_parameters_header_test
    tests/parameters/gfn1_d3_header_test.cpp
  )
  target_include_directories(xtbloom_gfn1_d3_parameters_header_test
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
  )
  target_compile_features(xtbloom_gfn1_d3_parameters_header_test PRIVATE cxx_std_17)
  add_test(NAME xtbloom.parameters.gfn1_d3_header
    COMMAND xtbloom_gfn1_d3_parameters_header_test
  )

  add_test(
    NAME xtbloom.parameters.generated
    COMMAND ${Python3_EXECUTABLE} tools/parameters/generate_gfn2.py --check
  )
  add_test(
    NAME xtbloom.parameters.gfn1_generated
    COMMAND ${Python3_EXECUTABLE} tools/parameters/generate_gfn1.py --check
  )
  add_test(
    NAME xtbloom.parameters.gfn1_d3_generated
    COMMAND ${Python3_EXECUTABLE} tools/parameters/generate_gfn1_d3.py --check
  )
  add_test(
    NAME xtbloom.parameters.python
    COMMAND ${Python3_EXECUTABLE} -m unittest discover
            -s tests/parameters -p "test_*.py" -v
  )
  add_test(
    NAME xtbloom.conformance.manifest
    COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_conformance.py check
  )
  add_test(
    NAME xtbloom.conformance.gfn1_manifest
    COMMAND ${Python3_EXECUTABLE} tools/conformance/gfn1_conformance.py check
  )
  add_test(
    NAME xtbloom.conformance.tmacl_evidence
    COMMAND ${Python3_EXECUTABLE} tools/conformance/tmacl_evidence.py
  )
  add_test(
    NAME xtbloom.conformance.python
    COMMAND ${Python3_EXECUTABLE} -m unittest discover
            -s tests/conformance -p "test_*.py" -v
  )
  if(BUILD_SHARED_LIBS AND XTBLOOM_CPU_LINALG_RUNTIME)
    add_test(
      NAME xtbloom.conformance.public_cpu
      COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_public_api.py
              --library $<TARGET_FILE:xtbloom> --backend cpu --memory-mode host
              --actual-dir ${CMAKE_CURRENT_BINARY_DIR}/conformance/public-api
    )
    set_tests_properties(xtbloom.conformance.public_cpu PROPERTIES
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
      ENVIRONMENT_MODIFICATION
        "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
      LABELS "conformance;public-api"
    )
    add_test(
      NAME xtbloom.conformance.gfn1_public_cpu
      COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_public_api.py
              --manifest ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/gfn1/manifest.json
              --library $<TARGET_FILE:xtbloom> --backend cpu --memory-mode host
              --actual-dir ${CMAKE_CURRENT_BINARY_DIR}/conformance/gfn1-public-api
    )
    set_tests_properties(xtbloom.conformance.gfn1_public_cpu PROPERTIES
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
      ENVIRONMENT_MODIFICATION
        "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
      LABELS "conformance;public-api;gfn1"
    )
    add_test(
      NAME xtbloom.conformance.gfn1_spin2_public_cpu
      COMMAND ${Python3_EXECUTABLE} tools/conformance/gfn1_public_spin2.py
              --library $<TARGET_FILE:xtbloom>
    )
    set_tests_properties(xtbloom.conformance.gfn1_spin2_public_cpu PROPERTIES
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
      ENVIRONMENT_MODIFICATION
        "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
      LABELS "conformance;public-api;gfn1"
    )
    add_test(
      NAME xtbloom.conformance.invariants_cpu
      COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_invariants.py
              --library $<TARGET_FILE:xtbloom> --backend cpu --memory-mode host
    )
    set_tests_properties(xtbloom.conformance.invariants_cpu PROPERTIES
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
      ENVIRONMENT_MODIFICATION
        "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
      LABELS "conformance;public-api"
    )
    add_test(
      NAME xtbloom.conformance.gfn1_invariants_cpu
      COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_invariants.py
              --manifest ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/gfn1/manifest.json
              --library $<TARGET_FILE:xtbloom> --backend cpu --memory-mode host
    )
    set_tests_properties(xtbloom.conformance.gfn1_invariants_cpu PROPERTIES
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
      ENVIRONMENT_MODIFICATION
        "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
      LABELS "conformance;public-api;gfn1"
    )
    if(XTBLOOM_HAS_CUDA)
      foreach(memory_mode IN ITEMS host device mixed)
        if(memory_mode STREQUAL "host")
          set(gfn1_cuda_suffix "")
        else()
          set(gfn1_cuda_suffix "_${memory_mode}")
        endif()
        add_test(
          NAME xtbloom.conformance.gfn1_public_cuda${gfn1_cuda_suffix}
          COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_public_api.py
                  --manifest ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/gfn1/manifest.json
                  --library $<TARGET_FILE:xtbloom> --backend cuda
                  --memory-mode ${memory_mode}
                  --actual-dir
                  ${CMAKE_CURRENT_BINARY_DIR}/conformance/gfn1-public-api-cuda-${memory_mode}
                  --skip-backend-unavailable
        )
        set_tests_properties(xtbloom.conformance.gfn1_public_cuda${gfn1_cuda_suffix} PROPERTIES
          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
          ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
          ENVIRONMENT_MODIFICATION
            "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
          LABELS "conformance;public-api;gfn1;cuda"
          SKIP_RETURN_CODE 77
        )
        add_test(
          NAME xtbloom.conformance.gfn1_invariants_cuda${gfn1_cuda_suffix}
          COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_invariants.py
                  --manifest ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/gfn1/manifest.json
                  --library $<TARGET_FILE:xtbloom> --backend cuda
                  --memory-mode ${memory_mode}
                  --skip-backend-unavailable
        )
        set_tests_properties(xtbloom.conformance.gfn1_invariants_cuda${gfn1_cuda_suffix} PROPERTIES
          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
          ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
          ENVIRONMENT_MODIFICATION
            "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
          LABELS "conformance;public-api;gfn1;cuda"
          SKIP_RETURN_CODE 77
        )
        add_test(
          NAME xtbloom.conformance.gfn1_spin2_public_cuda${gfn1_cuda_suffix}
          COMMAND ${Python3_EXECUTABLE} tools/conformance/gfn1_public_spin2.py
                  --library $<TARGET_FILE:xtbloom> --backend cuda
                  --memory-mode ${memory_mode}
                  --skip-backend-unavailable
        )
        set_tests_properties(xtbloom.conformance.gfn1_spin2_public_cuda${gfn1_cuda_suffix} PROPERTIES
          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
          ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
          ENVIRONMENT_MODIFICATION
            "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
          LABELS "conformance;public-api;gfn1;cuda"
          SKIP_RETURN_CODE 77
        )
      endforeach()
      unset(gfn1_cuda_suffix)
      add_test(
        NAME xtbloom.conformance.public_cuda
        COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_public_api.py
                --library $<TARGET_FILE:xtbloom> --backend cuda --memory-mode host
                --actual-dir ${CMAKE_CURRENT_BINARY_DIR}/conformance/public-api
                --skip-backend-unavailable
      )
      set_tests_properties(xtbloom.conformance.public_cuda PROPERTIES
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
        ENVIRONMENT_MODIFICATION
          "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
        LABELS "conformance;public-api"
        SKIP_RETURN_CODE 77
      )
      add_test(
        NAME xtbloom.conformance.invariants_cuda
        COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_invariants.py
                --library $<TARGET_FILE:xtbloom> --backend cuda --memory-mode host
                --skip-backend-unavailable
      )
      set_tests_properties(xtbloom.conformance.invariants_cuda PROPERTIES
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
        ENVIRONMENT_MODIFICATION
          "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
        LABELS "conformance;public-api"
        SKIP_RETURN_CODE 77
      )
      foreach(memory_mode IN ITEMS device mixed)
        add_test(
          NAME xtbloom.conformance.public_cuda_${memory_mode}
          COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_public_api.py
                  --library $<TARGET_FILE:xtbloom> --backend cuda
                  --memory-mode ${memory_mode}
                  --actual-dir ${CMAKE_CURRENT_BINARY_DIR}/conformance/public-api
                  --skip-backend-unavailable
        )
        set_tests_properties(xtbloom.conformance.public_cuda_${memory_mode} PROPERTIES
          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
          ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
          ENVIRONMENT_MODIFICATION
            "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
          LABELS "conformance;public-api"
          SKIP_RETURN_CODE 77
        )
        add_test(
          NAME xtbloom.conformance.invariants_cuda_${memory_mode}
          COMMAND ${Python3_EXECUTABLE} tools/conformance/xtbloom_invariants.py
                  --library $<TARGET_FILE:xtbloom> --backend cuda
                  --memory-mode ${memory_mode}
                  --skip-backend-unavailable
        )
        set_tests_properties(xtbloom.conformance.invariants_cuda_${memory_mode} PROPERTIES
          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
          ENVIRONMENT "MKL_INTERFACE_LAYER=LP64;MKL_THREADING_LAYER=SEQUENTIAL"
          ENVIRONMENT_MODIFICATION
            "${XTBLOOM_RUNTIME_LIBRARY_PATH_VARIABLE}=path_list_prepend:${XTBLOOM_CPU_LINALG_DIRECTORY}"
          LABELS "conformance;public-api"
          SKIP_RETURN_CODE 77
        )
      endforeach()
    endif()
  endif()
  add_test(
    NAME xtbloom.licensing
    COMMAND ${Python3_EXECUTABLE} tools/licensing/check_licenses.py
            --source-root ${CMAKE_CURRENT_SOURCE_DIR}
  )
  add_test(
    NAME xtbloom.licensing_unit
    COMMAND ${Python3_EXECUTABLE} -m unittest discover
            -s tests/licensing -p "test_*.py" -v
  )
  add_test(
    NAME xtbloom.oracle.tblite_observer_patch
    COMMAND ${Python3_EXECUTABLE} -m unittest discover
            -s tests/oracle -p "test_*.py" -v
  )
  add_test(
    NAME xtbloom.oracle.scc_corpus
    COMMAND ${Python3_EXECUTABLE}
            ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/generate_scc_corpus.py
            --source-root ${CMAKE_CURRENT_SOURCE_DIR}
            --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
            --check
  )
  set_tests_properties(xtbloom.oracle.scc_corpus PROPERTIES
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    LABELS "conformance;oracle"
  )
  add_test(
    NAME xtbloom.oracle.scc_corpus_v2
    COMMAND ${Python3_EXECUTABLE}
            ${CMAKE_CURRENT_SOURCE_DIR}/tools/oracle/tblite_scc_trace/generate_unrestricted_scc_corpus.py
            --source-root ${CMAKE_CURRENT_SOURCE_DIR}
            --corpus-dir ${CMAKE_CURRENT_SOURCE_DIR}/data/conformance/scc-traces
            --check
  )
  set_tests_properties(xtbloom.oracle.scc_corpus_v2 PROPERTIES
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    LABELS "conformance;oracle"
  )
  set_tests_properties(
    xtbloom.parameters.generated
    xtbloom.parameters.gfn1_generated
    xtbloom.parameters.gfn1_d3_generated
    xtbloom.parameters.python
    xtbloom.licensing
    xtbloom.licensing_unit
    xtbloom.conformance.manifest
    xtbloom.conformance.gfn1_manifest
    xtbloom.conformance.tmacl_evidence
    xtbloom.conformance.python
    xtbloom.oracle.tblite_observer_patch
    PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  )
endif()

install(TARGETS xtbloom EXPORT xtbloomTargets)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${XTBLOOM_GENERATED_INCLUDE_DIR}/xtbloom/version.h
  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xtbloom
)
# Legal material is part of the installed SDK contract. Keep project terms,
# third-party notices, and machine-readable provenance together so native
# consumers receive the same audit trail as source and Python distributions.
install(FILES LICENSE CUDA_MKL_LINKING_EXCEPTION THIRD_PARTY_NOTICES.md
  DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/xtbloom
)
install(DIRECTORY LICENSES/
  DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/xtbloom/third-party
  # Eigen is acquired and compiled only by the browser target. Its retained
  # legal records belong to the source/sdist and Pages boundaries, not native
  # SDK installs or Python wheels.
  PATTERN "eigen" EXCLUDE
)
install(FILES
  data/parameters/manifest.json
  data/parameters/sto_manifest.json
  data/parameters/spin_manifest.json
  data/parameters/d4_manifest.json
  data/parameters/gfn1_manifest.json
  data/parameters/gfn1_d3_manifest.json
  data/parameters/gfn1_legacy_sto_manifest.json
  data/parameters/mctc_manifest.json
  cmake/3rdparty/implib_manifest.json
  cmake/3rdparty/scipy_openblas32_manifest.json
  cmake/3rdparty/pyodide_openblas_manifest.json
  DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/xtbloom/provenance
)
install(FILES cmake/3rdparty/torch-stable/manifest.json
  DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/xtbloom/provenance
  RENAME torch_stable_manifest.json
)
install(FILES data/parameters/d4.NOTICE
  DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/xtbloom/third-party/d4
)
install(DIRECTORY data/parameters/licenses/
  DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/xtbloom/third-party/d4
)
install(EXPORT xtbloomTargets
  FILE xtbloomTargets.cmake
  NAMESPACE xtbloom::
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xtbloom
)

# A CUDA-enabled build records the compatible major version of the CUDA
# runtime it dlopens so the installed CMake config can warn consumers that the
# runtime they have may be incompatible (the library itself no longer links
# against the toolkit; see src/runtime/cuda_dlopen.c).
if(NOT XTBLOOM_HAS_CUDA)
  set(XTBLOOM_CUDA_TOOLKIT_MAJOR 0)
  set(XTBLOOM_CUDA_TOOLKIT_MINOR 0)
endif()
configure_package_config_file(
  cmake/xtbloomConfig.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/xtbloomConfig.cmake
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xtbloom
)
write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/xtbloomConfigVersion.cmake
  VERSION ${PROJECT_VERSION}
  COMPATIBILITY SameMajorVersion
)
install(FILES
  ${CMAKE_CURRENT_BINARY_DIR}/xtbloomConfig.cmake
  ${CMAKE_CURRENT_BINARY_DIR}/xtbloomConfigVersion.cmake
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xtbloom
)

message(STATUS "xtbloom product version: ${XTBLOOM_VERSION_FULL}")
message(STATUS "xtbloom CUDA backend: ${XTBLOOM_HAS_CUDA}")

if(XTBLOOM_BUILD_WEB_DEMO)
  add_subdirectory(web)
endif()
