The Insight Toolkit is organized into logical units of coherent functionality called modules. These modules are self-contained in a directory, whose components are organized into subdirectories with standardized names. A module usually has dependencies on other modules, which it declares. A module is defined with CMake scripts that inform the build system of its contents and dependencies.
The modularization effort significantly improves the extensibility of the toolkit and lowers the barrier to contribution.
Modules are organized into:
This chapter describes how to create a new module. The following sections are organized by the different directory components of the module. The chapter concludes with a section on how to add a third-party library dependency to a module.
Note that the Insight Toolkit community has adopted a Coding Style guideline for the sake of consistentcy and readability of the code. Such guideline is described in Chapter ??.
The top level directory of a module is used to define a module’s name and its dependencies. Two files are required:
The information described in these files is used to populate <ModuleName>.cmake files in the ITK module registry. The module registry is located at <ITK build directory>/lib/cmake/5.0/Modules/ in a build tree or <CMAKE_INSTALL_PREFIX>/lib/cmake/5.0/Modules/ in an install tree. These module files declare information about the module and what is required to use it. This includes its module dependencies, C++ include directories required to build against it, the libraries to link against, and CMake code required to use it in a CMake configured project.
When CMake starts processing a module, it begins with the top level CMakeLists.txt file. At a minimum, the CMakeLists.txt should contain
where MyModule is the name of the module.
The CMake variable <module-name>_LIBRARIES should be set to the names of the libraries, if any, that clients of the module need to link. This will be the same name as the library generated with the add_library command in a module’s src directory, described in further detail in the Libraries Section 9.3.
The path if(NOT ITK_SOURCE_DIR) is used when developing a module outside of the ITK source tree, i.e. an External module. An External module can be made available to the community by adding it to Modules/Remote/⋆.remote.cmake Remote module index in the ITK repository per Section ??.
The CMake macro itk_module_impl is defined in the file CMake/ITKModuleMacros.cmake. It will initiate processing of the remainder of a module’s CMake scripts. The script ITKModuleExternal calls itk_module_impl internally.
The itk-module.cmake is also a required CMake script at the top level of a module, but this file is used to declare
In this file, first set a CMake variable with the module’s description followed by a call to the itk_module macro, which is already defined by the time the script is read. For example, itk-module.cmake for the ITKCommon module is
toolkit. They include, basic data structures \(such as Points, Vectors,
Images, Regions\) the core of the process objects \(such as base
classes for image filters\) the pipeline infrastructure classes, the support
for multi-threading, and a collection of classes that isolate ITK from
platform specific features. It is anticipated that most other ITK modules will
depend on this one.")
itk_module(ITKCommon
ENABLE_SHARED
PRIVATE_DEPENDS
ITKDoubleConversion
COMPILE_DEPENDS
ITKKWSys
ITKVNLInstantiation
TEST_DEPENDS
ITKTestKernel
ITKMesh
ITKImageIntensity
ITKIOImageBase
DESCRIPTION
"${DOCUMENTATION}"
)
The description for the module should be escaped as a CMake string, and it should be formatted with Doxygen markup. This description is added to ITK’s generated Doxygen documentation when the module is added to the Remote module index. The description should describe the purpose and content of the module and reference an Insight Journal article for further information.
A module name is the only required positional argument to the itk_module macro. Named options that take one or argument are:
Public dependencies are added to the module’s INTERFACE_LINK_LIBRARIES, which is a list of transitive link dependencies. When this module is linked to by another target, the libraries listed (and recursively, their link interface libraries) will be provided to the target also. Private dependencies are linked to by this module, but not added to INTERFACE_LINK_LIBRARIES.
Compile Dependencies are added to CMake’s list of dependencies for the current module, ensuring that they are built before the current module, but they will not be linked either publicly or privately. They are only used to support the building of the current module.
The following additional options take no arguments:
All External and Remote modules should set the EXCLUDE_FROM_DEFAULT option.
Headers for the module, both ⋆.h declaration headers and ⋆.hxx template definition headers, should be added to the include directory. No other explicit CMake configuration is required.
This path will automatically be added to the build include directory paths for libraries (9.3) and tests (9.4) in the module and when another module declares this module as a dependency.
When a module is installed, headers are installed into a single directory common to all ITK header files.
When BUILD_TESTING is enabled, a header test is automatically created. This test simply builds a simple executable that #includes all header files in the include directory. This ensures that all included headers can be found, which tests the module’s dependency specification per Section 9.1.
Libraries generated by a module are created from source files with the .cxx extension in a module’s src directory. Some modules are header-only, and they will not generate any libraries; in this case, the src directory is omitted. When present, the src directory should contain a CMakeLists.txt file that describes how to build the library. A minimal CMakeLists.txt file is as follows.
The itk_module_add_library macro will create a library with the given sources. The macro will also link the library to the libraries defined by the module dependency specification per Section 9.1. Additionally, the macro will set CMake target properties associated with the current module to the given target.
If the ENABLE_SHARED option is set on a module, a shared library will be generated when the CMake option BUILD_SHARED_LIBS is enabled. A library symbol export specification header is also generated for the module. For a module with the name AModuleName, the generated header will have the name AModuleNameExport.h. Include the export header in the module source headers, and add the export specification macro to the contained classes. The macro name in this case would be called AModuleName_EXPORT. For example, the file itkFooClass.h would contain
Modules that do not build a library in their src directory or do not have export specifications on their class declarations should not set ENABLE_SHARED.
Regression tests for a module are placed in the test directory. This directory will contain a CMakeLists.txt with the CMake configuration, test sources, and optional Input and Baseline directories, which contain test input and baseline image datasets, respectively. Placement of the input and baseline image datasets within a given module directory is preferred over placement in the general Testing/Data directory; this ensures that a module’s data is only downloaded when the module is enabled. An exception to this rule may be widely used input datasets, such as the cthead1.png image.
An example CMake configuration for a test directory is shown below.
set(ModuleTemplateTests
itkMinimalStandardRandomVariateGeneratorTest.cxx
itkLogNormalDistributionImageSourceTest.cxx
)
CreateTestDriver(ModuleTemplate "${ModuleTemplate-Test_LIBRARIES}" "${ModuleTemplateTests}")
itk_add_test(NAME itkMinimalStandardRandomVariateGeneratorTest
COMMAND ModuleTemplateTestDriver itkMinimalStandardRandomVariateGeneratorTest
)
itk_add_test(NAME itkLogNormalDistributionImageSourceTest
COMMAND ModuleTemplateTestDriver --without-threads
--compare
${ITK_TEST_OUTPUT_DIR}/itkLogNormalDistributionImageSourceTestOutput.mha
DATA{Baseline/itkLogNormalDistributionImageSourceTestOutput.mha}
itkLogNormalDistributionImageSourceTest
${ITK_TEST_OUTPUT_DIR}/itkLogNormalDistributionImageSourceTestOutput.mha
)
The CMakeLists.txt file should start with a call to the itk_module_test macro. Next, the test sources are listed. The naming convention for unit test files is itk<ClassName>Test.cxx. Each test file should be written like a command line executable, but the name of the main function should be replaced with the name of the test. The function should accept int argc, char ⋆ argv[] as arguments. To reduce the time required for linking and to provide baseline comparison functionality, all tests are linked to into a single test driver executable. To generate the executable, call the CreateTestDriver macro.
Tests are defined with the itk_add_test macro. This is a wrapper around the CMake add_test command that will resolve content links in the DATA macro. Testing data paths are given inside the DATA macro. Content link files, stored in the source code directory, are replaced by actual content files in the build directory when CMake downloads the ITKData target at build time. A content link file has the same name as its target, but a .sha512 extension is added, and the .sha512 file’s contents are only the SHA512 hash of its target. Content links for data files in a Git distributed version control repository prevent repository bloat. To obtain content links, register an account at https://data.kitware.com. Upload images to your account’s My folders/Public folder. Once the image has been uploaded, click on the item’s link, then click the Show info icon. A Download key file icon will be available to download the content link. Place this file in the repository tree where referenced by the DATA macro.
When a test requires a new (or modified) input or baseline image dataset, the corresponding content link files have to be provided as well. Image datasets provided should be kept as small as possible. As a rule of thumb, their size should be under 50 kB.
Test commands should call the test driver executable, followed by options for the test, followed by the test function name, followed by arguments that are passed to the test. The test driver accepts options like --compare (or --compare-MD5 when using the MD5SUM hash) to compare output images to baselines or options that modify tolerances on comparisons. An exhaustive list of options is displayed in itkTestDriverInclude.h.
A few rules must be acknowledged to actually write a units test file itk<ClassName>Test.cxx for a given ITK class:
In any case, ITK provides with a number of classes and macros that ease the process of writing tests and checking the expected results. The following is an exhaustive list of such tools:
A test may have some input arguments. When a test does not need any input argument (e.g., it generates a synthetic input image), the main argument names may either be omitted (int itk<ClassName>Test( int, char⋆ [] )), or the itkNotUsed macro can be used (int itk<ClassName>Test( int itkNotUsed( argc ), char ⋆itkNotUsed( argv ) [] )), to avoid compiler warnings about unused variables.
The number of input arguments provided must be checked at the beginning of the test. If a test requires a fixed number of input arguments, then the argument number check should verify the exact number of arguments.
It is essential that a test is made quantitative, i.e., the methods’ returned values and the test’s output must be compared to a known ground-truth. As mentioned, ITK contains a series of methods to compare basic types. ITK also provide a powerful regression tool for a test that checks the validity of a process over an image, which is the most common case in ITK. To this end, the test is expected to write its output to a file. The first time the test is run, the output is expected to be manually placed within the test module’s Baseline folder. Hence, when CTest is executed, the distance between the test’s output and the expected output (i.e., the baseline) is computed. If the distance is below a configurable tolerance, the regression test is marked as a success.
Wrapping for programming languages like Python can be added to a module through a simple configuration in the module’s wrapping directory. While wrapping is almost entirely automatic, configuration is necessary to add two pieces of information,
When wrapping a class, dependencies, like the base class and other types used in the wrapped class’s interface, should also be wrapped. The wrapping system will emit a warning when a base class or other required type is not already wrapped to ensure proper wrapping coverage. Since module dependencies are wrapped by the build system before the current module, class wrapping build order is already correct module-wise. However, it may be required to wrap classes within a module in a specific order; this order can be specified in the wrapping/CMakeLists.txt file.
Many ITK classes are templated, which allows an algorithm to be written once yet compiled into optimized binary code for numerous pixel types and spatial dimensions. When wrapping these templated classes, the template instantiations to wrap must be chosen at build time. The template that should be used are configured in a module’s ⋆.wrap files. Wrapping is configured by calling CMake macros defined in the ITK/Wrapping/TypedefMacros.cmake file.
The wrapping/CMakeLists.txt file calls three macros, and optionally set a variable, WRAPPER_SUBMODULE_ORDER. The following example is from the ITKImageFilterBase module:
The itk_wrap_module macro takes the current module name as an argument. In some cases, classes defined in the ⋆.wrap files within a module may depend each other. The WRAPPER_SUBMODULE_ORDER variable is used to declare which submodules should be wrapped first and the order they should be wrapped.
Wrapping specification for classes is written in the module’s ⋆.wrap CMake script files. These files call wrapping CMake macros, and they specify which classes to wrap, whether smart pointer’s should be wrapped for the the class, and which template instantiations to wrap for a class.
Overall toolkit class template instantiations are parameterized by the CMake build configuration variables shown in Table 9.1. The wrapping configuration refers to these settings with the shorthand values listed in the second column.
CMake variable | Wrapping shorthand value |
ITK_WRAP_IMAGE_DIMS | List of unsigned integers |
ITK_WRAP_VECTOR_COMPONENTS | List of unsigned integers |
ITK_WRAP_double | D |
ITK_WRAP_float | F |
ITK_WRAP_complex_double | CD |
ITK_WRAP_complex_float | CF |
ITK_WRAP_vector_double | VD |
ITK_WRAP_vector_float | VF |
ITK_WRAP_covariate_vector_double | CVD |
ITK_WRAP_covariate_vector_float | CVF |
ITK_WRAP_signed_char | SC |
ITK_WRAP_signed_short | SS |
ITK_WRAP_signed_long | SL |
ITK_WRAP_unsigned_char | UC |
ITK_WRAP_unsigned_short | US |
ITK_WRAP_unsigned_long | UL |
ITK_WRAP_rgb_unsigned_char | RGBUC |
ITK_WRAP_rgb_unsigned_short | RGBUS |
ITK_WRAP_rgba_unsigned_char | RGBAUC |
ITK_WRAP_rgba_unsigned_short | RGBAUS |
Class wrap files call sets of wrapping macros for the class to be wrapped. The macros are often called in loops over the wrapping variables to instatiate the desired types. The following example demonstates wrapping the itk::ImportImageFilter class, taken from the ITK/Modules/Core/Common/wrapping/itkImportImageFilter.wrap file.
Instantiations for classes are determined by looping over CMake lists that collect sets of shorthand wrapping values, namely,
Templated classes are wrapped as type aliases for particular instantiations. The type aliases are named with a name mangling scheme for the template parameter types. The mangling of common types are stored in CMake variables listed in Table 9.2, Table 9.3, and Table 9.4. Mangling variables start with the prefix ITKM_ and their corresponding C++ type variables start with the prefix ITKT_.
CMake Variable | Value | |
Mangling | ITKM_B | B |
C++ Type | ITKT_B | bool |
Mangling | ITKM_UC | UC |
C++ Type | ITKT_UC | unsigned char |
Mangling | ITKM_US | US |
C++ Type | ITKT_US | unsigned short |
Mangling | ITKM_UI | UI |
C++ Type | ITKT_UI | unsigned integer |
Mangling | ITKM_UL | UL |
C++ Type | ITKT_UL | unsigned long |
Mangling | ITKM_SC | SC |
C++ Type | ITKT_SC | signed char |
Mangling | ITKM_SS | SS |
C++ Type | ITKT_SS | signed short |
Mangling | ITKM_SI | SI |
C++ Type | ITKT_SI | signed integer |
Mangling | ITKM_UL | UL |
C++ Type | ITKT_UL | signed long |
Mangling | ITKM_F | F |
C++ Type | ITKT_F | float |
Mangling | ITKM_D | D |
C++ Type | ITKT_D | double |
CMake Variable | Value | |
Mangling | ITKM_C${type} | C${type} |
C++ Type | ITKT_C${type} | std::complex<${type}> |
Mangling | ITKM_A${type} | A${type} |
C++ Type | ITKT_A${type} | itk::Array<${type}> |
Mangling | ITKM_FA${ITKM_${type}}${dim} | FA${ITKM_${type}}${dim} |
C++ Type | ITKT_FA${ITKM_${type}}${dim} | itk::FixedArray<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_RGB${dim} | RGB${dim} |
C++ Type | ITKT_RGB${dim} | itk::RGBPixel<${dim}> |
Mangling | ITKM_RGBA${dim} | RGBA${dim} |
C++ Type | ITKT_RGBA${dim} | itk::RGBAPixel<${dim}> |
Mangling | ITKM_V${ITKM_${type}}${dim} | V${ITKM_${type}}${dim} |
C++ Type | ITKT_V${ITKM_${type}}${dim} | itk::Vector<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_CV${ITKM_${type}}${dim} | CV${ITKM_${type}}${dim} |
C++ Type | ITKT_CV${ITKM_${type}}${dim} | itk::CovariantVector<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_VLV${ITKM_${type}}${dim} | VLV${ITKM_${type}}${dim} |
C++ Type | ITKT_VLV${ITKM_${type}}${dim} | itk::VariableLengthVector<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_SSRT${ITKM_${type}}${dim} | SSRT${ITKM_${type}}${dim} |
C++ Type | ITKT_SSRT${ITKM_${type}}${dim} | itk::SymmetricSecondRankTensor<${ITKT_${type}}, ${dim}> |
CMake Variable | Value | |
Mangling | ITKM_O${dim} | O${dim} |
C++ Type | ITKT_O${dim} | itk::Offset<${dim}> |
Mangling | ITKM_CI${ITKM_${type}}${dim} | CI${ITKM_${type}}${dim} |
C++ Type | ITKT_CI${ITKM_${type}}${dim} | itk::ContinuousIndex<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_P${ITKM_${type}}${dim} | P${ITKM_${type}}${dim} |
C++ Type | ITKT_P${ITKM_${type}}${dim} | itk::Point<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_I${ITKM_${type}}${dim} | I${ITKM_${type}}${dim} |
C++ Type | ITKT_I${ITKM_${type}}${dim} | itk::Image<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_VI${ITKM_${type}}${dim} | VI${ITKM_${type}}${dim} |
C++ Type | ITKT_VI${ITKM_${type}}${dim} | itk::VectorImage<${ITKT_${type}}, ${dim}> |
Mangling | ITKM_SO${dim} | SO${dim} |
C++ Type | ITKT_SO${dim} | itk::SpatialObject<${dim}> |
Mangling | ITKM_SE${dim} | SE${dim} |
C++ Type | ITKT_SE${dim} | itk::FlatStructuringElement<${dim}> |
Mangling | ITKM_H${ITKM_${type}} | H${ITKM_${type}} |
C++ Type | ITKT_H${ITKM_${type}} | itk::Statistics::Histogram<${ITKT${type}}> |
Mangling | ITKM_ST | Depends on platform |
C++ Type | ITKT_ST | itk::SizeValueType |
Mangling | ITKM_IT | Depends on platform |
C++ Type | ITKM_IT | itk::IdentifierType |
Mangling | ITKM_OT | Depends on platform |
C++ Type | ITKT_OT | itk::OffsetValueType |
There are a number of a wrapping macros called in the wrapping/⋆.wrap files. Macros are specialized for classes that use itk::SmartPointers and templated classes.
For non-templated classes, the itk_wrap_simple_class is used. This macro takes fully qualified name of the class as an argument. Lastly, the macro takes an optional argument that can have the values POINTER, POINTER_WITH_CONST_POINTER, or POINTER_WITH_SUPERCLASS. If this argument is passed, then the type alias classname::Pointer, classname::Pointer and classname::ConstPointer, or classname::Pointer and classname::Superclass::Pointer are wrapped. Thus, the wrapping configuration for itk::Object is
When wrapping templated classes, three or more macro calls are required. First, itk_wrap_class is called. Again, its arguments are the fully qualified followed by an option argument that can have the value POINTER, POINTER_WITH_CONST_POINTER, POINTER_WITH_SUPERCLASS, POINTER_WITH_2_SUPERCLASSES, EXPLICIT_SPECIALIZATION, POINTER_WITH_EXPLICIT_SPECIALIZATION, ENUM, or AUTOPOINTER. Next, a series of calls are made to macros that declare which templates to instantiate. Finally, the itk_end_wrap_class macro is called, which has no arguments.
The most general template wrapping macro is itk_wrap_template. Two arguments are required. The first argument is a mangled suffix to be added to the class name, which uniquely identifies the instantiation. This argument is usually specified at least partially with ITKM_ mangling variables. The second argument is the is template instantiation in C++ form. This argument is usually specified at least partially with ITKT_ C++ type variables. For example, wrapping for itk::ImageSpatialObject, which templated a dimension and pixel type, is configured as
# unsigned char required for the ImageMaskSpatialObject
UNIQUE(types "UC;${WRAP_ITK_SCALAR}")
foreach(d ${ITK_WRAP_IMAGE_DIMS})
foreach(t ${types})
itk_wrap_template("${d}${ITKM_${t}}" "${d},${ITKT_${t}}")
endforeach()
endforeach()
itk_end_wrap_class()
In addition to itk_wrap_template, there are template wrapping macros specialized for wrapping image filters. The highest level macro is itk_wrap_image_filter, which is used for wrapping image filters that need one or more image parameters of the same type. This macro has two required arguments. The first argument is a semicolon delimited CMake list of pixel types. The second argument is the number of image template arguments for the filter. An optional third argument is a dimensionality condition to restrict the dimensions that the filter can be instantiated. The dimensionality condition can be a number indicating the dimension allowed, a semicolon delimited CMake list of dimensions, or a string of the form n+, where n is a number, to indicate that instantiations are allowed for dimension n and above. The wrapping specification for itk::ThresholdMaximumConnectedComponentsImageFilter is
If it is desirable or required to instantiate an image filter with different image types, the itk_wrap_image_filter_combinations macro is applicable. This macro takes a variable number of parameters, where each parameter is a list of the possible image pixel types for the corresponding filter template parameters. A condition to restrict dimensionality may again be optionally passed as the last argument. For example, wrapping for itk::VectorMagnitudeImageFilter is specified with
The final template wrapping macro is itk_wrap_image_filter_types. This macro takes a variable number of arguments that should correspond to the image pixel types in the filter’s template parameter list. Again, an optional dimensionality condition can be specified as the last argument. For example, wrapping for itk::RGBToLuminanceImageFilter is specified with
if(ITK_WRAP_rgb_unsigned_char AND ITK_WRAP_unsigned_char)
itk_wrap_image_filter_types(RGBUC UC)
endif(ITK_WRAP_rgb_unsigned_char AND ITK_WRAP_unsigned_char)
if(ITK_WRAP_rgb_unsigned_short AND ITK_WRAP_unsigned_short)
itk_wrap_image_filter_types(RGBUS US)
endif(ITK_WRAP_rgb_unsigned_short AND ITK_WRAP_unsigned_short)
if(ITK_WRAP_rgba_unsigned_char AND ITK_WRAP_unsigned_char)
itk_wrap_image_filter_types(RGBAUC UC)
endif(ITK_WRAP_rgba_unsigned_char AND ITK_WRAP_unsigned_char)
if(ITK_WRAP_rgba_unsigned_short AND ITK_WRAP_unsigned_short)
itk_wrap_image_filter_types(RGBAUS US)
endif(ITK_WRAP_rgba_unsigned_short AND ITK_WRAP_unsigned_short)
itk_end_wrap_class()
In some cases, it necessary to specify the headers required to build wrapping sources for a class. To specify additional headers to included in the generated wrapping C++ source, use the itk_wrap_include macro. This macro takes the name of the header to include, and it can be called multiple times.
By default, the class wrapping macros include a header whose filename corresponds to the name of the class to be wrapped according to ITK naming conventions. To override the default behavior, set the CMake variable WRAPPER_AUTO_INCLUDE_HEADERS to OFF before calling itk_wrap_class. For example,
There are a number of convenience CMake macros available to manipulate lists of template parameters. These macros take the variable name to populate with their output as the first argument followed by input arguments. The itk_wrap_filter_dims macro will process the dimensionality condition previously described for the filter template wrapping macros. DECREMENT, INCREMENT are macros that operate on dimensions. The INTERSECTION macro finds the intersection of two list arguments. Finally, the UNIQUE macro removes duplicates from the given list.
When an ITK module depends on another ITK module, it simply lists its dependencies as described in Section 9.1. A module can also depend on non-ITK third-party libraries. This third-party library can be encapsulated in an ITK module – see examples in the ITK/Modules/ThirdParty directory. Or, the dependency can be built or installed on the system and found with CMake. This section describes how to add the CMake configuration to a module for it to find and use a third-party library dependency.
The itk-module-init.cmake file, if present, is found in the top level directory of the module next to the itk-module.cmake file. This file informs CMake of the build configuration and location of the third-party dependency. To inform CMake about the OpenCV library, use the find_package command,
A few additions are required to the top level CMakeLists.txt of the module.
First, the itk-module-init.cmake file should be explicitly included when building the module externally against an existing ITK build tree.
Optionally, the dependency libraries are added to the <module-name>_LIBRARIES variable. Alternatively, if the module creates a library, publically link to the dependency libraries. Our ITKVideoBridgeOpenCV module example creates its own library, named ITKVideoBridgeOpenCV, and publically links to the OpenCV libraries.
CMakeLists.txt:
src/CMakeLists.txt:
Next, CMake export code is created. This code is loaded by CMake when another project uses this module. The export code stores where the dependency was located when the module was built, and how CMake should find it. Two versions are required for the build tree and for the install tree.
set(ITKVideoBridgeOpenCV_EXPORT_CODE_INSTALL "
set(OpenCV_DIR \"${OpenCV_DIR}\")
find_package(OpenCV REQUIRED)
")
set(ITKVideoBridgeOpenCV_EXPORT_CODE_BUILD "
if(NOT ITK_BINARY_DIR)
set(OpenCV_DIR \"${OpenCV_DIR}\")
find_package(OpenCV REQUIRED)
endif()
")
Finally, set the <module-name>_SYSTEM_INCLUDE_DIRS and <module-name>_SYSTEM_LIBRARY_DIRS, if required, to append compilation header directories and library linking directories for this module.
For most ITK community members, the modularization of the toolkit is relatively transparent. The default configuration includes all the (default) modules into the ITK library, which is used to build their own ITK applications.
For ITK developers and code contributors, the modular structure imposes rules for organizing the source code, building the library and contributing to the ITK source code repository.
A Module may be developed outside the main ITK repository, but it may be made available in the ITK repository as a Remote Module. The Remote Module infrastructure enables fast dissemination of research code through ITK without increasing the size of the main repository. The Insight Journal (http://www.insight-_journal.org/) adds support for ITK module submissions with automatic dashboard testing (see Section ?? on page ?? for further details).
The source code of a Remote Module can be downloaded by CMake (with a CMake variable switch) at ITK CMake configuration time, making it a convenient way to distribute modular source code.
A module can be added to the list of remotes if it satisfies the following criteria:
At the beginning of the release candidate phase of a release, maintainers of failing module dashboard builds will be contacted. If a module’s dashboard submission is still failing at the last release candidate tagging, it will be removed before the final release.
Module names must be unique.
At no time in the future should a module in the main repository depend on a Remote Module.
The repository
provides a useful template to be used as a starting point for a new ITK module.
The procedure to publish a new module in ITK is summarized as follows:
After the Remote Module has experienced sufficient testing, and community members express broad interest in the contribution, the submitter can then move the contribution into the ITK repository via GitHub code review.
It is possible but not recommended to directly push a module to GitHub for review without submitting to Insight Journal first.