How to use `CMAKE_INSTALL_PREFIX` to solve `The `MODULE_DESTINATION` must not be an absolute path.` error

Hello,
I am in the process of upgrading MIT’s LabelFusion, an open-source RGBD data annotation tool for use in Ubuntu 22.04. It uses their in-house Direction app that used to use VTK <=4.8.

Since Ubuntu 22.04 comes equipped with Python 3.10 that supports VTK 9.3, I have built it successfully from source. Additionally my machine has QT5 installed from official binaries.

However, when building the Director app, I am running into the fatal error. Specifically it is generated from their DRCFilters.

CMake Error at /usr/local/lib/cmake/vtk-9.3/vtkModule.cmake:2220 (message):
  The `MODULE_DESTINATION` must not be an absolute path.  Use
  `CMAKE_INSTALL_PREFIX` to keep everything in a single installation prefix.
Call Stack (most recent call first):
  /usr/local/lib/cmake/vtk-9.3/vtkModuleWrapPython.cmake:875 (_vtk_module_check_destinations)
  cmake/wrap-python.cmake:47 (vtk_module_wrap_python)
  src/vtk/DRCFilters/CMakeLists.txt:227 (wrap_python)

The closest discussion I found to this error is here: cmake error with vtkModule.cmake where the discussion did not lead to a solution to this problem. Note, at that time, they too were using VTK 9.3

How do I go about solving this problem?

warp-python.cmake

# Needs to be manually set
set(VTK_CMAKE_DIR "${VTK_DIR}") # VTK_DIR points to its lib/cmake/vtk-9.3 file
#message(STATUS "VTK_DIR: ${VTK_DIR}")
#message(STATUS "VTK_CMAKE_DIR: ${VTK_DIR}")

if(NOT DEFINED VTK_CMAKE_DIR)
  message(SEND_ERROR "VTK_CMAKE_DIR is not defined, cannot load vtkWrapPython.cmake")
endif()

if(NOT VTK_WRAP_PYTHON)
  message(FATAL_ERROR "VTK was built without Python enabled (VTK_WRAP_PYTHON=FALSE).")
endif()

#include(${VTK_CMAKE_DIR}/vtkWrapPython.cmake) # VTK==7.1.1
include(${VTK_CMAKE_DIR}/vtkModuleWrapPython.cmake) # VTK>=8.9

function(wrap_python library_name sources)
  # Set the Python site-packages suffix for the wrapping
  set(VTK_PYTHON_SITE_PACKAGES_SUFFIX "lib/site-packages")

  vtk_module_wrap_python(
    MODULES ${library_name}
    TARGET ${library_name}Python
    WRAPPED_MODULES generated_python_sources
    INSTALL_HEADERS OFF
    PYTHON_PACKAGE "vtkmodules"
    # CMAKE_DESTINATION ${VTK_PYTHON_SITE_PACKAGES_SUFFIX}
  )

  add_library(${library_name}PythonD ${generated_python_sources})
  add_library(${library_name}Python MODULE ${library_name}PythonInit.cxx)

  target_link_libraries(${library_name}PythonD ${library_name})
  foreach(c ${VTK_LIBRARIES})
    target_link_libraries(${library_name}PythonD ${c}PythonD)
  endforeach(c)
  target_link_libraries(${library_name}Python ${library_name}PythonD)

  set_target_properties(${library_name}Python PROPERTIES PREFIX "")
  if(WIN32 AND NOT CYGWIN)
    set_target_properties(${library_name}Python PROPERTIES SUFFIX ".pyd")
  endif(WIN32 AND NOT CYGWIN)

  install(TARGETS ${library_name}Python DESTINATION ${DD_INSTALL_PYTHON_DIR}/director)
  install(TARGETS ${library_name}PythonD DESTINATION ${DD_INSTALL_LIB_DIR})
endfunction()

Cmake for the DRCFilters


# Cmake for DRCFilters library
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})

find_package(OpenGL REQUIRED)

find_package(VTK REQUIRED) # VTK should be found out here

find_package(Eigen REQUIRED)
include_directories(${EIGEN_INCLUDE_DIRS})

set(sources
  vtkDepthImageUtils.cxx
  vtkGridSource.cxx
  vtkFrameWidget.cxx
  vtkFrameWidgetRepresentation.cxx
  vtkInteractorStyleTerrain2.cxx
  vtkPickCenteredInteractorStyle.cxx
  )

