Skip to content

ENH: Build FFTW as an ITKFFTW third-party module with FetchContent - #6999

Draft
blowekamp wants to merge 1 commit into
InsightSoftwareConsortium:mainfrom
blowekamp:ENH-FFTW-third-party-module
Draft

blowekamp wants to merge 1 commit into
InsightSoftwareConsortium:mainfrom
blowekamp:ENH-FFTW-third-party-module

Conversation

@blowekamp

Copy link
Copy Markdown
Member

Build FFTW as a standard ITKFFTW third-party module using FetchContent, replacing the ExternalProject in itkExternal_FFTW.cmake. Downstream projects get FFTW through ITK::ITKFFTModule instead of FFTW-specific ITKConfig.cmake variables.

Design
  • FFTW 3.3.10 is fetched once; float and double are added as two scoped subdirectories. Both precisions share the existing SIMD defaults (FFTW_ENABLE_*).
  • FindFFTW takes COMPONENTS Double Float and defines FFTW::Double / FFTW::Float. For system FFTW the module sets ITKFFTW_EXPORT_CODE_INSTALL/BUILD (as ZLIB/TIFF do) so downstream projects re-run the finder; FFTW_ROOT is hinted to the FFTW ITK was built with unless the app sets one.
  • Bundled targets use the ITK:: namespace so no bare fftw3* compatibility targets are exported.
  • Module_ITKFFTW=ON with neither ITK_USE_FFTWD nor ITK_USE_FFTWF builds double precision.
  • ITKModuleMacros.cmake: source-less modules now register in ITKTargets_MODULES. Without this, an install whose only module is a system-library module exported no targets.
  • Removed ITK_FFTW_INCLUDE_PATH / ITK_FFTW_LIBDIR from ITKConfig.cmake (no remaining users in the tree).
AI assistance
  • Tool: GitHub Copilot CLI
  • Role: implemented the migration and the test matrix below; all changes were reviewed and run locally.
Test results

Clean builds on Linux x86_64 (GCC 13), each from an empty build directory:

  • Static, shared, and system FFTW with float+double: ctest -R 'FFT|FFTW' 94/94 passed in each.
  • Float-only and double-only ITKFFTW, FFTW disabled, and Module_ITKFFTW=ON alone (bundled and system): passed.
  • Python wrapping (float/double, 2D/3D): ITKFFT wrappers built; FFTW forward/inverse roundtrips passed in all four type/dimension combinations.
  • Downstream projects against build and install trees of static, shared, relocated, system, and custom-prefix FFTW installs, via imported targets, ITKFFTW only, UseITK, and a project defining its own fftw3* targets: 32/32 passed. Linked libraries were checked to be the expected FFTW in each case.

Not tested: Windows, macOS, MKL, cuFFTW.

PR Checklist

  • No API changes were made (or the changes have been approved)
  • No major design changes were made (or the changes have been approved)
  • Added test (or behavior not changed)
  • Updated API documentation (or API not changed)
  • Added license to new files (if any)
  • Added Python wrapping to new files (if any) as described in ITK Software Guide Section 9.5
  • Added ITK examples for all new major features (if any)

Replace the itkExternal_FFTW ExternalProject, which built the library
twice outside the module system, with a standard third-party module.
FFTW is fetched once and each precision is added as a subdirectory.

FindFFTW now provides FFTW::Double and FFTW::Float imported targets,
and the module re-runs it for downstream projects through the usual
EXPORT_CODE hooks. Remove the FFTW paths from ITKConfig.cmake.
@github-actions github-actions Bot added type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Enhancement Improvement of existing methods or implementation 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 23, 2026
@hjmjohnson

hjmjohnson commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

@blowekamp I tested this locally against its base and pushed possible fixes as separate commits on top of your head (af10dea2e1f): compare view. Same commits as draft hjmjohnson#19. Cherry-pick whatever you agree with.

  1. No precision selected should fail. Module_ITKFFTW=ON with neither ITK_USE_FFTWD nor ITK_USE_FFTWF currently builds double-precision FFTW. Suggested: a configure-time FATAL_ERROR (hjmjohnson/ITK@423199569fa).
  2. FFTW should always be optimized. The old ExternalProject forced Release; with add_subdirectory, a Debug ITK compiles FFTW with -g only. Suggested: use the release flags for every configuration (hjmjohnson/ITK@a4c89c95457).
  3. Duplicated logic. Precision is tested three times in Modules/ThirdParty/FFTW/CMakeLists.txt (precision list, components, library names) and the version string is separate from the hash (hjmjohnson/ITK@4e32bd759d0).
  4. ITKTargets_MODULES duplicates. The new append in ITKModuleMacros.cmake also runs for modules with sources, so 93 of 133 modules are listed twice. It's harmless today because the only reader checks for emptiness, but a one-line guard keeps it to source-less modules as the comment says (hjmjohnson/ITK@4bd00d1e035).
  5. GoogleTest instead of the C smoke test, one test per enabled precision (hjmjohnson/ITK@de4a7a7de97).
  6. Migration guide rather than ITK_LEGACY_REMOVE for the removed ITKConfig.cmake variables (hjmjohnson/ITK@6ed0cec6530); evidence below.

The GPL status message is fine as is.

What was tested (macOS arm64)
  • Base 46e45824cc2 vs this PR, with these configurations: bundled FFTW (build and install), system FFTW with FFTW_INCLUDE_PATH/FFTW*_BASE_LIB/FFTW*_THREADS_LIB hints pointing to a nonstandard copy, Debug, and no precision option.
  • Four downstream find_package(ITK) projects (${ITK_LIBRARIES}, ITK_USE_FILE, the removed variables, and the migrated form), each against both build and install trees.
  • With the fixes, Debug and both precisions: FFTW compiles with -O3 -DNDEBUG, and 73/73 ITKFFT + ITKFFTW tests pass. System FFTW: the GoogleTests pass. Install-tree consumers run with no DYLD_LIBRARY_PATH.
  • Install tree: no stray FFTW CMake package or pkg-config files; it is cleaner than the base.
  • Removed variables: no consumers found in about 120 local ecosystem repos or in GitHub code search outside copies of ITK. They were already empty in a base build tree, and a project still using them fails loudly at link time (-lfftw3).
  • FFTWD_LIB/FFTWF_LIB (the MINC/NIRAL superbuild style) never selected the base library before this PR either, so that is not a regression.
  • Bundled 3.3.10 reports fftw-3.3.9 from fftw_version(); that version is hard-coded in FFTW's own CMakeLists.

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:Filtering Issues affecting the Filtering module area:ThirdParty Issues affecting the ThirdParty module type:Enhancement Improvement of existing methods or implementation 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.

2 participants