InsightSoftwareConsortium / InsightSoftwareConsortium/ITK
External modules cannot wrap itkPyBuffer.h: Python include dir is not exported
- Dominant language
- C++
- Stars
- 1.7k
- Forks
- 748
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 64
Description
An external module that wraps `itkPyBuffer.h` cannot find `Python.h`: the Python include directory is never exported, so castxml fails outside ITK's own build tree.
## Reproduce
Build an external module that wraps `itkPyBuffer.h` (RTK does, via
`wrapping/itkPyBufferRTK.wrap`) against an ITK built with `ITK_WRAP_PYTHON=ON`:
```
FAILED: .../Wrapping/castxml_inputs/itkPyBufferRTK.xml
.../ITK/Modules/Bridge/NumPy/include/itkPyBuffer.h:30:10: fatal error: 'Python.h' file not found
30 | #include
```
The same target succeeds with the include supplied by hand:
```bash
CPATH="$CONDA_PREFIX/include/python3.14" ninja .../itkPyBufferRTK.xml # OK
```
## Cause
`Wrapping/Generators/Python/CMakeLists.txt:20` adds the Python include as a
**directory property**:
```cmake
include_directories("${Python3_INCLUDE_DIRS}")
```
and `Wrapping/Generators/CMakeLists.txt:99-104` re-reads that property and
re-applies it. Both act only inside ITK's own build tree.
An external module generates its `*.castxml.inc` from
`WRAPPER_LIBRARY_INCLUDE_DIRECTORIES` plus each dependency's
`INTERFACE_INCLUDE_DIRECTORIES`
(`Wrapping/macro_files/itk_auto_load_submodules.cmake:107,127,131`). The
exported `ITKBridgeNumPy.cmake` carries no Python include — its only Python
entry is `ITKBridgeNumPy_RUNTIME_LIBRARY_DIRS` — so the directory is absent
from the generated include list.
Measured on one such build: ITK's own `itkPyBuffer.castxml.inc` has 25 include
directories including `.../include/python3.14`; the external module's
`itkPyBufferRTK.castxml.inc` has 109 directories and none of them is Python's.
## Effect
The castxml step fails, wrapping never completes, and the module leaves a
`Config.py` in ITK's Python package with no `Python.py` and no
`_Python*.so`. Every later `import itk` in that build tree then raises
```
FileNotFoundError: .../itk/support/../RTKPython.py
```
while the lazy loader walks the factories, so unrelated consumers' Python tests
fail too.
## Possible directions
- Export the Python include with `ITKBridgeNumPy`'s interface, so any module
that consumes it inherits the directory.
- Or add `Python3_INCLUDE_DIRS` to the include list used to generate
`*.castxml.inc` for external modules.
Related in shape to #6860, where a wrapping/factory input also resolves only
inside ITK's own build tree.
Contributor guide
Research direction
Start with Wrapping/Generators/Python/CMakeLists.txt, Wrapping/Generators/CMakeLists.txt, and Wrapping/macro_files/itk_auto_load_submodules.cmake to trace how Python3_INCLUDE_DIRS reaches generated castxml include lists and exported interfaces. Reproduce the RTK external wrapping case with ITK_WRAP_PYTHON=ON and inspect the generated *.castxml.inc files. Done means an external wrapper can find Python.h, complete castxml generation, and produce its Python module artifacts without CPATH.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake, cpp, python
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100