set(headers
  vtkDepthImageUtils.h
  vtkDRCFiltersModule.h
  vtkFrameWidget.h
  vtkFrameWidgetRepresentation.h
  vtkGridSource.h
  vtkInteractorStyleTerrain2.h
  vtkPickCenteredInteractorStyle.h
  )

# extra source files to compile but do not python wrap
set(EXTRA_SRCS
  )

#####

option(USE_EDL_SHADERS OFF)
if(USE_EDL_SHADERS)

  set(GLSL_RESOURCES_DIR
      edl_resources/Shaders
      )

  set(GLSL_SRCS
    edl_compose
    edl_shade
    bilateral_filter
    depth_compose
    )

  # -----------------------------------------------------------------------------
  # Create custom commands to encode each glsl file into a C string literal
  # in a header file
  # -----------------------------------------------------------------------------
  if(NOT TARGET vtkEncodeString)
    message(SEND_ERROR "The required vtkEncodeString executable was not found.\nThis may indicate an error in your VTK install or configuration.")
  endif()

  foreach(file ${GLSL_SRCS})
    set(src ${CMAKE_CURRENT_SOURCE_DIR}/${GLSL_RESOURCES_DIR}/${file}.glsl)
    set(res ${CMAKE_CURRENT_BINARY_DIR}/${file}.cxx)
    add_custom_command(
      OUTPUT ${res}
      DEPENDS ${src}
      COMMAND vtkEncodeString
      ARGS ${res} ${src} ${file}
      )
    set(EXTRA_SRCS ${EXTRA_SRCS} ${res})
  endforeach(file)

endif()


#####

set(VTK_LIBRARIES
  vtkInteractionWidgets
  vtkInteractionStyle
  vtkRenderingFreeType
  vtkRenderingCore
  vtkRendering${VTK_RENDERING_BACKEND}
  vtkFiltersExtraction
  vtkFiltersCore
  vtkCommonCore
  )


set(deps
  ${VTK_LIBRARIES}
  ${OPENGL_LIBRARIES}
  )

set(pkg_deps)

if (USE_DRC)

  # requires libbot, lcm, eigen, drc lcmtypes

  find_package(LibBot REQUIRED MODULE)
  include_directories(${LIBBOT_INCLUDE_DIRS})

  find_package(Eigen REQUIRED)
  include_directories(${EIGEN_INCLUDE_DIRS})

  find_package(LCM REQUIRED)
  include_directories(${LCM_INCLUDE_DIRS})

  list(APPEND sources
    vtkMultisenseSource.cxx
    vtkLidarSource.cxx
  )

  list(APPEND headers
    vtkMultisenseSource.h
    vtkMultisenseUtils.h
    vtkLidarSource.h
  )

  list(APPEND deps
    ${LIBBOT_LIBRARIES}
    ${LCM_LIBRARIES}
  )

  list(APPEND pkg_deps
    drc-lcmtypes lcmtypes_maps
  )

endif()

if (USE_DRC_MAPS)
  find_package(Maps REQUIRED)
  find_package(PCL REQUIRED)

  list(APPEND sources vtkMapServerSource.cxx)
  list(APPEND headers vtkMapServerSource.h)
  include_directories(${PCL_INCLUDE_DIRS})
  include_directories(${MAPS_INCLUDE_DIRS})
  list(APPEND deps ${MAPS_LIBRARIES} ${PCL_LIBRARIES})
endif()

if (USE_DRC_PLANE_SEG)
  find_package(PlaneSeg REQUIRED)
  find_package(PCL REQUIRED)

  list(APPEND sources
    vtkPlaneSegmentation.cxx
    vtkRobustNormalEstimator.cxx
    vtkSurfaceFitter.cxx
  )

  list(APPEND headers
    vtkPlaneSegmentation.h
    vtkRobustNormalEstimator.h
    vtkSurfaceFitter.h
  )

  include_directories(${PLANE_SEG_INCLUDE_DIRS})
  include_directories(${PCL_INCLUDE_DIRS})
  list(APPEND deps ${PLANE_SEG_LIBRARIES} ${PCL_LIBRARIES})
endif()

if(USE_LCMGL)

  find_package(LibBot REQUIRED MODULE)
  include_directories(${LIBBOT_INCLUDE_DIRS})
  list(APPEND sources vtkLCMGLProp.cxx)
  list(APPEND headers vtkLCMGLProp.h)
  list(APPEND deps ${LIBBOT_LIBRARIES} ${OPENGL_LIBRARIES})

endif()

if(USE_OCTOMAP)

  setup_qt4()

  find_library(OCTOVIS_LIBRARY octovis)
  list(APPEND sources vtkOctomap.cxx)
  list(APPEND headers vtkOctomap.h)
  list(APPEND deps ${LIBBOT_LIBRARIES} ${OPENGL_LIBRARIES} ${OCTOVIS_LIBRARY})

  list(APPEND pkg_deps
    lcmtypes_octomap-utils
  )

endif()

if (USE_COLLECTIONS)

  list(APPEND sources vtkCollections.cxx)
  list(APPEND headers vtkCollections.h)
  list(APPEND deps ${OPENGL_LIBRARIES})

  list(APPEND pkg_deps
    lcmtypes_visualization
  )
endif()


set(library_name vtkDRCFilters)
add_library(${library_name} ${sources} ${EXTRA_SRCS})
target_link_libraries(${library_name} ${deps})

if(pkg_deps)
  use_pkg(${library_name} ${pkg_deps})
endif()

install(TARGETS ${library_name}
    EXPORT ${DD_TARGETS_NAME}
    RUNTIME DESTINATION ${DD_INSTALL_BIN_DIR}
    LIBRARY DESTINATION ${DD_INSTALL_LIB_DIR}
    ARCHIVE DESTINATION ${DD_INSTALL_LIB_DIR})

if(NOT VTK_WRAP_PYTHON)
  message(FATAL_ERROR "VTK was compiled without Python support. "
    "VTK_WRAP_PYTHON is OFF. You must use a version of VTK with Python. "
    "VTK_DIR is: ${VTK_DIR}")
endif()

include_directories(${PYTHON_INCLUDE_DIR})

# VTK_CMAKE_DIR is not found here
include(${CMAKE_SOURCE_DIR}/cmake/wrap-python.cmake)

add_custom_target(${library_name}Hierarchy)

#wrap_python(${library_name} "${sources}") # "${sources}" may be interpreted as one string
wrap_python(${library_name} ${sources}) #! ERROR OCCURS HERE


set_target_properties(${library_name}Python
  PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${DD_INSTALL_PYTHON_DIR}/director")
target_link_libraries(${library_name}Python ${PYTHON_LIBRARIES})
target_link_libraries(${library_name}PythonD ${PYTHON_LIBRARIES})
install_headers(${headers})

I got over this error by using the following in wrap-python.cmake

vtk_module_wrap_python(
    TARGET ${library_name}Python
    MODULES ${library_name}
    
    WRAPPED_MODULES generated_python_sources
    INSTALL_HEADERS OFF
    PYTHON_PACKAGE ${library_name}
    MODULE_DESTINATION "lib/${library_name}"
    #CMAKE_DESTINATION ${VTK_PYTHON_SITE_PACKAGES_SUFFIX}
    CMAKE_DESTINATION "lib/site-packages"
  )

But now I am getting this problem

CMake Error at /usr/local/lib/cmake/vtk-9.3/vtkModule.cmake:1348 (message):
  Failed to determine the real target for the `vtkDRCFilters` module.
Call Stack (most recent call first):
  /usr/local/lib/cmake/vtk-9.3/vtkModuleWrapPython.cmake:302 (_vtk_module_real_target)
  /usr/local/lib/cmake/vtk-9.3/vtkModuleWrapPython.cmake:944 (_vtk_module_wrap_python_library)
  cmake/wrap-python.cmake:23 (vtk_module_wrap_python)
  src/vtk/DRCFilters/CMakeLists.txt:227 (wrap_python)

The vtkDRCFilters target is not a module. The new wrapping infrastructure only supports wrapping VTK modules. You’ll need to crib from this example to build your library as a VTK module so that it gets the required metadata attached to it so that, for example, wrapping knows which headers to wrap.

@ben.boeckel thank you very much for the suggestion. The originals authors did have those two lines from their VTK 7.1 era. I have gotten over this problem by defining vtk_module_wrap_python using the following in the wrap-python.cmake file.

vtk_module_wrap_python(
    TARGET ${library_name}Python
    #MODULES ${library_name}
    MODULES ${modules}
    WRAPPED_MODULES generated_python_sources
    INSTALL_HEADERS OFF
    PYTHON_PACKAGE ${library_name}
    MODULE_DESTINATION "lib/${library_name}"
    #CMAKE_DESTINATION ${VTK_PYTHON_SITE_PACKAGES_SUFFIX}
    CMAKE_DESTINATION "lib/site-packages"
  )

But I am not sure what is happening here or why the error went away.