diff --git a/CMake/VTKConfig.cmake.in b/CMake/VTKConfig.cmake.in index 8042930a7bdde23ecb4f5e7ee2fc8a46c4a15fbe..3102900ff2680b2028992020c297a7a7ea228d67 100644 --- a/CMake/VTKConfig.cmake.in +++ b/CMake/VTKConfig.cmake.in @@ -83,6 +83,7 @@ SET(VTK_WRAP_PYTHON "@VTK_WRAP_PYTHON@") SET(VTK_WRAP_TCL "@VTK_WRAP_TCL@") SET(VTK_WRAP_JAVA "@VTK_WRAP_JAVA@") SET(VTK_QT_VERSION "@VTK_QT_VERSION@") +SET(VTK_ENABLE_KITS "@VTK_ENABLE_KITS@") # Do not add options or information here that is specific to a # particular module. Instead set <module>_EXPORT_OPTIONS and/or diff --git a/CMake/vtkModuleTop.cmake b/CMake/vtkModuleTop.cmake index d10dd488b97978b24ac6f92f67440dfc9c3fd0e4..53adb15fbd0a806ed579594da8c674b7a7db69e7 100644 --- a/CMake/vtkModuleTop.cmake +++ b/CMake/vtkModuleTop.cmake @@ -238,6 +238,8 @@ if(VTK_ENABLE_KITS) endforeach() endforeach() + list(REMOVE_DUPLICATES vtk_kits) + # Put all kits in the list (if they are not dependencies of any module, they # will be dropped otherwise). list(APPEND vtk_modules_and_kits ${vtk_kits}) diff --git a/CMake/vtkPythonWrapping.cmake b/CMake/vtkPythonWrapping.cmake index 217dfcf09632c5eb7309a40af8d7423a1173a413..1f6497efc007fa03937673832e77a711c97a8160 100644 --- a/CMake/vtkPythonWrapping.cmake +++ b/CMake/vtkPythonWrapping.cmake @@ -8,7 +8,34 @@ if(PYTHONINTERP_FOUND AND PYTHONLIBS_FOUND) endif() endif() -function(vtk_add_python_wrapping module_name) +# To support wrapping of either module or kit, this function +# has two signatures: +# 1) vtk_add_python_wrapping(<module_name> <sources_var>) +# 2) vtk_add_python_wrapping("<module_name>[ <module_name>]" <sources_var> <kit_name>) +# +# Legacy code may call this function with a single argument. In that case, +# vtk_add_python_wrapping_library() is called internally to maintain backwards +# compatibility. +function(vtk_add_python_wrapping module_names) + if(${ARGC} EQUAL 1) + set(_legacy TRUE) + message(AUTHOR_WARNING + "Calling vtk_add_python_wrapping() with a single argument is deprecated.\n" + "Replace calls like:\n" + " vtk_add_python_wrapping(\${module})\n" + "with:\n" + " vtk_add_python_wrapping(\${module} module_srcs)\n" + " vtk_add_python_wrapping_library(\${module} module_srcs \${module})") + endif() + if("${ARGV1}" MATCHES ".+") + set(sources_var ${ARGV1}) + endif() + if("${ARGV2}" MATCHES ".+") + list(REMOVE_AT ARGN 0) + set(target ${ARGN}) + else() + set(target ${module_names}) + endif() if(NOT VTK_WRAP_PYTHON_INIT_EXE) if(TARGET vtkWrapPythonInit) set (VTK_WRAP_PYTHON_INIT_EXE vtkWrapPythonInit) @@ -16,6 +43,37 @@ function(vtk_add_python_wrapping module_name) message(FATAL_ERROR "VTK must be built with Python wrapping turned on.") endif() endif() + + set(EXTRA_PYTHON_INCLUDE_DIRS) + set(KIT_HIERARCHY_FILE) + set(VTK_WRAP_HINTS_FILES) + + foreach(module_name IN LISTS module_names) + list(APPEND EXTRA_PYTHON_INCLUDE_DIRS ${${module_name}_PYTHON_INCLUDE_DIRS}) + + if(NOT ${module_name}_EXCLUDE_FROM_WRAP_HIERARCHY) + list(APPEND KIT_HIERARCHY_FILE ${${module_name}_WRAP_HIERARCHY_FILE}) + endif() + + if(${module_name}_WRAP_HINTS AND EXISTS "${${module_name}_WRAP_HINTS}") + list(APPEND VTK_WRAP_HINTS_FILES "${${module_name}_WRAP_HINTS}") + endif() + endforeach() + + if(VTK_WRAP_HINTS_FILES) + set(VTK_WRAP_HINTS ${VTK_WRAP_HINTS_FILES}) + endif() + + vtk_wrap_python(${target}Python Python_SRCS "${module_names}") + if(_legacy) + set(_sources "${Python_SRCS}" "${extra_srcs}") + vtk_add_python_wrapping_library(${module_names} _sources ${module_names}) + else() + set(${sources_var} "${Python_SRCS}" "${extra_srcs}" PARENT_SCOPE) + endif() +endfunction() + +function(vtk_add_python_wrapping_library module srcs) # Need to add the Wrapping/Python to the include directory set(_python_include_dirs ${VTK_SOURCE_DIR}/Wrapping/Python @@ -23,57 +81,52 @@ function(vtk_add_python_wrapping module_name) ${VTK_SOURCE_DIR}/Utilities/Python ${VTK_BINARY_DIR}/Utilities/Python ${PYTHON_INCLUDE_DIRS}) + set(XY ${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION}) if(NOT CMAKE_HAS_TARGET_INCLUDES) include_directories(${_python_include_dirs}) endif() - if(NOT ${module_name}_EXCLUDE_FROM_WRAP_HIERARCHY) - set(KIT_HIERARCHY_FILE ${${module_name}_WRAP_HIERARCHY_FILE}) - endif() - - string(REGEX REPLACE "^vtk" "" kit_name "${module_name}") - set(KIT ${kit_name}) - set(XY ${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION}) - # Figure out the dependent PythonXYD libraries for the module - unset(extra_links) - set(EXTRA_PYTHON_INCLUDE_DIRS ${${module_name}_PYTHON_INCLUDE_DIRS}) - foreach(dep ${${module_name}_DEPENDS}) - if(NOT "${module_name}" STREQUAL "${dep}" AND TARGET ${dep}PythonD) + set(extra_links) + foreach(dep IN LISTS ${module}_DEPENDS) + if(NOT "${module}" STREQUAL "${dep}" AND TARGET ${dep}PythonD) list(APPEND extra_links ${dep}PythonD) endif() endforeach() - if(${module_name}_WRAP_HINTS AND EXISTS "${${module_name}_WRAP_HINTS}") - set(VTK_WRAP_HINTS "${${module_name}_WRAP_HINTS}") - endif() - - vtk_wrap_python(${module_name}Python Python_SRCS ${module_name}) - vtk_add_library(${module_name}PythonD ${Python_SRCS} ${extra_srcs}) - get_property(output_name TARGET ${module_name}PythonD PROPERTY OUTPUT_NAME) + vtk_add_library(${module}PythonD ${${srcs}}) + get_property(output_name TARGET ${module}PythonD PROPERTY OUTPUT_NAME) string(REPLACE "PythonD" "Python${XY}D" output_name "${output_name}") - set_property(TARGET ${module_name}PythonD PROPERTY OUTPUT_NAME ${output_name}) + set_property(TARGET ${module}PythonD PROPERTY OUTPUT_NAME ${output_name}) if(CMAKE_HAS_TARGET_INCLUDES) - set_property(TARGET ${module_name}PythonD APPEND + set_property(TARGET ${module}PythonD APPEND PROPERTY INCLUDE_DIRECTORIES ${_python_include_dirs}) endif() - if(${module_name}_IMPLEMENTS) - set_property(TARGET ${module_name}PythonD PROPERTY COMPILE_DEFINITIONS - "${module_name}_AUTOINIT=1(${module_name})") - endif() - target_link_libraries(${module_name}PythonD LINK_PUBLIC ${module_name} + target_link_libraries(${module}PythonD LINK_PUBLIC vtkWrappingPythonCore ${extra_links} ${VTK_PYTHON_LIBRARIES}) if (MSVC) - set_target_properties(${module_name}PythonD + set_target_properties(${module}PythonD PROPERTIES STATIC_LIBRARY_FLAGS ${CMAKE_MODULE_LINKER_FLAGS}) endif() - _vtk_add_python_module(${module_name}Python ${module_name}PythonInit.cxx) - target_link_libraries(${module_name}Python ${module_name}PythonD) + foreach (submodule IN LISTS ARGN) + if(${submodule}_IMPLEMENTS) + set_property(TARGET ${module}PythonD APPEND PROPERTY COMPILE_DEFINITIONS + "${submodule}_AUTOINIT=1(${submodule})") + endif() + target_link_libraries(${module}PythonD LINK_PUBLIC ${submodule}) + endforeach () + + set(prefix ${module}) + if(_${module}_is_kit) + set(prefix ${prefix}${VTK_KIT_SUFFIX}) + endif() + _vtk_add_python_module(${module}Python ${prefix}PythonInit.cxx) + target_link_libraries(${module}Python ${module}PythonD) if(CMAKE_HAS_TARGET_INCLUDES) - set_property(TARGET ${module_name}Python APPEND + set_property(TARGET ${module}Python APPEND PROPERTY INCLUDE_DIRECTORIES ${_python_include_dirs}) endif() endfunction() diff --git a/CMake/vtkWrapPython.cmake b/CMake/vtkWrapPython.cmake index e550a6c0a69d551018edf4771b46b0e29cc69810..eecb44c2dc7f487bca5fe93e38bf9c3d1623b137 100644 --- a/CMake/vtkWrapPython.cmake +++ b/CMake/vtkWrapPython.cmake @@ -36,12 +36,12 @@ macro(VTK_WRAP_PYTHON3 TARGET SRC_LIST_NAME SOURCES) # collect the common wrapper-tool arguments set(_common_args) - if(VTK_WRAP_HINTS) - set(_common_args "${_common_args}--hints \"${VTK_WRAP_HINTS}\"\n") - endif() - if(KIT_HIERARCHY_FILE) - set(_common_args "${_common_args}--types \"${KIT_HIERARCHY_FILE}\"\n") - endif() + foreach(file IN LISTS VTK_WRAP_HINTS) + set(_common_args "${_common_args}--hints \"${file}\"\n") + endforeach() + foreach(file IN LISTS KIT_HIERARCHY_FILE) + set(_common_args "${_common_args}--types \"${file}\"\n") + endforeach() if(NOT CMAKE_VERSION VERSION_LESS 3.1 AND NOT VTK_ENABLE_KITS) # write wrapper-tool arguments to a file @@ -56,13 +56,21 @@ $<$<BOOL:$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>>: ") else() # all the include directories - string(REGEX REPLACE "Python\$" "" module "${TARGET}") - if(${module}_INCLUDE_DIRS) - set(TMP_INCLUDE_DIRS ${${module}_INCLUDE_DIRS}) - elseif(VTK_WRAP_INCLUDE_DIRS) - set(TMP_INCLUDE_DIRS ${VTK_WRAP_INCLUDE_DIRS}) + set(TMP_INCLUDE_DIRS) + set(_modules ${ARGN}) + if(NOT _modules) + string(REGEX REPLACE "Python\$" "" module "${TARGET}") + set(_modules ${module}) + endif() + foreach(module IN LISTS ${_modules}) + if(${module}_INCLUDE_DIRS) + list(APPEND TMP_INCLUDE_DIRS ${${module}_INCLUDE_DIRS}) + endif() + endforeach() + if(VTK_WRAP_INCLUDE_DIRS) + list(APPEND TMP_INCLUDE_DIRS ${VTK_WRAP_INCLUDE_DIRS}) else() - set(TMP_INCLUDE_DIRS ${VTK_INCLUDE_DIRS}) + list(APPEND TMP_INCLUDE_DIRS ${VTK_INCLUDE_DIRS}) endif() if(EXTRA_PYTHON_INCLUDE_DIRS) list(APPEND TMP_INCLUDE_DIRS ${EXTRA_PYTHON_INCLUDE_DIRS}) @@ -220,11 +228,13 @@ macro(vtk_find_header header include_dirs full_path) endforeach() endmacro() -# Macro that just takes the name of the module, figure the rest out from there. -macro(vtk_wrap_python TARGET SRC_LIST_NAME module) +# Macro that just takes the a list of module names, figure the rest out from there. +macro(vtk_wrap_python TARGET SRC_LIST_NAME) # List of all headers to wrap. set(headers_to_wrap) + foreach(module ${ARGN}) + # Decide what to do for each header. foreach(header ${${module}_HEADERS}) # Everything in this block is for headers that will be wrapped. @@ -241,6 +251,8 @@ macro(vtk_wrap_python TARGET SRC_LIST_NAME module) endif() endforeach() + endforeach() # end ARGN loop + # Delegate to vtk_wrap_python3 - vtk_wrap_python3(${TARGET} ${SRC_LIST_NAME} "${headers_to_wrap}") + vtk_wrap_python3(${TARGET} ${SRC_LIST_NAME} "${headers_to_wrap}" ${ARGN}) endmacro() diff --git a/Wrapping/Python/CMakeLists.txt b/Wrapping/Python/CMakeLists.txt index ff9706e8927e29bc8b7673bcb7aaf73a7f48cdf5..1e8ab79095012034fe40803c27a7d6c334d989f4 100644 --- a/Wrapping/Python/CMakeLists.txt +++ b/Wrapping/Python/CMakeLists.txt @@ -29,21 +29,143 @@ macro(vtk_include_recurse module) include_directories(${${module}_PYTHON_INCLUDE_DIRS}) endmacro() -# Loop through all modules that should be wrapped, and wrap them. -foreach(module ${VTK_PYTHON_MODULES}) - vtk_module_load(${module}) - vtk_module_headers_load(${module}) - vtk_include_recurse(${module}) - vtk_add_python_wrapping(${module}) -endforeach() + +set(VTK_PYTHON_MODULES_AND_KITS ${VTK_PYTHON_MODULES}) +set(_vtk_python_modules_only ${VTK_PYTHON_MODULES}) + +if(VTK_ENABLE_KITS) + set(_vtk_kits_with_suffix) + set(VTK_KIT_SUFFIX "Kit") # Required to avoid conflict with targets like vtkFiltersPython + # Create list of module that do not belong to any kits + foreach(kit IN LISTS vtk_kits) + # XXX Variable '_${kit}_modules' is set in vtkModuleTop.cmake + list(REMOVE_ITEM _vtk_python_modules_only ${_${kit}_modules}) + list(APPEND _vtk_kits_with_suffix ${kit}${VTK_KIT_SUFFIX}) + endforeach() + set(VTK_PYTHON_MODULES_AND_KITS ${_vtk_kits_with_suffix} ${_vtk_python_modules_only}) + + # Create dependency lists for kits (suffix: _DEPENDS). The function + # vtk_add_python_wrapping_libary uses these lists. + # + # Additionally, create subsets of the full dependency lists that contain only + # Python-wrapped kits and modules (suffix: _PYTHON_DEPENDS). These lists are + # used to topologically sort the dependency graph. + foreach(kit IN LISTS vtk_kits) + set(_module_depends) + foreach(module IN LISTS _${kit}_modules) + vtk_module_load(${module}) + list(APPEND _module_depends ${${module}_DEPENDS}) + endforeach() + + set(_kit_depends) + foreach(dep IN LISTS _module_depends) + if(${dep}_KIT) + list(APPEND _kit_depends ${${dep}_KIT}${VTK_KIT_SUFFIX}) + else() + list(APPEND _kit_depends ${dep}) + endif() + endforeach() + list(REMOVE_DUPLICATES _kit_depends) + set(${kit}${VTK_KIT_SUFFIX}_DEPENDS ${_kit_depends}) + + set(_kit_python_depends) + foreach(module IN LISTS ${kit}${VTK_KIT_SUFFIX}_DEPENDS) + list(FIND VTK_PYTHON_MODULES_AND_KITS ${module} _module_index) + if (_module_index GREATER -1) + list(APPEND _kit_python_depends ${module}) + endif() + endforeach() + list(REMOVE_DUPLICATES _kit_python_depends) + set(${kit}${VTK_KIT_SUFFIX}_PYTHON_DEPENDS ${_kit_python_depends}) + endforeach() + + # Create dependency lists for modules that also consider any dependent kits + # (suffix: _DEPENDS_WITH_KITS). These lists are used to override + # <module>_DEPENDS when calling vtk_add_python_wrapping_library. + # + # Additionally, create subsets of the full dependency lists that contain only + # Python-wrapped kits and modules (suffix: _PYTHON_DEPENDS). These lists are + # used to topologically sort the dependency graph. + foreach(module IN LISTS _vtk_python_modules_only) + vtk_module_load(${module}) + set(_saved_${module}_DEPENDS ${${module}_DEPENDS}) + + set(_module_depends_with_kits) + foreach(dep IN LISTS ${module}_DEPENDS) + if(${dep}_KIT) + list(APPEND _module_depends_with_kits ${${dep}_KIT}${VTK_KIT_SUFFIX}) + else() + list(APPEND _module_depends_with_kits ${dep}) + endif() + endforeach() + list(REMOVE_DUPLICATES _module_depends_with_kits) + set(${module}_DEPENDS_WITH_KITS ${_module_depends_with_kits}) + + set(_module_python_depends) + foreach(module IN LISTS ${module}_DEPENDS_WITH_KITS) + list(FIND VTK_PYTHON_MODULES_AND_KITS ${module} _module_index) + if (_module_index GREATER -1) + list(APPEND _module_python_depends ${module}) + endif() + endforeach() + list(REMOVE_DUPLICATES _module_python_depends) + set(${module}_PYTHON_DEPENDS ${_module_python_depends}) + endforeach() + + # Create list of kits and modules to wrap, ordered to satisfy dependencies. + include(${VTK_CMAKE_DIR}/TopologicalSort.cmake) + set(_vtk_python_wrapping_work_list ${VTK_PYTHON_MODULES_AND_KITS}) + topological_sort(_vtk_python_wrapping_work_list "" _PYTHON_DEPENDS) + + # Wrap kits and modules. + foreach(target IN LISTS _vtk_python_wrapping_work_list) + # Determine whether target is a kit or module + string(REGEX REPLACE "(.+)${VTK_KIT_SUFFIX}\$" "\\1" _stripped_target ${target}) + if(_${_stripped_target}_is_kit) + # Wrap kit + set(kit ${_stripped_target}) + set(kit_srcs) + foreach(module IN LISTS _${kit}_modules) + vtk_module_headers_load(${module}) + vtk_include_recurse(${module}) + endforeach() + vtk_add_python_wrapping("${_${kit}_modules}" kit_srcs ${kit}${VTK_KIT_SUFFIX}) + vtk_add_python_wrapping_library(${kit}${VTK_KIT_SUFFIX} kit_srcs ${_${kit}_modules}) + else() + # Wrap module + set(module ${_stripped_target}) + vtk_module_headers_load(${module}) + vtk_include_recurse(${module}) + vtk_add_python_wrapping(${module} module_srcs) + # Override module dependency list for vtk_add_python_wrapping_library + set(${module}_DEPENDS ${${module}_DEPENDS_WITH_KITS}) + vtk_add_python_wrapping_library(${module} module_srcs ${module}) + set(${module}_DEPENDS ${_saved_${module}_DEPENDS}) + endif() + endforeach() + + # Ensure that original module dependency lists are restored + foreach(module IN LISTS _vtk_python_modules_only) + set(${module}_DEPENDS ${_saved_${module}_DEPENDS}) + unset(_saved_${module}_DEPENDS) + endforeach() + +else(VTK_ENABLE_KITS) + # Loop through all modules that should be wrapped, and wrap them. + foreach(module IN LISTS _vtk_python_modules_only) + vtk_module_load(${module}) + vtk_module_headers_load(${module}) + vtk_include_recurse(${module}) + vtk_add_python_wrapping(${module} module_srcs) + vtk_add_python_wrapping_library(${module} module_srcs ${module}) + endforeach() +endif(VTK_ENABLE_KITS) + option(VTK_ENABLE_VTKPYTHON "Enable vtkpython and pvtkpython binaries" ON) mark_as_advanced(VTK_ENABLE_VTKPYTHON) if(VTK_ENABLE_VTKPYTHON) -# Now to build the vtkPython executable, configure the .py files etc. -get_property(VTK_PYTHON_MODULES GLOBAL PROPERTY VTK_PYTHON_WRAPPED) - vtk_module_load(vtkWrappingPythonCore) vtk_module_load(vtkPython) include_directories(${CMAKE_CURRENT_BINARY_DIR} @@ -166,7 +288,7 @@ if(PYTHON_EXECUTABLE) # Wrapping/Python/vtk/*.py unset(VTK_PYTHON_FILES) unset(VTK_PYTHON_IMPORT_ALL) - foreach(module ${VTK_PYTHON_MODULES}) + foreach(module IN LISTS VTK_PYTHON_MODULES_AND_KITS) set(VTK_PYTHON_IMPORT_ALL "${VTK_PYTHON_IMPORT_ALL}from .${module} import *\n") configure_file(vtk/module.py.in vtk/${module}.py @ONLY) @@ -295,7 +417,7 @@ if(PYTHON_EXECUTABLE) # Install python extension library that backs the modules if (BUILD_SHARED_LIBS AND NOT VTK_INSTALL_NO_LIBRARIES) - foreach(module ${VTK_PYTHON_MODULES}) + foreach(module IN LISTS VTK_PYTHON_MODULES_AND_KITS) install(TARGETS ${module}Python RUNTIME DESTINATION ${VTK_INSTALL_RUNTIME_DIR} COMPONENT RuntimeLibraries LIBRARY DESTINATION ${VTK_INSTALL_PYTHON_MODULE_DIR}/vtk COMPONENT RuntimeLibraries