COMP: Repair DCMTK build-tree export references for external consumers#6548
COMP: Repair DCMTK build-tree export references for external consumers#6548hjmjohnson wants to merge 1 commit into
Conversation
DCMTK's build-tree DCMTKTargets.cmake is written by the legacy export(TARGETS ... NAMESPACE DCMTK::), which prefixes DCMTK:: onto ITK's imported codec targets and records the nonexistent DCMTK::ITK::ITKZLIBModule (and TIFF/JPEG/PNG). An external consumer of an ITK build tree that resolves the DCMTK targets (e.g. an ANTs SuperBuild, where ITK_BINARY_DIR is unset in the find_package(ITK) scope) fails at generate with 'target DCMTK::ITK::ITKZLIBModule not found'. The install-tree export, written by install(EXPORT), resolves the same dependencies to their real ITK::* names and is unaffected. Rewrite the mis-prefixed link-interface entries in place after the existing find_package(DCMTK) import. Patching after import preserves the DCMTK_DIR seeding and every DCMTKConfig side effect (DCMTK_FOUND, DCMTK_INCLUDE_DIRS, ...), and corrects the targets regardless of whether the consumer imported them before or after find_package(ITK).
6eab740 to
ec1ff34
Compare
| list(JOIN _ITKDCMTK_LIB_NAMES " " _itkdcmtk_lib_names_spaced) | ||
| set( | ||
| ITKDCMTK_EXPORT_CODE_BUILD | ||
| " | ||
| if(NOT ITK_BINARY_DIR) | ||
| set(DCMTK_DIR \"${CMAKE_BINARY_DIR}\") | ||
| find_package(DCMTK REQUIRED NO_MODULE) | ||
| foreach(_itkdcmtk_lib ${_itkdcmtk_lib_names_spaced}) |
There was a problem hiding this comment.
Include suffixed targets
The repair loop uses the unsuffixed _ITKDCMTK_LIB_NAMES, but this file creates and links DCMTK::${_dcmtk_lib}${DCMTK_LIBRARY_SUFFIX} targets at lines 151-161. When DCMTK_LIBRARY_SUFFIX is non-empty, no DCMTK::dcmdata target exists, so the loop skips every exported DCMTK target and leaves the broken DCMTK::ITK::* references in the build-tree export.
Artifacts
Repro: deterministic suffixed DCMTK repair harness
- Contains supporting evidence from the run (text/x-python; charset=utf-8).
Repro: harness execution log showing skipped repair and remaining broken entry
- Keeps the command output available without making the summary code-heavy.
Repro: command-v output showing CMake and Ninja unavailable
- Keeps the command output available without making the summary code-heavy.
|
This solution does not seem quite right to me. If DCMTK saw ITK's provided libraries as "imported" targets it would not alter the namespace. I tries one way to modify the ITK's third party libraries to be imported target to DCMTK but it did not work. I may look into modifying how DCMTK does the exports. I have not found this type of issue in searches. I may create a minimal reproducible example and seek some advice on it. |
@blowekamp See DCMTK/dcmtk#150 for a minimal reproducible example. I am trying to build a forest of tools (ANTs, BRAINSTools, Slicer, SlicerExtensions, ITK-SNAP, .... and may others, and keep running into DCMTK build failures downstream. |
That is a good start to the MRE I was thinking. But I was going also going to create a minimal sub-project to replace DCMTK's library and export. On thing that is atypical in ITK is that the export name space is set as a property: ITK/CMake/ITKModuleMacros.cmake Lines 789 to 794 in a66345a I am currently looking at example cmake code which export multiple namespace to see how things can be done. |
|
@blowekamp Thank you for looking into this. If you find a workable solution, please just push over top of this PR, or close this and open a new PR. |
Repair DCMTK's build-tree export after
find_package(DCMTK)import — strip theDCMTK::prefix from any link-interface reference that is not an existing target (all genuineDCMTK::targets exist onceDCMTKTargets.cmakeis included) — so external consumers of an ITK build tree (e.g. an ANTs SuperBuild) survive CMake generate. Split out of #6543 at @blowekamp's request; the repair loop is line-for-line the fix proposed upstream in DCMTK/dcmtk#150, so it can be deleted verbatim when ITK's DCMTK pin includes that fix.Merge-ordering note: once #6543's namespaced linking is in, an external build-tree consumer fails at generate without this repair (repro below); on pre-#6543
mainthe same consumer already fails, but later, at link (baredcmdatanames resolving against the system DCMTK). Install-tree consumers are unaffected either way.Root cause
DCMTK's build-tree
DCMTKTargets.cmakeis written by the legacyexport(TARGETS ... NAMESPACE DCMTK::), which prefixesDCMTK::onto ITK's imported codec targets and records the nonexistentDCMTK::ITK::ITKZLIBModule(and TIFF/JPEG/PNG). An external consumer of an ITK build tree that resolves the DCMTK targets (whereITK_BINARY_DIRis unset in thefind_package(ITK)scope) fails at generate. The install-tree export, written byinstall(EXPORT), resolves the same dependencies to their realITK::*names and is unaffected.Patching after import (in
ITKDCMTK_EXPORT_CODE_BUILD) preserves theDCMTK_DIRseeding and everyDCMTKConfigside effect, and corrects the targets regardless of import order. The "normal" fix is proposed upstream as DCMTK/dcmtk#150 (identical repair, shipped inDCMTKConfig.cmakeitself); this in-ITK patch is the contained workaround until ITK's DCMTK pin includes it. The existence-checked form (rather than aDCMTK::ITK::string replace) also covers the second defect shape found while building the upstream minimal repro: ALIAS targets are recorded de-aliased (e.g.DCMTK::super_zlibwrap), with no::in the stripped name.Minimal reproduction (verified)
0a0a06c700a) with the vendored DCMTK:cmake -S consumer -B consumer-build -G Ninja -DITK_DIR=$PWD/ITK-build./consumer-build/t; echo $?→0).Testing performed
ITK-build/DCMTKTargets.cmakerecordsDCMTK::ITK::ITK{ZLIB,TIFF,JPEG,PNG}Module; the generated build-treeModules/ITKDCMTK.cmakecontains the rewrite loop.main: consumer generate passes (bare-name linking never resolves the brokenDCMTK::targets) but the final link fails against system DCMTK — the pre-existing breakage COMP: Link namespaced DCMTK targets in the DCMTK IO modules #6543 + this PR together eliminate.Composes with #6543 (kept independent: applies and configures standalone on
main).