Skip to content

ENH: Build DCMTK in-scope with FetchContent#6474

Draft
blowekamp wants to merge 8 commits into
InsightSoftwareConsortium:mainfrom
blowekamp:dcmtk-fetchcontent
Draft

ENH: Build DCMTK in-scope with FetchContent#6474
blowekamp wants to merge 8 commits into
InsightSoftwareConsortium:mainfrom
blowekamp:dcmtk-fetchcontent

Conversation

@blowekamp

@blowekamp blowekamp commented Jun 18, 2026

Copy link
Copy Markdown
Member

Replace the ExternalProject-based DCMTK build with FetchContent so DCMTK compiles in ITKs CMake scope, consuming ITKs codec targets directly and exporting namespaced DCMTK:: targets through ITKs module system.

DCMTK is exported in its own package and cmake target file. This reduced ITK burden and keeps the export code in DCMTK.

Supersedes #6397.

Changes
  • FetchContent replaces ExternalProject; DCMTK is configured as an add_subdirectory inside ITKs scope
  • Codec libraries wired via ITK::ITKTIFFModule / ITK::ITKJPEGModule / ITK::ITKPNGModule / ITK::ITKZLIBModule interface targets
  • DCMTK:: IMPORTED INTERFACE wrappers created so ITKTargets.cmake records namespaced target names that find_package(DCMTK) can satisfy
  • ITKDCMTK_EXPORT_CODE_BUILD / _INSTALL set to locate DCMTKConfig.cmake in build and install trees
  • DCMTK-internal CMake command overrides (CHECK_FUNCTION_EXISTS, CHECK_CXX_SYMBOL_EXISTS) renamed to DCMTK_CHECK_* to prevent leaking into sibling ITK modules
  • CACHE INTERNAL variable noise removed; normal variables suffice in FetchContent scope
AI assistance

GitHub Copilot (Claude Sonnet 4.6) assisted with CMake design, export target strategy, and identifying the global command override leak. All changes reviewed and committed by blowekamp.

hjmjohnson and others added 8 commits June 18, 2026 13:18
Replace the DCMTK ExternalProject with FetchContent + add_subdirectory so
DCMTK is configured in ITK's own CMake scope (the GDCM model). DCMTK now
consumes ITK's codec libraries as the live imported targets
(ITK::itktiff/itkpng/zlib/itkjpeg) through the standard *_LIBRARIES
variables -- no $<TARGET_FILE:> extraction or :::-separated CMAKE_ARGS.

itk_module_use() is called up front so the codec variables are populated
before DCMTK is configured. FetchContent_MakeAvailable(dcmtk) does the
add_subdirectory; EXCLUDE_FROM_ALL is not used because on the in-scope
DCMTK directory it leaks into ITK's own test targets and drops them from
the ALL build. Charset conversion honors the DCMTK_USE_ICU opt-in, wiring
ICU_ROOT through when set and otherwise using DCMTK's built-in oficonv
data. Build-tree namespace aliases are a placeholder pending full
module-target export.
Replace the placeholder build-tree aliases with itk_module_target(), which
applies ITK's output naming (itk<lib>-X.Y), creates the namespaced
ITK::<lib> aliases that itk_module_impl() links ITKDCMTKModule against, and
appends DCMTK's targets to ITK's build-tree targets file. The targets file
variable is set during module enablement, so this works before
itk_module_impl(). Installation is deferred, hence NO_INSTALL.
Disable warnings for the DCMTK subdirectory with itk_module_warnings_disable
before it is configured. ITK builds at /W4 while DCMTK builds at /W3, so
every DCMTK source previously emitted an MSVC D9025 flag-override warning on
top of DCMTK's own diagnostics. itk_module_impl() disables warnings for
third-party modules, but DCMTK is added before that call, so apply it here.
Drop NO_INSTALL so itk_module_target() installs the DCMTK libraries into
ITK's library directory and export set, and install each DCMTK module's
public headers (<module>/include/dcmtk) plus the generated config headers
into ITK's include tree so consumers of an installed ITK can include
<dcmtk/...>. install(EXPORT ITKTargets) generates cleanly: the DCMTK
targets' interface dependencies are ITK's exported codec targets, other
DCMTK targets, or system libraries.
Building DCMTK in ITK's shared CMake scope (FetchContent + add_subdirectory)
runs DCMTK's configure in that scope, with two side effects on sibling
third-party modules:

- Leftover CMAKE_REQUIRED_* state from DCMTK's probes. Snapshot and restore it
  around FetchContent_MakeAvailable(dcmtk).

- DCMTK's GenerateDCMTKConfigure.cmake globally redefines standard CMake check
  commands (CHECK_FUNCTION_EXISTS on Windows, CHECK_CXX_SYMBOL_EXISTS). CMake
  commands are global, so those overrides leak into ITK modules configured
  afterward: their CHECK_FUNCTION_EXISTS calls run DCMTK's header-less
  check_symbol_exists, report the function missing, and the module trips a
  #error -- MINC on tmpnam, GDCM on _strnicmp, depending on configure order.
  Restore the real implementations after DCMTK by including a copy of each
  module under a fresh path (include_guard(GLOBAL) blocks a plain re-include),
  fixing every dependent module regardless of order.

The ExternalProject build never hit either because DCMTK configures in a
separate CMake process.
CACHE INTERNAL vars in a FetchContent subdirectory scope pollute the
parent CMakeCache.txt. Normal variables suffice since FetchContent runs
add_subdirectory in the same scope, so DCMTK reads them directly.
Codec libraries updated to ITK module interface targets so transitive
include paths and link options propagate automatically.
Replace itk_module_target() wrapping with IMPORTED INTERFACE targets
named DCMTK::<lib>. Unlike ALIAS targets, IMPORTED targets preserve
their namespaced name in ITKTargets.cmake so downstream consumers can
satisfy the dependency via find_package(DCMTK).

Add ITKDCMTK_EXPORT_CODE_BUILD/INSTALL pointing consumers at the
DCMTKConfig.cmake written by DCMTK's own GenerateCMakeExports.cmake.

Drop CMAKE_REQUIRED_* snapshot/restore and CheckFunctionExists restore
workarounds; these are no longer needed after DCMTK's check commands
were renamed to DCMTK_CHECK_FUNCTION_EXISTS / DCMTK_CHECK_CXX_SYMBOL_EXISTS.
@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 area:ThirdParty Issues affecting the ThirdParty module labels Jun 18, 2026
@hjmjohnson

Copy link
Copy Markdown
Member

Hi Brad — looked over this. Two things:

Windows is a real failure, not a flake. Pixi-Cxx (windows-2022) dies with the MINC tmpnam #error C1189 in libminc/.../files.c:914. That's the same MSVC CHECK_FUNCTION_EXISTS-leak that 48839b3 ("Build in-scope DCMTK alongside MINC and GDCM on MSVC") was added to fix. 7727bef drops that workaround on the grounds that DCMTK's checks were renamed to DCMTK_CHECK_* — but this PR doesn't bump DCMTKGitTag.cmake (still for/itk-dcmtk-3.7.0-ccfd10b), and the config log still shows Looking for tmpnam - not found, so the global override is leaking into MINC again. Fix needs either the restore-workaround back, or a DCMTK fork tag that actually carries the DCMTK_CHECK_* rename.

Commit structure: all 8 commits touch only Modules/ThirdParty/DCMTK/CMakeLists.txt, and the last three (45ec44d/2839ecf/7727bef) revert or replace most of the first five — itk_module_use removed, CACHE INTERNAL removed, itk_module_target() swapped for DCMTK:: IMPORTED targets, and 48839b3 deleted outright. Once the Windows fix is settled I'd squash the whole thing to a single COMP: Build DCMTK in-scope with FetchContent commit — it's one cohesive build-system change to one file, and the intermediate states aren't independently buildable or bisection-worthy.

@blowekamp

Copy link
Copy Markdown
Member Author

Please see InsightSoftwareConsortium/DCMTK#2, which I was using locally to address that issue.

IMPORTED_LINK_INTERFACE_LIBRARIES
${ITKDCMTK_LIBDEP}
)
list(APPEND ITKDCMTK_LIBRARIES "DCMTK::${_dcmtk_target}")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linking to all DCMTK libraries results is overlooking for many used. For example:

target_link_libraries(
  ITKIODCMTK
  PUBLIC
    DCMTK::dcmdata
    DCMTK::dcmimgle
    DCMTK::dcmjpeg
    DCMTK::dcmjpls
)

Is all that is needed not all of DCMTK. Perhaps it would be best not to list all the libraries here, so that when DCMTK is used all libraries are not linked?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more complete investigation of the needed libraries and the optimal set will be conducted. That should also allow less of DCMTK to be built by default.

@blowekamp

Copy link
Copy Markdown
Member Author

@hjmjohnson I will not be working on this during the week end. You are welcome to rebase, squash and resolve difference with main, etc. Please let me review and merge when complete.

The comments are still the lengthly AI style and need to be refined and reviewed.

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants