Skip to content

BUG: FFTW follow-ups to #6999: oneMKL via MKLConfig, cuFFTW export, scoped FindFFTW, tests - #7020

Open
hjmjohnson wants to merge 7 commits into
InsightSoftwareConsortium:mainfrom
hjmjohnson:onemkl-fftw-fixes
Open

hjmjohnson wants to merge 7 commits into
InsightSoftwareConsortium:mainfrom
hjmjohnson:onemkl-fftw-fixes

Conversation

@hjmjohnson

@hjmjohnson hjmjohnson commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Follow-ups to #6999, tracked in #7027: oneMKL found through its own MKLConfig.cmake (MKL::MKL, per @blowekamp's suggestion), cuFFTW and oneMKL paths passed to downstream projects, FindFFTW variables kept out of those projects, an optimized bundled FFTW in Debug builds that keeps user flags such as sanitizers, and a GoogleTest for the ITKFFTW module.

Seven commits on main.

Commit Fixes
BUG: Find oneMKL 2024+ layout and export MKLROOT to FFTW consumers oneMKL 2024+ lib/ layout; consumers losing a custom MKLROOT (greptile P1 on #6999); system fftw3.h shadowing oneMKL's
BUG: Build bundled FFTW with release optimization in all configurations a Debug ITK compiled FFTW with -g and no optimization; only optimization flags are replaced, so -g and sanitizer flags are kept (greptile P2)
BUG: Add each module to ITKTargets_MODULES only once most modules listed twice
ENH: Add a GoogleTest for the ITKFFTW module the module had no test of its own
BUG: Export cuFFTW library paths to FFTW consumers consumers losing custom cuFFTW paths (greptile P1 on #6999)
ENH: Keep FindFFTW variables out of projects that find ITK FFTW_FOUND, FFTW_INCLUDE, FFTW{D,F}_LIBRARIES set in the consumer's scope; adds a migration guide entry
ENH: Find oneMKL through its MKLConfig.cmake package replaces the hand-written oneMKL library list, link group, MKL_ILP64 define, and include search with MKL::MKL (oneMKL 2021.3+); passes MKL_DIR to consumers; migration guide and build docs updated
oneMKL details
  1. oneMKL 2024+ installs libraries in MKLROOT/lib; FindFFTW searched only lib/intel64 and failed with libmkl_intel_ilp64.a not found. Defaults pointed at the retired compilers_and_libraries paths.
  2. With ITK_USE_SYSTEM_FFTW, the exported ITKFFTW module re-runs FindFFTW downstream but did not carry MKLROOT, so consumers fell back to the hard-coded default. ITK's MKLROOT now seeds the app's cache, the same way ENH: Build FFTW as an ITKFFTW third-party module with FetchContent #6999 seeds the FFTW library paths, unless the app sets MKLROOT.
  3. find_path() searches system directories before MKLROOT, so a system FFTW fftw3.h (/usr/include, from libfftw3-dev) was compiled against oneMKL's libraries. On reconfigure, MKLROOT was then derived from that path as /, and / was exported to consumers. Items 1 and 3 also affect main before ENH: Build FFTW as an ITKFFTW third-party module with FetchContent #6999.
  4. The 32-bit branch checked a misspelled WIN variable; oneMKL is 64-bit only, so it is now an error.
Why the FindFFTW variables are kept local rather than renamed

With a system FFTW the exported code runs FindFFTW in the scope of the app's find_package(ITK) (module loading uses macros), so every result variable reached the app. No ITK code reads them, and a search of 300 downstream repositories (the 47 projects in the downstream build forest, including RTK, plus 253 Slicer extensions) found no user. Renaming to FFTW_INCLUDE_DIRS/FFTW_LIBRARIES would collide with apps' own finders: Plastimatch sets FFTW_LIBRARIES before find_package(ITK). The search now runs inside a function, so only the FFTW::Double/FFTW::Float imported targets reach the app; the input hints (FFTW_INCLUDE_PATH, FFTW{D,F}_BASE_LIB, ...) are unchanged. Discussion: #6999 (comment).

Testing (at `b671b51`, before the patch-identical rebase onto main)

macOS arm64 (Apple clang, CMake 3.26), minimal ITK with Module_ITKFFT:

Case Result
Bundled, shared Release 91/91 FFT tests; 93/93 with Module_ITKFFTW=ON (new FFTWModule tests pass, double and float); install has only libitkfftw3* and fftw3.h; 6 consumers run
Bundled, static Debug 91/91; FFTW compiled with -O3 (no -g); 4 consumers run
Homebrew system FFTW 91/91; new GoogleTest 2/2; consumers including one with its own FindFFTW.cmake run
Variable check, system FFTW consumer that sets FFTW_LIBRARIES before find_package(ITK): before this PR 6 FindFFTW variables leak; now none leak, its value is kept, FFTW::Double exists, and it builds and runs
cuFFTW paths (fake cuFFTW outside default paths, configure only) before: consumer fails Could NOT find FFTW; now: consumer finds FFTW::Float from the exported paths
No precision selected configure fails with the expected message

Linux x86_64 (GCC 13.3, CMake 4.2):

Case Result
oneMKL 2026.1, static 91/91; consumers with no MKLROOT, an override, CMP0126 OLD, and the variable check all run
System FFTW (libfftw3-dev), renamed libraries, no threads library 91/91; consumers run; renamed library paths reused downstream
Bundled shared Release, static Debug 91/91; Debug FFTW compiled with -O3; consumers run

Shared install-tree consumers on Linux need LD_LIBRARY_PATH because ITK sets no install RPATH (same on main, tracked in #7027).

Windows: @dzenanz tested the oneMKL commit with MSVC 2022 (92/92, MKLROOT from the environment as a backslash path) in #6999 (comment). The release-flags commit has not been re-run on Windows Debug yet.

Testing of the last two changes (head 8441147)

MKLConfig.cmake path, Linux x86_64 (GCC 13.3, CMake 4.2, oneMKL 2026.1, static, minimal ITK with Module_ITKFFT):

Case Result
-DMKLROOT MKL_DIR found; 0 warnings; 91/91 FFT tests; install exports MKL_DIR unless the app sets MKLROOT
Consumers of that install (no MKLROOT, MKLROOT override, CMP0126 OLD, variable check) all configure, build, and run
MKLROOT only in the environment 91/91
MKL_DIR only 91/91
System FFTW, no MKL 91/91
ITK with MKL_LINK=dynamic 91/91; consumers inherit dynamic (3 libmkl shared libraries), -DMKL_LINK=static in the app overrides it, an app setting MKLROOT still gets dynamic

Bundled FFTW flags, macOS arm64, Debug: with CMAKE_C_FLAGS_DEBUG set to -g -fsanitize=address, then -g -fno-omit-frame-pointer, FFTW objects keep those flags plus -O3, with no -O0; FFT tests 94/94. (The sanitizer run itself deadlocks inside the pixi clang ASan runtime at startup on this macOS, before any ITK code runs, so the second flag was used to run the tests.) Linux GCC 13.3, Debug with -g -fno-omit-frame-pointer -I"/tmp/dbg hdrs": the quoted path reaches FFTW intact, with -O3 and no -O0; 93/93. MSVC flag removal (/Od /RTC1 /Zi /Ob0 -> /Zi) checked only with a cmake -P script.

AI assistance

Prepared with Claude Code at @hjmjohnson's direction: reproduced the failures, wrote the changes, and ran the tests above on macOS and a Linux host.

@github-actions github-actions Bot added type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Filtering Issues affecting the Filtering module area:ThirdParty Issues affecting the ThirdParty module area:Documentation Issues affecting the Documentation module labels Oct 27, 2026
@hjmjohnson

Copy link
Copy Markdown
Member Author

Rebased onto #6999's new head b5c5da0. The oneMKL commit conflicted with #6999's rewritten export block, so this force-push combines the rebase with a merge of that block. MKLROOT now seeds the app's cache, the same way #6999 seeds the FFTW library paths, rather than being set as a normal variable and unset afterward. The rest of the commit is unchanged. Retest results are in the PR description.

@blowekamp

Copy link
Copy Markdown
Member

Would it be easier to just drop MKL specialization in FindFFTW? Can we drop support for the older CMake configuration variables, and just use MKL's exported targets from its package?

Moving to the modern CMake targets has simplified much of the code by dropping the redeious and frequently incorrect management of these variables.

https://www.intel.com/content/www/us/en/docs/onemkl/developer-guide-macos/2023-0/cmake-config-for-onemkl.html

P.S. Perhaps the variables could be dropped with FFTW too?

@hjmjohnson hjmjohnson changed the title BUG: Find oneMKL 2024+ layout and export MKLROOT to FFTW consumers BUG: FFTW follow-ups to #6999: oneMKL, cuFFTW and MKLROOT export, scoped FindFFTW, tests Oct 28, 2026
@github-actions github-actions Bot removed the area:Filtering Issues affecting the Filtering module label Oct 29, 2026
@hjmjohnson
hjmjohnson marked this pull request as ready for review October 29, 2026 15:29
@hjmjohnson

hjmjohnson commented Oct 29, 2026 •

Copy link
Copy Markdown
Member Author

@blowekamp Good idea. It is now in this PR as the last commit, ENH: Find oneMKL through its MKLConfig.cmake package (MKL::MKL, oneMKL 2021.3+), tracked in #7027. FFTW itself has no usable CMake targets to switch to (Homebrew's config defines none, Ubuntu ships only pkg-config), so FindFFTW stays for FFTW.

@hjmjohnson
hjmjohnson marked this pull request as draft October 29, 2026 15:34
@greptile-apps

greptile-apps Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no new actionable issue remains.

Summary

Updates FFTW discovery, exports, bundled build flags, and tests.

  • ITK finds oneMKL through its own package and uses its FFTW interface.
  • Downstream apps keep the FFTW backend settings they need without inheriting finder variables.
  • Bundled FFTW keeps release optimization flags in every build configuration.
  • ITKFFTW tests now check impulse transforms at both supported precisions.
  • Module exports list each module only once.

The three supplied, unnumbered previous findings are addressed in the current code. No new actionable issue was found.

Reviews (4) · Last reviewed commit: "ENH: Find oneMKL through its MKLConfig.c..." · Reviewed by Greptile

@hjmjohnson
hjmjohnson force-pushed the onemkl-fftw-fixes branch 3 times, most recently from aa4c748 to 92f8755 Compare October 29, 2026 16:15
@hjmjohnson hjmjohnson changed the title BUG: FFTW follow-ups to #6999: oneMKL, cuFFTW and MKLROOT export, scoped FindFFTW, tests BUG: FFTW follow-ups to #6999: oneMKL via MKLConfig, cuFFTW export, scoped FindFFTW, tests Oct 29, 2026
@hjmjohnson

Copy link
Copy Markdown
Member Author

Force-push 6de1618..dd17871 is a plain rebase on main; dd17871..92f8755 is content only: the MKLConfig commit plus the greptile P2 fix folded into the release-flags commit.

@hjmjohnson

Copy link
Copy Markdown
Member Author

@greptileai review this draft before I make it official

Comment thread Modules/ThirdParty/FFTW/CMakeLists.txt Resolved
@hjmjohnson

Copy link
Copy Markdown
Member Author

@greptileai review this draft before I make it official

@hjmjohnson
hjmjohnson marked this pull request as ready for review October 29, 2026 19:29
@dzenanz

dzenanz commented Oct 30, 2026

Copy link
Copy Markdown
Member

Windows retest of #7020 at 8441147cdbe (Windows 11, MSVC 14.44 / VS 2022, CMake 4.4, ITK_USE_FFTWD=ON ITK_USE_FFTWF=ON Module_ITKFFTW=ON, ctest -R FFT)

Configuration Result
Bundled FFTW, Ninja Release 94/94
Bundled FFTW, Visual Studio 17 2022, Debug 94/94
Bundled FFTW, Visual Studio 17 2022, Release 94/94
oneMKL 2026.1 (conda-forge mkl-devel/mkl-static) via MKL_DIR 92/92, links mkl_intel_ilp64/mkl_core/mkl_sequential
System FFTW (conda-forge fftw 3.3.11, no separate threads libs) 94/94
cuFFTW (CUDA 13.2) configure OK, build fails, see below

The 94 includes the two new FFTWModule.* GTests. In the multi-config build, the bundled FFTW gets /O2 in Debug while keeping the debug CRT. The system FFTW threads-library regression I reported earlier is fixed.

A downstream project that links only ITK::ITKFFTModule and calls the FFTW API directly builds and runs against the bundled (build and install trees), oneMKL (without MKLROOT), and system FFTW install trees. None of FFTW_INCLUDE, FFTWD_LIB, FFTW_FOUND or MKLROOT leaks into the consumer's scope.

cuFFTW does not build, but the cause is older than this PR. itkFFTWComplexToComplex1DFFTImageFilter.hxx and nine other FFT headers include fftw3.h unconditionally, and CUDA ships only cufftw.h. Base 2e353bf3975 has the same includes. The exported ITKFFTW.cmake does carry ITK_USE_CUFFTW, CUFFTW_INCLUDE_PATH, CUFFT_LIB and CUFFTW_LIB. FindFFTW does not find the libraries on Windows without hints, because CUDA puts them in lib/x64.

Not tested: Python wrapping, the ITKFFTW GTest without explicit Module_ITKFFTW=ON (with ITK_BUILD_DEFAULT_MODULES=OFF the module is enabled only as a dependency, so its tests are not built).

AI assistance

Builds, tests, and this summary were prepared with Claude Code and reviewed by me.

oneMKL 2024 and later install libraries in MKLROOT/lib, so the
lib/intel64-only search failed with "libmkl_intel_ilp64.a not found".
Search both directories, and default MKLROOT to the oneAPI install
paths instead of the retired compilers_and_libraries locations.

find_path() searched system directories before MKLROOT, so a system
FFTW fftw3.h (e.g. /usr/include from libfftw3-dev) was used with the
oneMKL libraries, and a reconfigure then derived MKLROOT as "/". Search
only MKLROOT/include/fftw, and drop a cached path outside it.

With ITK_USE_SYSTEM_FFTW, a downstream find_package(ITK) re-runs
FindFFTW, which lost a custom MKLROOT. Seed the app's cache with ITK's
MKLROOT, as is done for the FFTW library paths, unless the app sets
MKLROOT. Honor an existing MKLROOT variable and keep it set under
CMP0126 OLD.

oneMKL is 64-bit only, so the ia32 branch (with its misspelled WIN
check) becomes an error. Rename MKL to oneMKL in the option, comments,
and build docs.
The removed ExternalProject forced FFTW_BUILD_TYPE=Release. As an
add_subdirectory, FFTW inherited the ITK build type, so a Debug ITK
compiled FFTW with -g and no optimization. A debuggable FFTW is of no
use to ITK and makes every FFT in a Debug build far slower.
The interface-library registration also ran for modules already added
when their src directory was processed, listing 93 of 133 modules
twice. Append only modules not yet in the list.
The ITKFFTW module had no test of its own. One GoogleTest driver now
checks each enabled precision through ITK::ITKFFTWModule: an impulse
must transform to a flat spectrum with a threaded plan. The test is
skipped for oneMKL and cuFFTW, which provide their own FFTW interface.
With ITK_USE_CUFFTW and ITK_USE_SYSTEM_FFTW, a downstream
find_package(ITK) re-runs FindFFTW but received none of the paths ITK
found, so a cuFFTW outside the default search paths was not found and
the app failed to configure.

Seed the app's cache with CUFFTW_INCLUDE_PATH, CUFFT_LIB, and
CUFFTW_LIB, as is done for the FFTW and oneMKL paths. Cache entries the
app already set are kept.
With a system FFTW, the exported ITKFFTW code runs FindFFTW in the
scope of the app's find_package(ITK), so FFTW_FOUND, FFTW_INCLUDE,
FFTW{D,F}_LIBRARIES, ITK_USE_MKL, and ITK_USE_CUFFTW were set in the
app and could overwrite its own FFTW variables.

Run the search inside a function. Imported targets do not follow
function scope, so the FFTW::Double and FFTW::Float targets that
ITK::ITKFFTWModule links still reach the app, while the variables and
the CMAKE_MODULE_PATH change stay local. No ITK code reads these
variables, and none of 300 downstream repositories checked does either.
FindFFTW listed oneMKL's static libraries, link flags, and include
paths by hand, which broke when oneMKL changed its layout. oneMKL
2021.3 and newer install MKLConfig.cmake, whose MKL::MKL target carries
the libraries, link group, and MKL_ILP64 define. Link it with the same
static, ILP64, sequential configuration, and pass MKL_DIR rather than
MKLROOT to projects that find ITK.
@hjmjohnson

Copy link
Copy Markdown
Member Author

@blowekamp: adopted for oneMKL in f3fe9fb. FindFFTW now finds it only through find_package(MKL CONFIG) and links MKL::MKL; MKLROOT is no longer read. cuFFTW was tested on Linux; Windows cuFFTW testing will be done later.

oneMKL change and limits
  • CMake/FindFFTW.cmake: removed the MKLROOT hints; MKL is found from MKL_DIR or CMAKE_PREFIX_PATH.
  • Modules/ThirdParty/FFTW/CMakeLists.txt: the exported ITKFFTW.cmake seeds MKL_DIR and the MKL_LINK, MKL_INTERFACE, and MKL_THREADING defaults only. The build guide and migration guide say MKLROOT is no longer read.
  • oneMKL was not built for this update; the machine used has none. A stub MKLConfig.cmake showed ITK configures without MKLROOT and that a project linking only ITK::ITKFFTWModule gets MKL::MKL and the include/fftw directory. Bundled and system FFTW build and pass both FFTWModule GTests. The oneMKL runs on Windows are @dzenanz's earlier results.
  • Dropping the legacy variables for plain FFTW too (the P.S.): not trivial. Homebrew's FFTW exports no CMake config targets and Ubuntu ships only pkg-config, so FindFFTW is still needed as the fallback. Trying find_package(FFTW3 CONFIG) first could be a later change.
cuFFTW on Linux (CUDA 13.3, two RTX 6000 Ada GPUs, GCC 13.3, tip f3fe9fb)
  • Configure works with ITK_USE_CUFFTW=ON once the CUDA tree is in CMAKE_PREFIX_PATH (.../targets/x86_64-linux). The exported ITKFFTW.cmake records ITK_USE_CUFFTW, CUFFTW_INCLUDE_PATH, CUFFT_LIB, and CUFFTW_LIB.
  • The ITKFFT build fails, for reasons that predate this PR. Eleven FFT headers include fftw3.h unconditionally (for example itkFFTWComplexToComplex1DFFTImageFilter.hxx:26). With a system fftw3.h installed it redeclares the types cufftw.h already defines. This is the Linux counterpart of the missing-header failure @dzenanz saw on Windows. upstream/main has the same includes and this PR does not touch them.
  • FindFFTW overwrites FFTW_INC_SEARCHPATH with a fixed list when MKL is off, so -DFFTW_INC_SEARCHPATH has no effect and the CUDA include directory is found only through CMAKE_PREFIX_PATH. Also unchanged from upstream/main.
  • No FFT tests ran with cuFFTW, because the build stops first. Windows cuFFTW testing will be done later.
AI assistance
  • Tool: Claude Code
  • Role: CMake change for oneMKL, cuFFTW test runs and summary
  • All changes were reviewed and tested locally before pushing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Documentation Issues affecting the Documentation module area:ThirdParty Issues affecting the ThirdParty module type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants