Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CMake/ITKModuleDoxygen.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
# ${_name}.dot file which defines the local dependency as graph
# which will be then processed by dot

# <source>/CMake in a build tree, the installed package directory otherwise.
if(EXISTS "${ITK_CMAKE_DIR}/../Utilities/Doxygen/mcdoc.py")
set(ITK_MCDOC_SCRIPT "${ITK_CMAKE_DIR}/../Utilities/Doxygen/mcdoc.py")
else()
set(ITK_MCDOC_SCRIPT "${ITK_CMAKE_DIR}/mcdoc.py")
endif()

macro(itk_module_doxygen _name)
# _content defines the content of the ${_name}.dox file
set(_content "/**\n")
Expand Down Expand Up @@ -49,7 +56,7 @@ macro(itk_module_doxygen _name)
NAME ${_name}InDoxygenGroup
COMMAND
${Python3_EXECUTABLE}
"${ITK_CMAKE_DIR}/../Utilities/Doxygen/mcdoc.py"
"${ITK_MCDOC_SCRIPT}"
check
${_name}
${${_name}_SOURCE_DIR}/include
Expand Down
29 changes: 15 additions & 14 deletions CMake/ITKModuleExternal.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -255,23 +255,24 @@ if(ITK_WRAPPING)
"${CMAKE_CURRENT_SOURCE_DIR}/wrapping/CMakeLists.txt"
)
set(EXTERNAL_WRAP_ITK_PROJECT ON)
set(WRAP_ITK_CMAKE_DIR "${ITK_CMAKE_DIR}/../Wrapping")
include("${WRAP_ITK_CMAKE_DIR}/TypedefMacros.cmake")
# Build tree
# <source>/CMake in a build tree, the installed package directory otherwise.
if(EXISTS "${ITK_CMAKE_DIR}/../Wrapping/CMakeLists.txt")
add_subdirectory(
"${ITK_CMAKE_DIR}/../Wrapping"
${CMAKE_CURRENT_BINARY_DIR}/Wrapping
)
# Install tree
elseif(EXISTS"${ITK_CMAKE_DIR}/Wrapping/CMakeLists.txt")
add_subdirectory(
"${ITK_CMAKE_DIR}/Wrapping"
${CMAKE_CURRENT_BINARY_DIR}/Wrapping
)
set(WRAP_ITK_CMAKE_DIR "${ITK_CMAKE_DIR}/../Wrapping")
elseif(EXISTS "${ITK_CMAKE_DIR}/Wrapping/CMakeLists.txt")
set(WRAP_ITK_CMAKE_DIR "${ITK_CMAKE_DIR}/Wrapping")
else()
message(FATAL_ERROR "Could not find wrapping infrastructure.")
message(
FATAL_ERROR
"Could not find wrapping infrastructure at ${ITK_CMAKE_DIR}. To wrap a module against an installed ITK, that ITK must be reconfigured with ITK_INSTALL_WRAPPING_DEVELOPMENT_FILES=ON, then rebuilt and reinstalled."
)
endif()
include("${WRAP_ITK_CMAKE_DIR}/TypedefMacros.cmake")
# Python registers the factories at import; the wrapping library must not.
set(ITK_WRAPPING_NO_FACTORY_REGISTER_MANAGER ON)
add_subdirectory(
"${WRAP_ITK_CMAKE_DIR}"
${CMAKE_CURRENT_BINARY_DIR}/Wrapping
)
endif()
endif()
# Create target to download data from the ITKData group. This must come after
Expand Down
17 changes: 15 additions & 2 deletions CMake/ITKModuleHeaderTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
# primary purpose of this test is to make sure there are not missing module
# dependencies.

# <source>/CMake in a build tree, the installed package directory otherwise.
if(EXISTS "${ITK_CMAKE_DIR}/../Utilities/Maintenance/BuildHeaderTest.py")
set(
ITK_BUILD_HEADER_TEST_SCRIPT
"${ITK_CMAKE_DIR}/../Utilities/Maintenance/BuildHeaderTest.py"
)
else()
set(ITK_BUILD_HEADER_TEST_SCRIPT "${ITK_CMAKE_DIR}/BuildHeaderTest.py")
endif()

