InsightSoftwareConsortium / InsightSoftwareConsortium/ITK
GoogleTest integration is inconsistent between build tree and install tree
- Dominant language
- C++
- Stars
- 1.7k
- Forks
- 748
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 64
Description
ITK's GoogleTest integration is inconsistent across the build tree / install tree boundary, and `TEST_DEPENDS ITKGoogleTest` does not survive export. Surfaced while reviewing #6780; the layers below are why that PR is being closed rather than extended.
An installed ITK ships public headers that `#include "gtest/gtest.h"` while shipping neither the gtest headers nor the `GTest::` targets.
### 1. `TEST_DEPENDS` does not export
The installed module file for a module carries `_DEPENDS`, `_PUBLIC_DEPENDS`, `_TRANSITIVE_DEPENDS` and `_PRIVATE_DEPENDS`. There is no `_TEST_DEPENDS` variable. `TEST_DEPENDS ITKGoogleTest` is therefore build-time only: it enables the module and puts `ITK::ITKGoogleTestModule` on the test kit's interface, and conveys nothing to a consumer of an installed ITK.
Installed Modules/ITKTestKernel.cmake, verbatim
```cmake
set(ITKTestKernel_DEPENDS "ITKCommon;ITKDoubleConversion;ITKFFT;ITKIOBMP;...;ITKKWSys")
set(ITKTestKernel_PUBLIC_DEPENDS "ITKCommon;ITKIOImageBase")
set(ITKTestKernel_TRANSITIVE_DEPENDS "ITKCommon;ITKDoubleConversion;ITKIOImageBase;ITKKWSys")
set(ITKTestKernel_PRIVATE_DEPENDS "ITKFFT;ITKIOBMP;...;ITKIOVTK")
set(ITKTestKernel_LIBRARIES "ITK::ITKTestKernel")
```
`ITKGoogleTest` appears nowhere, although `ITKTestKernel`'s `itk-module.cmake` declares it under `TEST_DEPENDS`.
### 2. Promoting the dependency to public is blocked by the install story
Moving `ITKGoogleTest` from `TEST_DEPENDS` to `DEPENDS` on `ITKTestKernel` would make every module with GoogleTest tests inherit it transitively, and is consistent with `ITKTestKernel`'s headers. It cannot be done while GoogleTest stays build-tree-only: in a `BUILD_TESTING=OFF` install, `ITKGoogleTest` is not enabled and `ITKGoogleTest.cmake` is not installed, so a consumer of `ITKTestKernel` hits a hard failure.
Failure mode
`itk_module_load` in `CMake/ITKModuleAPI.cmake`:
```cmake
include("${ITK_MODULES_DIR}/${mod}.cmake" OPTIONAL)
if(NOT ${mod}_LOADED)
message(FATAL_ERROR "No such module: \"${mod}\"")
```
A public dependency that is absent from the install is not a soft degradation; it is `No such module: "ITKGoogleTest"` for every consumer of `ITKTestKernel`.
### 3. Installed `itkGTest.h` has no gtest behind it
Three public headers include gtest and are installed; gtest itself is not.
| artifact | installed |
|---|---|
| `itkGTest.h`, `itkGTestPredicate.h`, `itkGTestTypedefsAndConstructors.h` | yes |
| `gtest/gtest.h`, which those three `#include` | no |
| `GTest::gtest` / `GTest::gtest_main` in `ITKTargets.cmake` | no (build tree: present) |
| `Modules/ITKGoogleTest.cmake` | yes, every variable empty |
A downstream project that includes `itkGTest.h` from an installed ITK does not compile unless it supplies GoogleTest itself, and has no target to link against from ITK's export.
How this was observed
macOS arm64, ITK built from `main` with `-DBUILD_TESTING=ON -DModule_ITKGoogleTest=ON -DITK_BUILD_DEFAULT_MODULES=OFF -DModule_ITKIONRRD=ON`, then `cmake --install`:
- `find -iname '*gtest*'` returns only ITK's own three headers.
- `grep -c 'GTest::' /lib/cmake/ITK-6.0/ITKTargets.cmake` → 0. The same grep against the build tree's `ITKTargets.cmake` → 14.
### Scope
This started as an easy fix for a rare corner case — seven modules that call `CreateGoogleTestDriver` without declaring `ITKGoogleTest`, breaking a narrow module selection. It is not that. Settling it means deciding whether an installed ITK supports GoogleTest-based downstream tests at all, and the answer determines everything above:
- **No** — then installing `itkGTest.h` and friends is the defect, and they should not be public installed headers.
- **Yes** — then GoogleTest must be exported (targets, or `find_package(GTest)` export code, or a documented consumer-supplies-it contract), and only then can `ITKTestKernel`'s dependency become public.
Neither direction is a small change, and both touch third-party policy set when GoogleTest was first vendored.
### Prior art in this area
- #6777, closed: added install-tree export code for GoogleTest. Closed because GoogleTest is build-tree-only by design.
- #6778, closed: enabled `ITKGoogleTest` whenever `BUILD_TESTING=ON`. Closed because `TEST_DEPENDS` is what keeps the CMake interface correct.
- #6780, closed in favour of this issue: declared `ITKGoogleTest` in the seven modules and added a guard in `CreateGoogleTestDriver`. Correct as far as it went, but it treats a symptom of the above.
Contributor guide
Research direction
Start by reading CMake/ITKModuleAPI.cmake, CMake/ITKModuleTest.cmake, Modules/Core/TestKernel/itk-module.cmake, the installed itkGTest*.h headers, and Modules/ThirdParty/GoogleTest/CMakeLists.txt. Reproduce the install-tree checks described in the issue with BUILD_TESTING enabled and disabled. Done means one documented GoogleTest policy is chosen and the module metadata, installed headers, targets, and consumer behavior consistently implement it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake, cpp
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100