This mechanism sets up CMake variables that allow a user to select which modules/libraries to create. Dependencies will be tracked down to ensure that all of a module's dependencies are also enabled. The modules are also arranged into groups. Groups allow you to set the enable flag for a group of modules at once. Thus, if you have several modules that are likely to be used together, you can create a group for them. This can be handy in converting user-friendly CMake options (such as `VTKm_ENABLE_RENDERING`) to the modules that enable that by pointing to the appropriate group.
10 KiB
Specifying modules in the VTK-m build system
The VTK-m build system comes with a module mechanism that allows a library or other target be optionally compiled based on CMake configuration variables. Additionally, modules can be optionally compiled based on their dependencies. That is, a module can be turned on if a module that depends on it wants to be compiled. Likewise, a module can be turned off if a module that it depends on cannot be compiled.
Module configuration
All modules have a "name" that is the same as the target created by the
module (for example, the name of a library). Every module has an associated
(advanced) CMake variable named VTKm_MODULE_ENABLE_<name>
. For example,
the module that builds the vtkm_filter_entity_extraction
filter has an
associated CMake variable named
VTKm_MODULE_ENABLE_vtkm_filter_entity_extraction
. This CMake variable can
be used to control whether the module should be included in the build. It
can be set to one of the following values.
YES
: Always create the module. If it is not possible to create the module, the CMake configuration fails.WANT
: Create the module if possible. If it is possible to create all modules it depends on, then this module will be created. If this is not possible, this module will not be created, but this will not cause an error in the configuration.DONT_WANT
: Create the module only if there is a dependency that requires it. This is useful for stripping out modules not directly needed but required for a select list of modules desired.NO
: Never create the module. Any module that depends on this module will also not be built.DEFAULT
: Does the default behavior. This is typically eitherWANT
orDONT_WANT
depending on other configuration.
The advantage of having these multiple options is that it becomes possible to turn off all modules except a select desired few and have the CMake configuration automatically determine dependencies.
Module groups
Modules can also declare themselves as part of a group. Module groups
provide a way to turn on/off the build of several related modules. For
example, there is a module group named FiltersCommon
that contains
modules with the most commonly used filters in VTK-m.
Every module group has an associated (advanced) CMake variable named
VTKm_GROUP_ENABLE_<name>
. For example, the FiltersCommon
group has an
associated CMake variable named VTKm_GROUP_ENABLE_FiltersCommon
. This
variable can be set to the same YES
/WANT
/DONT_WANT
/NO
/DEFAULT
values as those for the VTKm_MODULE_ENABLE
variables described earlier.
Default behavior
If a VTKm_MODULE_ENABLE_*
variable is set to DEFAULT
, then the
configuration first checks all the VTKm_GROUP_ENABLE_*
variables
associated with the groups the module belongs to. It will use the first
value not set to DEFAULT
that it encounters.
If all the module's group are also set to DEFAULT
(or the module does not
belong to any groups) then the behavior is based on the
VTKm_BUILD_ALL_LIBRARIES
CMake variable. If VTKm_BUILD_ALL_LIBRARIES
is
ON
, then the default behavior becomes WANT
. Otherwise, it becomes
DONT_WANT
.
Specifying a module
A module is created in much the same way as a normal target is made in
CMake: Create a directory with the appropriate source material and add a
CMakeLists.txt
file to specify how they are built. However, the main
difference is that you do not link to the directory with a CMake
add_subdirectory
command (or any other command like include
or
subdirs
).
Instead, you simply create a file named vtkm.module
and place it in the
same directory with the CMakeLists.txt
file. The VTK-m configuration will
automatically find this vtkm.module
file, recognize the directory as
containing a module, and automatically include the associated
CMakeLists.txt
in the build (given that the CMake configuration turns on
the module to be compiled).
Each vtkm.module
is a simple text file that contains a list of options.
Each option is provided by giving the name of the option followed by the
arguments for that option. The following options can be defined in a
vtkm.module
file. NAME
is required, but the rest are optional.
NAME
: The name of the target created by the module.GROUPS
: A list of all groups the module belongs to. If a module's enable flag is set toDEFAULT
, then the enable option is taken from the groups it belongs to.DEPENDS
: A list of all modules (or other libraries) on which this module depends. Everything in this list is added as a link library to the library created withvtkm_library
.PRIVATE_DEPENDS
: Same asDEPENDS
except that these libraries are added as private link libraries.OPTIONAL_DEPENDS
: A list of all modules that that are not strictly needed but will be used if available.TEST_DEPENDS
: A list of all modules (or other libraries) on which the tests for this module depends.TEST_OPTIONAL_DEPENDS
: A list of all modules that the test executable will like to if they exist, but are not necessary.NO_TESTING
: Normally, a module is expected to have a subdirectory namedtesting
, which will build any necessary testing executables and add ctest tests. If this option is given, no tests are added. (Note, modules generally should have tests.)
A vtkm.module
file may also have comments. Everything between a #
and
the end of the line will be ignored.
As an example, the vtkm_filter_entity_extraction
module (located in
vtkm/filter/entity_extraction
has a vtkm.module
file that looks like
the following.
NAME
vtkm_filter_entity_extraction
GROUPS
FiltersCommon
Filters
DEPENDS
vtkm_worklet
vtkm_filter_core
vtkm_filter_clean_grid
TEST_DEPENDS
vtkm_filter_clean_grid
vtkm_filter_entity_extraction
vtkm_source
Building the module
As mentioned earlier, a VTK-m module directory has its own
CMakeLists.txt
. There does not have to be anything particularly special
about the CMakeLists.txt
. If the module is building a library target
(which is typical), it should use the vtkm_library
CMake command to do so
to make sure the proper compiler flags are added.
Here is an example portion of the CMakeLists.txt
for the
vtkm_filter_entity_extraction
module. (Mainly, the definition of
variables containing source and header files is left out.)
vtkm_library(
NAME vtkm_filter_entity_extraction
HEADERS ${entity_extraction_headers}
DEVICE_SOURCES ${entity_extraction_sources_device}
USE_VTKM_JOB_POOL
)
target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_entity_extraction)
Note that if a library created by a module depends on the library created
by another module, it should be in the DEPENDS
list of vtkm.module
. For
example, the vtkm.module
contains vtkm_filter_clean_grid
in its
DEPENDS
list, and that library will automatically be added as a target
link library to vtkm_filter_entity_extraction
. You should avoid using
target_link_libraries
to link one module to another as the modules will
not be able to guarantee that all the targets will be created correctly.
Also note that the CMakeLists.txt
file should not include its testing
directory with add_subdirectory
. As described in the next section, the
testing directory will automatically be added, if possible. (Using
add_subdirectory
for other subdirectories on which the module depends is
OK.)
Module testing directory
All modules are expected to have a testing
subdirectory. This
subdirectory should contain its own CMakeLists.txt
that, typically,
builds a testing executable and adds the appropriate tests. (This is
usually done with the vtkm_unit_tests
CMake function.)
However, a module should not include its own testing
directory with
add_subdirectory
. This is because the tests for a module might have
dependencies that the module itself does not. For example, it is common for
filter tests to use a source to generate some test data. But what if the
CMake configuration has the source module turned off? Should the filter
module be turned off because the tests need the source module? No. Should
the source module be turned on just because some tests want it? No.
To resolve this issue, VTK-m modules allow for an extended set of
dependencies for the tests. This is specified with the TEST_DEPENDS
variable in vtkm.module
. It will then add the test only if all the test
dependencies are met.
If the dependencies for both the module itself and the module's tests are
met, then the testing
subdirectory of the module will be added to the
build. Like for the module itself, the CMakeLists.txt
in the testing
directory should build tests just like any other CMake directory. Here is
an example CMakeLists.txt
for the vtkm_filter_entity_extraction
module.
set(unit_tests
UnitTestExternalFacesFilter.cxx
UnitTestExtractGeometryFilter.cxx
UnitTestExtractPointsFilter.cxx
UnitTestExtractStructuredFilter.cxx
UnitTestGhostCellRemove.cxx
UnitTestMaskFilter.cxx
UnitTestMaskPointsFilter.cxx
UnitTestThresholdFilter.cxx
UnitTestThresholdPointsFilter.cxx
)
set(libraries
vtkm_filter_clean_grid
vtkm_filter_entity_extraction
vtkm_source
)
vtkm_unit_tests(
SOURCES ${unit_tests}
LIBRARIES ${libraries}
USE_VTKM_JOB_POOL
)
Testing if a module is being built
The easiest way to test if a module is being built (in CMake) is to check whether the associated target exists.
if(TARGET vtkm_filter_entity_extraction)
# Do stuff dependent on vtkm_filter_entity_extraction library/module
endif()
Note that this only works in a module if the module properly depends on the named target. It only works outside of modules if modules have already been processed.
Debugging modules
Because modules depend on each other, and these dependencies affect whether
a particular module will be built, it can sometimes be difficult to
understand why a particular module is or is not built. To help diagnose
problems with modules, you can turn on extra reporting with the
VTKm_VERBOSE_MODULES
CMake variable.
When VTKm_VERBOSE_MODULES
is set to OFF
(the default), then the parsing
and dependency resolution of the modules is silent unless there is an
error. When VTKm_VERBOSE_MODULES
is set to ON
, then information about
what modules are found, which modules are built, and why they are or are
not built are added as status messages during CMake configuration.