# Improve performance of MSVC GUI, by reducing number of header tests.
set(MAXIMUM_NUMBER_OF_HEADERS_default 35)
if(MSVC)
Expand Down Expand Up @@ -114,8 +124,7 @@ macro(itk_module_headertest _name)
OUTPUT
${_header_test_src}
COMMAND
${Python3_EXECUTABLE}
${ITK_CMAKE_DIR}/../Utilities/Maintenance/BuildHeaderTest.py ${_name}
${Python3_EXECUTABLE} ${ITK_BUILD_HEADER_TEST_SCRIPT} ${_name}
${${_name}_SOURCE_DIR} ${${_name}_BINARY_DIR}
${MAXIMUM_NUMBER_OF_HEADERS} ${_test_num}
)
Expand All @@ -126,6 +135,10 @@ macro(itk_module_headertest _name)
${ITK_MODULE_${_name}_TARGETS_NAMESPACE}${_name}Module
${ITK_MODULE_${_name}_TARGETS_NAMESPACE}ITKKWSysModule
)
# UseITK's register manager references every IO factory the ITK enables.
if(NOT ITK_SOURCE_DIR)
target_link_libraries(${_test_name} PRIVATE ${ITK_LIBRARIES})
endif()

target_link_options(
${_test_name}
Expand Down
4 changes: 4 additions & 0 deletions CMake/ITKModuleKWStyleTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ if(
AND
NOT
CMAKE_CROSSCOMPILING
AND
EXISTS
"${ITK_CMAKE_DIR}/../Utilities/KWStyle/BuildKWStyle.cmake"
)
# Only an ITK source tree carries BuildKWStyle.cmake; an install tree does not.
include(${ITK_CMAKE_DIR}/../Utilities/KWStyle/BuildKWStyle.cmake)
elseif(NOT KWSTYLE_FOUND)
set(ITK_USE_KWSTYLE OFF)
Expand Down
4 changes: 4 additions & 0 deletions CMake/ITKModuleTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ EM_ASM(
${KIT_LIBS}
${ITKTestKernel_LIBRARIES}
)
# UseITK's register manager references every IO factory the ITK enables.
if(NOT ITK_SOURCE_DIR)
target_link_libraries(${KIT}TestDriver PRIVATE ${ITK_LIBRARIES})
endif()
target_link_options(
${KIT}TestDriver
PRIVATE
Expand Down
21 changes: 21 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,27 @@ install(
CMake/itkTransformIOFactoryRegisterManager.h.in
CMake/itkMeshIOFactoryRegisterManager.h.in
CMake/ITKInitializeCXXStandard.cmake
# The transitive closure of include(ITKModuleExternal).
CMake/ITKModuleExternal.cmake
CMake/ITKModuleMacros.cmake
CMake/ITKModuleTest.cmake
CMake/ITKModuleInfo.cmake.in
CMake/ITKSetPython3Vars.cmake
CMake/ITKInitializeBuildType.cmake
CMake/ITKWindowsUtf8.cmake
CMake/ITKExternalData.cmake
CMake/ITKDownloadSetup.cmake
CMake/ExternalData.cmake
CMake/ExternalData_config.cmake.in
CMake/WrappingConfigCommon.cmake
CMake/itkRemoveTestFiles.cmake
CMake/ITKModuleDoxygen.cmake
CMake/ITKModuleHeaderTest.cmake
CMake/ITKModuleKWStyleTest.cmake
CMake/ITKModuleCPPCheckTest.cmake
CMake/CppcheckTargets.cmake
Utilities/Maintenance/BuildHeaderTest.py
Utilities/Doxygen/mcdoc.py
DESTINATION ${ITK_INSTALL_PACKAGE_DIR}
COMPONENT Development
)
Expand Down
22 changes: 22 additions & 0 deletions Documentation/docs/contributing/module_workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ jobs:
pypi_password: ${{ secrets.pypi_password }}
```

## Building an external module against an installed ITK

An external module can be configured, built, and Python-wrapped against an
installed ITK prefix rather than an ITK build tree. Point `ITK_DIR` at the
installed package directory, for example
`<prefix>/lib/cmake/ITK-6.0`, and configure the module as usual.

Wrapping additionally requires the SWIG type indices and the wrapping CMake
infrastructure, which ITK installs only on request because the payload is
tens of megabytes. To make an installed prefix usable as a wrapping SDK, the
ITK being installed must be configured with:

```bash
cmake -DITK_WRAP_PYTHON:BOOL=ON \
-DITK_INSTALL_WRAPPING_DEVELOPMENT_FILES:BOOL=ON <itk-source>
```

then rebuilt and reinstalled. Configuring a module with `ITK_WRAP_PYTHON=ON`
against a prefix that lacks these files fails with "Could not find wrapping
infrastructure"; the remedy is to reconfigure, rebuild, and reinstall the ITK
the module points at, not to change anything in the module.

## Further Reading

For more information visit README documentation at the [ITKRemoteModuleBuildTestPackageAction](https://github.com/InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/blob/main/README.md#itkremotemodulebuildtestpackageaction) project.
54 changes: 54 additions & 0 deletions Wrapping/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,57 @@ if(ITK_WRAP_PYTHON)
unset(ITK_STUB_DIR CACHE)
unset(ITK_PKL_DIR CACHE)
endif()

# Lands under the package directory, where an installed consumer's ITK_DIR already points.
if(ITK_INSTALL_WRAPPING_DEVELOPMENT_FILES)
set(_itk_wrapping_install_dir "${ITK_INSTALL_PACKAGE_DIR}/Wrapping")

macro(_itk_install_wrapping_development _source_dir _destination)
install(
DIRECTORY
"${_source_dir}/"
DESTINATION "${_destination}"
COMPONENT ${WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER}WrappingDevelopment
FILES_MATCHING
${ARGN}
)
endmacro()

_itk_install_wrapping_development(
"${WrapITK_SOURCE_DIR}"
"${_itk_wrapping_install_dir}"
PATTERN
"*.cmake"
PATTERN
"CMakeLists.txt"
PATTERN
"*.i"
PATTERN
"*.in"
PATTERN
"*.py"
PATTERN
"*.h"
PATTERN
"images"
EXCLUDE
PATTERN
"Tests"
EXCLUDE
)

_itk_install_wrapping_development(
"${WRAP_ITK_TYPEDEFS_DIRECTORY}"
"${_itk_wrapping_install_dir}/Typedefs"
PATTERN
"*.i"
PATTERN
"*.idx"
PATTERN
"*.mdx"
PATTERN
"*.h"
)

unset(_itk_wrapping_install_dir)
endif()
9 changes: 9 additions & 0 deletions Wrapping/TypedefMacros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ macro(itk_wrap_module library_name)
set(WRAPPER_LIBRARY_NAME "${library_name}")
message(STATUS "${WRAPPER_LIBRARY_NAME}: Creating module.")

# Drop the register managers the consumer tree's UseITK put on this directory.
if(ITK_WRAPPING_NO_FACTORY_REGISTER_MANAGER)
foreach(_factory_name ${ITK_FACTORY_LIST})
string(TOUPPER ${_factory_name} _factory_uc)
remove_definitions(-DITK_${_factory_uc}_FACTORY_REGISTER_MANAGER)
endforeach()
unset(_factory_uc)
endif()

# Mark the current source dir for inclusion because it may contain header files.
include_directories(BEFORE "${CMAKE_CURRENT_SOURCE_DIR}")
include_directories(BEFORE ${WRAPPER_LIBRARY_INCLUDE_DIRECTORIES})
Expand Down
10 changes: 10 additions & 0 deletions Wrapping/WrappingOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ else()
set(ITK_WRAPPING OFF CACHE INTERNAL "Build external languages support" FORCE)
endif()

# Opt-in: the SWIG type indices are tens of MB.
cmake_dependent_option(
ITK_INSTALL_WRAPPING_DEVELOPMENT_FILES
"Install the wrapping infrastructure and SWIG type indices so that external modules can be wrapped against an installed ITK"
OFF
"ITK_WRAPPING"
OFF
)
mark_as_advanced(ITK_INSTALL_WRAPPING_DEVELOPMENT_FILES)

cmake_dependent_option(
ITK_PYTHON_RELEASE_GIL
"Release Python Global Interpreter Lock (GIL) during ITK operations"
Expand Down
4 changes: 4 additions & 0 deletions Wrapping/macro_files/itk_auto_load_submodules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ function(generate_castxml_commandline_flags)

# create the files used to pass the file to include to castxml
set(include_dir_list ${WRAPPER_LIBRARY_INCLUDE_DIRECTORIES})
# From an install tree the dependency targets carry no ITK include dirs.
if(ITK_INCLUDE_DIRS)
list(APPEND include_dir_list ${ITK_INCLUDE_DIRS})
endif()
list(REMOVE_DUPLICATES include_dir_list)

# CONFIG_CASTXML_INC_CONTENTS - variable used for building contents to write with file(GENERATE)
Expand Down
Loading