From d9a6036a0719d4dc9795389d98d0bd0080e6b0e5 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sun, 7 Jun 2026 12:02:23 -0500 Subject: [PATCH] ENH: Modernize CUDA wiring and auto-detect default VKFFT backend * itk-module-init.cmake: replace removed find_package(CUDA) with enable_language(CUDA) + find_package(CUDAToolkit). Auto-pick a default VKFFT_BACKEND when not set: CUDA if a CUDA compiler is found, Metal if the Apple Metal/Foundation/QuartzCore frameworks probe successfully, otherwise OpenCL. * itk-module-init.cmake: handle VKFFT_BACKEND=5 (Metal) by locating the required Apple frameworks early. * src/CMakeLists.txt: link CUDA::cuda_driver instead of the bare 'cuda' name so conda/cross toolchains that do not search /usr/lib/x86_64-linux-gnu resolve libcuda. * CMakeLists.txt: pull the vendored VkFFT sources with EXCLUDE_FROM_ALL so the upstream VkFFT_TestSuite benchmark (which hard-requires CL/cl.h and vulkan/vulkan.h) is not built unless explicitly requested. Assisted-by: Claude Code (claude-opus-4-7) -- CMake modernization and Metal auto-detect branch. --- CMakeLists.txt | 6 +++++- itk-module-init.cmake | 37 ++++++++++++++++++++++++++++++++++--- src/CMakeLists.txt | 2 +- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd698f3f..344aef41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,11 @@ if(BUILD_VKFFT) GIT_REPOSITORY ${VkFFT_GIT_REPOSITORY} GIT_TAG ${VkFFT_GIT_TAG} ) - FetchContent_MakeAvailable(vkfft_lib) + FetchContent_GetProperties(vkfft_lib) + if(NOT vkfft_lib_POPULATED) + FetchContent_Populate(vkfft_lib) + add_subdirectory(${vkfft_lib_SOURCE_DIR} ${vkfft_lib_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() set(vkfft_INCLUDE_DIR "${vkfft_lib_SOURCE_DIR}/vkFFT") else() diff --git a/itk-module-init.cmake b/itk-module-init.cmake index 8975ddc2..ac65fbe3 100644 --- a/itk-module-init.cmake +++ b/itk-module-init.cmake @@ -1,10 +1,34 @@ # # Find the packages required by this module # -set(VKFFT_BACKEND 3 CACHE STRING "1 - CUDA, 3 - OpenCL, 4 - Level Zero, 5 - Metal") +if(NOT DEFINED VKFFT_BACKEND) + include(CheckLanguage) + check_language(CUDA) + set(_vkfft_have_metal FALSE) + if(APPLE) + find_library(_vkfft_metal_probe Metal) + find_library(_vkfft_foundation_probe Foundation) + find_library(_vkfft_quartzcore_probe QuartzCore) + if(_vkfft_metal_probe AND _vkfft_foundation_probe AND _vkfft_quartzcore_probe) + set(_vkfft_have_metal TRUE) + endif() + endif() + if(CMAKE_CUDA_COMPILER) + set(_vkfft_backend_default 1) + elseif(_vkfft_have_metal) + set(_vkfft_backend_default 5) + else() + set(_vkfft_backend_default 3) + endif() +else() + set(_vkfft_backend_default ${VKFFT_BACKEND}) +endif() +set(VKFFT_BACKEND ${_vkfft_backend_default} CACHE STRING "1 - CUDA, 3 - OpenCL, 4 - Level Zero, 5 - Metal") if(${VKFFT_BACKEND} EQUAL 1) - find_package(CUDA 9.0 REQUIRED) - find_library(CUDA_NVRTC_LIB libnvrtc nvrtc HINTS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64" "/usr/lib64" "/usr/local/cuda/lib64") + enable_language(CUDA) + find_package(CUDAToolkit REQUIRED) + set(CUDA_LIBRARIES CUDA::cudart) + find_library(CUDA_NVRTC_LIB libnvrtc nvrtc HINTS "${CUDAToolkit_LIBRARY_DIR}" "/usr/lib64" "/usr/local/cuda/lib64") elseif(${VKFFT_BACKEND} EQUAL 3) find_package(OpenCL REQUIRED) elseif(${VKFFT_BACKEND} EQUAL 4) @@ -19,4 +43,11 @@ elseif(${VKFFT_BACKEND} EQUAL 4) if(NOT LevelZero_INCLUDE_DIR OR NOT LevelZero_LIBRARY) message(FATAL_ERROR "VKFFT_BACKEND=4 (Level Zero) requires the oneAPI Level Zero loader (ze_loader) and headers (level_zero/ze_api.h).") endif() +elseif(${VKFFT_BACKEND} EQUAL 5) + if(NOT APPLE) + message(FATAL_ERROR "VKFFT_BACKEND=5 (Metal) requires Apple platforms (macOS/iOS, including Apple Silicon).") + endif() + find_library(METAL_FRAMEWORK Metal REQUIRED) + find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED) + find_library(QUARTZCORE_FRAMEWORK QuartzCore REQUIRED) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5b97549..08ea03ae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,7 +7,7 @@ set(VkFFTBackend_SRCS itk_module_add_library(VkFFTBackend ${VkFFTBackend_SRCS}) if(${VKFFT_BACKEND} EQUAL 1) - target_link_libraries(VkFFTBackend PUBLIC ${CUDA_LIBRARIES} cuda ${CUDA_NVRTC_LIB} VkFFT half) + target_link_libraries(VkFFTBackend PUBLIC ${CUDA_LIBRARIES} CUDA::cuda_driver ${CUDA_NVRTC_LIB} VkFFT half) if(MSVC) else() set_source_files_properties(itkVkCommon.cpp PROPERTIES LANGUAGE CUDA)