diff --git a/CMake/FindNumpy.cmake b/CMake/FindNumpy.cmake new file mode 100644 index 0000000000..4170adb613 --- /dev/null +++ b/CMake/FindNumpy.cmake @@ -0,0 +1,29 @@ +# Variables set by this script +# NUMPY_FOUND +# NUMPY_INCLUDE_DIR + +find_package(PackageHandleStandardArgs) + +# numpy dir defined, own numpy deployed in python runtime +if(DEFINED Numpy_DIR AND EXISTS ${Numpy_DIR}) + if(EXISTS ${Numpy_DIR}/core/include) + set(NUMPY_INCLUDE_DIR ${Numpy_DIR}/core/include) + endif() +else() #numpy dir not defined + execute_process ( + COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" + OUTPUT_VARIABLE output + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(DEFINED output AND EXISTS ${output} ) + set (NUMPY_INCLUDE_DIR ${output}) + endif() +endif() + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Numpy DEFAULT_MSG NUMPY_INCLUDE_DIR) + +MARK_AS_ADVANCED ( + NUMPY_INCLUDE_DIR +) + diff --git a/CMake/MITKDashboardSetup.cmake b/CMake/MITKDashboardSetup.cmake index caf521922a..c1b322fc43 100644 --- a/CMake/MITKDashboardSetup.cmake +++ b/CMake/MITKDashboardSetup.cmake @@ -1,193 +1,197 @@ # This file is intended to be included at the end of a custom MITKDashboardScript.TEMPLATE.cmake file list(APPEND CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") # # Automatically determined properties # set(MY_OPERATING_SYSTEM ) if(UNIX) # Download a utility script set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/mitkDetectOS.sh;hb=${hb}") set(dest "${CTEST_SCRIPT_DIRECTORY}/mitkDetectOS.sh") downloadFile("${url}" "${dest}") execute_process(COMMAND sh "${dest}" RESULT_VARIABLE _result OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT _result) set(MY_OPERATING_SYSTEM "${_out}") endif() endif() if(NOT MY_OPERATING_SYSTEM) set(MY_OPERATING_SYSTEM "${CMAKE_HOST_SYSTEM}") # Windows 7, Linux-2.6.32, Darwin... endif() site_name(CTEST_SITE) if(NOT DEFINED MITK_USE_QT) set(MITK_USE_QT 1) endif() if(MITK_USE_QT) if(NOT QT_QMAKE_EXECUTABLE) find_program(QT_QMAKE_EXECUTABLE NAMES qmake qmake-qt4 HINTS ${QT_BINARY_DIR}) endif() execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} --version OUTPUT_VARIABLE MY_QT_VERSION RESULT_VARIABLE qmake_error) if(qmake_error) message(FATAL_ERROR "Error when executing ${QT_QMAKE_EXECUTABLE} --version\n${qmake_error}") endif() string(REGEX REPLACE ".*Qt version ([0-9.]+) .*" "\\1" MY_QT_VERSION ${MY_QT_VERSION}) endif() # # Project specific properties # if(NOT CTEST_BUILD_NAME) if(MITK_USE_QT) set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} Qt${MY_QT_VERSION} ${CTEST_BUILD_CONFIGURATION}") else() set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} ${CTEST_BUILD_CONFIGURATION}") endif() endif() set(PROJECT_BUILD_DIR "MITK-build") set(CTEST_PATH "$ENV{PATH}") if(WIN32) set(ANN_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ANN-build/${CTEST_BUILD_CONFIGURATION}") set(CPPUNIT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/CppUnit-build/${CTEST_BUILD_CONFIGURATION}") set(GLUT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLUT-build/${CTEST_BUILD_CONFIGURATION}") set(GLEW_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLEW-build/${CTEST_BUILD_CONFIGURATION}") set(TINYXML_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/tinyxml-build/${CTEST_BUILD_CONFIGURATION}") set(QWT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Qwt-build/${CTEST_BUILD_CONFIGURATION}") set(QXT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Qxt-build/${CTEST_BUILD_CONFIGURATION}") set(VTK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/VTK-build/bin/${CTEST_BUILD_CONFIGURATION}") set(ACVD_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ACVD-build/bin/${CTEST_BUILD_CONFIGURATION}") set(ITK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ITK-build/bin/${CTEST_BUILD_CONFIGURATION}") set(BOOST_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Boost-install/lib") set(GDCM_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GDCM-build/bin/${CTEST_BUILD_CONFIGURATION}") set(OPENCV_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/OpenCV-build/bin/${CTEST_BUILD_CONFIGURATION}") set(POCO_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Poco-install/lib") set(SOFA_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/SOFA-build/bin/${CTEST_BUILD_CONFIGURATION}") set(BLUEBERRY_OSGI_DIR "${CTEST_BINARY_DIRECTORY}/MITK-build/bin/BlueBerry/org.blueberry.osgi/bin/${CTEST_BUILD_CONFIGURATION}") set(CTEST_PATH "${CTEST_PATH};${CPPUNIT_BINARY_DIR};${QT_BINARY_DIR};${VTK_BINARY_DIR};${ANN_BINARY_DIR};${GLUT_BINARY_DIR};${GLEW_BINARY_DIR};${TINYXML_BINARY_DIR};${QWT_BINARY_DIR};${QXT_BINARY_DIR};${ACVD_BINARY_DIR};${ITK_BINARY_DIR};${BOOST_BINARY_DIR};${GDCM_BINARY_DIR};${OPENCV_BINARY_DIR};${POCO_BINARY_DIR};${SOFA_BINARY_DIR};${BLUEBERRY_OSGI_DIR}") endif() set(ENV{PATH} "${CTEST_PATH}") set(SUPERBUILD_TARGETS "") # If the dashscript doesn't define a GIT_REPOSITORY variable, let's define it here. if(NOT DEFINED GIT_REPOSITORY OR GIT_REPOSITORY STREQUAL "") set(GIT_REPOSITORY "http://git.mitk.org/MITK.git") endif() # # Display build info # message("Site name: ${CTEST_SITE}") message("Build name: ${CTEST_BUILD_NAME}") message("Script Mode: ${SCRIPT_MODE}") message("Coverage: ${WITH_COVERAGE}, MemCheck: ${WITH_MEMCHECK}") # # Set initial cache options # if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") set(CTEST_USE_LAUNCHERS 1) set(ENV{CTEST_USE_LAUNCHERS_DEFAULT} 1) endif() # Remove this if block after all dartclients work if(DEFINED ADDITIONNAL_CMAKECACHE_OPTION) message(WARNING "Rename ADDITIONNAL to ADDITIONAL in your dartlclient script: ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") set(ADDITIONAL_CMAKECACHE_OPTION ${ADDITIONNAL_CMAKECACHE_OPTION}) endif() if(NOT DEFINED MITK_USE_ACVD) set(MITK_USE_ACVD 1) endif() if(NOT DEFINED MITK_USE_Boost) set(MITK_USE_Boost 1) endif() if(NOT DEFINED MITK_USE_OpenCV) set(MITK_USE_OpenCV 1) endif() if(NOT DEFINED MITK_USE_Poco) set(MITK_USE_Poco 1) endif() if(NOT DEFINED MITK_USE_SOFA) set(MITK_USE_SOFA 1) endif() if(NOT DEFINED MITK_BUILD_ALL_APPS) set(MITK_BUILD_ALL_APPS TRUE) endif() if(NOT DEFINED BLUEBERRY_BUILD_ALL_PLUGINS) set(BLUEBERRY_BUILD_ALL_PLUGINS TRUE) endif() if(NOT DEFINED MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS TRUE) endif() if(NOT DEFINED MITK_BUILD_EXAMPLES) set(MITK_BUILD_EXAMPLES TRUE) endif() +if(NOT DEFINED MITK_USE_Python) + set(MITK_USE_Python TRUE) +endif() + if(NOT BUILD_DiffusionMiniApps) set(BUILD_DiffusionMiniApps TRUE) endif() set(INITIAL_CMAKECACHE_OPTIONS " BLUEBERRY_BUILD_ALL_PLUGINS:BOOL=${MITK_BUILD_ALL_PLUGINS} MITK_BUILD_ALL_PLUGINS:BOOL=${MITK_BUILD_ALL_PLUGINS} MITK_BUILD_ALL_APPS:BOOL=${MITK_BUILD_ALL_APPS} MITK_BUILD_EXAMPLES:BOOL=${MITK_BUILD_EXAMPLES} SUPERBUILD_EXCLUDE_MITKBUILD_TARGET:BOOL=TRUE MITK_USE_ACVD:BOOL=${MITK_USE_ACVD} MITK_USE_Boost:BOOL=${MITK_USE_Boost} MITK_USE_OpenCV:BOOL=${MITK_USE_OpenCV} MITK_USE_Poco:BOOL=${MITK_USE_Poco} MITK_USE_SOFA:BOOL=${MITK_USE_SOFA} MITK_USE_QT:BOOL=${MITK_USE_QT} ${ADDITIONAL_CMAKECACHE_OPTION} ") if(MITK_USE_QT) set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS} QT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}") endif() # Write a cache file for populating the MITK initial cache (not the superbuild cache). # This can be used to provide variables which are not passed through the # superbuild process to the MITK configure step) if(MITK_INITIAL_CACHE) set(mitk_cache_file "${CTEST_SCRIPT_DIRECTORY}/mitk_initial_cache.txt") file(WRITE "${mitk_cache_file}" "${MITK_INITIAL_CACHE}") set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS} MITK_INITIAL_CACHE_FILE:INTERNAL=${mitk_cache_file} ") endif() # # Download and include dashboard driver script # set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/MITKDashboardDriverScript.cmake;hb=${hb}") set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.driver) downloadFile("${url}" "${dest}") include(${dest}) diff --git a/CMake/PackageDepends/MITK_Numpy_Config.cmake b/CMake/PackageDepends/MITK_Numpy_Config.cmake new file mode 100644 index 0000000000..d10c0eaa78 --- /dev/null +++ b/CMake/PackageDepends/MITK_Numpy_Config.cmake @@ -0,0 +1,4 @@ +if(MITK_USE_Python) + find_package(Numpy REQUIRED) + list(APPEND ALL_INCLUDE_DIRECTORIES ${NUMPY_INCLUDE_DIR}) +endif() diff --git a/CMake/PackageDepends/MITK_SimpleITK_Config.cmake b/CMake/PackageDepends/MITK_SimpleITK_Config.cmake new file mode 100644 index 0000000000..5c1925b95a --- /dev/null +++ b/CMake/PackageDepends/MITK_SimpleITK_Config.cmake @@ -0,0 +1,4 @@ +find_package(SimpleITK REQUIRED CONFIG) +list(APPEND ALL_INCLUDE_DIRECTORIES ${SimpleITK_INCLUDE_DIRS}) +list(APPEND ALL_LIBRARIES ${SimpleITK_LIBRARIES}) +link_directories(${SimpleITK_LIBRARY_DIRS}) diff --git a/CMake/mitkFunctionExternalPythonBuildStep.cmake b/CMake/mitkFunctionExternalPythonBuildStep.cmake new file mode 100644 index 0000000000..0a6f55570d --- /dev/null +++ b/CMake/mitkFunctionExternalPythonBuildStep.cmake @@ -0,0 +1,39 @@ +#! CMake function that runs a python build step from a setup.py script, +#! e.g. python setup.py build. This is used to build external python +#! libraries like numpy. The function takes the necessary build steps, +#! python executable etc. as arguments. The specific build command executed +#! by the runtime is passed as ARGN. +#! +#! params: +#! proj - The name of the project +#! step - Buildstep used to label the generated outputs, e.g. configure;build;install +#! _python_executable - The python executable +#! _bin_dir - The current binary from where commands are executed relative to it +#! ARGN - Python command that will be run in the _bin_dir/proj-src folder +#! e.g. setup.py build --someflags +#! +function(mitkFunctionExternalPythonBuildStep proj step _python_executable _bin_dir) + + # the specific python build command run by this step + set(_command ${ARGN}) + + message("Running ${proj} ${step}:${PYTHON_EXECUTABLE} ${_command}") + + execute_process( + COMMAND ${_python_executable} ${_command} + WORKING_DIRECTORY ${_bin_dir}/${proj}-src + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE error + ) + set(output_file "${_bin_dir}/${proj}-cmake/${proj}_${step}_step_output.txt") + file(WRITE ${output_file} ${output}) + + set(error_file "${_bin_dir}/${proj}-cmake/${proj}_${step}_step_error.txt") + file(WRITE ${error_file} ${error}) + + if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "Error in: ${proj}: ${error}") + endif() +endfunction() + diff --git a/CMake/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake index 6b3c31fb2f..fa721ede9c 100644 --- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake +++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake @@ -1,165 +1,175 @@ function(mitkFunctionGetLibrarySearchPaths search_path intermediate_dir) set(_dir_candidates ${MITK_VTK_LIBRARY_DIRS} ${MITK_ITK_LIBRARY_DIRS} "${MITK_BINARY_DIR}/bin" "${MITK_BINARY_DIR}/bin/plugins") # Determine the Qt4/5 library installation prefix set(_qmake_location ) if(MITK_USE_Qt4) set(_qmake_location ${QT_QMAKE_EXECUTABLE}) elseif(MITK_USE_Qt5 AND TARGET ${Qt5Core_QMAKE_EXECUTABLE}) get_property(_qmake_location TARGET ${Qt5Core_QMAKE_EXECUTABLE} PROPERTY IMPORT_LOCATION) endif() if(_qmake_location) if(NOT _qt_install_libs) if(WIN32) execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_BINS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) else() execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_LIBS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) endif() file(TO_CMAKE_PATH "${_qt_install_libs}" _qt_install_libs) set(_qt_install_libs ${_qt_install_libs} CACHE INTERNAL "Qt library installation prefix" FORCE) endif() if(_qt_install_libs) list(APPEND _dir_candidates ${_qt_install_libs}) endif() elseif(MITK_USE_QT) message(WARNING "The qmake executable could not be found.") endif() get_property(_additional_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) if(_additional_paths) list(APPEND _dir_candidates ${_additional_paths}) endif() if(VTK_DIR) find_package(VTK QUIET) if(VTK_RUNTIME_LIBRARY_DIRS) list(APPEND _dir_candidates ${VTK_RUNTIME_LIBRARY_DIRS}) endif() endif() # The code below is sub-optimal. It makes assumptions about # the structure of the build directories, pointed to by # the *_DIR variables. Instead, we should rely on package # specific "LIBRARY_DIRS" variables, if they exist. if(WIN32) if(DCMTK_DIR) list(APPEND _dir_candidates "${DCMTK_DIR}/bin") endif() if(OpenCV_DIR) list(APPEND _dir_candidates "${OpenCV_DIR}/bin") endif() if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/bin") + if(Python_DIR) + list(APPEND _dir_candidates "${Python_DIR}/bin") + endif() + if(SimpleITK_DIR) + list(APPEND _dir_candidates "${SimpleITK_DIR}/bin") endif() list(APPEND _dir_candidates "${ITK_DIR}/bin") else() if(DCMTK_DIR) list(APPEND _dir_candidates "${DCMTK_DIR}/lib") endif() if(OpenCV_DIR) list(APPEND _dir_candidates "${OpenCV_DIR}/lib") endif() if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/lib") + if(Python_DIR) + list(APPEND _dir_candidates "${Python_DIR}/lib") + endif() + if(SimpleITK_DIR) + list(APPEND _dir_candidates "${SimpleITK_DIR}/lib") endif() list(APPEND _dir_candidates "${ITK_DIR}/lib") endif() if(MITK_USE_Python AND CTK_PYTHONQT_INSTALL_DIR) list(APPEND _dir_candidates "${CTK_PYTHONQT_INSTALL_DIR}/bin") endif() if(MITK_USE_Boost AND MITK_USE_Boost_LIBRARIES AND NOT MITK_USE_SYSTEM_Boost) list(APPEND _dir_candidates "${Boost_LIBRARY_DIR}") endif() if(ACVD_DIR) list(APPEND _dir_candidates "${ACVD_DIR}/bin") endif() if(ANN_DIR) list(APPEND _dir_candidates "${ANN_DIR}") endif() if(CppUnit_DIR) list(APPEND _dir_candidates "${CppUnit_DIR}") endif() if(GLUT_DIR) list(APPEND _dir_candidates "${GLUT_DIR}") endif() if(GDCM_DIR) list(APPEND _dir_candidates "${GDCM_DIR}/bin") endif() if(GLEW_DIR) list(APPEND _dir_candidates "${GLEW_DIR}") endif() if(tinyxml_DIR) list(APPEND _dir_candidates "${tinyxml_DIR}") endif() if(Poco_DIR) list(APPEND _dir_candidates "${Poco_DIR}/lib") endif() if(Qwt_DIR) list(APPEND _dir_candidates "${Qwt_DIR}") endif() if(Qxt_DIR) list(APPEND _dir_candidates "${Qxt_DIR}") endif() if(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD) list(APPEND _dir_candidates "${MITK_PMD_SDK_DIR}/plugins" "${MITK_PMD_SDK_DIR}/bin") endif() if(MITK_USE_CTK) list(APPEND _dir_candidates "${CTK_LIBRARY_DIRS}") foreach(_ctk_library ${CTK_LIBRARIES}) if(${_ctk_library}_LIBRARY_DIRS) list(APPEND _dir_candidates "${${_ctk_library}_LIBRARY_DIRS}") endif() endforeach() endif() if(MITK_USE_BLUEBERRY) if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY) if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") list(APPEND _dir_candidates "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") else() list(APPEND _dir_candidates "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") endif() endif() endif() if(MITK_LIBRARY_DIRS) list(APPEND _dir_candidates ${MITK_LIBRARY_DIRS}) endif() list(REMOVE_DUPLICATES _dir_candidates) set(_search_dirs ) foreach(_dir ${_dir_candidates}) if(EXISTS "${_dir}/${intermediate_dir}") list(APPEND _search_dirs "${_dir}/${intermediate_dir}") else() list(APPEND _search_dirs "${_dir}") endif() endforeach() # Special handling for "internal" search dirs. The intermediate directory # might not have been created yet, so we can't check for its existence. # Hence we just add it for Windows without checking. set(_internal_search_dirs "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins") if(WIN32) foreach(_dir ${_internal_search_dirs}) set(_search_dirs "${_dir}/${intermediate_dir}" ${_search_dirs}) endforeach() else() set(_search_dirs ${_internal_search_dirs} ${_search_dirs}) endif() list(REMOVE_DUPLICATES _search_dirs) set(${search_path} ${_search_dirs} PARENT_SCOPE) endfunction() diff --git a/CMake/mitkFunctionInstallPython.cmake b/CMake/mitkFunctionInstallPython.cmake new file mode 100644 index 0000000000..d8ea8a74f5 --- /dev/null +++ b/CMake/mitkFunctionInstallPython.cmake @@ -0,0 +1,156 @@ +#! This CMake macro installs the python runtime with +#! all python related libraries and toolkits. Py files are +#! searched one by one with a globbing expression to generate a list used +#! by the mac and NSIS installer. +#! +#! params: +#! _python_libs Returns a list of the installed libraries. Used to fixup the bundle. +#! _python_dirs Returns a list with the directories containig the dependencies +#! to the installed libs. +#! _app_bundle App bundle name in case of a Apple bundle. +#! +function(mitkFunctionInstallPython _python_libs_out _python_dirs_out _app_bundle) + + # find package sets the python version numbers + find_package(PythonLibs REQUIRED) + find_package(PythonInterp REQUIRED) + + set(_python_libs ) + set(_python_dirs ) + # set the destination bundle + set(_destination bin) + if(APPLE) + set(_destination ${_app_bundle}) + endif() + + if(UNIX) + # apple and linux only supports .so as loadable extension + set(PYTHON_LIB_SUFFIX .so) + set(_py_include_postfix python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/) + set(_python_runtime_dir lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}) + else(WIN32) + # windows only supports pyd as loadable extension + set(PYTHON_LIB_SUFFIX .pyd) + set(_py_include_postfix ) + set(_python_runtime_dir Lib) + endif() + + # install OpenCV python wrapping + if(MITK_USE_OpenCV) + list(APPEND _python_libs "cv2${PYTHON_LIB_SUFFIX}") + + if(UNIX) + install(FILES "${OpenCV_DIR}/lib/cv2${PYTHON_LIB_SUFFIX}" DESTINATION ${_destination}) + else() + install(FILES "${OpenCV_DIR}/lib/Release/cv2${PYTHON_LIB_SUFFIX}" DESTINATION ${_destination}) + endif() + + if(UNIX AND NOT APPLE) + install(CODE "file(RPATH_REMOVE + FILE \"\${CMAKE_INSTALL_PREFIX}/bin/cv2${CMAKE_SHARED_LIBRARY_SUFFIX}\")") + endif() + + list(APPEND _python_dirs "${OpenCV_DIR}/lib") + endif() + + # install VTK python wrapping + find_package(VTK REQUIRED) + + set(_VTK_PYTHON_TARGETS ) + + # find all vtk python wrapped targets + foreach(_lib ${VTK_LIBRARIES}) + # exclude system libs + if(${_lib} MATCHES "^vtk.+") + # use only python wrapped modules ( targets end with PythonD ) + if(TARGET ${_lib}PythonD) + list(APPEND _VTK_PYTHON_TARGETS ${_lib}Python) + endif() + endif() + endforeach() + + # install the python modules and loaders + foreach(_target ${_VTK_PYTHON_TARGETS}) + # get the properties of the python wrapped target + if( CMAKE_BUILD_TYPE STREQUAL "Debug") + get_target_property(_target_lib "${_target}D" IMPORTED_LOCATION_DEBUG) + else() + get_target_property(_target_lib "${_target}D" IMPORTED_LOCATION_RELEASE) + endif() + get_filename_component(_filepath "${_target_lib}" PATH) + + install(FILES "${_filepath}/${_target}${PYTHON_LIB_SUFFIX}" DESTINATION ${_destination}) + + if(UNIX AND NOT APPLE ) + install(CODE "file(RPATH_REMOVE + FILE \"\${CMAKE_INSTALL_PREFIX}/bin/${_target}${PYTHON_LIB_SUFFIX}\")") + endif() + list(APPEND _python_libs "${_target}${PYTHON_LIB_SUFFIX}") + endforeach() + + # install vtk python. This folder contains all *.py and + # *.pyc files for VTK module loading. + # glob through all files, NSIS can't use directories + file(GLOB_RECURSE item RELATIVE "${VTK_DIR}/Wrapping/Python/vtk" "${VTK_DIR}/Wrapping/Python/vtk/*.py*") + foreach(f ${item}) + get_filename_component(_filepath "${f}" PATH) + install(FILES "${VTK_DIR}/Wrapping/Python/vtk/${f}" DESTINATION ${_destination}/Python/vtk/${_filepath}) + endforeach() + + list(APPEND _python_dirs "${VTK_DIR}/lib") + + # install the python runtime from the superbuild + if(NOT MITK_USE_SYSTEM_PYTHON) + if(UNIX) + list(APPEND _python_dirs "${Python_DIR}/lib") + else() #WIN32 + list(APPEND _python_dirs "${Python_DIR}/libs") + list(APPEND _python_dirs "${Python_DIR}/bin") + endif() + + file(GLOB_RECURSE item RELATIVE "${Python_DIR}/${_python_runtime_dir}" "${Python_DIR}/${_python_runtime_dir}/*") + foreach(f ${item}) + get_filename_component(_filepath "${f}" PATH) + install(FILES "${Python_DIR}/${_python_runtime_dir}/${f}" DESTINATION ${_destination}/Python/${_python_runtime_dir}/${_filepath}) + endforeach() + + # config will by read out at runtime + install(FILES "${Python_DIR}/include/${_py_include_postfix}pyconfig.h" DESTINATION ${_destination}/Python/include/${_py_include_postfix}) + + # add simple itk python wrapping file to the dependency list to resolve linked libraries + file(GLOB_RECURSE item RELATIVE "${Python_DIR}/${_python_runtime_dir}" "${Python_DIR}/${_python_runtime_dir}/_SimpleITK${PYTHON_LIB_SUFFIX}") + foreach(f ${item}) + list(APPEND _python_libs "Python/${_python_runtime_dir}/${f}") + if(UNIX AND NOT APPLE) + install(CODE "file(RPATH_REMOVE + FILE \"\${CMAKE_INSTALL_PREFIX}/bin/Python/${_python_runtime_dir}/${f}\")") + endif() + endforeach() + else() + # Deploy the SimpleITK egg into the MITK installer + set(_sitk_userbase_install ${SimpleITK_DIR}/Wrapping/PythonPackage/${_python_runtime_dir}/site-packages) + + # install everything in the userbase into Python/SimpleITK + file(GLOB_RECURSE item RELATIVE "${_sitk_userbase_install}" "${_sitk_userbase_install}/*") + foreach(f ${item}) + get_filename_component(_filepath "${f}" PATH) + install(FILES "${_sitk_userbase_install}/${f}" DESTINATION ${_destination}/Python/SimpleITK/${_filepath}) + endforeach() + + # find and add the _SimpleITK library to the dependencies + file(GLOB_RECURSE item RELATIVE "${_sitk_userbase_install}" "${_sitk_userbase_install}/_SimpleITK${PYTHON_LIB_SUFFIX}") + foreach(f ${item}) + list(APPEND _python_libs "Python/SimpleITK/${f}") + if(UNIX AND NOT APPLE) + install(CODE "file(RPATH_REMOVE + FILE \"\${CMAKE_INSTALL_PREFIX}/bin/Python/SimpleITK/${f}\")") + endif() + endforeach() + endif() + + list(REMOVE_DUPLICATES _python_dirs) + + set(${_python_libs_out} ${_python_libs} PARENT_SCOPE) + set(${_python_dirs_out} ${_python_dirs} PARENT_SCOPE) +endfunction() + diff --git a/CMake/mitkMacroInstall.cmake b/CMake/mitkMacroInstall.cmake index 5efadc76c3..8385998d6b 100644 --- a/CMake/mitkMacroInstall.cmake +++ b/CMake/mitkMacroInstall.cmake @@ -1,177 +1,192 @@ # # MITK specific install macro # # On Mac everything is installed for each bundle listed in MACOSX_BUNDLE_NAMES # by replacing the DESTINATION parameter. Everything else is passed to the CMake INSTALL command # # Usage: MITK_INSTALL( ) # macro(MITK_INSTALL) set(ARGS ${ARGN}) set(install_directories "") list(FIND ARGS DESTINATION _destination_index) # set(_install_DESTINATION "") if(_destination_index GREATER -1) message(SEND_ERROR "MITK_INSTALL macro must not be called with a DESTINATION parameter.") ### This code was a try to replace a given DESTINATION #math(EXPR _destination_index ${_destination_index} + 1) #list(GET ARGS ${_destination_index} _install_DESTINATION) #string(REGEX REPLACE ^bin "" _install_DESTINATION ${_install_DESTINATION}) else() if(NOT MACOSX_BUNDLE_NAMES) install(${ARGS} DESTINATION bin) else() foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) install(${ARGS} DESTINATION ${bundle_name}.app/Contents/MacOS/${_install_DESTINATION}) endforeach() endif() endif() endmacro() # Fix _target_location # This is used in several install macros macro(_fixup_target) if(NOT intermediate_dir) if(WIN32 AND NOT MINGW) set(intermediate_dir Release) else() set(intermediate_dir .) endif() endif() + set(_python_libs ) + set(_python_dirs ) + if(MITK_USE_Python) + include(mitkFunctionInstallPython) + mitkFunctionInstallPython(_python_libs _python_dirs "${_bundle_dest_dir}") + endif() + mitkFunctionGetLibrarySearchPaths(_search_paths ${intermediate_dir}) install(CODE " set(_bundle_dest_dir \"${_bundle_dest_dir}\") if(_bundle_dest_dir) set(_bin_path \"\${CMAKE_INSTALL_PREFIX}/\${_bundle_dest_dir}\") else() set(_bin_path \"\${CMAKE_INSTALL_PREFIX}/bin\") endif() macro(gp_item_default_embedded_path_override item default_embedded_path_var) get_filename_component(_item_name \"\${item}\" NAME) get_filename_component(_item_path \"\${item}\" PATH) # We have to fix all path references to build trees for plugins if(NOT _item_path MATCHES \"\${CMAKE_INSTALL_PREFIX}/${_bundle_dest_dir}\") # item with relative path or embedded path pointing to some build dir set(full_path \"full_path-NOTFOUND\") file(GLOB_RECURSE full_path \${CMAKE_INSTALL_PREFIX}/${_bundle_dest_dir}/\${_item_name} ) list(LENGTH full_path full_path_length) if(full_path_length GREATER 1) list(GET full_path 0 full_path) endif() get_filename_component(_item_path \"\${full_path}\" PATH) endif() set(_plugins_path \"\${_bin_path}/plugins\") if(_item_path STREQUAL _plugins_path OR (_item_path MATCHES \"\${_plugins_path}/\" AND _item_name MATCHES \"liborg\") # this is for legacy BlueBerry bundle support ) # Only fix plugins message(\"override: \${item}\") message(\"found file: \${_item_path}/\${_item_name}\") if(APPLE) string(REPLACE \${CMAKE_INSTALL_PREFIX}/${_bundle_dest_dir} @executable_path \${default_embedded_path_var} \"\${_item_path}\" ) else() set(\${default_embedded_path_var} \"\${_item_path}\") endif() message(\"override result: \${\${default_embedded_path_var}}\") endif() endmacro(gp_item_default_embedded_path_override) macro(gp_resolved_file_type_override file type) if(NOT APPLE) get_filename_component(_file_path \"\${file}\" PATH) get_filename_component(_file_name \"\${file}\" NAME) if(_file_path MATCHES \"^\${CMAKE_INSTALL_PREFIX}\") set(\${type} \"local\") endif() if(_file_name MATCHES gdiplus) set(\${type} \"system\") endif(_file_name MATCHES gdiplus) endif() endmacro(gp_resolved_file_type_override) if(NOT APPLE) macro(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var) if(\${item} MATCHES \"blueberry_osgi\") get_filename_component(_item_name \${item} NAME) set(\${resolved_item_var} \"\${exepath}/plugins/\${_item_name}\") set(\${resolved_var} 1) endif() endmacro() endif() if(\"${_install_GLOB_PLUGINS}\" STREQUAL \"TRUE\") set(GLOBBED_PLUGINS ) set(_bb_osgi_lib \"\${_bin_path}/liborg_blueberry_osgi${CMAKE_SHARED_LIBRARY_SUFFIX}\") if(EXISTS \"\${_bb_osgi_lib}\") list(APPEND GLOBBED_PLUGINS \"\${_bb_osgi_lib}\") endif() # Iterate over all sub-directories which contain plug-ins # (BlueBerry plug-ins, Qt plug-ins, and auto-load modules) file(GLOB _children \"\${_bin_path}/*\") foreach(_child \${_children}) if(IS_DIRECTORY \${_child}) set(_plugins ) set(_modules ) file(GLOB_RECURSE _plugins \"\${_child}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\") if(_plugins) list(APPEND GLOBBED_PLUGINS \${_plugins}) endif() # Now glob for all modules which might have a different extensions. # E.g. on MacOS plugins could have a .dylib extension as well as a .so extension if(NOT \"${CMAKE_SHARED_MODULE_SUFFIX}\" STREQUAL \"\" AND NOT \"${CMAKE_SHARED_MODULE_SUFFIX}\" STREQUAL \"${CMAKE_SHARED_LIBRARY_SUFFIX}\") file(GLOB_RECURSE _modules \"\${_child}/*${CMAKE_SHARED_MODULE_SUFFIX}\") endif() if(_modules) list(APPEND GLOBBED_PLUGINS \${_modules}) endif() endif() endforeach() endif() set(PLUGINS ) foreach(_plugin ${_install_PLUGINS} \${GLOBBED_PLUGINS}) get_filename_component(_plugin_realpath \${_plugin} REALPATH) list(APPEND PLUGINS \${_plugin_realpath}) endforeach() + foreach(_py_lib ${_python_libs}) + list(APPEND PLUGINS \"\${_bin_path}/\${_py_lib}\") + endforeach() + if(PLUGINS) list(REMOVE_DUPLICATES PLUGINS) endif(PLUGINS) message(\"globbed plugins: \${PLUGINS}\") set(CMAKE_MODULE_PATH ${MITK_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) set(DIRS \"${_search_paths}\") set(_additional_search_paths ${_install_LIBRARY_DIRS}) if(_additional_search_paths) set(DIRS \"\${DIRS};\${_additional_search_paths}\") endif() foreach(_plugin \${PLUGINS}) get_filename_component(_pluginpath \${_plugin} PATH) list(APPEND DIRS \"\${_pluginpath}\") endforeach(_plugin) + foreach(_dir ${_python_dirs}) + list(APPEND DIRS \"\${_dir}\") + endforeach() + list(REMOVE_DUPLICATES DIRS) # use custom version of BundleUtilities include(BundleUtilities) fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${_target_location}\" \"\${PLUGINS}\" \"\${DIRS}\") ") endmacro() diff --git a/CMakeExternals/CTK.cmake b/CMakeExternals/CTK.cmake index 81d35de915..14bd3c0c93 100644 --- a/CMakeExternals/CTK.cmake +++ b/CMakeExternals/CTK.cmake @@ -1,95 +1,98 @@ #----------------------------------------------------------------------------- # CTK #----------------------------------------------------------------------------- if(MITK_USE_CTK) # Sanity checks if(DEFINED CTK_DIR AND NOT EXISTS ${CTK_DIR}) message(FATAL_ERROR "CTK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj CTK) set(proj_DEPENDENCIES ) set(CTK_DEPENDS ${proj}) if(NOT DEFINED CTK_DIR) set(revision_tag fd3ecf96) #IF(${proj}_REVISION_TAG) # SET(revision_tag ${${proj}_REVISION_TAG}) #ENDIF() set(ctk_optional_cache_args ) if(MITK_USE_Python) + if(NOT MITK_USE_SYSTEM_PYTHON) + list(APPEND proj_DEPENDENCIES Python) + endif() list(APPEND ctk_optional_cache_args -DCTK_LIB_Scripting/Python/Widgets:BOOL=ON -DCTK_ENABLE_Python_Wrapping:BOOL=ON -DCTK_APP_ctkSimplePythonShell:BOOL=ON -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} ) else() list(APPEND ctk_optional_cache_args -DCTK_LIB_Scripting/Python/Widgets:BOOL=OFF -DCTK_ENABLE_Python_Wrapping:BOOL=OFF -DCTK_APP_ctkSimplePythonShell:BOOL=OFF ) endif() if(MITK_USE_DCMTK) list(APPEND ctk_optional_cache_args -DDCMTK_DIR:PATH=${DCMTK_DIR} ) list(APPEND proj_DEPENDENCIES DCMTK) else() list(APPEND ctk_optional_cache_args -DDCMTK_URL:STRING=${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/CTK_DCMTK_085525e6.tar.gz ) endif() FOREACH(type RUNTIME ARCHIVE LIBRARY) IF(DEFINED CTK_PLUGIN_${type}_OUTPUT_DIRECTORY) LIST(APPEND mitk_optional_cache_args -DCTK_PLUGIN_${type}_OUTPUT_DIRECTORY:PATH=${CTK_PLUGIN_${type}_OUTPUT_DIRECTORY}) ENDIF() ENDFOREACH() ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/CTK_${revision_tag}.tar.gz URL_MD5 a33be5c622fee05179c55e67a7d1b9cf UPDATE_COMMAND "" INSTALL_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${ctk_optional_cache_args} -DDESIRED_QT_VERSION:STRING=${DESIRED_QT_VERSION} -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DGit_EXECUTABLE:FILEPATH=${GIT_EXECUTABLE} -DGIT_EXECUTABLE:FILEPATH=${GIT_EXECUTABLE} -DCTK_LIB_CommandLineModules/Backend/LocalProcess:BOOL=ON -DCTK_LIB_CommandLineModules/Frontend/QtGui:BOOL=ON -DCTK_LIB_PluginFramework:BOOL=ON -DCTK_LIB_DICOM/Widgets:BOOL=ON -DCTK_LIB_XNAT/Core:BOOL=ON -DCTK_PLUGIN_org.commontk.eventadmin:BOOL=ON -DCTK_PLUGIN_org.commontk.configadmin:BOOL=ON -DCTK_USE_GIT_PROTOCOL:BOOL=OFF -DDCMTK_URL:STRING=${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/CTK_DCMTK_085525e6.tar.gz -DqRestAPI_URL:STRING=${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/qRestAPI_5f3a03b1.tar.gz DEPENDS ${proj_DEPENDENCIES} ) set(CTK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/CableSwig.cmake b/CMakeExternals/CableSwig.cmake deleted file mode 100644 index 73cc64f959..0000000000 --- a/CMakeExternals/CableSwig.cmake +++ /dev/null @@ -1,44 +0,0 @@ -#----------------------------------------------------------------------------- -# CableSwig -#----------------------------------------------------------------------------- - -if(MITK_USE_Python) - -# Sanity checks -if(DEFINED CableSwig_DIR AND NOT EXISTS ${CableSwig_DIR}) - message(FATAL_ERROR "CableSwig_DIR variable is defined but corresponds to non-existing directory") -endif() - -set(proj CableSwig) -set(proj_DEPENDENCIES ) -set(CableSwig_DEPENDS ${proj}) - -if(NOT DEFINED CableSwig_DIR) - - set(additional_cmake_args ) - - ExternalProject_Add(${proj} - SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src - BINARY_DIR ${proj}-build - PREFIX ${proj}-cmake - URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/CableSwig-ITK-3.20.0-v2.tar.gz - URL_MD5 893882bf8b4fbfbae3fe8c747a75f7a0 - INSTALL_COMMAND "" - CMAKE_GENERATOR ${gen} - CMAKE_ARGS - ${ep_common_args} - ${additional_cmake_args} - -DBUILD_TESTING:BOOL=OFF - -DSWIG_BUILD_EXAMPLES:BOOL=OFF - DEPENDS ${proj_DEPENDENCIES} - ) - - set(CableSwig_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) - -else() - - mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") - -endif() - -endif() diff --git a/CMakeExternals/ITK.cmake b/CMakeExternals/ITK.cmake index 2dde71437d..779cfb7ec8 100644 --- a/CMakeExternals/ITK.cmake +++ b/CMakeExternals/ITK.cmake @@ -1,98 +1,72 @@ #----------------------------------------------------------------------------- # ITK #----------------------------------------------------------------------------- # Sanity checks if(DEFINED ITK_DIR AND NOT EXISTS ${ITK_DIR}) message(FATAL_ERROR "ITK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj ITK) set(proj_DEPENDENCIES GDCM) -if(MITK_USE_Python) - list(APPEND proj_DEPENDENCIES CableSwig) -endif() + if(MITK_USE_OpenCV) list(APPEND proj_DEPENDENCIES OpenCV) endif() set(ITK_DEPENDS ${proj}) if(NOT DEFINED ITK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF) endif() - if(MITK_USE_Python) - - list(APPEND additional_cmake_args - -DITK_WRAPPING:BOOL=ON - -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} - -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} - -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} - -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} - #-DPYTHON_LIBRARIES=${PYTHON_LIBRARY} - #-DPYTHON_DEBUG_LIBRARIES=${PYTHON_DEBUG_LIBRARIES} - -DCableSwig_DIR:PATH=${CableSwig_DIR} - #-DITK_WRAP_JAVA:BOOL=OFF - -DITK_WRAP_unsigned_char:BOOL=ON - #-DITK_WRAP_double:BOOL=ON - -DITK_WRAP_rgb_unsigned_char:BOOL=ON - #-DITK_WRAP_rgba_unsigned_char:BOOL=ON - -DITK_WRAP_signed_char:BOOL=ON - #-DWRAP_signed_long:BOOL=ON - -DITK_WRAP_signed_short:BOOL=ON - -DITK_WRAP_short:BOOL=ON - -DITK_WRAP_unsigned_long:BOOL=ON - ) - else() - list(APPEND additional_cmake_args - -DUSE_WRAP_ITK:BOOL=OFF - ) - endif() + list(APPEND additional_cmake_args + -DUSE_WRAP_ITK:BOOL=OFF + ) if(MITK_USE_OpenCV) list(APPEND additional_cmake_args -DModule_ITKVideoBridgeOpenCV:BOOL=ON -DOpenCV_DIR:PATH=${OpenCV_DIR} ) endif() # Keep the behaviour of ITK 4.3 which by default turned on ITK Review # see MITK bug #17338 list(APPEND additional_cmake_args -DModule_ITKReview:BOOL=ON ) set(ITK_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchITK-4.5.1.cmake) ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/InsightToolkit-4.5.1-3e550bf8.tar.gz URL_MD5 80e433ffc0e81cdc19a03dd02a3c329b INSTALL_COMMAND "" PATCH_COMMAND ${ITK_PATCH_COMMAND} CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${additional_cmake_args} -DBUILD_TESTING:BOOL=OFF -DBUILD_EXAMPLES:BOOL=OFF -DITK_USE_SYSTEM_GDCM:BOOL=ON -DGDCM_DIR:PATH=${GDCM_DIR} DEPENDS ${proj_DEPENDENCIES} ) set(ITK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/Numpy.cmake b/CMakeExternals/Numpy.cmake new file mode 100644 index 0000000000..03121b31a1 --- /dev/null +++ b/CMakeExternals/Numpy.cmake @@ -0,0 +1,88 @@ +#----------------------------------------------------------------------------- +# Numpy +#----------------------------------------------------------------------------- +if( MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON ) + # Sanity checks + if(DEFINED Numpy_DIR AND NOT EXISTS ${Numpy_DIR}) + message(FATAL_ERROR "Numpy_DIR variable is defined but corresponds to non-existing directory") + endif() + + if( NOT DEFINED Numpy_DIR ) + set(proj Numpy) + set(${proj}_DEPENDENCIES Python) + set(Numpy_DEPENDS ${proj}) + + # setup build environment and disable fortran, blas and lapack + set(_numpy_env + " + set(ENV{F77} \"\") + set(ENV{F90} \"\") + set(ENV{FFLAGS} \"\") + set(ENV{ATLAS} \"None\") + set(ENV{BLAS} \"None\") + set(ENV{LAPACK} \"None\") + set(ENV{MKL} \"None\") + set(ENV{VS_UNICODE_OUTPUT} \"\") + set(ENV{CC} \"${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}\") + set(ENV{CFLAGS} \"${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\") + set(ENV{CXX} \"${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}\") + set(ENV{CXXFLAGS} \"${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\") + set(ENV{LDFLAGS} \"${CMAKE_LINKER_FLAGS} ${CMAKE_LINKER_FLAGS_RELEASE}\") + + ") + + set(_numpy_build_step ${MITK_SOURCE_DIR}/CMake/mitkFunctionExternalPythonBuildStep.cmake) + + set(_configure_step ${CMAKE_BINARY_DIR}/${proj}-cmake/${proj}_configure_step.cmake) + file(WRITE ${_configure_step} + "${_numpy_env} + include(\"${_numpy_build_step}\") + file(WRITE \"${CMAKE_BINARY_DIR}/${proj}-src/site.cfg\" \"\") + mitkFunctionExternalPythonBuildStep(${proj} configure ${PYTHON_EXECUTABLE} \"${CMAKE_BINARY_DIR}\" setup.py config) + ") + + # build step + set(_build_step ${CMAKE_BINARY_DIR}/${proj}-cmake/${proj}_build_step.cmake) + file(WRITE ${_build_step} + "${_numpy_env} + include(\"${_numpy_build_step}\") + mitkFunctionExternalPythonBuildStep(${proj} build ${PYTHON_EXECUTABLE} \"${CMAKE_BINARY_DIR}\" setup.py build --fcompiler=none) + ") + + # install step + set(_install_dir ${Python_DIR}) + if(WIN32) + STRING(REPLACE "/" "\\\\" _install_dir ${Python_DIR}) + endif() + + set(_install_step ${CMAKE_BINARY_DIR}/${proj}-cmake/${proj}_install_step.cmake) + file(WRITE ${_install_step} + "${_numpy_env} + include(\"${_numpy_build_step}\") + mitkFunctionExternalPythonBuildStep(${proj} install ${PYTHON_EXECUTABLE} \"${CMAKE_BINARY_DIR}\" setup.py install --prefix=${_install_dir}) + ") + + set(Numpy_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/numpy-1.4.1.tar.gz) + set(Numpy_MD5 "5c7b5349dc3161763f7f366ceb96516b") + + ExternalProject_Add(${proj} + URL ${Numpy_URL} + URL_MD5 ${Numpy_MD5} + SOURCE_DIR ${proj}-src + PREFIX ${proj}-cmake + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -P ${_configure_step} + BUILD_COMMAND ${CMAKE_COMMAND} -P ${_build_step} + INSTALL_COMMAND ${CMAKE_COMMAND} -P ${_install_step} + + DEPENDS + ${${proj}_DEPENDENCIES} + ) + + set(Numpy_DIR ${MITK_PYTHON_SITE_DIR}/numpy) + + else() + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + endif() +endif() + diff --git a/CMakeExternals/OpenCV.cmake b/CMakeExternals/OpenCV.cmake index 6df5c6522c..77dd1d3942 100644 --- a/CMakeExternals/OpenCV.cmake +++ b/CMakeExternals/OpenCV.cmake @@ -1,92 +1,97 @@ #----------------------------------------------------------------------------- # OpenCV #----------------------------------------------------------------------------- if(MITK_USE_OpenCV) # Sanity checks if(DEFINED OpenCV_DIR AND NOT EXISTS ${OpenCV_DIR}) message(FATAL_ERROR "OpenCV_DIR variable is defined but corresponds to non-existing directory") endif() set(proj OpenCV) set(proj_DEPENDENCIES) set(OpenCV_DEPENDS ${proj}) if(NOT DEFINED OpenCV_DIR) set(additional_cmake_args -DBUILD_opencv_java:BOOL=OFF -DBUILD_opencv_ts:BOOL=OFF -DBUILD_PERF_TESTS:BOOL=OFF ) if(MITK_USE_Python) #message(STATUS "PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}") #message(STATUS "PYTHON_DEBUG_LIBRARY: ${PYTHON_DEBUG_LIBRARY}") #message(STATUS "PYTHON_INCLUDE_DIR: ${PYTHON_INCLUDE_DIR}") #message(STATUS "PYTHON_LIBRARY: ${PYTHON_LIBRARY}") - list(APPEND additional_cmake_args -DBUILD_opencv_python:BOOL=ON -DBUILD_NEW_PYTHON_SUPPORT:BOOL=ON -DPYTHON_DEBUG_LIBRARY:FILEPATH=${PYTHON_DEBUG_LIBRARY} -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} + #-DPYTHON_LIBRARIES=${PYTHON_LIBRARY} #-DPYTHON_DEBUG_LIBRARIES=${PYTHON_DEBUG_LIBRARIES} ) + if(NOT MITK_USE_SYSTEM_PYTHON) + list(APPEND proj_DEPENDENCIES Python Numpy) + # export python home + set(ENV{PYTHONHOME} "${Python_DIR}") + endif() else() list(APPEND additional_cmake_args -DBUILD_opencv_python:BOOL=OFF -DBUILD_NEW_PYTHON_SUPPORT:BOOL=OFF ) endif() # 12-05-02, muellerm, added QT usage by OpenCV if QT is used in MITK # 12-09-11, muellerm, removed automatic usage again, since this will struggle with the MITK Qt application object if(MITK_USE_QT) list(APPEND additional_cmake_args -DWITH_QT:BOOL=OFF -DWITH_QT_OPENGL:BOOL=OFF -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() set(OpenCV_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchOpenCV-2.4.8.2.cmake) set(opencv_url ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/OpenCV-2.4.8.2.tar.gz) set(opencv_url_md5 07fa7c1d225ea7fe8eeb1270a6b00e69) ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake URL ${opencv_url} URL_MD5 ${opencv_url_md5} INSTALL_COMMAND "" PATCH_COMMAND ${OpenCV_PATCH_COMMAND} CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DBUILD_DOCS:BOOL=OFF -DBUILD_TESTS:BOOL=OFF -DBUILD_EXAMPLES:BOOL=OFF -DBUILD_DOXYGEN_DOCS:BOOL=OFF -DWITH_CUDA:BOOL=ON ${additional_cmake_args} DEPENDS ${proj_DEPENDENCIES} ) set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/PCRE.cmake b/CMakeExternals/PCRE.cmake new file mode 100644 index 0000000000..6b2dc67d1d --- /dev/null +++ b/CMakeExternals/PCRE.cmake @@ -0,0 +1,35 @@ +#-------------------------------------------------------------------------- +# PCRE (Perl Compatible Regular Expressions) +#-------------------------------------------------------------------------- +if(MITK_USE_PCRE) + if(DEFINED PCRE_DIR AND NOT EXISTS ${PCRE_DIR}) + message(FATAL_ERROR "PCRE_DIR variable is defined but corresponds to non-existing directory") + endif() + if(NOT PCRE_DIR) + + set(proj PCRE) + set(${proj}_DEPENDENCIES "") + set(PCRE_TARGET_VERSION 8.35) + + ExternalProject_add(${proj} + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/pcre-8.35.tar.gz + URL_MD5 "ed58bcbe54d3b1d59e9f5415ef45ce1c" + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build + INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install + PREFIX ${proj}-cmake + CONFIGURE_COMMAND /./configure + CC=${CMAKE_C_COMPILER}${CMAKE_C_COMPILER_ARG1} + LDFLAGS=${CMAKE_LINKER_FLAGS} ${CMAKE_LINKER_FLAGS_RELEASE} + CXX=${CMAKE_CXX_COMPILER}${CMAKE_CXX_COMPILER_ARG1} + --prefix= + --disable-shared + DEPENDS "${${proj}_DEPENDENCIES}" + ) + + set(PCRE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install) + + else() + mitkMacroEmptyExternalProject(${proj} "${${proj}_DEPENDENCIES}") + endif() +endif() diff --git a/CMakeExternals/PatchPython.cmake b/CMakeExternals/PatchPython.cmake new file mode 100644 index 0000000000..a9e3587124 --- /dev/null +++ b/CMakeExternals/PatchPython.cmake @@ -0,0 +1,8 @@ +# +# Windows python 2.7.3 patches for the CMake build system +# https://github.com/davidsansome/python-cmake-buildsystem/tree/master/cmake/patches-win32 +# +set(in ${CMAKE_CURRENT_LIST_DIR}/msvc9compiler.py.patched) +set(out ${PYTHON_SOURCE_DIR}/Lib/distutils/msvc9compiler.py) + +execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${in} ${out}) diff --git a/CMakeExternals/PatchSimpleITK.cmake b/CMakeExternals/PatchSimpleITK.cmake new file mode 100644 index 0000000000..185fad393d --- /dev/null +++ b/CMakeExternals/PatchSimpleITK.cmake @@ -0,0 +1,18 @@ +# Called by ITK.cmake (ExternalProject_Add) as a patch for ITK to work with external GDCM 2.2.1 +# and remove all itk video libs to resolve external windows linker errors with opencv + +set(path "CMakeLists.txt") +file(STRINGS ${path} contents NEWLINE_CONSUME) +string(REPLACE "ITK_LIBRARY_DIRS}\")" "ITK_LIBRARY_DIRS}\" \"\${GDCM_DIR}/bin\") + list(REMOVE_ITEM ITK_LIBRARIES ITKVideoBridgeOpenCV ITKVideoCore ITKVideoIO)" contents ${contents}) +set(CONTENTS ${contents}) +configure_file(${TEMPLATE_FILE} ${path} @ONLY) + +# fix for double import targets +set(path "SimpleITKConfig.cmake.in") +file(STRINGS ${path} contents NEWLINE_CONSUME) +string(REPLACE "if(NOT ITK_TARGETS_IMPORTED)" "if(NOT TARGET ITKCommon)" contents ${contents}) +set(CONTENTS ${contents}) +string(REPLACE "if(NOT SimpleITK_TARGETS_IMPORTED)" "if(NOT TARGET SimpleITKCommon)" contents ${contents}) +set(CONTENTS ${contents}) +configure_file(${TEMPLATE_FILE} ${path} @ONLY) diff --git a/CMakeExternals/Python.cmake b/CMakeExternals/Python.cmake new file mode 100644 index 0000000000..58e5718c7d --- /dev/null +++ b/CMakeExternals/Python.cmake @@ -0,0 +1,175 @@ +#---------------------------------------------------------------------- +# Python +#---------------------------------------------------------------------- +if( MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON ) + # Sanity checks + if(DEFINED Python_DIR AND NOT EXISTS ${Python_DIR}) + message(FATAL_ERROR "Python_DIR variable is defined but corresponds to non-existing directory") + endif() + + if(NOT DEFINED Python_DIR) + set(proj Python) + set(Python_DEPENDENCIES ZLIB Python-src) + set(Python_DEPENDS ${proj}) + + set(MITK_PYTHON_MAJOR_VERSION 2) + set(MITK_PYTHON_MINOR_VERSION 7) + set(MITK_PYTHON_PATCH_VERSION 3) + + set(PYTHON_SOURCE_PACKAGE Python-${MITK_PYTHON_MAJOR_VERSION}.${MITK_PYTHON_MINOR_VERSION}.${MITK_PYTHON_PATCH_VERSION}) + set(PYTHON_SOURCE_DIR "${CMAKE_BINARY_DIR}/${PYTHON_SOURCE_PACKAGE}") + # patch the VS compiler config + + if(WIN32) + set(PYTHON_PATCH_COMMAND PATCH_COMMAND ${CMAKE_COMMAND} -DPYTHON_SOURCE_DIR:PATH=${PYTHON_SOURCE_DIR} -P ${CMAKE_CURRENT_LIST_DIR}/Patch${proj}.cmake) + endif() + + # download the source code + ExternalProject_Add(Python-src + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/${PYTHON_SOURCE_PACKAGE}.tgz + URL_MD5 "2cf641732ac23b18d139be077bd906cd" + PREFIX ${CMAKE_BINARY_DIR}/${PYTHON_SOURCE_PACKAGE}-cmake + SOURCE_DIR "${PYTHON_SOURCE_DIR}" + ${PYTHON_PATCH_COMMAND} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + set(additional_cmake_cache_args ) + list(APPEND additional_cmake_cache_args + -DBUILTIN_ARRAY:BOOL=ON + -DBUILTIN_AUDIOOP:BOOL=ON + -DBUILTIN_BINASCII:BOOL=ON + -DBUILTIN_BISECT:BOOL=ON + -DBUILTIN_BSDB:BOOL=ON + -DBUILTIN_BSSDB:BOOL=ON + -DBUILTIN_BZ2:BOOL=ON + -DBUILTIN_CMATH:BOOL=ON + -DBUILTIN_COLLECTIONS:BOOL=ON + -DBUILTIN_CODECS_CN:BOOL=ON + -DBUILTIN_CODECS_HK:BOOL=ON + -DBUILTIN_CODECS_ISO2022:BOOL=ON + -DBUILTIN_CODECS_JP:BOOL=ON + -DBUILTIN_CODECS_KR:BOOL=ON + -DBUILTIN_CODECS_TW:BOOL=ON + -DBUILTIN_CPICKLE:BOOL=ON + -DBUILTIN_CRYPT:BOOL=ON + -DBUILTIN_CSTRINGIO:BOOL=ON + -DBUILTIN_CSV:BOOL=ON + -DBUILTIN_CTYPES:BOOL=OFF + #-DBUILTIN_CTYPES_TEST:BOOL=OFF + #-DBUILTIN_CURSES:BOOL=ON + -DBUILTIN_DATETIME:BOOL=ON + -DBUILTIN_DBM:BOOL=ON + -DBUILTIN_ELEMENTTREE:BOOL=ON + -DBUILTIN_FCNTL:BOOL=ON + -DBUILTIN_FUNCTOOLS:BOOL=ON + -DBUILTIN_FUTURE_BUILTINS:BOOL=ON + -DBULTIN_GDBM:BOOL=ON + -DBUILTIN_GRP:BOOL=ON + -DBUILTIN_HASHLIB:BOOL=ON + -DBUILTIN_HEAPQ:BOOL=ON + -DBUILTIN_HOTSHOT:BOOL=ON + -DBUILTIN_IO:BOOL=ON + -DBUILTIN_ITERTOOLS:BOOL=ON + -DBUILTIN_JSON:BOOL=ON + -DBUILTIN_LOCALE:BOOL=ON + -DBUILTIN_LSPROF:BOOL=ON + -DBUILTIN_MATH:BOOL=ON + -DBUILTIN_MMAP:BOOL=ON + -DBUILTIN_MULTIBYTECODEC:BOOL=ON + -DBUILTIN_MD5:BOOL=ON + -DBUILTIN_MULTIPROCESSING:BOOL=ON + -DBUILTIN_NIS:BOOL=ON + -DBUILTIN_NIT:BOOL=ON + -DBUILTIN_OPERATOR:BOOL=ON + -DBUILTIN_PARSER:BOOL=ON + -DBUILTIN_POSIX:BOOL=ON + -DBUILTIN_PWD:BOOL=ON + -DBUILTIN_PYEXPAT:BOOL=ON + -DBUILTIN_READLINE:BOOL=ON + -DBUILTIN_RESOURCE:BOOL=ON + -DBULTIN_RANDOM:BOOL=ON + -DBUILTIN_SCPROXY:BOOL=OFF + -DBUILTIN_SELECT:BOOL=ON + -DBUILTIN_SHA:BOOL=ON + -DBUILTIN_SHA256:BOOL=ON + -DBUILTIN_SHA512:BOOL=ON + -DBUILTIN_SOCKET:BOOL=ON + -DBUILTIN_SPWD:BOOL=ON + -DBUILTIN_SQLITE3:BOOL=OFF + -DBUILTIN_SSL:BOOL=ON + -DBUILTIN_STROP:BOOL=ON + -DBUILTIN_STRUCT:BOOL=ON + -DBUILTIN_SUBPROCESS:BOOL=ON + -DBUILTIN_SYSLOG:BOOL=ON + -DBUILTIN_TERMIOS:BOOL=ON + #-DBUILTIN_TESTCAPI:BOOL=OFF + -DBUILTIN_TIME:BOOL=ON + -DBUILTIN_TKINTER:BOOL=ON + -DBUILTIN_UNICODEDATA:BOOL=ON + -DBUILTIN_WINREG:BOOL=ON + -DBUILTIN_ZLIB:BOOL=OFF + -DUSE_SYSTEM_ZLIB:BOOL=ON + ) + + # CMake build environment for python from: + # https://github.com/davidsansome/python-cmake-buildsystem + ExternalProject_Add(${proj} + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/python-cmake-buildsystem-47845c55.tar.gz + URL_MD5 "6e49d1ed93a5a0fff7621430c163d2d1" + SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src + PREFIX ${proj}-cmake + BINARY_DIR ${proj}-build + INSTALL_DIR ${proj}-install + CMAKE_ARGS + ${ep_common_args} + -DCMAKE_INSTALL_PREFIX:PATH= + CMAKE_CACHE_ARGS + -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} + -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} + #-DBUILD_TESTING:BOOL=OFF + -DBUILD_SHARED:BOOL=ON + -DBUILD_STATIC:BOOL=OFF + -DUSE_SYSTEM_LIBRARIES:BOOL=OFF + ${additional_cmake_cache_args} + -DZLIB_INCLUDE_DIR:PATH=${ZLIB_INCLUDE_DIR} + -DZLIB_LIBRARY:FILEPATH=${ZLIB_LIBRARY} + DEPENDS + ${Python_DEPENDENCIES} + ) + + set(Python_DIR "${CMAKE_BINARY_DIR}/${proj}-install") + + if(UNIX) + set(PYTHON_EXECUTABLE "${Python_DIR}/bin/python${CMAKE_EXECUTABLE_SUFFIX}") + set(PYTHON_INCLUDE_DIR "${Python_DIR}/include/python${MITK_PYTHON_MAJOR_VERSION}.${MITK_PYTHON_MINOR_VERSION}") + set(PYTHON_LIBRARY "${Python_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}python${MITK_PYTHON_MAJOR_VERSION}.${MITK_PYTHON_MINOR_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") + set(MITK_PYTHON_SITE_DIR "${Python_DIR}/lib/python${MITK_PYTHON_MAJOR_VERSION}.${MITK_PYTHON_MINOR_VERSION}/site-packages") + else() + set(PYTHON_EXECUTABLE "${Python_DIR}/bin/python${CMAKE_EXECUTABLE_SUFFIX}") + set(PYTHON_INCLUDE_DIR "${Python_DIR}/include") + set(PYTHON_LIBRARY "${Python_DIR}/libs/python${MITK_PYTHON_MAJOR_VERSION}${MITK_PYTHON_MINOR_VERSION}.lib") + set(MITK_PYTHON_SITE_DIR "${Python_DIR}/Lib/site-packages") + endif() + + # pre compile all *.py files in the runtime after install step + ExternalProject_Add_Step(${proj} compile_step + COMMAND ${PYTHON_EXECUTABLE} -m compileall + DEPENDEES install + ) + + # use the python executable in the build dir for unix systems. The stripped + # ones will cause conflicts if system libraries are present during the build/configure process + # of opencv, since they will try to lookup the sys path first if no lib is directly + # linked with it s path into the executable + if(UNIX) + set(PYTHON_EXECUTABLE "${CMAKE_BINARY_DIR}/${proj}-build/bin/python${CMAKE_EXECUTABLE_SUFFIX}") + endif() + + else() + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + endif() +endif() + diff --git a/CMakeExternals/SimpleITK.cmake b/CMakeExternals/SimpleITK.cmake new file mode 100644 index 0000000000..0e394acf42 --- /dev/null +++ b/CMakeExternals/SimpleITK.cmake @@ -0,0 +1,128 @@ +#----------------------------------------------------------------------------- +# SimpleITK +#----------------------------------------------------------------------------- + +if(MITK_USE_SimpleITK) + + # Sanity checks + if(DEFINED SimpleITK_DIR AND NOT EXISTS ${SimpleITK_DIR}) + message(FATAL_ERROR "SimpleITK_DIR variable is defined but corresponds to non-existing directory") + endif() + + set(proj SimpleITK) + set(proj_DEPENDENCIES ITK GDCM Swig) + + if(MITK_USE_OpenCV) + list(APPEND proj_DEPENDENCIES OpenCV) + endif() + + set(SimpleITK_DEPENDS ${proj}) + + if(NOT DEFINED SimpleITK_DIR) + + set(additional_cmake_args ) + + list(APPEND additional_cmake_args + -DWRAP_CSHARP:BOOL=OFF + -DWRAP_TCL:BOOL=OFF + -DWRAP_LUA:BOOL=OFF + -DWRAP_PYTHON:BOOL=OFF + -DWRAP_JAVA:BOOL=OFF + -DWRAP_RUBY:BOOL=OFF + -DWRAP_R:BOOL=OFF + ) + + if(MITK_USE_Python) + list(APPEND additional_cmake_args + -DWRAP_PYTHON:BOOL=ON + -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} + -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} + -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} + -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} + ) + if(NOT MITK_USE_SYSTEM_PYTHON) + list(APPEND proj_DEPENDENCIES Python) + endif() + endif() + + #TODO: Installer and testing works only with static libs on MAC + set(_build_shared ON) + if(APPLE) + set(_build_shared OFF) + endif() + + set(SimpleITK_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchSimpleITK.cmake) + + ExternalProject_Add(${proj} + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/SimpleITK-0.8.0.tar.gz + URL_MD5 "d98f2e5442228e324ef62111febc7446" + SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src + BINARY_DIR ${proj}-build + PREFIX ${proj}-cmake + INSTALL_DIR ${proj}-install + PATCH_COMMAND ${SimpleITK_PATCH_COMMAND} + CMAKE_ARGS + ${ep_common_args} + # -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON + CMAKE_CACHE_ARGS + ${additional_cmake_args} + -DBUILD_SHARED_LIBS:BOOL=${_build_shared} + -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/${proj}-install + -DCMAKE_INSTALL_NAME_DIR:STRING=/lib + -DSimpleITK_BUILD_DISTRIBUTE:BOOL=ON + -DSimpleITK_PYTHON_THREADS:BOOL=ON + -DUSE_SYSTEM_ITK:BOOL=ON + -DBUILD_TESTING:BOOL=OFF + -DBUILD_EXAMPLES:BOOL=OFF + -DGDCM_DIR:PATH=${GDCM_DIR} + -DITK_DIR:PATH=${ITK_DIR} + -DSWIG_DIR:PATH=${SWIG_DIR} + -DSWIG_EXECUTABLE:FILEPATH=${SWIG_EXECUTABLE} + DEPENDS ${proj_DEPENDENCIES} + ) + + set(SimpleITK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) + + if( MITK_USE_Python ) + # PythonDir needs to be fixed for the python interpreter by + # changing dir delimiter for Windows + set(_install_dir ${Python_DIR}) + if(WIN32) + STRING(REPLACE "/" "\\\\" _install_dir ${Python_DIR}) + endif() + # Build python distribution with easy install. If a own runtime is used + # embedd the egg into the site-package folder of the runtime + if(NOT MITK_USE_SYSTEM_PYTHON) + ExternalProject_Add_Step(${proj} sitk_python_install_step + COMMAND ${PYTHON_EXECUTABLE} setup.py install --prefix=${_install_dir} + DEPENDEES build + WORKING_DIRECTORY ${SimpleITK_DIR}/Wrapping/PythonPackage + ) + # Build egg into custom user base folder and deploy it later into installer + # https://pythonhosted.org/setuptools/easy_install.html#use-the-user-option-and-customize-pythonuserbase + else() + set(_userbase_install ${SimpleITK_DIR}/Wrapping/PythonPackage/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) + if(WIN32) + set(_userbase_install ${SimpleITK_DIR}/Wrapping/PythonPackage/Lib/site-packages) + endif() + ExternalProject_Add_Step(${proj} sitk_create_userbase_step + COMMAND ${CMAKE_COMMAND} -E make_directory ${_userbase_install} + DEPENDEES build + WORKING_DIRECTORY ${SimpleITK_DIR}/Wrapping/PythonPackage + ) + ExternalProject_Add_Step(${proj} sitk_python_install_step + COMMAND PYTHONUSERBASE=${SimpleITK_DIR}/Wrapping/PythonPackage ${PYTHON_EXECUTABLE} setup.py install --user + DEPENDEES sitk_create_userbase_step + WORKING_DIRECTORY ${SimpleITK_DIR}/Wrapping/PythonPackage + ) + endif() + endif() + + else() + + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + + endif() + +endif() + diff --git a/CMakeExternals/Swig.cmake b/CMakeExternals/Swig.cmake new file mode 100644 index 0000000000..550680dae7 --- /dev/null +++ b/CMakeExternals/Swig.cmake @@ -0,0 +1,64 @@ +#------------------------------------------------------------ +# SWIG (Simple Wrapper Interface Generator) +#----------------------------------------------------------- +if(MITK_USE_SWIG) + if(DEFINED Swig_DIR AND NOT EXISTS ${Swig_DIR}) + message(FATAL_ERROR "Swig_DIR variable is defined but corresponds to non-existing directory") + endif() + + if(NOT SWIG_DIR) + set(SWIG_TARGET_VERSION 3.0.2) + set(proj Swig) + set(Swig_DEPENDENCIES ) + set(Swig_DEPENDS ) + + # binary SWIG for windows + if(WIN32) + set(swig_source_dir ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}) + + # swig.exe available as pre-built binary on Windows: + ExternalProject_Add(Swig + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/swigwin-${SWIG_TARGET_VERSION}.zip + URL_MD5 "3f18de4fc09ab9abb0d3be37c11fbc8f" + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + set(SWIG_DIR ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}) # path specified as source in ep + set(SWIG_EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}/swig.exe) + + else() + + list(APPEND Swig_DEPENDENCIES PCRE) + + # swig uses bison find it by cmake and pass it down + find_package(BISON) + set(BISON_FLAGS "" CACHE STRING "Flags used by bison") + mark_as_advanced( BISON_FLAGS) + + ExternalProject_add(${proj} + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/swig-${SWIG_TARGET_VERSION}.tar.gz + URL_MD5 "62f9b0d010cef36a13a010dc530d0d41" + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build + INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install + PREFIX ${proj}-cmake + CONFIGURE_COMMAND /./configure + CC=${CMAKE_C_COMPILER}${CMAKE_C_COMPILER_ARG1} + LDFLAGS=${CMAKE_LINKER_FLAGS} ${CMAKE_LINKER_FLAGS_RELEASE} + CXX=${CMAKE_CXX_COMPILER}${CMAKE_CXX_COMPILER_ARG1} + --prefix= + --with-pcre-prefix=${PCRE_DIR} + --without-octave + --with-python=${PYTHON_EXECUTABLE} + DEPENDS ${Swig_DEPENDENCIES} + ) + + set(SWIG_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install/share/swig/${SWIG_TARGET_VERSION}) + set(SWIG_EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install/bin/swig) + + endif() + endif(NOT SWIG_DIR) +endif() diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake index a3ef5f7bd6..495f9a4e28 100644 --- a/CMakeExternals/VTK.cmake +++ b/CMakeExternals/VTK.cmake @@ -1,94 +1,95 @@ #----------------------------------------------------------------------------- # VTK #----------------------------------------------------------------------------- if(WIN32) option(VTK_USE_SYSTEM_FREETYPE OFF) else(WIN32) option(VTK_USE_SYSTEM_FREETYPE ON) endif(WIN32) # Sanity checks if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR}) message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj VTK) set(proj_DEPENDENCIES ) set(VTK_DEPENDS ${proj}) if(NOT DEFINED VTK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF -DVTK_USE_VIDEO4WINDOWS:BOOL=OFF # no header files provided by MinGW ) endif() if(MITK_USE_Python) + if(NOT MITK_USE_SYSTEM_PYTHON) + list(APPEND proj_DEPENDENCIES Python) + endif() list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=ON -DVTK_USE_TK:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} - #-DPYTHON_LIBRARIES=${PYTHON_LIBRARY} - #-DPYTHON_DEBUG_LIBRARIES=${PYTHON_DEBUG_LIBRARIES} ) else() list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF ) endif() if(MITK_USE_QT) list(APPEND additional_cmake_args -DVTK_QT_VERSION:STRING=${DESIRED_QT_VERSION} -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DModule_vtkGUISupportQt:BOOL=ON -DModule_vtkGUISupportQtWebkit:BOOL=ON -DModule_vtkGUISupportQtSQL:BOOL=ON -DModule_vtkRenderingQt:BOOL=ON -DVTK_Group_Qt:BOOL=ON ) endif() set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/VTK-6.1.0.tar.gz) set(VTK_URL_MD5 25e4dfb3bad778722dcaec80cd5dab7d) ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake URL ${VTK_URL} URL_MD5 ${VTK_URL_MD5} INSTALL_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DVTK_WRAP_TCL:BOOL=OFF -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WRAP_JAVA:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=ON -DVTK_USE_SYSTEM_FREETYPE:BOOL=${VTK_USE_SYSTEM_FREETYPE} -DVTK_LEGACY_REMOVE:BOOL=ON -DModule_vtkTestingRendering:BOOL=ON -DVTK_MAKE_INSTANTIATORS:BOOL=ON ${additional_cmake_args} DEPENDS ${proj_DEPENDENCIES} ) set(VTK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/ZLIB.cmake b/CMakeExternals/ZLIB.cmake new file mode 100644 index 0000000000..57310a059f --- /dev/null +++ b/CMakeExternals/ZLIB.cmake @@ -0,0 +1,39 @@ +#------------------------------------------------------------------ +# ZLIB +#------------------------------------------------------------------ +if(MITK_USE_ZLIB) + if(NOT DEFINED ZLIB_DIR) + set(proj ZLIB) + set(${proj}_DEPENDENCIES ) + set(ZLIB_DEPENDS ${proj}) + + # Using the ZLIB from CTK: + # https://github.com/commontk/zlib + ExternalProject_Add(${proj} + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/zlib-66a75305.tar.gz + URL_MD5 "4c3f572b487ae7947fd88ec363533bc5" + SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src + BINARY_DIR ${proj}-build + PREFIX ${proj}-cmake + INSTALL_DIR ${proj}-install + CMAKE_ARGS + ${ep_common_args} + CMAKE_CACHE_ARGS + -DBUILD_SHARED_LIBS:BOOL=OFF + -DZLIB_MANGLE_PREFIX:STRING=mitk_zlib_ + -DCMAKE_INSTALL_PREFIX:PATH= + DEPENDS + ${ZLIB_DEPENDENCIES} + ) + set(ZLIB_DIR ${CMAKE_BINARY_DIR}/${proj}-install) + set(ZLIB_INCLUDE_DIR ${ZLIB_DIR}/include) + if(WIN32) + set(ZLIB_LIBRARY ${ZLIB_DIR}/lib/zlib.lib) + else() + set(ZLIB_LIBRARY ${ZLIB_DIR}/lib/libzlib.a) + endif() + else() + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + endif() +endif() + diff --git a/CMakeExternals/msvc9compiler.py.patched b/CMakeExternals/msvc9compiler.py.patched new file mode 100644 index 0000000000..daf78685a2 --- /dev/null +++ b/CMakeExternals/msvc9compiler.py.patched @@ -0,0 +1,924 @@ +"""distutils.msvc9compiler + +Contains MSVCCompiler, an implementation of the abstract CCompiler class +for the Microsoft Visual Studio 2008. + +The module is compatible with VS 2005 and VS 2008. You can find legacy support +for older versions of VS in distutils.msvccompiler. +""" + +# Written by Perry Stoll +# hacked by Robin Becker and Thomas Heller to do a better job of +# finding DevStudio (through the registry) +# ported to VS2005 and VS 2008 by Christian Heimes + +__revision__ = "$Id$" + +import os +import subprocess +import sys +import re + +from distutils.errors import (DistutilsExecError, DistutilsPlatformError, + CompileError, LibError, LinkError) +from distutils.ccompiler import CCompiler, gen_lib_options +from distutils import log +from distutils.util import get_platform + +import _winreg + +RegOpenKeyEx = _winreg.OpenKeyEx +RegEnumKey = _winreg.EnumKey +RegEnumValue = _winreg.EnumValue +RegError = _winreg.error + +HKEYS = (_winreg.HKEY_USERS, + _winreg.HKEY_CURRENT_USER, + _winreg.HKEY_LOCAL_MACHINE, + _winreg.HKEY_CLASSES_ROOT) + +NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32) +if NATIVE_WIN64: + # Visual C++ is a 32-bit application, so we need to look in + # the corresponding registry branch, if we're running a + # 64-bit Python on Win64 + VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f" + WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" + VC_SXS_KEY = r"Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7" + VS_SXS_KEY = r"Software\Wow6432Node\Microsoft\VisualStudio\SxS\VS7" +else: + VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f" + WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Microsoft\.NETFramework" + VC_SXS_KEY = r"Software\Microsoft\VisualStudio\SxS\VC7" + VS_SXS_KEY = r"Software\Microsoft\VisualStudio\SxS\VS7" + +# A map keyed by get_platform() return values to values accepted by +# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is +# the param to cross-compile on x86 targetting amd64.) +PLAT_TO_VCVARS = { + 'win32' : 'x86', + 'win-amd64' : 'amd64', + 'win-ia64' : 'ia64', +} + +# Add the first found value of InstallationFolder from this list of +# keys to %PATH% +KEY_BASE = r"Software\Microsoft\\" +WINSDK_KEYS = [KEY_BASE + "Microsoft SDKs\\Windows\\" + rest for rest in ( + r"v%s", + r"v%sA" +)] + +# A map from VC version to Windows SDK version, to be used as the format +# parameter for each element of WINSDK_KEYS. +# See the following page for more details: +# - http://en.wikipedia.org/wiki/Microsoft_Windows_SDK#Versions +# - http://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History +WINSDK_VERSION_MAP = { + '9.0': ['6.0', '7.0'], # VS2008 + '10.0': ['7.0', '7.1'], # VS2010 + '11.0': ['7.1', '8.0', '8.1'], # VS2012 +} + +class Reg: + """Helper class to read values from the registry + """ + + def get_value(cls, path, key): + for base in HKEYS: + d = cls.read_values(base, path) + if d and key in d: + return d[key] + raise KeyError(key) + get_value = classmethod(get_value) + + def read_keys(cls, base, key): + """Return list of registry keys.""" + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + L = [] + i = 0 + while True: + try: + k = RegEnumKey(handle, i) + except RegError: + break + L.append(k) + i += 1 + return L + read_keys = classmethod(read_keys) + + def read_values(cls, base, key): + """Return dict of registry keys and values. + + All names are converted to lowercase. + """ + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + d = {} + i = 0 + while True: + try: + name, value, type = RegEnumValue(handle, i) + except RegError: + break + name = name.lower() + d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) + i += 1 + return d + read_values = classmethod(read_values) + + def convert_mbcs(s): + dec = getattr(s, "decode", None) + if dec is not None: + try: + s = dec("mbcs") + except UnicodeError: + pass + return s + convert_mbcs = staticmethod(convert_mbcs) + +class MacroExpander: + + def __init__(self, version): + self.macros = {} + self.vsbase = VS_BASE % version + self.load_macros(version) + + def set_macro(self, macro, path, key): + self.macros["$(%s)" % macro] = Reg.get_value(path, key) + + def load_macros(self, version): + self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir") + self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir") + self.set_macro("FrameworkDir", NET_BASE, "installroot") + try: + if version >= 8.0: + self.set_macro("FrameworkSDKDir", NET_BASE, + "sdkinstallrootv2.0") + else: + raise KeyError("sdkinstallrootv2.0") + except KeyError: + raise DistutilsPlatformError( + """Python was built with Visual Studio 2008; +extensions must be built with a compiler than can generate compatible binaries. +Visual Studio 2008 was not found on this system. If you have Cygwin installed, +you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""") + + if version >= 9.0: + self.set_macro("FrameworkVersion", self.vsbase, "clr version") + self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder") + else: + p = r"Software\Microsoft\NET Framework Setup\Product" + for base in HKEYS: + try: + h = RegOpenKeyEx(base, p) + except RegError: + continue + key = RegEnumKey(h, 0) + d = Reg.get_value(base, r"%s\%s" % (p, key)) + self.macros["$(FrameworkVersion)"] = d["version"] + + def sub(self, s): + for k, v in self.macros.items(): + s = s.replace(k, v) + return s + +def get_build_version(): + """Return the version of MSVC that was used to build Python. + + For Python 2.3 and up, the version number is included in + sys.version. For earlier versions, assume the compiler is MSVC 6. + """ + prefix = "MSC v." + i = sys.version.find(prefix) + if i == -1: + return 6 + i = i + len(prefix) + s, rest = sys.version[i:].split(" ", 1) + majorVersion = int(s[:-2]) - 6 + minorVersion = int(s[2:3]) / 10.0 + # I don't think paths are affected by minor version in version 6 + if majorVersion == 6: + minorVersion = 0 + if majorVersion >= 6: + return majorVersion + minorVersion + # else we don't know what version of the compiler this is + return None + +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths + +def removeDuplicates(variable): + """Remove duplicate values of an environment variable. + """ + oldList = variable.split(os.pathsep) + newList = [] + for i in oldList: + if i not in newList: + newList.append(i) + newVariable = os.pathsep.join(newList) + return newVariable + +# deprecated +def find_vcvarsall(version): + """Find the vcvarsall.bat file + + At first it tries to find the productdir of VS 2008 in the registry. If + that fails it falls back to the VS90COMNTOOLS env var. + """ + vsbase = VS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + productdir = None + + # trying Express edition + if productdir is None: + vsbase = VSEXPRESS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + productdir = None + log.debug("Unable to find productdir in registry") + + if not productdir or not os.path.isdir(productdir): + toolskey = "VS%0.f0COMNTOOLS" % version + toolsdir = os.environ.get(toolskey, None) + + if toolsdir and os.path.isdir(toolsdir): + productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC") + productdir = os.path.abspath(productdir) + if not os.path.isdir(productdir): + log.debug("%s is not a valid directory" % productdir) + return None + else: + log.debug("Env var %s is not set or invalid" % toolskey) + if not productdir: + log.debug("No productdir found") + return None + vcvarsall = os.path.join(productdir, "vcvarsall.bat") + if os.path.isfile(vcvarsall): + return vcvarsall + log.debug("Unable to find vcvarsall.bat") + return None + +def query_vcvarsall(version, arch="x86"): + """Launch vcvarsall.bat and read the settings from its environment + """ + + paths = [] + includes = [] + libs = [] + + def _append_if_exists(list_, path): + if os.path.isdir(path): + list_.append(path) + + def _add_bin_paths(base, paths): + if arch.endswith("ia64"): + _append_if_exists(paths, base + r"\bin\ia64") + elif arch.endswith("64"): + _append_if_exists(paths, base + r"\bin\x64") + _append_if_exists(paths, base + r"\bin\amd64") + elif arch.endswith("x86"): + _append_if_exists(paths, base + r"\bin") + + def _get_include_lib_paths(base): + existing_includes = [] + existing_libs = [] + _append_if_exists(existing_includes, base + r"\include") + if arch.endswith("ia64"): + _append_if_exists(existing_libs, base + r"\lib\ia64") + elif arch.endswith("64"): + _append_if_exists(existing_libs, base + r"\lib\x64") + _append_if_exists(existing_libs, base + r"\lib\amd64") + elif arch.endswith("x86"): + _append_if_exists(existing_libs, base + r"\lib") + + return (existing_includes, existing_libs) + + result = [] + + versionstr = '%.1f' % version + + vcpaths = Reg.read_values(_winreg.HKEY_LOCAL_MACHINE, VC_SXS_KEY) + vcinstalldir = vcpaths[versionstr] + vsinstalldir = Reg.read_values(_winreg.HKEY_LOCAL_MACHINE, VS_SXS_KEY).get(versionstr, vcinstalldir + "..") + + # set PATH to include: + # %VCINSTALLDIR%\bin[\x64|\amd64|\ia64] + # %VCINSTALLDIR%\VCPackages + + if vcinstalldir: + _add_bin_paths(vcinstalldir, paths) + _append_if_exists(paths, "%s\\VCPackages" % (vcinstalldir)) + + # set PATH to include: + # %VSINSTALLDIR%\Common7\IDE + # %VSINSTALLDIR%\Common7\Tools + # %VSINSTALLDIR%\Common7\Tools\bin + + if vsinstalldir: + _append_if_exists(paths, "%s\\Common7\\IDE" % (vsinstalldir)) + _append_if_exists(paths, "%s\\Common7\\Tools" % (vsinstalldir)) + _append_if_exists(paths, "%s\\Common7\\Tools\\bin" % (vsinstalldir)) + + # set PATH to include: + # %FrameworkDir%\%Framework35Version% + # %FrameworkDir%\%FrameworkVersion% + + frameworkdir = vcpaths.get("frameworkdir64" if arch == "amd64" else "frameworkdir32") + if frameworkdir: + _append_if_exists(paths, frameworkdir + r"\v3.5") + frameworkver = vcpaths.get("frameworkver64" if arch == "amd64" else "frameworkdir32") + if frameworkver: + _append_if_exists(paths, r"%s\%s" % (frameworkdir, frameworkver)) + + def _get_sdk_installationfolder(sdkver): + for sdkkey in WINSDK_KEYS: + try: + sdk_install = Reg.get_value(sdkkey % sdkver, "installationfolder") + except KeyError: + pass + else: + return sdk_install + return None + + sdk_available = False + + for sdkver in WINSDK_VERSION_MAP[versionstr]: + + # set PATH to include: + # %WindowsSdkDir%bin[\x64|\amd64|\ia64] + # set INCLUDE to include: + # %WindowsSdkDir%include + # and LIB to include + # %WindowsSdkDir%lib[\x64|\amd64|\ia64] + + sdk_install = _get_sdk_installationfolder(sdkver) + if sdk_install is not None: + (sdk_includes, sdk_libs) = _get_include_lib_paths(sdk_install) + sdk_available = len(sdk_includes) > 0 and len(sdk_libs) > 0 + if sdk_available: + _add_bin_paths(sdk_install, paths) + includes += sdk_includes + libs += sdk_libs + print("Windows SDK %s complete" % sdkver) + break + else: + print("Windows SDK %s incomplete" % sdkver) + else: + print("Windows SDK %s not found" % sdkver) + + # set INCLUDE to include: + # %VCINSTALLDIR%\include + # and LIB to include + # %VCINSTALLDIR%\lib[\x64|\amd64|\ia64] + + if vcinstalldir: + (vc_includes, vc_libs) = _get_include_lib_paths(vcinstalldir) + includes += vc_includes + libs += vc_libs + + result = { + "path": ";".join(paths), + "include": ";".join(includes), + "lib": ";".join(libs), + } + + print("Start -----------------------------------------") + import pprint as pp + for k in result.keys(): + print(">>>>>> key:%s" % k) + pp.pprint(result[k].split(';')) + print("End -----------------------------------------") + + return result + +# More globals +VERSION = get_build_version() +if VERSION < 8.0: + raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION) +# MACROS = MacroExpander(VERSION) + +class MSVCCompiler(CCompiler) : + """Concrete class that implements an interface to Microsoft Visual C++, + as defined by the CCompiler abstract class.""" + + compiler_type = 'msvc' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + _rc_extensions = ['.rc'] + _mc_extensions = ['.mc'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = (_c_extensions + _cpp_extensions + + _rc_extensions + _mc_extensions) + res_extension = '.res' + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + def __init__(self, verbose=0, dry_run=0, force=0): + CCompiler.__init__ (self, verbose, dry_run, force) + self.__version = VERSION + self.__root = r"Software\Microsoft\VisualStudio" + # self.__macros = MACROS + self.__paths = [] + # target platform (.plat_name is consistent with 'bdist') + self.plat_name = None + self.__arch = None # deprecated name + self.initialized = False + + def initialize(self, plat_name=None): + # multi-init means we would need to check platform same each time... + assert not self.initialized, "don't init multiple times" + if plat_name is None: + plat_name = get_platform() + # sanity check for platforms to prevent obscure errors later. + ok_plats = 'win32', 'win-amd64', 'win-ia64' + if plat_name not in ok_plats: + raise DistutilsPlatformError("--plat-name must be one of %s" % + (ok_plats,)) + + if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): + # Assume that the SDK set up everything alright; don't try to be + # smarter + self.cc = "cl.exe" + self.linker = "link.exe" + self.lib = "lib.exe" + self.rc = "rc.exe" + self.mc = "mc.exe" + else: + # On x86, 'vcvars32.bat amd64' creates an env that doesn't work; + # to cross compile, you use 'x86_amd64'. + # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross + # compile use 'x86' (ie, it runs the x86 compiler directly) + # No idea how itanium handles this, if at all. + if plat_name == get_platform() or plat_name == 'win32': + # native build or cross-compile to win32 + plat_spec = PLAT_TO_VCVARS[plat_name] + else: + # cross compile from win32 -> some 64bit + plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \ + PLAT_TO_VCVARS[plat_name] + + vc_env = query_vcvarsall(VERSION, plat_spec) + + # take care to only use strings in the environment. + self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep) + os.environ['lib'] = vc_env['lib'].encode('mbcs') + os.environ['include'] = vc_env['include'].encode('mbcs') + + if len(self.__paths) == 0: + raise DistutilsPlatformError("Python was built with %s, " + "and extensions need to be built with the same " + "version of the compiler, but it isn't installed." + % self.__product) + + self.cc = self.find_exe("cl.exe") + self.linker = self.find_exe("link.exe") + self.lib = self.find_exe("lib.exe") + self.rc = self.find_exe("rc.exe") # resource compiler + self.mc = self.find_exe("mc.exe") # message compiler + #self.set_path_env_var('lib') + #self.set_path_env_var('include') + + # extend the MSVC path with the current path + try: + for p in os.environ['path'].split(';'): + self.__paths.append(p) + except KeyError: + pass + self.__paths = normalize_and_reduce_paths(self.__paths) + os.environ['path'] = ";".join(self.__paths) + + self.preprocess_options = None + if self.__arch == "x86": + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', + '/Z7', '/D_DEBUG'] + else: + # Win64 + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-', + '/Z7', '/D_DEBUG'] + + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] + if self.__version >= 10: + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO', '/Manifest'] + if self.__version >= 7: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + ] + if self.__version >= 10: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None', '/Manifest' + ] + self.ldflags_static = [ '/nologo'] + + self.initialized = True + + # -- Worker methods ------------------------------------------------ + + def object_filenames(self, + source_filenames, + strip_dir=0, + output_dir=''): + # Copied from ccompiler.py, extended to return .res as 'object'-file + # for .rc input file + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + (base, ext) = os.path.splitext (src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError ("Don't know how to compile %s" % src_name) + if strip_dir: + base = os.path.basename (base) + if ext in self._rc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + elif ext in self._mc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + if not self.initialized: + self.initialize() + compile_info = self._setup_compile(output_dir, macros, include_dirs, + sources, depends, extra_postargs) + macros, objects, extra_postargs, pp_opts, build = compile_info + + compile_opts = extra_preargs or [] + compile_opts.append ('/c') + if debug: + compile_opts.extend(self.compile_options_debug) + else: + compile_opts.extend(self.compile_options) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) + + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj + try: + self.spawn([self.rc] + pp_opts + + [output_opt] + [input_opt]) + except DistutilsExecError, msg: + raise CompileError(msg) + continue + elif ext in self._mc_extensions: + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + h_dir = os.path.dirname(src) + rc_dir = os.path.dirname(obj) + try: + # first compile .MC to .RC and .H file + self.spawn([self.mc] + + ['-h', h_dir, '-r', rc_dir] + [src]) + base, _ = os.path.splitext (os.path.basename (src)) + rc_file = os.path.join (rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn([self.rc] + + ["/fo" + obj] + [rc_file]) + + except DistutilsExecError, msg: + raise CompileError(msg) + continue + else: + # how to handle this file? + raise CompileError("Don't know how to compile %s to %s" + % (src, obj)) + + output_opt = "/Fo" + obj + try: + self.spawn([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError(msg) + + return objects + + + def create_static_lib(self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + output_filename = self.library_filename(output_libname, + output_dir=output_dir) + + if self._need_link(objects, output_filename): + lib_args = objects + ['/OUT:' + output_filename] + if debug: + pass # XXX what goes here? + try: + self.spawn([self.lib] + lib_args) + except DistutilsExecError, msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + + def link(self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + fixed_args = self._fix_lib_args(libraries, library_dirs, + runtime_library_dirs) + (libraries, library_dirs, runtime_library_dirs) = fixed_args + + if runtime_library_dirs: + self.warn ("I don't know what to do with 'runtime_library_dirs': " + + str (runtime_library_dirs)) + + lib_opts = gen_lib_options(self, + library_dirs, runtime_library_dirs, + libraries) + if output_dir is not None: + output_filename = os.path.join(output_dir, output_filename) + + if self._need_link(objects, output_filename): + if target_desc == CCompiler.EXECUTABLE: + if debug: + ldflags = self.ldflags_shared_debug[1:] + else: + ldflags = self.ldflags_shared[1:] + else: + if debug: + ldflags = self.ldflags_shared_debug + else: + ldflags = self.ldflags_shared + + export_opts = [] + for sym in (export_symbols or []): + export_opts.append("/EXPORT:" + sym) + + ld_args = (ldflags + lib_opts + export_opts + + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + build_temp = os.path.dirname(objects[0]) + if export_symbols is not None: + (dll_name, dll_ext) = os.path.splitext( + os.path.basename(output_filename)) + implib_file = os.path.join( + build_temp, + self.library_filename(dll_name)) + ld_args.append ('/IMPLIB:' + implib_file) + + self.manifest_setup_ldargs(output_filename, build_temp, ld_args) + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + self.mkpath(os.path.dirname(output_filename)) + try: + self.spawn([self.linker] + ld_args) + except DistutilsExecError, msg: + raise LinkError(msg) + + # embed the manifest + # XXX - this is somewhat fragile - if mt.exe fails, distutils + # will still consider the DLL up-to-date, but it will not have a + # manifest. Maybe we should link to a temp file? OTOH, that + # implies a build environment error that shouldn't go undetected. + mfinfo = self.manifest_get_embed_info(target_desc, ld_args) + if mfinfo is not None: + mffilename, mfid = mfinfo + out_arg = '-outputresource:%s;%s' % (output_filename, mfid) + try: + self.spawn(['mt.exe', '-nologo', '-manifest', + mffilename, out_arg]) + except DistutilsExecError, msg: + raise LinkError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): + # If we need a manifest at all, an embedded manifest is recommended. + # See MSDN article titled + # "How to: Embed a Manifest Inside a C/C++ Application" + # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) + # Ask the linker to generate the manifest in the temp dir, so + # we can check it, and possibly embed it, later. + temp_manifest = os.path.join( + build_temp, + os.path.basename(output_filename) + ".manifest") + ld_args.append('/MANIFESTFILE:' + temp_manifest) + + def manifest_get_embed_info(self, target_desc, ld_args): + # If a manifest should be embedded, return a tuple of + # (manifest_filename, resource_id). Returns None if no manifest + # should be embedded. See http://bugs.python.org/issue7833 for why + # we want to avoid any manifest for extension modules if we can) + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + temp_manifest = arg.split(":", 1)[1] + break + else: + # no /MANIFESTFILE so nothing to do. + return None + if target_desc == CCompiler.EXECUTABLE: + # by default, executables always get the manifest with the + # CRT referenced. + mfid = 1 + else: + # Extension modules try and avoid any manifest if possible. + mfid = 2 + temp_manifest = self._remove_visual_c_ref(temp_manifest) + if temp_manifest is None: + return None + return temp_manifest, mfid + + def _remove_visual_c_ref(self, manifest_file): + try: + # Remove references to the Visual C runtime, so they will + # fall through to the Visual C dependency of Python.exe. + # This way, when installed for a restricted user (e.g. + # runtimes are not in WinSxS folder, but in Python's own + # folder), the runtimes do not need to be in every folder + # with .pyd's. + # Returns either the filename of the modified manifest or + # None if no manifest should be embedded. + manifest_f = open(manifest_file) + try: + manifest_buf = manifest_f.read() + finally: + manifest_f.close() + pattern = re.compile( + r"""|)""", + re.DOTALL) + manifest_buf = re.sub(pattern, "", manifest_buf) + pattern = "\s*" + manifest_buf = re.sub(pattern, "", manifest_buf) + # Now see if any other assemblies are referenced - if not, we + # don't want a manifest embedded. + pattern = re.compile( + r"""|)""", re.DOTALL) + if re.search(pattern, manifest_buf) is None: + return None + + manifest_f = open(manifest_file, 'w') + try: + manifest_f.write(manifest_buf) + return manifest_file + finally: + manifest_f.close() + except IOError: + pass + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option(self, dir): + return "/LIBPATH:" + dir + + def runtime_library_dir_option(self, dir): + raise DistutilsPlatformError( + "don't know how to set runtime library search path for MSVC++") + + def library_option(self, lib): + return self.library_filename(lib) + + + def find_library_file(self, dirs, lib, debug=0): + # Prefer a debugging library if found (and requested), but deal + # with it if we don't have one. + if debug: + try_names = [lib + "_d", lib] + else: + try_names = [lib] + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename (name)) + if os.path.exists(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None + + # Helper methods for using the MSVC registry settings + + def find_exe(self, exe): + """Return path to an MSVC executable program. + + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + for p in self.__paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + + # didn't find it; try existing path + for p in os.environ['Path'].split(';'): + fn = os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): + return fn + + return exe diff --git a/CMakeLists.txt b/CMakeLists.txt index fbda3fd3e3..1f9cf77483 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1066 +1,1076 @@ set(DESIRED_QT_VERSION 4 CACHE STRING "Pick a version of Qt to use: 4 or 5") if(DESIRED_QT_VERSION MATCHES "4") cmake_minimum_required(VERSION 2.8.9) else() cmake_minimum_required(VERSION 2.8.12) endif() #----------------------------------------------------------------------------- # Include ctest launchers for dashboard in case of makefile generator #----------------------------------------------------------------------------- if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") include(CTestUseLaunchers) endif() #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Build MITK and the projects it depends on via SuperBuild.cmake." ON) if(MITK_USE_SUPERBUILD) project(MITK-superbuild) set(MITK_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(MITK_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(MITK) endif() #----------------------------------------------------------------------------- # Warn if source or build path is too long #----------------------------------------------------------------------------- if(WIN32) set(_src_dir_length_max 50) set(_bin_dir_length_max 50) if(MITK_USE_SUPERBUILD) set(_src_dir_length_max 43) # _src_dir_length_max - strlen(ITK-src) set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build) endif() string(LENGTH "${MITK_SOURCE_DIR}" _src_n) string(LENGTH "${MITK_BINARY_DIR}" _bin_n) # The warnings should be converted to errors if(_src_n GREATER _src_dir_length_max) message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})." "Please move the MITK source code directory to a directory with a shorter path." ) endif() if(_bin_n GREATER _bin_dir_length_max) message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})." "Please move the MITK build directory to a directory with a shorter path." ) endif() endif() #----------------------------------------------------------------------------- # See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details #----------------------------------------------------------------------------- set(project_policies CMP0001 # NEW: CMAKE_BACKWARDS_COMPATIBILITY should no longer be used. CMP0002 # NEW: Logical target names must be globally unique. CMP0003 # NEW: Libraries linked via full path no longer produce linker search paths. CMP0004 # NEW: Libraries linked may NOT have leading or trailing whitespace. CMP0005 # NEW: Preprocessor definition values are now escaped automatically. CMP0006 # NEW: Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION. CMP0007 # NEW: List command no longer ignores empty elements. CMP0008 # NEW: Libraries linked by full-path must have a valid library file name. CMP0009 # NEW: FILE GLOB_RECURSE calls should not follow symlinks by default. CMP0010 # NEW: Bad variable reference syntax is an error. CMP0011 # NEW: Included scripts do automatic cmake_policy PUSH and POP. CMP0012 # NEW: if() recognizes numbers and boolean constants. CMP0013 # NEW: Duplicate binary directories are not allowed. CMP0014 # NEW: Input directories must have CMakeLists.txt CMP0020 # NEW: Automatically link Qt executables to qtmain target on Windows ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake) set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionSuppressWarnings) include(mitkFunctionEnableBuildConfiguration) include(FeatureSummary) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY AND NOT EXISTS ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) message("Creating directory MITK_CMAKE_${type}_OUTPUT_DIRECTORY: ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") file(MAKE_DIRECTORY "${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") endif() if(MITK_USE_SUPERBUILD) set(output_dir ${MITK_BINARY_DIR}/bin) if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_BINARY_DIR}/MITK-build/bin) endif() else() if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(output_dir ${MITK_BINARY_DIR}/bin) else() set(output_dir ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) endif() endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) macro(env_option name doc value) set(_value $ENV{${name}}) if("${_value}" STREQUAL "") set(_value ${value}) endif() option(${name} "${doc}" ${_value}) endmacro() # ----------------------------------------- # Qt version related variables env_option(MITK_USE_QT "Use Nokia's Qt library" ON) set(MITK_DESIRED_QT_VERSION ${DESIRED_QT_VERSION}) if(MITK_USE_QT) # find the package at the very beginning, so that QT4_FOUND is available if(DESIRED_QT_VERSION MATCHES 4) set(MITK_QT4_MINIMUM_VERSION 4.7) find_package(Qt4 ${MITK_QT4_MINIMUM_VERSION} REQUIRED) set(MITK_USE_Qt4 TRUE) set(MITK_USE_Qt5 FALSE) endif() if(DESIRED_QT_VERSION MATCHES 5) set(MITK_QT5_MINIMUM_VERSION 5.0.0) set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 TRUE) set(QT5_INSTALL_PREFIX "" CACHE PATH "The install location of Qt5") set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT5_INSTALL_PREFIX}) find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED) endif() else() set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 FALSE) endif() # ----------------------------------------- # MITK_USE_* build variables env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) set(MITK_BUILD_TUTORIAL OFF CACHE INTERNAL "Deprecated! Use MITK_BUILD_EXAMPLES instead!") env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" ${MITK_BUILD_TUTORIAL}) env_option(MITK_USE_ACVD "Use Approximated Centroidal Voronoi Diagrams" OFF) env_option(MITK_USE_CppUnit "Use CppUnit for unit tests" ON) if(BUILD_TESTING AND NOT MITK_USE_CppUnit) message("> Forcing MITK_USE_CppUnit to ON because BUILD_TESTING=ON") set(MITK_USE_CppUnit ON CACHE BOOL "Use CppUnit for unit tests" FORCE) endif() env_option(MITK_USE_GLEW "Use the GLEW library" ON) env_option(MITK_USE_Boost "Use the Boost C++ library" OFF) env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ${MITK_USE_Qt4}) env_option(MITK_USE_CTK "Use CTK in MITK" ${MITK_USE_Qt4}) env_option(MITK_USE_DCMTK "EXPERIMENTAL, superbuild only: Use DCMTK in MITK" ${MITK_USE_CTK}) env_option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF) env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) env_option(MITK_USE_Poco "Use the Poco library" ON) env_option(MITK_USE_SOFA "Use Simulation Open Framework Architecture" OFF) env_option(MITK_USE_Python "Use Python wrapping in MITK" OFF) +env_option(MITK_USE_SimpleITK "Use the SimpleITK library" OFF) set(MITK_USE_CableSwig ${MITK_USE_Python}) option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON) set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations") set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS Custom Default All) mitkFunctionEnableBuildConfiguration() mark_as_advanced(MITK_BUILD_ALL_APPS MITK_USE_CppUnit MITK_USE_GLEW MITK_USE_CTK MITK_USE_DCMTK MITK_ENABLE_PIC_READER MITK_BUILD_CONFIGURATION ) if(MITK_USE_Python) - FIND_PACKAGE(PythonLibs REQUIRED) - FIND_PACKAGE(PythonInterp REQUIRED) + if(APPLE) + message(WARNING "Python wrapping is unsuported on mac OSX!") + set(MITK_USE_Python OFF CACHE BOOL "Use Python wrapping in MITK" FORCE) + else() + option(MITK_USE_SYSTEM_PYTHON "Use the system python runtime" OFF) + # SimpleITK is required when python is enabled + set(MITK_USE_SimpleITK ON CACHE BOOL "Use the SimpleITK library" FORCE) + if(MITK_USE_SYSTEM_PYTHON) + FIND_PACKAGE(PythonLibs REQUIRED) + FIND_PACKAGE(PythonInterp REQUIRED) + else() + FIND_PACKAGE(PythonLibs) + FIND_PACKAGE(PythonInterp) + endif() + endif() endif() if(MITK_USE_Boost) option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF) set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries") endif() if(MITK_USE_BLUEBERRY AND NOT MITK_USE_Qt4) message("> Forcing MITK_USE_BLUEBERRY to OFF because Qt4 is not used.") set(MITK_USE_BLUEBERRY OFF CACHE BOOL "Build the BlueBerry application platform" FORCE) endif() if(MITK_USE_CTK AND NOT MITK_USE_Qt4) message("> Forcing MITK_USE_CTK to OFF because Qt4 is not used.") set(MITK_USE_CTK OFF CACHE BOOL "Use CTK in MITK" FORCE) endif() if(MITK_USE_BLUEBERRY) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) mark_as_advanced(MITK_BUILD_ALL_PLUGINS) if(NOT MITK_USE_CTK) message("> Forcing MITK_USE_CTK to ON because of MITK_USE_BLUEBERRY") set(MITK_USE_CTK ON CACHE BOOL "Use CTK in MITK" FORCE) endif() endif() if(MITK_USE_CTK AND NOT MITK_USE_DCMTK) message("> Forcing MITK_USE_DCMTK to ON because of MITK_USE_CTK") set(MITK_USE_DCMTK ON CACHE BOOL "Use DCMTK in MITK" FORCE) endif() if(MITK_USE_SOFA) # SOFA requires at least CMake 2.8.8 set(SOFA_CMAKE_VERSION 2.8.8) if(${CMAKE_VERSION} VERSION_LESS ${SOFA_CMAKE_VERSION}) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n Minimum required CMake version: ${SOFA_CMAKE_VERSION}\n Installed CMake version: ${CMAKE_VERSION}") endif() # SOFA/ITK combination requires at least MSVC 2010 if(MSVC_VERSION AND MSVC_VERSION LESS 1600) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n MSVC versions less than 2010 are not supported.") endif() # SOFA requires boost library if(MITK_USE_SOFA AND NOT MITK_USE_Boost) message("Forcing MITK_USE_Boost to ON because of MITK_USE_SOFA") set(MITK_USE_Boost ON CACHE BOOL "" FORCE) endif() # SOFA requires boost system library list(FIND MITK_USE_Boost_LIBRARIES system _result) if(_result LESS 0) message("Adding 'system' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES system) endif() # SOFA requires boost thread library list(FIND MITK_USE_Boost_LIBRARIES thread _result) if(_result LESS 0) message("Adding 'thread' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES thread) endif() set(MITK_USE_Boost_LIBRARIES ${MITK_USE_Boost_LIBRARIES} CACHE STRING "" FORCE) # Allow setting external SOFA plugins directory and SOFA plugins set(MITK_USE_SOFA_PLUGINS_DIR ${MITK_USE_SOFA_PLUGINS_DIR} CACHE PATH "External SOFA plugins directory" FORCE) set(MITK_USE_SOFA_PLUGINS ${MITK_USE_SOFA_PLUGINS} CACHE PATH "List of semicolon-separated plugin names" FORCE) endif() # Customize the default pixel types for multiplex macros set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS ) # consistency checks if(NOT MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES) set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES) set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES) set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) string(REPLACE "," ";" _integral_types ${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES}) string(REPLACE "," ";" _floating_types ${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES}) foreach(_scalar_type ${_integral_types} ${_floating_types}) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}itk::VariableLengthVector<${_scalar_type}>,") endforeach() string(LENGTH "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" _length) math(EXPR _length "${_length} - 1") string(SUBSTRING "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" 0 ${_length} MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES ${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} CACHE STRING "List of vector pixel types used in AccessByItk and InstantiateAccessFunction macros for itk::VectorImage types" FORCE) endif() if(NOT MITK_ACCESSBYITK_DIMENSIONS) set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") endif() #----------------------------------------------------------------------------- # Project.xml #----------------------------------------------------------------------------- # A list of topologically ordered targets set(CTEST_PROJECT_SUBPROJECTS) if(MITK_USE_BLUEBERRY) list(APPEND CTEST_PROJECT_SUBPROJECTS BlueBerry) endif() list(APPEND CTEST_PROJECT_SUBPROJECTS MITK-Core MITK-CoreUI MITK-IGT MITK-ToF MITK-DTI MITK-Registration MITK-Modules # all modules not contained in a specific subproject MITK-Plugins # all plugins not contained in a specific subproject MITK-Examples Unlabeled # special "subproject" catching all unlabeled targets and tests ) # Configure CTestConfigSubProject.cmake that could be used by CTest scripts configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in ${MITK_BINARY_DIR}/CTestConfigSubProject.cmake) if(CTEST_PROJECT_ADDITIONAL_TARGETS) # those targets will be executed at the end of the ctest driver script # and they also get their own subproject label set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}") else() set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}") endif() # Generate Project.xml file expected by the CTest driver script mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD}) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(MITK_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") # Print configuration summary message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL) return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(WriteBasicConfigVersionFile) include(CheckCXXSourceCompiles) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(MacroParseArguments) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkFunctionOrganizeSources) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionCompileSnippets) include(mitkFunctionUseModules) include(mitkMacroCreateModuleConf) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCreateModule) include(mitkMacroCreateExecutable) include(mitkMacroCheckModule) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroUseModule) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON) mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW) # TODO: check if necessary option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON) mark_as_advanced(USE_ITKZLIB) if(NOT MITK_FAST_TESTING) if(DEFINED MITK_CTEST_SCRIPT_MODE AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") ) set(MITK_FAST_TESTING 1) endif() endif() #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on Mac OSX all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(MITK_USE_BLUEBERRY AND APPLE) include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) list(GET target_info_list 0 app_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} Mitk${app_name}) endif() endforeach() endif() #----------------------------------------------------------------------------- # Set symbol visibility Flags #----------------------------------------------------------------------------- # MinGW does not export all symbols automatically, so no need to set flags if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW) set(VISIBILITY_CXX_FLAGS ) #"-fvisibility=hidden -fvisibility-inlines-hidden") endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # MITK C/CXX Flags #----------------------------------------------------------------------------- set(MITK_C_FLAGS "${COVERAGE_C_FLAGS}") set(MITK_C_FLAGS_DEBUG ) set(MITK_C_FLAGS_RELEASE ) set(MITK_CXX_FLAGS "${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS}") set(MITK_CXX_FLAGS_DEBUG ) set(MITK_CXX_FLAGS_RELEASE ) set(MITK_EXE_LINKER_FLAGS ) set(MITK_SHARED_LINKER_FLAGS ) if(WIN32) set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -D_WIN32_WINNT=0x0501 -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN") set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} /wd4231") # warning C4231: nonstandard extension used : 'extern' before template explicit instantiation # the following line should be removed after fixing bug 17637 mitkFunctionCheckCompilerFlags("/wd4316" MITK_CXX_FLAGS) # warning C4316: object alignment on heap endif() if(NOT MSVC_VERSION) foreach(_flag -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Wno-error=gnu -Wno-error=unknown-pragmas # The strict-overflow warning is generated by ITK template code -Wno-error=strict-overflow -Woverloaded-virtual -Wstrict-null-sentinel #-Wold-style-cast #-Wsign-promo # the following two lines should be removed after ITK-3097 has # been resolved, see also MITK bug 15279 -Wno-unused-local-typedefs -Wno-array-bounds -fdiagnostics-show-option ) mitkFunctionCheckCAndCXXCompilerFlags(${_flag} MITK_C_FLAGS MITK_CXX_FLAGS) endforeach() endif() if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" MITK_SHARED_LINKER_FLAGS) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" MITK_SHARED_LINKER_FLAGS) endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) # With older version of gcc supporting the flag -fstack-protector-all, an extra dependency to libssp.so # is introduced. If gcc is smaller than 4.4.0 and the build type is Release let's not include the flag. # Doing so should allow to build package made for distribution using older linux distro. if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0")) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) endif() if(MINGW) # suppress warnings about auto imported symbols set(MITK_SHARED_LINKER_FLAGS "-Wl,--enable-auto-import ${MITK_SHARED_LINKER_FLAGS}") endif() set(MITK_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}") endif() set(MITK_MODULE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(MITK_EXE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_RENDERING_TESTING OFF "Enable the MITK rendering tests. Requires x-server in Linux.") #Rendering testing does not work for Linux nightlies, thus it is disabled per default #and activated for Mac and Windows. if(WIN32 OR APPLE) set(MITK_ENABLE_RENDERING_TESTING ON) endif() mark_as_advanced( MITK_ENABLE_RENDERING_TESTING ) # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output") if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR}) file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR}) endif() # Test the external project template if(MITK_USE_BLUEBERRY) include(mitkTestProjectTemplate) endif() # Test the package target include(mitkPackageTest) endif() configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h) #----------------------------------------------------------------------------- # MITK_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild. # In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR) set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Compile Utilities and set-up MITK variables #----------------------------------------------------------------------------- include(mitkSetupVariables) #----------------------------------------------------------------------------- # Cleanup #----------------------------------------------------------------------------- file(GLOB _MODULES_CONF_FILES ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) if(_MODULES_CONF_FILES) file(REMOVE ${_MODULES_CONF_FILES}) endif() add_subdirectory(Utilities) if(MITK_USE_BLUEBERRY) # We need to hack a little bit because MITK applications may need # to enable certain BlueBerry plug-ins. However, these plug-ins # are validated separately from the MITK plug-ins and know nothing # about potential MITK plug-in dependencies of the applications. Hence # we cannot pass the MITK application list to the BlueBerry # ctkMacroSetupPlugins call but need to extract the BlueBerry dependencies # from the applications and set them explicitly. include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled and if target_libraries.cmake exists if((${option_name} OR MITK_BUILD_ALL_APPS) AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") foreach(_target_dep ${target_libraries}) if(_target_dep MATCHES org_blueberry_) string(REPLACE _ . _app_bb_dep ${_target_dep}) # explicitly set the build option for the BlueBerry plug-in set(BLUEBERRY_BUILD_${_app_bb_dep} ON CACHE BOOL "Build the ${_app_bb_dep} plug-in") endif() endforeach() endif() endforeach() set(mbilog_DIR "${mbilog_BINARY_DIR}") if(MITK_BUILD_ALL_PLUGINS) set(BLUEBERRY_BUILD_ALL_PLUGINS ON) endif() set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/) add_subdirectory(BlueBerry) set(BlueBerry_DIR ${CMAKE_CURRENT_BINARY_DIR}/BlueBerry CACHE PATH "The directory containing a CMake configuration file for BlueBerry" FORCE) include(mitkMacroCreateCTKPlugin) endif() #----------------------------------------------------------------------------- # Set C/CXX and linker flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MITK_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MITK_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MITK_C_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MITK_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MITK_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MITK_MODULE_LINKER_FLAGS}") #----------------------------------------------------------------------------- # Add custom targets representing CDash subprojects #----------------------------------------------------------------------------- foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") add_custom_target(${subproject}) endif() endforeach() #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Core) add_subdirectory(Modules) if(MITK_USE_BLUEBERRY) find_package(BlueBerry REQUIRED) set(MITK_DEFAULT_SUBPROJECTS MITK-Plugins) # Plug-in testing (needs some work to be enabled again) if(BUILD_TESTING) include(berryTestingHelpers) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp") get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE) if(APPLE AND _is_macosx_bundle) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp") endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") set(mitk_plugins_fullpath ) foreach(mitk_plugin ${MITK_EXT_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake) include(${MITK_PRIVATE_MODULES}/PluginList.cmake) foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin}) endforeach() endif() if(MITK_BUILD_EXAMPLES) include("${CMAKE_CURRENT_SOURCE_DIR}/Examples/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) list(APPEND mitk_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) endforeach() endif() # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$") set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") set(mitk_apps_fullpath ) foreach(mitk_app ${MITK_APPS}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}") endforeach() if (mitk_plugins_fullpath) ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) endif() set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake") if(${PROJECT_NAME}_PLUGIN_LIBRARIES) ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE}) else() file(REMOVE ${MITK_PLUGIN_USE_FILE}) set(MITK_PLUGIN_USE_FILE ) endif() # 11.3.13, change, muellerm: activate python bundle if python and blueberry is active if( MITK_USE_Python ) set(MITK_BUILD_org.mitk.gui.qt.python ON) endif() endif() -#----------------------------------------------------------------------------- -# Python Wrapping -#----------------------------------------------------------------------------- -option(MITK_USE_Python "Build Python integration for MITK (requires CableSwig)." OFF) - #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(Documentation) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) # MITK_APPS is set in Applications/AppList.cmake (included somewhere above # if MITK_USE_BLUEBERRY is set to ON). if(MITK_APPS) set(activated_apps_no 0) list(LENGTH MITK_APPS app_count) # Check how many apps have been enabled # If more than one app has been activated, the we use the # default CPack configuration. Otherwise that apps configuration # will be used, if present. foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) MATH(EXPR activated_apps_no "${activated_apps_no} + 1") endif() endforeach() if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS)) # Corner case if there is only one app in total set(use_project_cpack ON) elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS) # Only one app is enabled (no "build all" flag set) set(use_project_cpack ON) else() # Less or more then one app is enabled set(use_project_cpack OFF) endif() foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) # check whether application specific configuration files will be used if(use_project_cpack) # use files if they exist if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") endif() if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in") set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake") configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in ${CPACK_PROJECT_CONFIG_FILE} @ONLY) set(use_default_config OFF) endif() endif() # add link to the list list(APPEND CPACK_CREATE_DESKTOP_LINKS "${target_dir}") endif() endforeach() endif() # if no application specific configuration file was used, use default if(use_default_config) configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") endif() # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake") file(REMOVE ${MITK_EXPORTS_FILE}) set(targets_to_export) get_property(module_targets GLOBAL PROPERTY MITK_MODULE_TARGETS) if(module_targets) list(APPEND targets_to_export ${module_targets}) endif() if(MITK_USE_BLUEBERRY) if(MITK_PLUGIN_LIBRARIES) list(APPEND targets_to_export ${MITK_PLUGIN_LIBRARIES}) endif() endif() export(TARGETS ${targets_to_export} APPEND FILE ${MITK_EXPORTS_FILE}) set(MITK_EXPORTED_TARGET_PROPERTIES ) foreach(target_to_export ${targets_to_export}) get_target_property(autoload_targets ${target_to_export} MITK_AUTOLOAD_TARGETS) if(autoload_targets) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_TARGETS \"${autoload_targets}\")") endif() get_target_property(autoload_dir ${target_to_export} MITK_AUTOLOAD_DIRECTORY) if(autoload_dir) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_DIRECTORY \"${autoload_dir}\")") endif() endforeach() get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY) set(VISIBILITY_AVAILABLE 0) set(visibility_test_flag "") mitkFunctionCheckCompilerFlags("-fvisibility=hidden" visibility_test_flag) if(visibility_test_flag) # The compiler understands -fvisiblity=hidden (probably gcc >= 4 or Clang) set(VISIBILITY_AVAILABLE 1) endif() configure_file(mitkExportMacros.h.in ${MITK_BINARY_DIR}/mitkExportMacros.h) configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) file(GLOB _MODULES_CONF_FILES RELATIVE ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME} ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) set(MITK_MODULE_NAMES) foreach(_module ${_MODULES_CONF_FILES}) string(REPLACE Config.cmake "" _module_name ${_module}) list(APPEND MITK_MODULE_NAMES ${_module_name}) endforeach() configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${MITK_VERSION_STRING} COMPATIBILITY AnyNewerVersion) # If we are under Windows, create two batch files which correctly # set up the environment for the application and for Visual Studio if(WIN32) include(mitkFunctionCreateWindowsBatchScript) set(VS_SOLUTION_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sln") foreach(VS_BUILD_TYPE debug release) mitkFunctionCreateWindowsBatchScript("${MITK_SOURCE_DIR}/CMake/StartVS.bat.in" ${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat ${VS_BUILD_TYPE}) endforeach() endif(WIN32) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) #----------------------------------------------------------------------------- # MITK Examples #----------------------------------------------------------------------------- if(MITK_BUILD_EXAMPLES) # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Examples) endif() #----------------------------------------------------------------------------- # Print configuration summary #----------------------------------------------------------------------------- message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL ) + diff --git a/MITKConfig.cmake.in b/MITKConfig.cmake.in index d4c40e210a..04a6c39106 100644 --- a/MITKConfig.cmake.in +++ b/MITKConfig.cmake.in @@ -1,201 +1,203 @@ # Update the CMake module path set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "@MITK_SOURCE_DIR@/CMake") set(CppMicroServices_DIR "@MITK_BINARY_DIR@/Core/CppMicroServices") # Include MITK macros include(MacroParseArguments) include(mitkFunctionCheckMitkCompatibility) include(mitkFunctionOrganizeSources) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionUseModules) include(mitkMacroCreateModuleConf) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCreateModule) include(mitkMacroCreateExecutable) include(mitkMacroCheckModule) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroUseModule) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroCreateCTKPlugin) include(mitkMacroGetPMDPlatformString) # Standard CMake macros include(FeatureSummary) # The MITK version number set(MITK_VERSION_MAJOR "@MITK_VERSION_MAJOR@") set(MITK_VERSION_MINOR "@MITK_VERSION_MINOR@") set(MITK_VERSION_PATCH "@MITK_VERSION_PATCH@") set(MITK_VERSION_STRING "@MITK_VERSION_STRING@") # MITK compiler flags set(MITK_C_FLAGS "@MITK_C_FLAGS@") set(MTTK_C_FLAGS_DEBUG "@MITK_C_FLAGS_DEBUG@") set(MITK_C_FLAGS_RELEASE "@MITK_C_FLAGS_RELEASE@") set(MITK_CXX_FLAGS "@MITK_CXX_FLAGS@") set(MTTK_CXX_FLAGS_DEBUG "@MITK_CXX_FLAGS_DEBUG@") set(MITK_CXX_FLAGS_RELEASE "@MITK_CXX_FLAGS_RELEASE@") set(MITK_EXE_LINKER_FLAGS "@MITK_EXE_LINKER_FLAGS@") set(MITK_SHARED_LINKER_FLAGS "@MITK_SHARED_LINKER_FLAGS@") set(MITK_MODULE_LINKER_FLAGS "@MITK_MODULE_LINKER_FLAGS@") # Internal version numbers, used for approximate compatibility checks # of a MITK development version (non-release). set(MITK_VERSION_PLUGIN_SYSTEM 2) # dropped legacy BlueBerry plug-in CMake support # MITK specific variables set(MITK_SOURCE_DIR "@MITK_SOURCE_DIR@") set(MITK_BINARY_DIR "@MITK_BINARY_DIR@") set(MITK_CMAKE_DIR "@MITK_CMAKE_DIR@") set(UTILITIES_DIR "@UTILITIES_DIR@") set(REGISTER_QFUNCTIONALITY_CPP_IN "@REGISTER_QFUNCTIONALITY_CPP_IN@") set(MITK_MODULES_PACKAGE_DEPENDS_DIR "@MITK_MODULES_PACKAGE_DEPENDS_DIR@") set(MODULES_PACKAGE_DEPENDS_DIRS "@MODULES_PACKAGE_DEPENDS_DIRS@") set(MITK_DOXYGEN_TAGFILE_NAME "@MITK_DOXYGEN_TAGFILE_NAME@") if(MODULES_CONF_DIRS) list(APPEND MODULES_CONF_DIRS "@MODULES_CONF_DIRS@") list(REMOVE_DUPLICATES MODULES_CONF_DIRS) else() set(MODULES_CONF_DIRS "@MODULES_CONF_DIRS@") endif() set(MODULES_CONF_DIRNAME "@MODULES_CONF_DIRNAME@") foreach(_module @MITK_MODULE_NAMES@) set(${_module}_CONFIG_FILE "@MITK_BINARY_DIR@/@MODULES_CONF_DIRNAME@/${_module}Config.cmake") endforeach() # External projects set(CTK_DIR "@CTK_DIR@") set(ANN_DIR "@ANN_DIR@") set(CppUnit_DIR "@CppUnit_DIR@") set(GLEW_DIR "@GLEW_DIR@") set(tinyxml_DIR "@tinyxml_DIR@") set(ITK_DIR "@ITK_DIR@") set(VTK_DIR "@VTK_DIR@") set(DCMTK_DIR "@DCMTK_DIR@") set(GDCM_DIR "@GDCM_DIR@") set(BOOST_ROOT "@BOOST_ROOT@") set(OpenCV_DIR "@OpenCV_DIR@") set(Poco_DIR "@Poco_DIR@") set(SOFA_DIR "@SOFA_DIR@") set(Qwt_DIR "@Qwt_DIR@") set(Qxt_DIR "@Qxt_DIR@") set(ACVD_DIR "@ACVD_DIR@") set(MITK_QMAKE_EXECUTABLE "@QT_QMAKE_EXECUTABLE@") set(MITK_DATA_DIR "@MITK_DATA_DIR@") +set(SimpleITK_DIR "@SimpleITK_DIR@") # External SDK directories set(MITK_PMD_SDK_DIR @MITK_PMD_SDK_DIR@) # MITK use variables set(MITK_USE_QT @MITK_USE_QT@) set(MITK_USE_Qt4 @MITK_USE_Qt4@) set(MITK_USE_Qt5 @MITK_USE_Qt5@) set(MITK_DESIRED_QT_VERSION @DESIRED_QT_VERSION@) set(MITK_USE_BLUEBERRY @MITK_USE_BLUEBERRY@) set(MITK_USE_SYSTEM_Boost @MITK_USE_SYSTEM_Boost@) set(MITK_USE_Boost @MITK_USE_Boost@) set(MITK_USE_Boost_LIBRARIES @MITK_USE_Boost_LIBRARIES@) set(MITK_USE_CTK @MITK_USE_CTK@) set(MITK_USE_DCMTK @MITK_USE_DCMTK@) set(MITK_USE_OpenCV @MITK_USE_OpenCV@) set(MITK_USE_SOFA @MITK_USE_SOFA@) set(MITK_USE_Python @MITK_USE_Python@) +set(MITK_USE_SimpleITK @MITK_USE_SimpleITK@) set(MITK_USE_ACVD @MITK_USE_ACVD@) if(MITK_USE_Qt4) set(MITK_QT4_MINIMUM_VERSION @MITK_QT4_MINIMUM_VERSION@) find_package(Qt4 ${MITK_QT4_MINIMUM_VERSION} REQUIRED) elseif(MITK_USE_Qt5) set(MITK_QT5_MINIMUM_VERSION @MITK_QT5_MINIMUM_VERSION@) find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED) endif() # MITK ToF use variables set(MITK_TOF_PMDCAMCUBE_AVAILABLE @MITK_USE_TOF_PMDCAMCUBE@) if(MITK_TOF_PMDCAMCUBE_AVAILABLE AND NOT ${PROJECT_NAME} STREQUAL "MITK") option(MITK_USE_TOF_PMDCAMCUBE "Enable support for PMD Cam Cube" @MITK_USE_TOF_PMDCAMCUBE@) mark_as_advanced(MITK_USE_TOF_PMDCAMCUBE) endif() set(MITK_TOF_PMDCAMBOARD_AVAILABLE @MITK_USE_TOF_PMDCAMBOARD@) if(MITK_TOF_PMDCAMBOARD_AVAILABLE AND NOT ${PROJECT_NAME} STREQUAL "MITK") option(MITK_USE_TOF_PMDCAMBOARD "Enable support for PMD Cam Board" @MITK_USE_TOF_PMDCAMBOARD@) mark_as_advanced(MITK_USE_TOF_PMDCAMBOARD) endif() set(MITK_TOF_PMDO3_AVAILABLE @MITK_USE_TOF_PMDO3@) if(MITK_TOF_PMDO3_AVAILABLE AND NOT ${PROJECT_NAME} STREQUAL "MITK") option(MITK_USE_TOF_PMDO3 "Enable support for PMD =3" @MITK_USE_TOF_PMDO3@) mark_as_advanced(MITK_USE_TOF_PMDO3) endif() set(MITK_TOF_KINECT_AVAILABLE @MITK_USE_TOF_KINECT@) if(MITK_TOF_KINECT_AVAILABLE AND NOT ${PROJECT_NAME} STREQUAL "MITK") option(MITK_USE_TOF_KINECT "Enable support for Kinect" @MITK_USE_TOF_KINECT@) mark_as_advanced(MITK_USE_TOF_KINECT) endif() set(MITK_TOF_MESASR4000_AVAILABLE @MITK_USE_TOF_MESASR4000@) if(MITK_TOF_MESASR4000_AVAILABLE AND NOT ${PROJECT_NAME} STREQUAL "MITK") option(MITK_USE_TOF_MESASR4000 "Enable support for MESA SR4000" @MITK_USE_TOF_MESASR4000@) mark_as_advanced(MITK_USE_TOF_MESASR4000) endif() if(MITK_USE_IGT) #include("${MITK_DIR}/mitkIGTConfig.cmake") endif() # Install rules for ToF libraries loaded at runtime include("@MITK_BINARY_DIR@/mitkToFHardwareInstallRules.cmake") if(NOT MITK_EXPORTS_FILE_INCLUDED) if(EXISTS "@MITK_EXPORTS_FILE@") set(MITK_EXPORTS_FILE_INCLUDED 1) include("@MITK_EXPORTS_FILE@") endif() endif() # BlueBerry support if(MITK_USE_BLUEBERRY) set(BlueBerry_DIR "@MITK_BINARY_DIR@/BlueBerry") # Don't include the BlueBerry exports file, since the targets are # also exported in the MITK exports file set(BB_PLUGIN_EXPORTS_FILE_INCLUDED 1) find_package(BlueBerry) if(NOT BlueBerry_FOUND) message(SEND_ERROR "MITK does not seem to be configured with BlueBerry support. Set MITK_USE_BLUEBERRY to ON in your MITK build configuration.") endif() set(MITK_PLUGIN_USE_FILE "@MITK_PLUGIN_USE_FILE@") if(MITK_PLUGIN_USE_FILE) if(EXISTS "${MITK_PLUGIN_USE_FILE}") include("${MITK_PLUGIN_USE_FILE}") endif() endif() set(MITK_PLUGIN_PROVISIONING_FILE "@MITK_EXTAPP_PROVISIONING_FILE@") set(MITK_PROVISIONING_FILES "${BLUEBERRY_PLUGIN_PROVISIONING_FILE}" "${MITK_PLUGIN_PROVISIONING_FILE}") endif() # Set properties on exported targets @MITK_EXPORTED_TARGET_PROPERTIES@ diff --git a/Modules/Python/CMakeLists.txt b/Modules/Python/CMakeLists.txt index 475bb4d8bf..3025dd6481 100644 --- a/Modules/Python/CMakeLists.txt +++ b/Modules/Python/CMakeLists.txt @@ -1,12 +1,26 @@ if( MITK_USE_Python ) + if(NOT MITK_USE_SYSTEM_PYTHON) + add_definitions( -DUSE_MITK_BUILTIN_PYTHON ) + endif() + + set(OpenCV_DEP ) + if(MITK_USE_OpenCV) + set(OpenCV_DEP OpenCV) + endif() + + # workaround until testing has a package depends + set(SimpleITK_DEP ) + if(BUILD_TESTING AND NOT APPLE) + set(SimpleITK_DEP SimpleITK) + endif() + MITK_CREATE_MODULE( DEPENDS MitkCore EXPORT_DEFINE MITK_PYTHON_EXPORT - PACKAGE_DEPENDS Qt4|QtGui CTK PythonLibs + PACKAGE_DEPENDS Qt4|QtGui CTK|CTKScriptingPythonCore+CTKScriptingPythonWidgets PythonLibs VTK|vtkPython+vtkWrappingPythonCore Numpy ${SimpleITK_DEP} ${OpenCV_DEP} ) - configure_file(PythonPath.h.in - "${CMAKE_CURRENT_BINARY_DIR}/PythonPath.h" @ONLY) + configure_file(PythonPath.h.in "${CMAKE_CURRENT_BINARY_DIR}/PythonPath.h" @ONLY) add_subdirectory(Testing) endif() diff --git a/Modules/Python/PythonPath.h.in b/Modules/Python/PythonPath.h.in index 6f5daf2961..d62c631f5a 100644 --- a/Modules/Python/PythonPath.h.in +++ b/Modules/Python/PythonPath.h.in @@ -1,21 +1,19 @@ #ifdef _DEBUG #define PYTHON_PATH_BUILD_TYPE "/Debug" #else #define PYTHON_PATH_BUILD_TYPE "/Release" #endif #define PYTHONPATH_COMMAND "import sys\n"\ -"sys.path.append('@ITK_LIBRARY_DIRS@')\n"\ -"sys.path.append('@ITK_DIR@/Wrapping/WrapITK/Python')\n"\ -"sys.path.append('@ITK_LIBRARY_DIRS@" PYTHON_PATH_BUILD_TYPE "')\n"\ -"sys.path.append('@ITK_DIR@/Wrapping/WrapITK/Python" PYTHON_PATH_BUILD_TYPE "')\n"\ -"sys.path.append('@ITK_DIR@/Wrapping/Generators/Python')\n"\ -"sys.path.append('@ITK_DIR@/lib')\n"\ -"sys.path.append('@VTK_LIBRARY_DIRS@')\n"\ +"sys.path.append('@SimpleITK_DIR@/bin')\n"\ +"sys.path.append('@SimpleITK_DIR@/lib')\n"\ +"sys.path.append('@SimpleITK_DIR@/Wrapping')\n"\ "sys.path.append('@VTK_DIR@/Wrapping/Python')\n"\ +"sys.path.append('@VTK_DIR@/lib')\n"\ "sys.path.append('@VTK_DIR@/bin" PYTHON_PATH_BUILD_TYPE "')\n"\ -"sys.path.append('@VTK_DIR@/Wrapping/Python')\n"\ "sys.path.append('@OpenCV_DIR@/lib" PYTHON_PATH_BUILD_TYPE "')\n"\ "sys.path.append('@OpenCV_DIR@/lib')\n"\ "sys.path.append('@OpenCV_DIR@/bin')\n"\ "sys.path.append('@OpenCV_DIR@/bin" PYTHON_PATH_BUILD_TYPE "')" + +#define PYTHONHOME "@Python_DIR@" diff --git a/Modules/Python/QmitkCtkPythonShell.cpp b/Modules/Python/QmitkCtkPythonShell.cpp index f8c676dccb..c5f8a7aee0 100644 --- a/Modules/Python/QmitkCtkPythonShell.cpp +++ b/Modules/Python/QmitkCtkPythonShell.cpp @@ -1,91 +1,91 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkCtkPythonShell.h" #include #include #include #include #include #include "mitkPythonService.h" #include #include #include struct QmitkCtkPythonShellData { mitk::PythonService* m_PythonService; us::ServiceReference m_PythonServiceRef; }; QmitkCtkPythonShell::QmitkCtkPythonShell(QWidget* parent) : ctkPythonConsole(parent), d( new QmitkCtkPythonShellData ) { MITK_DEBUG("QmitkCtkPythonShell") << "retrieving IPythonService"; us::ModuleContext* context = us::GetModuleContext(); d->m_PythonServiceRef = context->GetServiceReference(); d->m_PythonService = dynamic_cast ( context->GetService(d->m_PythonServiceRef) ); MITK_DEBUG("QmitkCtkPythonShell") << "checking IPythonService"; Q_ASSERT( d->m_PythonService ); MITK_DEBUG("QmitkCtkPythonShell") << "initialize m_PythonService"; this->initialize( d->m_PythonService->GetPythonManager() ); MITK_DEBUG("QmitkCtkPythonShell") << "m_PythonService initialized"; } QmitkCtkPythonShell::~QmitkCtkPythonShell() { us::ModuleContext* context = us::GetModuleContext(); context->UngetService( d->m_PythonServiceRef ); delete d; } void QmitkCtkPythonShell::dragEnterEvent(QDragEnterEvent *event) { event->accept(); } void QmitkCtkPythonShell::dropEvent(QDropEvent *event) { QList urls = event->mimeData()->urls(); for(int i = 0; i < urls.size(); i++) { d->m_PythonService->Execute( urls[i].toString().toStdString(), mitk::IPythonService::SINGLE_LINE_COMMAND ); } } bool QmitkCtkPythonShell::canInsertFromMimeData( const QMimeData *source ) const { return true; } void QmitkCtkPythonShell::executeCommand(const QString& command) { MITK_DEBUG("QmitkCtkPythonShell") << "executing command " << command.toStdString(); - ctkPythonConsole::executeCommand(command); + d->m_PythonService->Execute(command.toStdString(),mitk::IPythonService::MULTI_LINE_COMMAND); d->m_PythonService->NotifyObserver(command.toStdString()); } void QmitkCtkPythonShell::Paste(const QString &command) { if( this->isVisible() ) { this->exec( command ); //this->executeCommand( command ); } } diff --git a/Modules/Python/QmitkPythonSnippets.cpp b/Modules/Python/QmitkPythonSnippets.cpp index 975944557c..b0947c81af 100644 --- a/Modules/Python/QmitkPythonSnippets.cpp +++ b/Modules/Python/QmitkPythonSnippets.cpp @@ -1,483 +1,483 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPythonSnippets.h" #include "QmitkPythonScriptEditorHighlighter.h" #include #include #include struct QmitkPythonSnippetsData { QString m_AutoSaveFileName; QString m_SaveFileName; QAction* m_PasteSnippet; QAction* m_RemoveSnippet; QAction* m_RenameSnippet; QAction* m_AddSnippet; QAction* m_RestoreDefaultSnippets; QAction* m_LoadSnippets; QAction* m_SaveSnippets; QToolBar* m_Toolbar; QComboBox* m_Name; QTextEdit* m_Content; QGridLayout* m_Layout; QmitkPythonSnippets::QStringMap m_Snippets; }; const QString QmitkPythonSnippets::DEFAULT_SNIPPET_FILE( ":/mitkPython/PythonSnippets.xml" ); const QString QmitkPythonSnippets::SNIPPETS_ROOT_XML_ELEMENT_NAME( "PythonSnippets" ); const QString QmitkPythonSnippets::SNIPPETS_XML_ELEMENT_NAME( "PythonSnippet" ); QmitkPythonSnippets::QmitkPythonSnippets( const QString& _AutoSaveFileName, QWidget* parent ) : QWidget(parent), d(new QmitkPythonSnippetsData) { d->m_SaveFileName = QDir::currentPath(); d->m_AutoSaveFileName = _AutoSaveFileName; - if( !this->LoadStringMap( d->m_AutoSaveFileName, d->m_Snippets ) ) + if( !QmitkPythonSnippets::LoadStringMap( d->m_AutoSaveFileName, d->m_Snippets ) ) { - this->LoadStringMap( DEFAULT_SNIPPET_FILE, d->m_Snippets ); + QmitkPythonSnippets::LoadStringMap( DEFAULT_SNIPPET_FILE, d->m_Snippets ); } d->m_PasteSnippet = new QAction(this); d->m_PasteSnippet->setObjectName(QString::fromUtf8("PasteSnippet")); QIcon icon; icon.addFile(QString::fromUtf8(":/mitkPython/edit-paste.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_PasteSnippet->setIcon(icon); d->m_PasteSnippet->setToolTip("Paste snippet!"); d->m_PasteSnippet->setEnabled(false); d->m_RemoveSnippet = new QAction(this); d->m_RemoveSnippet->setObjectName(QString::fromUtf8("RemoveSnippet")); QIcon icon1; icon1.addFile(QString::fromUtf8(":/mitkPython/edit-delete.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_RemoveSnippet->setIcon(icon1); d->m_RemoveSnippet->setToolTip("Remove snippet."); d->m_RemoveSnippet->setEnabled(false); d->m_RenameSnippet = new QAction(this); d->m_RenameSnippet->setObjectName(QString::fromUtf8("RenameSnippet")); QIcon icon2; icon2.addFile(QString::fromUtf8(":/mitkPython/edit-find-replace.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_RenameSnippet->setIcon(icon2); d->m_RenameSnippet->setToolTip("Rename snippet."); d->m_RenameSnippet->setEnabled(false); d->m_AddSnippet = new QAction(this); d->m_AddSnippet->setObjectName(QString::fromUtf8("AddSnippet")); QIcon icon3; icon3.addFile(QString::fromUtf8(":/mitkPython/document-new.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_AddSnippet->setIcon(icon3); d->m_AddSnippet->setToolTip("Add snippet."); d->m_RestoreDefaultSnippets = new QAction(this); d->m_RestoreDefaultSnippets->setObjectName(QString::fromUtf8("RestoreDefaultSnippets")); QIcon icon4; icon4.addFile(QString::fromUtf8(":/mitkPython/edit-clear.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_RestoreDefaultSnippets->setIcon(icon4); d->m_RestoreDefaultSnippets->setToolTip("Restore default snippets"); d->m_LoadSnippets = new QAction(this); d->m_LoadSnippets->setToolTip("Load Snippets from disk."); d->m_LoadSnippets->setObjectName(QString::fromUtf8("LoadSnippets")); QIcon icon5; icon5.addFile(QString::fromUtf8(":/mitkPython/document-open.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_LoadSnippets->setIcon(icon5); d->m_SaveSnippets = new QAction(this); d->m_SaveSnippets->setToolTip("Save Snippets to disk."); d->m_SaveSnippets->setObjectName(QString::fromUtf8("SaveSnippets")); QIcon icon6; icon6.addFile(QString::fromUtf8(":/mitkPython/document-save.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_SaveSnippets->setIcon(icon6); d->m_SaveSnippets->setEnabled(false); d->m_Toolbar = new QToolBar; d->m_Toolbar->addAction( d->m_PasteSnippet ); d->m_Toolbar->addAction( d->m_AddSnippet ); d->m_Toolbar->addAction( d->m_RemoveSnippet ); d->m_Toolbar->addAction( d->m_RenameSnippet ); d->m_Toolbar->addAction( d->m_RestoreDefaultSnippets ); d->m_Toolbar->addAction( d->m_SaveSnippets ); d->m_Toolbar->addAction( d->m_LoadSnippets ); d->m_Name = new QComboBox; d->m_Name->setObjectName(QString::fromUtf8("Name")); d->m_Content = new QTextEdit(this); d->m_Content->setObjectName(QString::fromUtf8("Content")); d->m_Content->setEnabled(false); QmitkPythonScriptEditorHighlighter* highlighter = new QmitkPythonScriptEditorHighlighter( d->m_Content->document() ); d->m_Layout = new QGridLayout; d->m_Layout->addWidget( d->m_Toolbar, 0, 0, 1, 1 ); d->m_Layout->addWidget( d->m_Name, 1, 0, 1, 1 ); d->m_Layout->addWidget( d->m_Content, 2, 0, 1, 1 ); d->m_Layout->setContentsMargins(2,2,2,2); this->setLayout(d->m_Layout); QMetaObject::connectSlotsByName(this); this->Update(); } QmitkPythonSnippets::~QmitkPythonSnippets() { delete d; } void QmitkPythonSnippets::on_PasteSnippet_triggered( bool ) { emit PasteCommandRequested( d->m_Content->toPlainText() ); } void QmitkPythonSnippets::on_RenameSnippet_triggered(bool) { QString oldname = d->m_Name->currentText(); QString name = oldname; bool ok = false; while( true ) { name = QInputDialog::getText(this, tr("Add new snippet"), tr("Name of snippet:"), QLineEdit::Normal, name, &ok); if (ok) { if ( d->m_Snippets.contains(name) ) { QMessageBox::warning(this, tr("Duplicate name."), tr("The entered name already exists. Enter another one or cancel the operation."), QMessageBox::Ok, QMessageBox::Ok ); } else { QString tmpSnippet = d->m_Snippets[oldname]; d->m_Snippets.remove(oldname); d->m_Snippets[name] = tmpSnippet; this->Update(name); this->SaveStringMap( d->m_AutoSaveFileName, d->m_Snippets ); break; } } else { break; } } } void QmitkPythonSnippets::on_AddSnippet_triggered(bool) { bool ok; QString name = QInputDialog::getText(this, tr("Add new snippet"), tr("Name of snippet:"), QLineEdit::Normal, "newSnippet", &ok); if (ok && !name.isEmpty()) { MITK_DEBUG("QmitkPythonSnippets") << "creating unique name for " << name.toStdString(); name = this->CreateUniqueName(name); MITK_DEBUG("QmitkPythonSnippets") << "creating snippet " << name.toStdString(); d->m_Snippets[name] = ""; this->Update(name); this->SaveStringMap( d->m_AutoSaveFileName, d->m_Snippets ); } } QString QmitkPythonSnippets::CreateUniqueName( const QString& name ) const { QString newName = name; size_t i = 2; while( d->m_Snippets.contains(name) ) { newName = name + QString("_%1").arg(i); ++i; } return newName; } void QmitkPythonSnippets::on_RemoveSnippet_triggered(bool) { QString name = d->m_Name->currentText(); QString question = QString("Really remove Snippet %1?").arg(name); int remove = QMessageBox::question( this, QString("Confirm removal"), question, QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); if( remove == QMessageBox::Yes || remove == QMessageBox::Ok ) { d->m_Snippets.remove(name); this->Update(); this->SaveStringMap( d->m_AutoSaveFileName, d->m_Snippets ); } } void QmitkPythonSnippets::on_RestoreDefaultSnippets_triggered(bool) { QString question = QString("Really restore default Snippets?"); int remove = QMessageBox::question( this, QString("Confirm restoring"), question, QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); if( remove == QMessageBox::Yes || remove == QMessageBox::Ok ) { - this->LoadStringMap( DEFAULT_SNIPPET_FILE, d->m_Snippets ); + QmitkPythonSnippets::LoadStringMap( DEFAULT_SNIPPET_FILE, d->m_Snippets ); this->Update(); this->SaveStringMap( d->m_AutoSaveFileName, d->m_Snippets ); } } void QmitkPythonSnippets::on_Name_currentIndexChanged(int i) { bool validSelection = i >= 0 ; d->m_PasteSnippet->setEnabled(validSelection); d->m_RemoveSnippet->setEnabled(validSelection); d->m_RenameSnippet->setEnabled(validSelection); d->m_Content->setEnabled(validSelection); d->m_SaveSnippets->setEnabled(validSelection); if( validSelection ) { QString name = d->m_Name->currentText(); MITK_DEBUG("QmitkPythonSnippets") << "selected snippet " << name.toStdString(); d->m_Content->setText( d->m_Snippets[name] ); MITK_DEBUG("QmitkPythonSnippets") << "selected snippet content " << d->m_Snippets[name].toStdString(); } } void QmitkPythonSnippets::SaveStringMap(const QString &filename, const QmitkPythonSnippets::QStringMap &map) const { MITK_DEBUG("QmitkPythonSnippets") << "saving to xml file " << filename.toStdString(); if( filename.isEmpty() ) { MITK_WARN("QmitkPythonSnippets") << "empty auto save file path given. quit."; return; } QFile file(filename); file.open(QIODevice::WriteOnly); if( !file.isOpen() ) { MITK_WARN("QmitkPythonSnippets") << "could not open file " << filename.toStdString() << " for writing"; return; } QXmlStreamWriter xmlWriter(&file); xmlWriter.setAutoFormatting(true); xmlWriter.writeStartDocument(); xmlWriter.writeStartElement(SNIPPETS_ROOT_XML_ELEMENT_NAME); QStringMap::const_iterator it = d->m_Snippets.begin(); while( it != d->m_Snippets.end() ) { { MITK_DEBUG("QmitkPythonSnippets") << "SNIPPETS_XML_ELEMENT_NAME " << SNIPPETS_XML_ELEMENT_NAME.toStdString(); MITK_DEBUG("QmitkPythonSnippets") << "writing item " << it.key().toStdString(); } xmlWriter.writeStartElement(SNIPPETS_XML_ELEMENT_NAME); xmlWriter.writeAttribute( "key", it.key() ); xmlWriter.writeAttribute( "value", it.value() ); xmlWriter.writeEndElement(); ++it; } xmlWriter.writeEndDocument(); if( file.isOpen() ) file.close(); { MITK_DEBUG("QmitkPythonSnippets") << "SaveStringMap successful "; } } -bool QmitkPythonSnippets::LoadStringMap( const QString& filename, QmitkPythonSnippets::QStringMap& oldMap ) const +bool QmitkPythonSnippets::LoadStringMap( const QString& filename, QmitkPythonSnippets::QStringMap& oldMap ) { MITK_DEBUG("QmitkPythonSnippets") << "loading from xml file " << filename.toStdString(); QStringMap map; QXmlStreamReader xmlReader; QFile file; QByteArray data; // resource file if( filename.startsWith(":") ) { QResource res( filename ); data = QByteArray( reinterpret_cast< const char* >( res.data() ), res.size() ); xmlReader.addData( data ); } else { file.setFileName( filename ); if (!file.open(QFile::ReadOnly | QFile::Text)) { MITK_ERROR << "Error: Cannot read file " << qPrintable(filename) << ": " << qPrintable(file.errorString()); return false; } xmlReader.setDevice(&file); } xmlReader.readNext(); while(!xmlReader.atEnd()) { xmlReader.readNext(); if(xmlReader.name() == SNIPPETS_XML_ELEMENT_NAME) { QXmlStreamAttributes attributes = xmlReader.attributes(); QString key; QString value; if(attributes.hasAttribute("key")) { key = attributes.value("key").toString(); } if(attributes.hasAttribute("value")) { value = attributes.value("value").toString(); } if( !key.isEmpty() ) { MITK_DEBUG("QmitkPythonSnippets") << "loaded snippet " << key.toStdString(); MITK_DEBUG("QmitkPythonSnippets") << "value " << value.toStdString(); map[key] = value; } } } if (xmlReader.hasError()) { MITK_ERROR << "Error: Failed to parse file " << qPrintable(filename) << ": " << qPrintable(xmlReader.errorString()); return false; } else if (file.error() != QFile::NoError) { MITK_ERROR << "Error: Cannot read file " << qPrintable(filename) << ": " << qPrintable(file.errorString()); return false; } if( file.isOpen() ) file.close(); oldMap = map; return true; } void QmitkPythonSnippets::Update(const QString &name) { d->m_Name->clear(); d->m_Content->clear(); MITK_DEBUG("QmitkPythonSnippets") << "size of snippets " << d->m_Snippets.size(); QStringMap::const_iterator it = d->m_Snippets.begin(); while( it != d->m_Snippets.end() ) { MITK_DEBUG("QmitkPythonSnippets") << "adding item " << it.key().toStdString(); d->m_Name->addItem( it.key() ); ++it; } int index = d->m_Name->findText( name ); if( index >= 0 ) { MITK_DEBUG("QmitkPythonSnippets") << "selecting index " << index; d->m_Name->setCurrentIndex(index); } } void QmitkPythonSnippets::on_Content_textChanged() { if( d->m_Content->isEnabled() ) { QString name = d->m_Name->currentText(); QString snippet = d->m_Content->toPlainText(); d->m_Snippets[name] = snippet; this->SaveStringMap( d->m_AutoSaveFileName, d->m_Snippets ); MITK_DEBUG("QmitkPythonSnippets") << "SaveStringMap successful"; } } void QmitkPythonSnippets::on_SaveSnippets_triggered(bool) { QString fileName = QFileDialog::getSaveFileName(this, "Save snippets", d->m_SaveFileName, "XML files (*.xml)"); if( !fileName.isEmpty() ) { d->m_SaveFileName = fileName; this->SaveStringMap( d->m_SaveFileName, d->m_Snippets ); } } void QmitkPythonSnippets::on_LoadSnippets_triggered(bool) { QString fileName = QFileDialog::getOpenFileName(this, "Load snippets", d->m_SaveFileName, "XML files (*.xml)"); if( !fileName.isEmpty() ) { d->m_SaveFileName = fileName; QString question = QString("Your current snippets will be overwritten. Proceed?"); int overwrite = QMessageBox::warning(this, QString("Confirm overwrite"), question, QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); if( overwrite == QMessageBox::Yes ) { this->LoadStringMap( d->m_SaveFileName, d->m_Snippets ); this->Update( d->m_Name->currentText() ); this->SaveStringMap( d->m_AutoSaveFileName, d->m_Snippets ); } } } diff --git a/Modules/Python/QmitkPythonSnippets.h b/Modules/Python/QmitkPythonSnippets.h index 39c808a419..998e0a635b 100644 --- a/Modules/Python/QmitkPythonSnippets.h +++ b/Modules/Python/QmitkPythonSnippets.h @@ -1,104 +1,105 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QmitkPythonSnippets_H #define _QmitkPythonSnippets_H #include #include #include struct QmitkPythonSnippetsData; /// /// a widget that holds snippets and serializes the snippets to a certain places class MITK_PYTHON_EXPORT QmitkPythonSnippets: public QWidget { Q_OBJECT public: static const QString DEFAULT_SNIPPET_FILE; static const QString SNIPPETS_ROOT_XML_ELEMENT_NAME; static const QString SNIPPETS_XML_ELEMENT_NAME; /// /// typedef for string map typedef QMap QStringMap; /// /// build ui here /// the snippets will be loaded from _AutoSaveFileName if not empty and readable /// otherwise the default snippets will be loaded QmitkPythonSnippets( const QString& _AutoSaveFileName="", QWidget* parent=0 ); /// /// delete d pointer virtual ~QmitkPythonSnippets(); + /// + /// read string map from xml file + static bool LoadStringMap( const QString& filename, QStringMap& oldMap ); + signals: /// /// this class whishes to paste sth command void PasteCommandRequested(const QString& command); protected slots: /// /// emits PasteCommandRequested signal void on_PasteSnippet_triggered( bool checked = false ); /// /// ask for name as long as it exists, call update() void on_RenameSnippet_triggered( bool checked = false ); /// /// ask for name, create snippet, call update() void on_AddSnippet_triggered( bool checked = false ); /// /// remove the current snippet, call update() void on_RemoveSnippet_triggered( bool checked = false ); /// /// call LoadStringMap with d->m_DefaultSnippetsAutoSaveFileName void on_RestoreDefaultSnippets_triggered( bool checked = false ); /// /// update action state (enable/disable), update text box void on_Name_currentIndexChanged( int i ); /// /// save changed snippet void on_Content_textChanged(); /// /// ask for file, save snippets void on_SaveSnippets_triggered( bool checked = false ); /// /// ask for file, load snippets (do not replace) void on_LoadSnippets_triggered( bool checked = false ); protected: /// /// write string map to xml file void SaveStringMap( const QString& filename, const QStringMap& map ) const; /// - /// read string map from xml file - bool LoadStringMap( const QString& filename, QStringMap& oldMap ) const; - /// /// creates a name which does not exist in the list QString CreateUniqueName(const QString &name) const; /// /// update combo box /// if name is passed, the according element will be selected void Update(const QString &name = ""); private: /// /// d pointer declaration (holds members) QmitkPythonSnippetsData* d; }; #endif // _QmitkPythonSnippets_H_INCLUDED diff --git a/Modules/Python/QmitkPythonVariableStackTableModel.cpp b/Modules/Python/QmitkPythonVariableStackTableModel.cpp index a06b9f9002..d345dd0962 100755 --- a/Modules/Python/QmitkPythonVariableStackTableModel.cpp +++ b/Modules/Python/QmitkPythonVariableStackTableModel.cpp @@ -1,223 +1,230 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPythonVariableStackTableModel.h" #include #include #include #include #include #include const QString QmitkPythonVariableStackTableModel::MITK_IMAGE_VAR_NAME = "mitkImage"; const QString QmitkPythonVariableStackTableModel::MITK_SURFACE_VAR_NAME = "mitkSurface"; QmitkPythonVariableStackTableModel::QmitkPythonVariableStackTableModel(QObject *parent) :QAbstractTableModel(parent) { us::ModuleContext* context = us::GetModuleContext(); m_PythonServiceRef = context->GetServiceReference(); m_PythonService = context->GetService(m_PythonServiceRef); m_PythonService->AddPythonCommandObserver( this ); } QmitkPythonVariableStackTableModel::~QmitkPythonVariableStackTableModel() { us::ModuleContext* context = us::GetModuleContext(); context->UngetService( m_PythonServiceRef ); m_PythonService->RemovePythonCommandObserver( this ); } bool QmitkPythonVariableStackTableModel::dropMimeData ( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent ) { // Early exit, returning true, but not actually doing anything (ignoring data). if (action == Qt::IgnoreAction) return true; // Note, we are returning true if we handled it, and false otherwise bool returnValue = false; if(data->hasFormat("application/x-mitk-datanodes")) { MITK_DEBUG("QmitkPythonVariableStackTableModel") << "dropped MITK DataNode"; returnValue = true; QString arg = QString(data->data("application/x-mitk-datanodes").data()); QStringList listOfDataNodeAddressPointers = arg.split(","); QStringList::iterator slIter; int i = 0; - int j = 0; for (slIter = listOfDataNodeAddressPointers.begin(); slIter != listOfDataNodeAddressPointers.end(); slIter++) { long val = (*slIter).toLong(); mitk::DataNode* node = static_cast((void*)val); mitk::Image* mitkImage = dynamic_cast(node->GetData()); MITK_DEBUG("QmitkPythonVariableStackTableModel") << "mitkImage is not null " << (mitkImage != 0? "true": "false"); + QRegExp rx("^\\d"); + QString varName(node->GetName().c_str()); + // regex replace every character that is not allowed in a python variable + varName = varName.replace(QRegExp("[.\\+\\-*\\s\\/\\n\\t\\r]"),QString("_")); + if( mitkImage ) { - QString varName = MITK_IMAGE_VAR_NAME; + if ( varName.isEmpty() ) + varName = MITK_IMAGE_VAR_NAME; + if ( rx.indexIn(varName) == 0) + varName.prepend("_").prepend(MITK_IMAGE_VAR_NAME); + if( i > 0 ) - varName = QString("%1%2").arg(MITK_IMAGE_VAR_NAME).arg(i); + varName = QString("%1%2").arg(varName).arg(i); MITK_DEBUG("QmitkPythonVariableStackTableModel") << "varName" << varName.toStdString(); bool exportAsCvImage = mitkImage->GetDimension() == 2 && m_PythonService->IsOpenCvPythonWrappingAvailable(); if( exportAsCvImage ) { int ret = QMessageBox::question(NULL, "Export option", - "2D image detected. Export as OpenCV image to Python instead of an ITK image?", + "2D image detected. Export as OpenCV image to Python instead of an SimpleITK image?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - exportAsCvImage = ret == QMessageBox::Yes; if(exportAsCvImage) { - m_PythonService->CopyToPythonAsCvImage( mitkImage, MITK_IMAGE_VAR_NAME.toStdString() ); + varName = MITK_IMAGE_VAR_NAME; + m_PythonService->CopyToPythonAsCvImage( mitkImage, varName.toStdString() ); ++i; } } if( !exportAsCvImage ) { - if( m_PythonService->IsItkPythonWrappingAvailable() ) + if( m_PythonService->IsSimpleItkPythonWrappingAvailable() ) { - m_PythonService->CopyToPythonAsItkImage( mitkImage, MITK_IMAGE_VAR_NAME.toStdString() ); + m_PythonService->CopyToPythonAsSimpleItkImage( mitkImage, varName.toStdString() ); ++i; } else { - MITK_ERROR << "ITK Python wrapping not available. Skipping export for image " << node->GetName(); + MITK_ERROR << "SimpleITK Python wrapping not available. Skipping export for image " << node->GetName(); } } } else { mitk::Surface* surface = dynamic_cast(node->GetData()); MITK_DEBUG("QmitkPythonVariableStackTableModel") << "found surface"; if( surface ) { - QString varName = MITK_SURFACE_VAR_NAME; - MITK_DEBUG("QmitkPythonVariableStackTableModel") << "varName" << varName.toStdString(); + if (varName.isEmpty() ) + varName = MITK_SURFACE_VAR_NAME; + if ( rx.indexIn(varName) == 0) + varName.prepend("_").prepend(MITK_SURFACE_VAR_NAME); - if( j > 0 ) - varName = QString("%1%2").arg(MITK_SURFACE_VAR_NAME).arg(j); - MITK_DEBUG("varName") << "varName" << varName.toStdString(); + MITK_DEBUG("QmitkPythonVariableStackTableModel") << "varName" << varName; if( m_PythonService->IsVtkPythonWrappingAvailable() ) { - m_PythonService->CopyToPythonAsVtkPolyData( surface, MITK_SURFACE_VAR_NAME.toStdString() ); - ++j; + m_PythonService->CopyToPythonAsVtkPolyData( surface, varName.toStdString() ); } else { MITK_ERROR << "VTK Python wrapping not available. Skipping export for surface " << node->GetName(); } } } } } return returnValue; } QVariant QmitkPythonVariableStackTableModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant headerData; // show only horizontal header if ( role == Qt::DisplayRole ) { if( orientation == Qt::Horizontal ) { // first column: "Attribute" if(section == 0) headerData = "Attribute"; else if(section == 1) headerData = "Type"; else if(section == 2) headerData = "Value"; } } return headerData; } Qt::ItemFlags QmitkPythonVariableStackTableModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); if(index.isValid()) return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | flags; else return Qt::ItemIsDropEnabled | flags; } int QmitkPythonVariableStackTableModel::rowCount(const QModelIndex &) const { return m_VariableStack.size(); } int QmitkPythonVariableStackTableModel::columnCount(const QModelIndex &) const { return 3; } QVariant QmitkPythonVariableStackTableModel::data(const QModelIndex &index, int role) const { if (index.isValid() && !m_VariableStack.empty()) { if(role == Qt::DisplayRole) { mitk::PythonVariable item = m_VariableStack.at(index.row()); if(index.column() == 0) return QString::fromStdString(item.m_Name); if(index.column() == 1) return QString::fromStdString(item.m_Type); if(index.column() == 2) return QString::fromStdString(item.m_Value); } } return QVariant(); } QStringList QmitkPythonVariableStackTableModel::mimeTypes() const { return QAbstractTableModel::mimeTypes(); QStringList types; types << "application/x-mitk-datanodes"; types << "application/x-qabstractitemmodeldatalist"; return types; } Qt::DropActions QmitkPythonVariableStackTableModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } void QmitkPythonVariableStackTableModel::CommandExecuted(const std::string& pythonCommand) { MITK_DEBUG("QmitkPythonVariableStackTableModel") << "command was executed " << pythonCommand; m_VariableStack = m_PythonService->GetVariableStack(); QAbstractTableModel::reset(); } std::vector QmitkPythonVariableStackTableModel::GetVariableStack() const { return m_VariableStack; } diff --git a/Modules/Python/QmitkPythonVariableStackTableView.cpp b/Modules/Python/QmitkPythonVariableStackTableView.cpp index 4921eaec4f..a5a7425567 100755 --- a/Modules/Python/QmitkPythonVariableStackTableView.cpp +++ b/Modules/Python/QmitkPythonVariableStackTableView.cpp @@ -1,107 +1,116 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPythonVariableStackTableView.h" #include #include #include #include #include +#include QmitkPythonVariableStackTableView::QmitkPythonVariableStackTableView(QWidget *parent) :QTableView(parent) { m_TableModel = new QmitkPythonVariableStackTableModel(parent); m_TableModel->CommandExecuted(""); this->setSelectionBehavior( QAbstractItemView::SelectRows ); this->setAlternatingRowColors(true); this->setDropIndicatorShown(true); this->setAcceptDrops(true); this->setModel( m_TableModel ); us::ModuleContext* context = us::GetModuleContext(); us::ServiceReference serviceRef = context->GetServiceReference(); m_PythonService = context->GetService(serviceRef); connect( this, SIGNAL(doubleClicked ( const QModelIndex& )), this, SLOT( OnVariableStackDoubleClicked(const QModelIndex&) ) ); } QmitkPythonVariableStackTableView::~QmitkPythonVariableStackTableView() { } void QmitkPythonVariableStackTableView::SetDataStorage(mitk::DataStorage *_DataStorage) { m_DataStorage = _DataStorage; } void QmitkPythonVariableStackTableView::OnVariableStackDoubleClicked(const QModelIndex &index) { if( m_DataStorage.IsNull() || m_PythonService == 0 ) { MITK_ERROR << "QmitkPythonVariableStackTableView not configured correctly. Quit"; return; } int row = index.row(); std::vector variableStack = m_TableModel->GetVariableStack(); { MITK_DEBUG("QmitkPythonVariableStackTableView") << "row " << row; MITK_DEBUG("QmitkPythonVariableStackTableView") << "variableStack.size(): " << variableStack.size(); } QString varName = QString::fromStdString( variableStack.at(row).m_Name ); QString type = QString::fromStdString( variableStack.at(row).m_Type ); QString value = QString::fromStdString( variableStack.at(row).m_Value ); { MITK_DEBUG("QmitkPythonVariableStackTableView") << "varName: " << varName.toStdString(); MITK_DEBUG("QmitkPythonVariableStackTableView") << "type: " << type.toStdString(); } mitk::Image::Pointer mitkImage; mitk::Surface::Pointer mitkSurface; - if( type.startsWith("itkImage") ) + if( type.startsWith("Image") ) { - mitkImage = m_PythonService->CopyItkImageFromPython(varName.toStdString()); + mitkImage = m_PythonService->CopySimpleItkImageFromPython(varName.toStdString()); } else if( type.startsWith("numpy.ndarray") ) { mitkImage = m_PythonService->CopyCvImageFromPython(varName.toStdString()); } else if( value.startsWith("(vtkPolyData)") ) { mitkSurface = m_PythonService->CopyVtkPolyDataFromPython(varName.toStdString()); } std::string nodeName = varName.toStdString(); - mitk::DataNode::Pointer node = mitk::DataNode::New(); - node->SetName ( nodeName ); + mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode(nodeName); + + // only create data node if it does not exist + if ( node.IsNull() ) + { + node = mitk::DataNode::New(); + node->SetName ( nodeName ); + m_DataStorage->Add(node); + } if( mitkImage.IsNotNull() ) { node->SetData( mitkImage ); } else if( mitkSurface.IsNotNull() ) { node->SetData( mitkSurface ); + // init renderwindow geometry + mitk::RenderingManager::GetInstance()->InitializeViews(mitkSurface->GetGeometry()); } - m_DataStorage->Add(node); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Modules/Python/Testing/CMakeLists.txt b/Modules/Python/Testing/CMakeLists.txt index c1470c885b..153cd81e2e 100644 --- a/Modules/Python/Testing/CMakeLists.txt +++ b/Modules/Python/Testing/CMakeLists.txt @@ -1,4 +1 @@ MITK_CREATE_MODULE_TESTS() - -mitkAddCustomModuleTest(mitkCopyToPythonAsItkImage_CopyPic3DToPythonAndBackToMitk_ImageIsEqual mitkCopyToPythonAsItkImageTest ${MITK_DATA_DIR}/Pic3D.nrrd) - diff --git a/Modules/Python/Testing/files.cmake b/Modules/Python/Testing/files.cmake index c8e9fe00e2..fb6dc38d7e 100644 --- a/Modules/Python/Testing/files.cmake +++ b/Modules/Python/Testing/files.cmake @@ -1,7 +1,13 @@ set(MODULE_TESTS mitkPythonTest.cpp + mitkVtkPythonTest.cpp ) -set(MODULE_CUSTOM_TESTS - mitkCopyToPythonAsItkImageTest.cpp -) +if(MITK_USE_OpenCV) + set(MODULE_TESTS ${MODULE_TESTS} mitkCvPythonTest.cpp) +endif() + +if(MITK_USE_SimpleITK) + set(MODULE_TESTS ${MODULE_TESTS} mitkSimpleItkPythonTest.cpp) +endif() + diff --git a/Modules/Python/Testing/mitkCommonPythonTest.h b/Modules/Python/Testing/mitkCommonPythonTest.h new file mode 100644 index 0000000000..420e97bcb7 --- /dev/null +++ b/Modules/Python/Testing/mitkCommonPythonTest.h @@ -0,0 +1,72 @@ + +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mitk +{ + +class CommonPythonTestSuite : public mitk::TestFixture +{ + +protected: + mitk::PythonService* m_PythonService; + mitk::Image::Pointer m_Image; + mitk::Image::Pointer m_Image2D; + mitk::Surface::Pointer m_Surface; + QMap m_Snippets; + +public: + + void setUp() + { + //get the context of the python module + us::Module* module = us::ModuleRegistry::GetModule("MitkPython"); + us::ModuleContext* context = module->GetModuleContext(); + //get the service which is generated in the PythonModuleActivator + us::ServiceReference serviceRef = context->GetServiceReference(); + m_PythonService = dynamic_cast( context->GetService(serviceRef) ); + + m_Image = mitk::IOUtil::LoadImage(GetTestDataFilePath("Pic3D.nrrd")); + m_Image2D = mitk::IOUtil::LoadImage(GetTestDataFilePath("Png2D-bw.png")); + m_Surface = mitk::IOUtil::LoadSurface(GetTestDataFilePath("binary.stl")); + + QmitkPythonSnippets::LoadStringMap(QmitkPythonSnippets::DEFAULT_SNIPPET_FILE,m_Snippets); + } + + void tearDown() + { + m_Image = NULL; + m_Image2D = NULL; + m_Surface = NULL; + } +}; + +} diff --git a/Modules/Python/Testing/mitkCopyToPythonAsItkImageTest.cpp b/Modules/Python/Testing/mitkCopyToPythonAsItkImageTest.cpp deleted file mode 100644 index c9d0e5cd32..0000000000 --- a/Modules/Python/Testing/mitkCopyToPythonAsItkImageTest.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -int mitkCopyToPythonAsItkImageTest(int /*argc*/, char* argv[]) -{ - MITK_TEST_BEGIN("mitkCopyToPythonAsItkImageTest") - - //get the context of the python module - us::Module* module = us::ModuleRegistry::GetModule("MitkPython"); - us::ModuleContext* context = module->GetModuleContext(); - //get the service which is generated in the PythonModuleActivator - us::ServiceReference serviceRef = context->GetServiceReference(); - mitk::PythonService* pythonService = dynamic_cast( context->GetService(serviceRef) ); - MITK_TEST_CONDITION(pythonService->IsItkPythonWrappingAvailable() == true, "Is Python available?"); - - mitk::Image::Pointer testImage = mitk::IOUtil::LoadImage(std::string(argv[1])); - - //give it a name in python - std::string nameOfImageInPython("mitkImage"); - - MITK_TEST_CONDITION( pythonService->CopyToPythonAsItkImage( testImage, nameOfImageInPython) == true, "Valid image copied to python import should return true."); - mitk::Image::Pointer pythonImage = pythonService->CopyItkImageFromPython(nameOfImageInPython); - - - itk::Index<3> index; - index[0] = 128; - index[1] = 128; - index[2] = 24; - - try{ - // pic3D of type char - mitk::ImagePixelReadAccessor pythonImageAccesor(pythonImage); - - //TODO Use the assert comparison methods once we have them implemented and remove GetPixelValueByIndex - MITK_TEST_CONDITION( pythonImageAccesor.GetDimension(0) == 256, "Is the 1st dimension of Pic3D still 256?"); - MITK_TEST_CONDITION( pythonImageAccesor.GetDimension(1) == 256, "Is the 2nd dimension of Pic3D still 256?"); - MITK_TEST_CONDITION( pythonImageAccesor.GetDimension(2) == 49, "Is the 3rd dimension of Pic3D still 49?"); - - MITK_TEST_CONDITION( pythonImageAccesor.GetPixelByIndex(index) == 96, "Is the value of Pic3D at (128,128,24) still 96?"); - }catch(...) - { - MITK_TEST_CONDITION( false, "Image is not readable! "); - } - - MITK_TEST_END() -} diff --git a/Modules/Python/Testing/mitkCvPythonTest.cpp b/Modules/Python/Testing/mitkCvPythonTest.cpp new file mode 100644 index 0000000000..6f41448807 --- /dev/null +++ b/Modules/Python/Testing/mitkCvPythonTest.cpp @@ -0,0 +1,58 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +class mitkCvPythonTestSuite : public mitk::CommonPythonTestSuite +{ + CPPUNIT_TEST_SUITE(mitkCvPythonTestSuite); + MITK_TEST(testCVImageTransfer); + MITK_TEST(testOpenCVMedianFilter); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testCVImageTransfer() + { + std::string varName("mitkImage"); + CPPUNIT_ASSERT_MESSAGE ( "Is OpenCV Python Wrapping available?", + m_PythonService->IsOpenCvPythonWrappingAvailable() == true ); + + CPPUNIT_ASSERT_MESSAGE( "Valid image copied to python import should return true.", + m_PythonService->CopyToPythonAsCvImage( m_Image2D, varName) == true ); + + mitk::Image::Pointer pythonImage = m_PythonService->CopyCvImageFromPython(varName); + + // todo pixeltypes do not match, cv is changing it + //CPPUNIT_ASSERT_MESSAGE( "Compare if images are equal after transfer.", + // mitk::Equal(pythonImage,m_Image2D) ); + } + + //TODO opencv median filter, add cpp test code + void testOpenCVMedianFilter() + { + // simple itk median filter in python + CPPUNIT_ASSERT_MESSAGE ( "Is OpenCV Python Wrapping available?", m_PythonService->IsOpenCvPythonWrappingAvailable() == true ); + + CPPUNIT_ASSERT_MESSAGE( "Valid image copied to python import should return true.", m_PythonService->CopyToPythonAsCvImage(m_Image2D, "mitkImage") == true ); + + m_PythonService->Execute( m_Snippets["opencv median filter"].toStdString(), mitk::IPythonService::MULTI_LINE_COMMAND ); + + CPPUNIT_ASSERT_MESSAGE( "Python execute error occured.", !m_PythonService->PythonErrorOccured()); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkCvPython) diff --git a/Modules/Python/Testing/mitkSimpleItkPythonTest.cpp b/Modules/Python/Testing/mitkSimpleItkPythonTest.cpp new file mode 100644 index 0000000000..e2d6cce2cb --- /dev/null +++ b/Modules/Python/Testing/mitkSimpleItkPythonTest.cpp @@ -0,0 +1,201 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include +#include +#include + +#include "SimpleITK.h" + +namespace sitk = itk::simple; + +namespace mitk { + static mitk::Image::Pointer SimpleItkToMitkImage( sitk::Image& sitkImage ); + static sitk::Image MitkToSimpleItkImage( mitk::Image* image ); +} + +sitk::Image mitk::MitkToSimpleItkImage( mitk::Image* image ) +{ + const mitk::Vector3D spacing = image->GetGeometry()->GetSpacing(); + mitk::Point3D origin = image->GetGeometry()->GetOrigin(); + mitk::PixelType pixelType = image->GetPixelType(); + mitk::ImageReadAccessor ra(image); + void* buffer = (void*) ra.GetData(); + sitk::ImportImageFilter importer; + + std::vector sitkSpacing; + sitkSpacing.push_back(spacing[0]); + sitkSpacing.push_back(spacing[1]); + sitkSpacing.push_back(spacing[2]); + std::vector sitkOrigin; + sitkOrigin.push_back(origin[0]); + sitkOrigin.push_back(origin[1]); + sitkOrigin.push_back(origin[2]); + std::vector sitkSize; + + for ( unsigned int i = 0; i < image->GetDimension(); ++i ) + sitkSize.push_back(image->GetDimensions()[i]); + + importer.SetSpacing(sitkSpacing); + importer.SetSize(sitkSize); + importer.SetOrigin(sitkOrigin); + + if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) { + importer.SetBufferAsDouble((double*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) { + importer.SetBufferAsFloat((float*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) { + importer.SetBufferAsInt16((int16_t*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) { + importer.SetBufferAsInt8((int8_t*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) { + importer.SetBufferAsInt32((int32_t*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) { + importer.SetBufferAsInt64((int64_t*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) { + importer.SetBufferAsUInt8((uint8_t*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) { + importer.SetBufferAsUInt32((uint32_t*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) { + importer.SetBufferAsUInt64((uint64_t*) buffer); + } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) { + importer.SetBufferAsUInt16((uint16_t*) buffer); + } + + return importer.Execute(); +} + +mitk::Image::Pointer mitk::SimpleItkToMitkImage( sitk::Image& sitkImage ) +{ + mitk::Image::Pointer image = mitk::Image::New(); + void* buffer = NULL; + mitk::PixelType pixelType = MakeScalarPixelType(); + std::vector sitkSpacing = sitkImage.GetSpacing(); + double spacing[3] = { sitkSpacing[0], sitkSpacing[1], sitkSpacing[2] }; + std::vector sitkOrigin = sitkImage.GetOrigin(); + double origin[3] = { sitkOrigin[0], sitkOrigin[1], sitkOrigin[2] }; + std::vector sitkSize = sitkImage.GetSize(); + unsigned int dimensions[4] = { 1,1,1,1}; + + for ( size_t i = 0; i < sitkSize.size(); ++i ) + dimensions[i] = sitkSize[i]; + + size_t size = 0; + if ( sitkImage.GetPixelIDValue() == sitk::sitkInt8 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsInt8(); + size = sizeof(char); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkInt16 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsInt16(); + size = sizeof(short); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkInt32 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsInt32(); + size = sizeof(int); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkInt64 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsInt64(); + size = sizeof(long); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkUInt8 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsUInt8(); + size = sizeof(unsigned char); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkUInt16 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsUInt16(); + size = sizeof(unsigned short); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkUInt32 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsUInt32(); + size = sizeof(unsigned int); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkUInt64 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsUInt64(); + size = sizeof(unsigned long); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkFloat32 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsFloat(); + size = sizeof(float); + } else if( sitkImage.GetPixelIDValue() == sitk::sitkFloat64 ) { + pixelType = MakeScalarPixelType(); + buffer = (void*) sitkImage.GetBufferAsDouble(); + size = sizeof(double); + } + + image->Initialize(pixelType,sitkImage.GetDimension(),dimensions); + image->SetSpacing(spacing); + image->SetOrigin(origin); + + for(size_t i = 0; i < sitkSize.size(); ++i ) + size *= sitkSize[i]; + + mitk::ImageWriteAccessor wa(image); + + memcpy(wa.GetData(),buffer, size); + + return image; +} + + +class mitkSimpleItkPythonTestSuite : public mitk::CommonPythonTestSuite +{ + CPPUNIT_TEST_SUITE(mitkSimpleItkPythonTestSuite); + MITK_TEST(testSimpleItkImageTransfer); + MITK_TEST(testSimpleITKMedianFilterSnippet); + CPPUNIT_TEST_SUITE_END(); + + +public: + + void testSimpleItkImageTransfer() + { + std::string varName("mitkImage"); + CPPUNIT_ASSERT_MESSAGE ( "Is SimpleITK Python Wrapping available?", + m_PythonService->IsSimpleItkPythonWrappingAvailable() == true ); + + CPPUNIT_ASSERT_MESSAGE( "Valid image copied to python import should return true.", + m_PythonService->CopyToPythonAsSimpleItkImage( m_Image, varName) == true ); + + mitk::Image::Pointer pythonImage = m_PythonService->CopySimpleItkImageFromPython(varName); + + CPPUNIT_ASSERT_MESSAGE( "Compare if images are equal after transfer.", + mitk::Equal(*pythonImage.GetPointer(),*m_Image.GetPointer(), mitk::eps,true) ); + } + + + void testSimpleITKMedianFilterSnippet() + { + // simple itk median filter in cpp + sitk::MedianImageFilter medianFilter; + medianFilter.SetRadius(1); + sitk::Image sitkImage = medianFilter.Execute(mitk::MitkToSimpleItkImage(m_Image)); + mitk::Image::Pointer mitkImage = mitk::SimpleItkToMitkImage(sitkImage); + + // simple itk median filter in python + CPPUNIT_ASSERT_MESSAGE ( "Is SimpleItk Python Wrapping available?", m_PythonService->IsSimpleItkPythonWrappingAvailable() == true ); + + CPPUNIT_ASSERT_MESSAGE( "Valid image copied to python import should return true.", m_PythonService->CopyToPythonAsSimpleItkImage(m_Image, "mitkImage") == true ); + + m_PythonService->Execute( m_Snippets["medianfilter"].toStdString(), mitk::IPythonService::MULTI_LINE_COMMAND ); + CPPUNIT_ASSERT_MESSAGE( "Python execute error occured.", !m_PythonService->PythonErrorOccured()); + + mitk::Image::Pointer pythonImage = m_PythonService->CopySimpleItkImageFromPython("mitkImage_new"); + + CPPUNIT_ASSERT_MESSAGE( "Compare if images are equal.", mitk::Equal(*pythonImage.GetPointer(), *mitkImage.GetPointer(),mitk::eps,true) ); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkSimpleItkPython) diff --git a/Modules/Python/Testing/mitkVtkPythonTest.cpp b/Modules/Python/Testing/mitkVtkPythonTest.cpp new file mode 100644 index 0000000000..3fb2662006 --- /dev/null +++ b/Modules/Python/Testing/mitkVtkPythonTest.cpp @@ -0,0 +1,95 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +// vtk cone sample snippet +#include +// vtk decimate pro snippet +#include + +#include + +class mitkVtkPythonTestSuite : public mitk::CommonPythonTestSuite +{ + CPPUNIT_TEST_SUITE(mitkVtkPythonTestSuite); + MITK_TEST(testSurfaceTransfer); + MITK_TEST(testVtkCreateConePythonSnippet); + MITK_TEST(testVtkDecimateProPythonSnippet); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testSurfaceTransfer() + { + std::string varName("mitkSurface"); + CPPUNIT_ASSERT_MESSAGE ( "Is VTK Python Wrapping available?", m_PythonService->IsVtkPythonWrappingAvailable() == true ); + + CPPUNIT_ASSERT_MESSAGE( "Valid surface copied to python import should return true.", + m_PythonService->CopyToPythonAsVtkPolyData( m_Surface, varName) == true ); + + mitk::Surface::Pointer pythonSurface = m_PythonService->CopyVtkPolyDataFromPython(varName); + + CPPUNIT_ASSERT_MESSAGE( "Compare if surfaces are equal after transfer.", mitk::Equal(*pythonSurface.GetPointer(),*m_Surface.GetPointer(),mitk::eps,true) ); + } + + void testVtkCreateConePythonSnippet() + { + // cone in cpp + mitk::Surface::Pointer mitkSurface = mitk::Surface::New(); + vtkSmartPointer coneSrc = vtkSmartPointer::New(); + coneSrc->SetResolution(60); + coneSrc->SetCenter(-2,0,0); + coneSrc->Update(); + mitkSurface->SetVtkPolyData(coneSrc->GetOutput()); + + // run python code + CPPUNIT_ASSERT_MESSAGE ( "Is VTK Python Wrapping available?", m_PythonService->IsVtkPythonWrappingAvailable() == true ); + + m_PythonService->Execute( m_Snippets["vtk: create cone"].toStdString(), mitk::IPythonService::MULTI_LINE_COMMAND ); + CPPUNIT_ASSERT_MESSAGE( "Python execute error occured.", !m_PythonService->PythonErrorOccured()); + + mitk::Surface::Pointer pythonSurface = m_PythonService->CopyVtkPolyDataFromPython("cone"); + + CPPUNIT_ASSERT_MESSAGE( "Compare if cones are equal.", mitk::Equal(*pythonSurface.GetPointer(), *mitkSurface.GetPointer(), mitk::eps,true) ); + } + + void testVtkDecimateProPythonSnippet() + { + // decimate pro in cpp + mitk::Surface::Pointer mitkSurface = mitk::Surface::New(); + vtkSmartPointer deci = vtkSmartPointer::New(); + deci->SetInputData(m_Surface->GetVtkPolyData()); + deci->SetTargetReduction(0.9); + deci->PreserveTopologyOn(); + deci->Update(); + mitkSurface->SetVtkPolyData(deci->GetOutput()); + + // decimate pro in python + CPPUNIT_ASSERT_MESSAGE ( "Is VTK Python Wrapping available?", m_PythonService->IsVtkPythonWrappingAvailable() == true ); + + CPPUNIT_ASSERT_MESSAGE( "Valid surface copied to python import should return true.", m_PythonService->CopyToPythonAsVtkPolyData( m_Surface, "mitkSurface") == true ); + + m_PythonService->Execute( m_Snippets["vtk.vtkDecimatePro"].toStdString(), mitk::IPythonService::MULTI_LINE_COMMAND ); + CPPUNIT_ASSERT_MESSAGE( "Python execute error occured.", !m_PythonService->PythonErrorOccured()); + + mitk::Surface::Pointer pythonSurface = m_PythonService->CopyVtkPolyDataFromPython("mitkSurface_new"); + + CPPUNIT_ASSERT_MESSAGE( "Compare if surfaces are equal.", mitk::Equal(*pythonSurface.GetPointer(), *mitkSurface.GetPointer(), mitk::eps,true) ); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkVtkPython) diff --git a/Modules/Python/documentation/mitkPython.dox b/Modules/Python/documentation/mitkPython.dox index dbfb3994e9..52f27b2c52 100644 --- a/Modules/Python/documentation/mitkPython.dox +++ b/Modules/Python/documentation/mitkPython.dox @@ -1,43 +1,49 @@ /** \page mitkPython_Overview The MITK Python Module -

Brief description

-The MITK Python Module provides a service class for interactively run python code (passed as C++ strings) and evaluate the results. Furthermore the service class offers means to convert an MITK Image to an ITK/OpenCV image in their wrapped python environment. Thus, one can process MITK images with Python Code from the OpenCV and ITK wrapping system. Furthermore one can convert an mitk::Surface to a vtkPolyData in its Python environment.
-Under the hood, the MITK build system takes care that the wrapping build process for ITK/VTK/OpenCV is correctly initiated and all paths are correctly set within MITK code. - -

Build Instructions

-- Install Python 2.x -- Activate MITK_USE_Python in the superbuild process of MITK -- Provide CMake with the correct Python paths (if not found automatically) -- Build MITK: All wrapping will be setup by the MITK superbuild routine - -

Known problems and workarounds

- -

System: Linux/OSX/gcc
-Problem: An error during the build process occurs: -

-Linking CXX shared library libPythonQt.so
-/usr/bin/ld: error: /usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../../lib/libpython2.7.a(abstract.o): requires dynamic R_X86_64_PC32 reloc against 'PyErr_Occurred' which may overflow at runtime; recompile with -fPIC
-
-Workaround: Try setting the CMake var PYTHON_LIBRARY to the shared object, e.g. /usr/lib/libpython2.7.so -

-

System: Linux/gcc (maybe Mac OS)
-Problem: An error during the build process occurs: -

-Scanning dependencies of target install_wrapitk_compatibility
-[ 40%] Built target install_wrapitk_compatibility
-[ 40%] Generating swigrun.xml
-gccxml_cc1plus: error: gccxml_builtins.h: No such file or directory
-make[5]: *** [Wrapping/WrapITK/SwigRuntime/swigrun.xml] Error 1
-make[4]: *** [Wrapping/WrapITK/SwigRuntime/CMakeFiles/SwigRuntimePython.dir/all] Error 2
-make[3]: *** [all] Error 2
-make[2]: *** [ITK-cmake/src/ITK-stamp/ITK-build] Error 2
-make[1]: *** [CMakeFiles/ITK.dir/all] Error 2
-make: *** [all] Error 2
-
-Workaround: Install CableSwig from the software repo and set the CMake var EXTERNAL_CableSwig_DIR to the directory containing CableSwigConfig.cmake, on linux usually /usr/lib/CableSwig -

+\section sec1 Brief description +The MITK Python Module provides a service class for interactively run python code (passed as C++ strings) and +evaluate the results. Furthermore the service class offers means to convert an MITK Image to an ITK/OpenCV image in their wrapped python environment. +Thus, one can process MITK images with Python Code from the OpenCV and ITK wrapping system. +Furthermore one can convert an mitk::Surface to a vtkPolyData in its Python environment.
+Under the hood, the MITK build system takes care that the wrapping build process for SimpleITK/VTK/OpenCV is correctly initiated and all paths are correctly set within MITK code. +To use the features of the different toolkits make sure they are enabled during the superbuild process. +\section sec2 Build Instructions + +The following build options are available: +
    +
  • MITK_USE_Python +
  • MITK_USE_SYSTEM_PYTHON +
+ +\subsection ssec1 MITK_USE_Python +MITK_USE_Python enables the python wrapping in MITK. When the option is activated +the build of the additional dependency SimpleITK is also enabled. The default behaviour is to download and build +Python 2.7.3 with numpy and embed it into MITK.To use an own custom runtime see MITK_USE_SYSTEM_PYTHON. + +\subsection ssec2 MITK_USE_SYSTEM_PYTHON +This option is deactivated by default. If MITK_USE_SYSTEM_PYTHON is activated the python runtime from the system is used. +The user can also specify it's own runtime by modifing the variables added by the +FindPythonLib.cmake script. Note: A Python runtime with numpy is needed to use the MITK Python wrapping. + +\section sec3 Suported Data Types +The following data types in MITK are supported in the MITK Python Wrapping: +
    +
  • Image +
  • Surface +
+ +\subsection ssec4 Image +Mitk Images can be transferred to python. The images are copied in-memory and +transferred as a numpy array to Python and vice versa. The MITK python wrapping creates a SimpleITK image +using the numpy array with the properties of the MITK Image. Two dimensional images +can also be transferred as an OpenCV image to python. + +\subsection ssec5 Surface +Surfaces within mitk can be transferred as a vtkPolyData Object to Python. +The surfaces are fully memory mapped. When changing a python wrapped surface +the original object is also modified on the C++ side of MITK. */ diff --git a/Modules/Python/files.cmake b/Modules/Python/files.cmake index 66fb3a3ce7..c4fe74b329 100644 --- a/Modules/Python/files.cmake +++ b/Modules/Python/files.cmake @@ -1,28 +1,34 @@ SET(CPP_FILES mitkIPythonService.cpp mitkPythonActivator.cpp mitkPythonService.cpp QmitkCtkPythonShell.cpp QmitkPythonVariableStackTableModel.cpp QmitkPythonVariableStackTableView.cpp QmitkPythonScriptEditorHighlighter.cpp QmitkPythonTextEditor.cpp QmitkPythonSnippets.cpp ) +if(BUILD_TESTING) + SET(H_FILES + Testing/mitkCommonPythonTest.h + ) +endif() + #SET(UI_FILES # QmitkPythonSnippets.ui #) SET(MOC_H_FILES QmitkCtkPythonShell.h QmitkPythonVariableStackTableModel.h QmitkPythonVariableStackTableView.h QmitkPythonScriptEditorHighlighter.h QmitkPythonTextEditor.h QmitkPythonSnippets.h ) set(QRC_FILES resources/mitkPython.qrc ) diff --git a/Modules/Python/mitkIPythonService.h b/Modules/Python/mitkIPythonService.h index ddde271380..d9af572e60 100644 --- a/Modules/Python/mitkIPythonService.h +++ b/Modules/Python/mitkIPythonService.h @@ -1,141 +1,141 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkIPythonService_h #define mitkIPythonService_h // mitk #include #include "mitkImage.h" //for microservices #include #include "mitkSurface.h" #include namespace mitk { /// /// describes a python variable (data container) /// \see IPythonService::GetVariableStack() /// struct PythonVariable { std::string m_Name; std::string m_Type; std::string m_Value; }; /// /// a PythonCommandObserver gets informed as soon as a python command was issued /// \see IPythonService::AddPythonCommandObserver() /// class PythonCommandObserver { public: virtual void CommandExecuted(const std::string& pythonCommand) = 0; }; /// /// The central service for issuing Python Code /// The class also enables to transfer mitk images to python as itk::Image and vice versa /// \see IPythonService::GetVariableStack() /// class MITK_PYTHON_EXPORT IPythonService { public: /// /// Constant representing a single line command /// \see IPythonService::Execute() static const int SINGLE_LINE_COMMAND = 0; /// /// Constant representing a command in which the commands are seperated by new lines, i.e. "\\n" /// \see IPythonService::Execute() static const int MULTI_LINE_COMMAND = 1; /// /// Constant representing a single line command x which is run as "eval(x)" /// \see IPythonService::Execute() static const int EVAL_COMMAND = 2; /// /// Executes a python command. /// \return A variant containing the return value as string of the python code (if any) virtual std::string Execute( const std::string& pythonCommand, int commandType = SINGLE_LINE_COMMAND ) = 0; /// /// Executes a python script. virtual void ExecuteScript( const std::string& pathToPythonScript ) = 0; /// /// \return true if the last call to Execute...() resulted in an error, false otherwise virtual bool PythonErrorOccured() const = 0; /// /// \return The list of variables in the __main__ namespace virtual std::vector GetVariableStack() const = 0; /// /// \return true if a variable with this name is defined in the __main__ namespace, false otherwise virtual bool DoesVariableExist(const std::string& name) const = 0; /// /// adds a command observer which is informed after a command was issued with "Execute" virtual void AddPythonCommandObserver( PythonCommandObserver* observer ) = 0; /// /// removes a specific command observer virtual void RemovePythonCommandObserver( PythonCommandObserver* observer ) = 0; /// /// notify all observer. this should only be used if it can be garantueed that the /// current python interpreter instance got another command from anywhere else /// the the Execute() method of this service, e.g. the shell widget uses this function /// since it does not use Execute() virtual void NotifyObserver( const std::string& command ) = 0; /// /// \return true, if itk wrapping is available, false otherwise - virtual bool IsItkPythonWrappingAvailable() = 0; + virtual bool IsSimpleItkPythonWrappingAvailable() = 0; /// /// copies an mitk image as itk image into the python interpreter process /// the image will be available as "varName" in python if everythin worked /// \return true if image was copied, else false - virtual bool CopyToPythonAsItkImage( mitk::Image* image, const std::string& varName ) = 0; + virtual bool CopyToPythonAsSimpleItkImage( mitk::Image* image, const std::string& varName ) = 0; /// /// copies an itk image from the python process that is named "varName" /// \return the image or 0 if copying was not possible - virtual mitk::Image::Pointer CopyItkImageFromPython( const std::string& varName ) = 0; + virtual mitk::Image::Pointer CopySimpleItkImageFromPython( const std::string& varName ) = 0; /// /// \return true, if OpenCv wrapping is available, false otherwise virtual bool IsOpenCvPythonWrappingAvailable() = 0; /// /// \see CopyToPythonAsItkImage() virtual bool CopyToPythonAsCvImage( mitk::Image* image, const std::string& varName ) = 0; /// /// \see CopyCvImageFromPython() virtual mitk::Image::Pointer CopyCvImageFromPython( const std::string& varName ) = 0; /// /// \return true, if vtk wrapping is available, false otherwise virtual bool IsVtkPythonWrappingAvailable() = 0; /// /// \see CopyToPythonAsItkImage() virtual bool CopyToPythonAsVtkPolyData( mitk::Surface* surface, const std::string& varName ) = 0; /// /// \see CopyCvImageFromPython() virtual mitk::Surface::Pointer CopyVtkPolyDataFromPython( const std::string& varName ) = 0; /// /// nothing to do here virtual ~IPythonService(); // leer in mitkIPythonService.cpp implementieren }; } US_DECLARE_SERVICE_INTERFACE(mitk::IPythonService, "org.mitk.services.IPythonService") #endif diff --git a/Modules/Python/mitkPythonService.cpp b/Modules/Python/mitkPythonService.cpp index df84c3fef3..da852eab10 100644 --- a/Modules/Python/mitkPythonService.cpp +++ b/Modules/Python/mitkPythonService.cpp @@ -1,529 +1,646 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPythonService.h" #include #include #include #include #include #include "PythonPath.h" +#include +#include +#include +#include +#include + +#ifndef WIN32 + #include +#endif const QString mitk::PythonService::m_TmpDataFileName("temp_mitk_data_file"); +#ifdef USE_MITK_BUILTIN_PYTHON + static char* pHome = NULL; +#endif mitk::PythonService::PythonService() : m_ItkWrappingAvailable( true ), m_OpenCVWrappingAvailable( true ), m_VtkWrappingAvailable( true ), m_ErrorOccured( false ) { { MITK_DEBUG << "will init python if necessary"; } bool pythonInitialized = static_cast( Py_IsInitialized() ); //m_PythonManager.isPythonInitialized() ); { MITK_DEBUG << "pythonInitialized " << pythonInitialized; MITK_DEBUG << "m_PythonManager.isPythonInitialized() " << m_PythonManager.isPythonInitialized(); } // due to strange static var behaviour on windows Py_IsInitialized() returns correct value while // m_PythonManager.isPythonInitialized() does not because it has been constructed and destructed again if( !m_PythonManager.isPythonInitialized() ) { try { +//TODO a better way to do this +#ifndef WIN32 +#if defined (__APPLE__) || defined(MACOSX) + const char* library = "libpython2.7.dylib"; +#else + const char* library = "libpython2.7.so"; +#endif + dlerror(); + if(dlopen(library, RTLD_NOW | RTLD_GLOBAL) == 0 ) + { + mitkThrow() << "Python runtime could not be loaded: " << dlerror(); + } +#endif + + std::string programPath = mitk::IOUtil::GetProgramPath(); + QDir programmDir( QString( programPath.c_str() ).append("/Python") ); + QString pythonCommand; + // Set the pythonpath variable depending if + // we have an installer or development environment + if ( programmDir.exists() ) { + // runtime directory used in installers + pythonCommand.append( QString("import site, sys\n") ); + pythonCommand.append( QString("sys.path.append('')\n") ); + pythonCommand.append( QString("sys.path.append('%1')\n").arg(programPath.c_str()) ); + pythonCommand.append( QString("sys.path.append('%1/Python')").arg(programPath.c_str()) ); +#ifndef USE_MITK_BUILTIN_PYTHON + pythonCommand.append( QString("\nsite.addsitedir('%1/Python/SimpleITK')").arg(programPath.c_str()) ); +#endif + } else { + pythonCommand.append(PYTHONPATH_COMMAND); + } + if( pythonInitialized ) m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut|PythonQt::PythonAlreadyInitialized); else m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut); - MITK_DEBUG("PythonService") << "initalizing python"; - m_PythonManager.initialize(); - - MITK_DEBUG("PythonService") << "python initalized"; +// set python home if own runtime is used +#ifdef USE_MITK_BUILTIN_PYTHON + QString pythonHome; + if ( programmDir.exists() ) + pythonHome.append(QString("%1/Python").arg(programPath.c_str())); + else + pythonHome.append(PYTHONHOME); - QString pythonCommand(PYTHONPATH_COMMAND); - MITK_DEBUG("PythonService") << "registering python paths" << PYTHONPATH_COMMAND; - m_PythonManager.executeString( pythonCommand, ctkAbstractPythonManager::FileInput ); + if(pHome) delete[] pHome; + pHome = new char[pythonHome.toStdString().length() + 1]; - /* - //system("export LD_LIBRARY_PATH=/local/muellerm/mitk/bugsquashing/bin-debug/VTK-build/bin:$LD_LIBRARY_PATH"); - //m_PythonManager.executeString( "print sys.path", ctkAbstractPythonManager::SingleInput ); - //MITK_DEBUG("mitk::PythonService") << "result of 'sys.path': " << result.toString().toStdString(); + strcpy(pHome,pythonHome.toStdString().c_str()); + Py_SetPythonHome(pHome); + MITK_DEBUG("PythonService") << "PythonHome: " << pHome; +#endif - //m_PythonManager.executeString( "sys.path.append('/usr/share/pyshared/numpy')", ctkAbstractPythonManager::SingleInput ); - //m_PythonManager.executeString( "import numpy", ctkAbstractPythonManager::SingleInput ); + MITK_DEBUG("PythonService") << "initalizing python"; + m_PythonManager.initialize(); - MITK_DEBUG("mitk::PythonService") << "Trying to import ITK"; - m_PythonManager.executeString( "import itk", ctkAbstractPythonManager::SingleInput ); - m_ItkWrappingAvailable = !m_PythonManager.pythonErrorOccured(); - MITK_DEBUG("mitk::PythonService") << "m_ItkWrappingAvailable: " << (m_ItkWrappingAvailable? "yes": "no"); - if( !m_ItkWrappingAvailable ) +#ifdef USE_MITK_BUILTIN_PYTHON + PyObject* dict = PyDict_New(); + // Import builtin modules + if (PyDict_GetItemString(dict, "__builtins__") == NULL) { - MITK_WARN << "ITK Python wrapping not available. Please check build settings or PYTHONPATH settings."; + PyObject* builtinMod = PyImport_ImportModule("__builtin__"); + if (builtinMod == NULL || + PyDict_SetItemString(dict, "__builtins__", builtinMod) != 0) + { + Py_DECREF(dict); + Py_XDECREF(dict); + return; + } + Py_DECREF(builtinMod); } +#endif - { - MITK_DEBUG("mitk::PythonService") << "Trying to import OpenCv"; - PyRun_SimpleString("import cv2\n"); - if (PyErr_Occurred()) - { - PyErr_Print(); - } - else - m_OpenCVWrappingAvailable = true; - - //m_PythonManager.executeString( "import cv2", ctkAbstractPythonManager::SingleInput ); - MITK_DEBUG("mitk::PythonService") << "Investigate if an error occured while importing cv2"; - //m_OpenCVWrappingAvailable = !m_PythonManager.pythonErrorOccured(); - MITK_DEBUG("mitk::PythonService") << "m_OpenCVWrappingAvailable: " << (m_OpenCVWrappingAvailable? "yes": "no"); - if( !m_OpenCVWrappingAvailable ) - { - MITK_WARN << "OpenCV Python wrapping not available. Please check build settings or PYTHONPATH settings."; - } - } + MITK_DEBUG("PythonService")<< "Python Search paths: " << Py_GetPath(); + MITK_DEBUG("PythonService") << "python initalized"; - MITK_DEBUG("mitk::PythonService") << "Trying to import VTK"; - m_PythonManager.executeString( "import vtk", ctkAbstractPythonManager::SingleInput ); - m_VtkWrappingAvailable = !m_PythonManager.pythonErrorOccured(); - MITK_DEBUG("mitk::PythonService") << "m_VtkWrappingAvailable: " << (m_VtkWrappingAvailable? "yes": "no"); - if( !m_VtkWrappingAvailable ) - { - MITK_WARN << "VTK Python wrapping not available. Please check build settings or PYTHONPATH settings."; - } - */ + MITK_DEBUG("PythonService") << "registering python paths" << PYTHONPATH_COMMAND; + m_PythonManager.executeString( pythonCommand, ctkAbstractPythonManager::FileInput ); } catch (...) { MITK_DEBUG("PythonService") << "exception initalizing python"; } - } - - //m_PythonManager.executeString( "for path in sys.path:\n print path\n", ctkAbstractPythonManager::SingleInput ); - //m_PythonManager.executeString( "for k, v in os.environ.items():\n print \"%s=%s\" % (k, v)", ctkAbstractPythonManager::SingleInput ); - //m_PythonManager.executeFile("/local/muellerm/Dropbox/13-02-11-python-wrapping/interpreterInfo.py"); - //std::string result = m_PythonManager.executeString( "5+5", ctkAbstractPythonManager::EvalInput ); - //MITK_DEBUG("mitk::PythonService") << "result of '5+5': " << result.toString().toStdString(); } mitk::PythonService::~PythonService() { - //QVariant result = m_PythonManager.executeString( "sys.getrefcount(cv2)", ctkAbstractPythonManager::EvalInput ); - //MITK_DEBUG("mitk::PythonService") << "sys.getrefcount(cv2): " << result.toString().toStdString(); - - //m_PythonManager.executeString( "del sys.modules[\"cv2\"]", ctkAbstractPythonManager::SingleInput ); - //m_PythonManager.executeString( "del cv2", ctkAbstractPythonManager::SingleInput ); MITK_DEBUG("mitk::PythonService") << "destructing PythonService"; + +#ifdef USE_MITK_BUILTIN_PYTHON + if(pHome) + delete[] pHome; +#endif } std::string mitk::PythonService::Execute(const std::string &stdpythonCommand, int commandType) { QString pythonCommand = QString::fromStdString(stdpythonCommand); + { + MITK_DEBUG("mitk::PythonService") << "pythonCommand = " << pythonCommand.toStdString(); + MITK_DEBUG("mitk::PythonService") << "commandType = " << commandType; + } - { - MITK_DEBUG("mitk::PythonService") << "pythonCommand = " << pythonCommand.toStdString(); - MITK_DEBUG("mitk::PythonService") << "commandType = " << commandType; - } - - QVariant result; - bool commandIssued = true; + QVariant result; + bool commandIssued = true; - if(commandType == IPythonService::SINGLE_LINE_COMMAND ) - result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::SingleInput ); - else if(commandType == IPythonService::MULTI_LINE_COMMAND ) - result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::FileInput ); - else if(commandType == IPythonService::EVAL_COMMAND ) - result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::EvalInput ); - else - commandIssued = false; + if(commandType == IPythonService::SINGLE_LINE_COMMAND ) + result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::SingleInput ); + else if(commandType == IPythonService::MULTI_LINE_COMMAND ) + result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::FileInput ); + else if(commandType == IPythonService::EVAL_COMMAND ) + result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::EvalInput ); + else + commandIssued = false; - if(commandIssued) - { - this->NotifyObserver(pythonCommand.toStdString()); - m_ErrorOccured = PythonQt::self()->hadError(); - } + if(commandIssued) + { + this->NotifyObserver(pythonCommand.toStdString()); + m_ErrorOccured = PythonQt::self()->hadError(); + } - return result.toString().toStdString(); + return result.toString().toStdString(); } void mitk::PythonService::ExecuteScript( const std::string& pythonScript ) { m_PythonManager.executeFile(QString::fromStdString(pythonScript)); } std::vector mitk::PythonService::GetVariableStack() const { - std::vector list; + std::vector list; + + PyObject* dict = PyImport_GetModuleDict(); + PyObject* object = PyDict_GetItemString(dict, "__main__"); + PyObject* dirMain = PyObject_Dir(object); + PyObject* tempObject = 0; + PyObject* strTempObject = 0; - PyObject* dict = PyImport_GetModuleDict(); - PyObject* object = PyDict_GetItemString(dict, "__main__"); - PyObject* dirMain = PyObject_Dir(object); - PyObject* tempObject = 0; - PyObject* strTempObject = 0; + if(dirMain) + { + std::string name, attrValue, attrType; - if(dirMain) + for(int i = 0; iob_type->tp_name; + + strTempObject = PyObject_Repr(tempObject); + if(strTempObject && ( PyUnicode_Check(strTempObject) || PyString_Check(strTempObject) ) ) + attrValue = PyString_AsString(strTempObject); + else + attrValue = ""; - for(int i = 0; iob_type->tp_name; - - strTempObject = PyObject_Repr(tempObject); - if(strTempObject && ( PyUnicode_Check(strTempObject) || PyString_Check(strTempObject) ) ) - attrValue = PyString_AsString(strTempObject); - else - attrValue = ""; - - mitk::PythonVariable var; - var.m_Name = name; - var.m_Value = attrValue; - var.m_Type = attrType; - list.push_back(var); - } + mitk::PythonVariable var; + var.m_Name = name; + var.m_Value = attrValue; + var.m_Type = attrType; + list.push_back(var); } + } - return list; + return list; } bool mitk::PythonService::DoesVariableExist(const std::string& name) const { bool varExists = false; std::vector allVars = this->GetVariableStack(); - for(int i = 0; i< allVars.size(); i++) + for(unsigned int i = 0; i< allVars.size(); i++) { if( allVars.at(i).m_Name == name ) { varExists = true; break; } } return varExists; } void mitk::PythonService::AddPythonCommandObserver(mitk::PythonCommandObserver *observer) { if(!m_Observer.contains(observer)) m_Observer.append(observer); } void mitk::PythonService::RemovePythonCommandObserver(mitk::PythonCommandObserver *observer) { m_Observer.removeOne(observer); } void mitk::PythonService::NotifyObserver(const std::string &command) { MITK_DEBUG("mitk::PythonService") << "number of observer " << m_Observer.size(); - for( size_t i=0; i< m_Observer.size(); ++i ) + for( int i=0; i< m_Observer.size(); ++i ) { m_Observer.at(i)->CommandExecuted(command); } } QString mitk::PythonService::GetTempDataFileName(const std::string& ext) const { QString tmpFolder = QDir::tempPath(); QString fileName = tmpFolder + QDir::separator() + m_TmpDataFileName + QString::fromStdString(ext); return fileName; } -bool mitk::PythonService::CopyToPythonAsItkImage(mitk::Image *image, const std::string &stdvarName) +bool mitk::PythonService::CopyToPythonAsSimpleItkImage(mitk::Image *image, const std::string &stdvarName) { QString varName = QString::fromStdString( stdvarName ); - // save image - QString fileName = this->GetTempDataFileName( mitk::IOUtil::DEFAULTIMAGEEXTENSION ); - fileName = QDir::fromNativeSeparators( fileName ); - - MITK_DEBUG("PythonService") << "Saving temporary file " << fileName.toStdString(); - if( !mitk::IOUtil::SaveImage(image, fileName.toStdString()) ) - { - MITK_ERROR << "Temporary file could not be created."; - } - else + QString command; + unsigned int* imgDim = image->GetDimensions(); + int npy_nd = 1; + npy_intp* npy_dims = new npy_intp[1]; + npy_dims[0] = imgDim[0] * imgDim[1] * imgDim[2]; + // access python module + PyObject *pyMod = PyImport_AddModule((char*)"__main__"); + // global dictionarry + PyObject *pyDict = PyModule_GetDict(pyMod); + const mitk::Vector3D spacing = image->GetGeometry()->GetSpacing(); + const mitk::Point3D origin = image->GetGeometry()->GetOrigin(); + mitk::PixelType pixelType = image->GetPixelType(); + itk::ImageIOBase::IOPixelType ioPixelType = image->GetPixelType().GetPixelType(); + PyObject* npyArray = NULL; + mitk::ImageReadAccessor racc(image); + void* array = (void*) racc.GetData(); + + // default pixeltype: unsigned short + NPY_TYPES npy_type = NPY_USHORT; + std::string sitk_type = "sitkUInt8"; + if( ioPixelType == itk::ImageIOBase::SCALAR ) { - // TODO CORRECT TYPE SETUP, MAKE MITK_DEBUG("PythonService") MITK_DEBUG("PythonService") - int dim = image->GetDimension(); - mitk::PixelType pixelType = image->GetPixelType(); - itk::ImageIOBase::IOPixelType ioPixelType = image->GetPixelType().GetPixelType(); - - // default pixeltype: unsigned short - QString type = "US"; - if( ioPixelType == itk::ImageIOBase::SCALAR ) - { - if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) - type = "D"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) - type = "F"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) - type = "SS"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) - type = "SC"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) - type = "SI"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) - type = "SL"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) - type = "UC"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) - type = "UI"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) - type = "UL"; - else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) - type = "US"; + if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) { + npy_type = NPY_DOUBLE; + sitk_type = "sitkFloat64"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) { + npy_type = NPY_FLOAT; + sitk_type = "sitkFloat32"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) { + npy_type = NPY_SHORT; + sitk_type = "sitkInt16"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) { + npy_type = NPY_BYTE; + sitk_type = "sitkInt8"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) { + npy_type = NPY_INT; + sitk_type = "sitkInt32"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) { + npy_type = NPY_LONG; + sitk_type = "sitkInt64"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) { + npy_type = NPY_UBYTE; + sitk_type = "sitkUInt8"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) { + npy_type = NPY_UINT; + sitk_type = "sitkUInt32"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) { + npy_type = NPY_LONG; + sitk_type = "sitkUInt64"; + } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) { + npy_type = NPY_USHORT; + sitk_type = "sitkUInt16"; } + } else { + MITK_WARN << "not a scalar pixeltype"; + return false; + } - MITK_DEBUG("PythonService") << "Got mitk image with type " << type.toStdString() << " and dim " << dim; - - QString command; - - command.append( QString("imageType = itk.Image[itk.%1, %2]\n") .arg( type ).arg( dim ) ); - - command.append( QString("readerType = itk.ImageFileReader[imageType]\n") ); - command.append( QString("reader = readerType.New()\n") ); - command.append( QString("reader.SetFileName( \"%1\" )\n") .arg(fileName) ); - command.append( QString("reader.Update()\n") ); - command.append( QString("%1 = reader.GetOutput()\n").arg( varName ) ); + // creating numpy array + import_array1 (true); + npyArray = PyArray_SimpleNewFromData(npy_nd,npy_dims,npy_type,array); + + // add temp array it to the python dictionary to access it in python code + const int status = PyDict_SetItemString( pyDict,QString("%1_numpy_array") + .arg(varName).toStdString().c_str(), + npyArray ); + + // sanity check + if ( status != 0 ) + return false; + + command.append( QString("%1 = sitk.Image(%2,%3,%4,sitk.%5)\n").arg(varName) + .arg(QString::number(imgDim[0])) + .arg(QString::number(imgDim[1])) + .arg(QString::number(imgDim[2])) + .arg(QString(sitk_type.c_str())) ); + command.append( QString("%1.SetSpacing([%2,%3,%4])\n").arg(varName) + .arg(QString::number(spacing[0])) + .arg(QString::number(spacing[1])) + .arg(QString::number(spacing[2])) ); + command.append( QString("%1.SetOrigin([%2,%3,%4])\n").arg(varName) + .arg(QString::number(origin[0])) + .arg(QString::number(origin[1])) + .arg(QString::number(origin[2])) ); + // directly access the cpp api from the lib + command.append( QString("_SimpleITK._SetImageFromArray(%1_numpy_array,%1)\n").arg(varName) ); + command.append( QString("del %1_numpy_array").arg(varName) ); - MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); - MITK_INFO << this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); + MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); + this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); - QFile file( fileName ); - MITK_DEBUG("PythonService") << "Removing file " << fileName.toStdString(); - file.remove(); - return true; - } - return false; + return true; } -mitk::Image::Pointer mitk::PythonService::CopyItkImageFromPython(const std::string &stdvarName) +mitk::Image::Pointer mitk::PythonService::CopySimpleItkImageFromPython(const std::string &stdvarName) { + double*ds = NULL; + // access python module + PyObject *pyMod = PyImport_AddModule((char*)"__main__"); + // global dictionarry + PyObject *pyDict = PyModule_GetDict(pyMod); + mitk::Image::Pointer mitkImage = mitk::Image::New(); + mitk::Vector3D spacing; + mitk::Point3D origin; + QString command; QString varName = QString::fromStdString( stdvarName ); - mitk::Image::Pointer mitkImage; - QString command; - QString fileName = GetTempDataFileName( mitk::IOUtil::DEFAULTIMAGEEXTENSION ); - fileName = QDir::fromNativeSeparators( fileName ); - MITK_DEBUG("PythonService") << "Saving temporary file with python itk code " << fileName.toStdString(); + command.append( QString("%1_numpy_array = sitk.GetArrayFromImage(%1)\n").arg(varName) ); + command.append( QString("%1_spacing = numpy.asarray(%1.GetSpacing())\n").arg(varName) ); + command.append( QString("%1_origin = numpy.asarray(%1.GetOrigin())\n").arg(varName) ); + command.append( QString("%1_dtype = %1_numpy_array.dtype.name").arg(varName) ); - command.append( QString( "writer = itk.ImageFileWriter[ %1 ].New()\n").arg( varName ) ); - command.append( QString( "writer.SetFileName( \"%1\" )\n").arg(fileName) ); - command.append( QString( "writer.SetInput( %1 )\n").arg(varName) ); - command.append( QString( "writer.Update()\n" ) ); + MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); + this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); - MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); - this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); + PyObject* py_dtype = PyDict_GetItemString(pyDict,QString("%1_dtype").arg(varName).toStdString().c_str() ); + std::string dtype = PyString_AsString(py_dtype); + PyArrayObject* py_data = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_numpy_array").arg(varName).toStdString().c_str() ); + PyArrayObject* py_spacing = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_spacing").arg(varName).toStdString().c_str() ); + PyArrayObject* py_origin = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_origin").arg(varName).toStdString().c_str() ); + + size_t sz = sizeof(short); + mitk::PixelType pixelType = MakeScalarPixelType(); + if( dtype.compare("float64") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(double); + } else if( dtype.compare("float32") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(float); + } else if( dtype.compare("int16") == 0) { + pixelType = MakeScalarPixelType(); + sz = sizeof(short); + } else if( dtype.compare("int8") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(char); + } else if( dtype.compare("int32") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(int); + } else if( dtype.compare("int64") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(long); + } else if( dtype.compare("uint8") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(unsigned char); + } else if( dtype.compare("uint32") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(unsigned int); + } else if( dtype.compare("uint64") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(unsigned long); + } else if( dtype.compare("uint16") == 0 ) { + pixelType = MakeScalarPixelType(); + sz = sizeof(unsigned short); + } - try - { - MITK_DEBUG("PythonService") << "Loading temporary file " << fileName.toStdString() << " as MITK image"; - mitkImage = mitk::IOUtil::LoadImage( fileName.toStdString() ); - } - catch(std::exception& e) - { - MITK_ERROR << e.what(); - } + unsigned int* dimensions = new unsigned int[py_data->nd]; + // fill backwards , nd data saves dimensions in opposite direction + for( int i = 0; i < py_data->nd; ++i ) + { + dimensions[i] = py_data->dimensions[py_data->nd - 1 - i]; + sz *= dimensions[i]; + } - QFile file(fileName); - if( file.exists() ) - { - MITK_DEBUG("PythonService") << "Removing temporary file " << fileName.toStdString(); - file.remove(); - } + mitkImage->Initialize(pixelType, py_data->nd, dimensions); + mitkImage->SetChannel(py_data->data); + + ds = (double*)py_spacing->data; + spacing[0] = ds[0]; + spacing[1] = ds[1]; + spacing[2] = ds[2]; + mitkImage->GetGeometry()->SetSpacing(spacing); + + ds = (double*)py_origin->data; + origin[0] = ds[0]; + origin[1] = ds[1]; + origin[2] = ds[2]; + mitkImage->GetGeometry()->SetOrigin(origin); + + // cleanup + command.clear(); + command.append( QString("del %1_numpy_array\n").arg(varName) ); + command.append( QString("del %1_dtype\n").arg(varName) ); + command.append( QString("del %1_spacing\n").arg(varName) ); + command.append( QString("del %1_origin").arg(varName) ); + MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); + this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); + + delete[] dimensions; - return mitkImage; + return mitkImage; } bool mitk::PythonService::CopyToPythonAsCvImage( mitk::Image* image, const std::string& stdvarName ) { QString varName = QString::fromStdString( stdvarName ); bool convert = false; if(image->GetDimension() != 2) { MITK_ERROR << "Only 2D images allowed for OpenCV images"; return convert; } // try to save mitk image QString fileName = this->GetTempDataFileName( ".bmp" ); fileName = QDir::fromNativeSeparators( fileName ); MITK_DEBUG("PythonService") << "Saving temporary file " << fileName.toStdString(); if( !mitk::IOUtil::SaveImage(image, fileName.toStdString()) ) { MITK_ERROR << "Temporary file " << fileName.toStdString() << " could not be created."; return convert; } QString command; command.append( QString("%1 = cv2.imread(\"%2\")\n") .arg( varName ).arg( fileName ) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); MITK_DEBUG("PythonService") << "Removing file " << fileName.toStdString(); QFile file(fileName); file.remove(); convert = true; return convert; } mitk::Image::Pointer mitk::PythonService::CopyCvImageFromPython( const std::string& stdvarName ) { QString varName = QString::fromStdString( stdvarName ); mitk::Image::Pointer mitkImage; QString command; QString fileName = GetTempDataFileName( ".bmp" ); fileName = QDir::fromNativeSeparators( fileName ); MITK_DEBUG("PythonService") << "run python command to save image with opencv to " << fileName.toStdString(); command.append( QString( "cv2.imwrite(\"%1\", %2)\n").arg( fileName ).arg( varName ) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); try { MITK_DEBUG("PythonService") << "Loading temporary file " << fileName.toStdString() << " as MITK image"; mitkImage = mitk::IOUtil::LoadImage( fileName.toStdString() ); } catch(std::exception& e) { MITK_ERROR << e.what(); } QFile file(fileName); if( file.exists() ) { MITK_DEBUG("PythonService") << "Removing temporary file " << fileName.toStdString(); file.remove(); } return mitkImage; } ctkAbstractPythonManager *mitk::PythonService::GetPythonManager() { return &m_PythonManager; } mitk::Surface::Pointer mitk::PythonService::CopyVtkPolyDataFromPython( const std::string& stdvarName ) { - QString varName = QString::fromStdString( stdvarName ); - mitk::Surface::Pointer newSurface; - + // access python module + PyObject *pyMod = PyImport_AddModule((char*)"__main__"); + // global dictionarry + PyObject *pyDict = PyModule_GetDict(pyMod); + // python memory address + PyObject *pyAddr = NULL; + // cpp address + size_t addr = 0; + mitk::Surface::Pointer surface = mitk::Surface::New(); QString command; - QString fileName = GetTempDataFileName( ".stl" ); - fileName = QDir::fromNativeSeparators( fileName ); + QString varName = QString::fromStdString( stdvarName ); - MITK_DEBUG("PythonService") << "run python command to save polydata with vtk to " << fileName.toStdString(); - command = QString ( - "vtkStlWriter = vtk.vtkSTLWriter()\n" - "vtkStlWriter.SetInput(%1)\n" - "vtkStlWriter.SetFileName(\"%2\")\n" - "vtkStlWriter.Write()\n").arg(varName).arg(fileName); + command.append( QString("%1_addr_str = %1.GetAddressAsString(\"vtkPolyData\")\n").arg(varName) ); + // remove 0x from the address + command.append( QString("%1_addr = int(%1_addr_str[5:],16)").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); - try - { - MITK_DEBUG("PythonService") << "Loading temporary file " << fileName.toStdString() << " as MITK Surface"; - newSurface = mitk::IOUtil::LoadSurface( fileName.toStdString() ); - } - catch(std::exception& e) - { - MITK_ERROR << e.what(); - } + // get address of the object + pyAddr = PyDict_GetItemString(pyDict,QString("%1_addr").arg(varName).toStdString().c_str()); - QFile file(fileName); - if( file.exists() ) - { - MITK_DEBUG("PythonService") << "Removing temporary file " << fileName.toStdString(); - file.remove(); - } + // convert to long + addr = PyInt_AsLong(pyAddr); + + MITK_DEBUG << "Python object address: " << addr; + + // get the object + vtkPolyData* poly = (vtkPolyData*)((void*)addr); + surface->SetVtkPolyData(poly); + + // delete helper variables from python stack + command = ""; + command.append( QString("del %1_addr_str\n").arg(varName) ); + command.append( QString("del %1_addr").arg(varName) ); + + MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); + this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); - return newSurface; + return surface; } bool mitk::PythonService::CopyToPythonAsVtkPolyData( mitk::Surface* surface, const std::string& stdvarName ) { QString varName = QString::fromStdString( stdvarName ); - bool convert = false; + std::ostringstream oss; + std::string addr = ""; + QString command; + QString address; - // try to save mitk image - QString fileName = this->GetTempDataFileName( ".stl" ); - fileName = QDir::fromNativeSeparators( fileName ); - MITK_DEBUG("PythonService") << "Saving temporary file " << fileName.toStdString(); - if( !mitk::IOUtil::SaveSurface( surface, fileName.toStdString() ) ) - { - MITK_ERROR << "Temporary file " << fileName.toStdString() << " could not be created."; - return convert; - } + oss << (void*) ( surface->GetVtkPolyData() ); - QString command; + // get the address + addr = oss.str(); + + // remove "0x" + address = QString::fromStdString(addr.substr(2)); + + command.append( QString("%1 = vtk.vtkPolyData(\"%2\")\n").arg(varName).arg(address) ); - command.append( QString("vtkStlReader = vtk.vtkSTLReader()\n") ); - command.append( QString("vtkStlReader.SetFileName(\"%1\")\n").arg( fileName ) ); - command.append( QString("vtkStlReader.Update()\n") ); - command.append( QString("%1 = vtkStlReader.GetOutput()\n").arg( varName ) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); - MITK_DEBUG("PythonService") << "Removing file " << fileName.toStdString(); - QFile file(fileName); - file.remove(); - convert = true; - return convert; + return true; } -bool mitk::PythonService::IsItkPythonWrappingAvailable() +bool mitk::PythonService::IsSimpleItkPythonWrappingAvailable() { - this->Execute( "import itk\n", IPythonService::SINGLE_LINE_COMMAND ); - this->Execute( "print \"Using ITK version \" + itk.Version.GetITKVersion()\n", IPythonService::SINGLE_LINE_COMMAND ); + this->Execute( "import SimpleITK as sitk\n", IPythonService::SINGLE_LINE_COMMAND ); + // directly access cpp lib + this->Execute( "import _SimpleITK\n", IPythonService::SINGLE_LINE_COMMAND ); + m_ItkWrappingAvailable = !this->PythonErrorOccured(); + + // check for numpy + this->Execute( "import numpy\n", IPythonService::SINGLE_LINE_COMMAND ); + + if ( this->PythonErrorOccured() ) + MITK_ERROR << "Numpy not found."; m_ItkWrappingAvailable = !this->PythonErrorOccured(); return m_ItkWrappingAvailable; } bool mitk::PythonService::IsOpenCvPythonWrappingAvailable() { this->Execute( "import cv2\n", IPythonService::SINGLE_LINE_COMMAND ); m_OpenCVWrappingAvailable = !this->PythonErrorOccured(); return m_OpenCVWrappingAvailable; } bool mitk::PythonService::IsVtkPythonWrappingAvailable() { this->Execute( "import vtk", IPythonService::SINGLE_LINE_COMMAND ); - this->Execute( "print \"Using VTK version \" + vtk.vtkVersion.GetVTKVersion()\n", IPythonService::SINGLE_LINE_COMMAND ); + //this->Execute( "print \"Using VTK version \" + vtk.vtkVersion.GetVTKVersion()\n", IPythonService::SINGLE_LINE_COMMAND ); m_VtkWrappingAvailable = !this->PythonErrorOccured(); return m_VtkWrappingAvailable; } bool mitk::PythonService::PythonErrorOccured() const { return m_ErrorOccured; } diff --git a/Modules/Python/mitkPythonService.h b/Modules/Python/mitkPythonService.h index a566b8214d..37f1b34d0d 100644 --- a/Modules/Python/mitkPythonService.h +++ b/Modules/Python/mitkPythonService.h @@ -1,105 +1,105 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkPythonService_h #define mitkPythonService_h #include "mitkIPythonService.h" #include #include #include "mitkSurface.h" #include namespace mitk { /// /// implementation of the IPythonService using ctkabstractpythonmanager /// \see IPythonService class MITK_PYTHON_EXPORT PythonService: public itk::LightObject, public mitk::IPythonService { public: /// /// instantiate python manager here PythonService(); /// /// empty implementation... ~PythonService(); /// /// \see IPythonService::Execute() std::string Execute( const std::string& pythonCommand, int commandType = SINGLE_LINE_COMMAND ); /// /// \see IPythonService::ExecuteScript() void ExecuteScript(const std::string &pathToPythonScript); /// /// \see IPythonService::PythonErrorOccured() bool PythonErrorOccured() const; /// /// \see IPythonService::GetVariableStack() std::vector GetVariableStack() const; /// /// \see IPythonService::DoesVariableExist() bool DoesVariableExist(const std::string& name) const; /// /// \see IPythonService::AddPythonCommandObserver() void AddPythonCommandObserver( PythonCommandObserver* observer ); /// /// \see IPythonService::RemovePythonCommandObserver() void RemovePythonCommandObserver( PythonCommandObserver* observer ); /// /// \see IPythonService::NotifyObserver() void NotifyObserver( const std::string& command ); /// /// \see IPythonService::IsItkPythonWrappingAvailable() - bool IsItkPythonWrappingAvailable(); + bool IsSimpleItkPythonWrappingAvailable(); /// /// \see IPythonService::CopyToPythonAsItkImage() - bool CopyToPythonAsItkImage( mitk::Image* image, const std::string& varName ); + bool CopyToPythonAsSimpleItkImage( mitk::Image* image, const std::string& varName ); /// /// \see IPythonService::CopyItkImageFromPython() - mitk::Image::Pointer CopyItkImageFromPython( const std::string& varName ); + mitk::Image::Pointer CopySimpleItkImageFromPython( const std::string& varName ); /// /// \see IPythonService::IsOpenCvPythonWrappingAvailable() bool IsOpenCvPythonWrappingAvailable(); /// /// \see IPythonService::CopyToPythonAsCvImage() bool CopyToPythonAsCvImage( mitk::Image* image, const std::string& varName ); /// /// \see IPythonService::CopyCvImageFromPython() mitk::Image::Pointer CopyCvImageFromPython( const std::string& varName ); /// /// \see IPythonService::IsVtkPythonWrappingAvailable() bool IsVtkPythonWrappingAvailable(); /// /// \see IPythonService::CopyToPythonAsVtkPolyData() bool CopyToPythonAsVtkPolyData( mitk::Surface* surface, const std::string& varName ); /// /// \see IPythonService::CopyVtkPolyDataFromPython() mitk::Surface::Pointer CopyVtkPolyDataFromPython( const std::string& varName ); /// /// \return the ctk abstract python manager instance ctkAbstractPythonManager* GetPythonManager(); protected: QString GetTempDataFileName(const std::string &ext) const; private: QList m_Observer; ctkAbstractPythonManager m_PythonManager; static const QString m_TmpDataFileName; bool m_ItkWrappingAvailable; bool m_OpenCVWrappingAvailable; bool m_VtkWrappingAvailable; bool m_ErrorOccured; }; } #endif diff --git a/Modules/Python/resources/PythonSnippets.xml b/Modules/Python/resources/PythonSnippets.xml index a301307dd3..7e8a1bcb5d 100644 --- a/Modules/Python/resources/PythonSnippets.xml +++ b/Modules/Python/resources/PythonSnippets.xml @@ -1,7 +1,7 @@ - - + + diff --git a/Plugins/org.mitk.gui.qt.python/documentation/UserManual/MitkPythonPluginView.png b/Plugins/org.mitk.gui.qt.python/documentation/UserManual/MitkPythonPluginView.png new file mode 100644 index 0000000000..befab56719 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.python/documentation/UserManual/MitkPythonPluginView.png differ diff --git a/Plugins/org.mitk.gui.qt.python/documentation/UserManual/QmitkPython.dox b/Plugins/org.mitk.gui.qt.python/documentation/UserManual/QmitkPython.dox index d1ab3c52fe..0696c4eed9 100644 --- a/Plugins/org.mitk.gui.qt.python/documentation/UserManual/QmitkPython.dox +++ b/Plugins/org.mitk.gui.qt.python/documentation/UserManual/QmitkPython.dox @@ -1,10 +1,35 @@ /** \page org_mitk_gui_qt_python The Python Plugin Available sections: - \ref org_mitk_gui_qt_pythonOverview + - \ref org_mitk_gui_qt_pythonUsage + - \ref org_mitk_gui_qt_PythonConsole + - \ref org_mitk_gui_qt_PythonSnippets \section org_mitk_gui_qt_pythonOverview Overview The Python view provides the graphical front end to run Python code through the mitkPython module. Furthermore the ITK/VTK/OpenCV Python wrapping can be used. +Images and surfaces in the DataManager can be transferred via a drag & drop mechanism into the MITK Python Console. + +\section org_mitk_gui_qt_pythonUsage Transfer data +Images and surfaces can be tranferred from the data manger into the python console. To transfer an image or +surface simply drag it from the data manager into the Variable Stack view, as shown in Figure. +A new entry will appear in the Variable Stack, as soon as the data is transferred. As soon as the +entry is available the object can be accessed and modified in the python console. Three dimensional +images will be copied in-memory to python via numpy and a SimpleITK image object is created with the +same properties. When a two dimensional image is transferred the user can choose to transfer it as an OpenCV +image object. Surfaces are fully memory mapped as a vtkPolyData object. To transfer an image or surface +from the python runtime to the data manager just double click on the corresponding entry in the Variable Stack View. + +\imageMacro{QmitkPythonView.png,"Screenshot of the MITK Python Plugin",20} + +\section org_mitk_gui_qt_PythonConsole +The Python console can be used for interactive programming. All items in the data storage can be accessed +in the python console. The console can also be used to load python scripts and run them. + +\section org_mitk_gui_qt_PythonSnippets +The python plugin contains some code snippets of SimpleITK/VTK/OpenCV that can be run in the python console. +Snippets can be modified and saved by the user. + */ diff --git a/SuperBuild.cmake b/SuperBuild.cmake index bf9eaecd94..c314290dca 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -1,454 +1,483 @@ #----------------------------------------------------------------------------- # Convenient macro allowing to download a file #----------------------------------------------------------------------------- macro(downloadFile url dest) file(DOWNLOAD ${url} ${dest} STATUS status) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") endif() endmacro() #----------------------------------------------------------------------------- # MITK Prerequisites #----------------------------------------------------------------------------- if(UNIX AND NOT APPLE) include(mitkFunctionCheckPackageHeader) # Check for libxt-dev mitkFunctionCheckPackageHeader(StringDefs.h libxt-dev /usr/include/X11/) # Check for libtiff4-dev mitkFunctionCheckPackageHeader(tiff.h libtiff4-dev) # Check for libwrap0-dev mitkFunctionCheckPackageHeader(tcpd.h libwrap0-dev) endif() #----------------------------------------------------------------------------- # Qt options for external projects and MITK #----------------------------------------------------------------------------- if(MITK_USE_QT) set(qt_project_args -DDESIRED_QT_VERSION:STRING=${DESIRED_QT_VERSION}) else() set(qt_project_args ) endif() if(MITK_USE_Qt4) list(APPEND qt_project_args -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() #----------------------------------------------------------------------------- # ExternalProjects #----------------------------------------------------------------------------- set(external_projects + ZLIB + Python + Numpy tinyxml GLUT ANN CppUnit GLEW VTK ACVD GDCM - CableSwig OpenCV Poco ITK Boost DCMTK CTK SOFA MITKData Qwt + PCRE + Swig + SimpleITK ) # Qxt supports Qt5. We need to also support it in QxtCMakeLists.txt #if(MITK_USE_Qt4) list(APPEND external_projects Qxt) #endif() # These are "hard" dependencies and always set to ON set(MITK_USE_tinyxml 1) set(MITK_USE_ANN 1) set(MITK_USE_GLEW 1) set(MITK_USE_GDCM 1) set(MITK_USE_ITK 1) set(MITK_USE_VTK 1) # Semi-hard dependencies, enabled by user-controlled variables -set(MITK_USE_CableSwig ${MITK_USE_Python}) if(MITK_USE_QT) set(MITK_USE_Qwt 1) #if(MITK_USE_Qt4) set(MITK_USE_Qxt 1) #TODO: Check how Qxt builds with Qt 5 #endif() endif() if(MITK_USE_SOFA) set(MITK_USE_GLUT 1) endif() +if(NOT MITK_USE_SYSTEM_PYTHON) + set(MITK_USE_ZLIB 1) +endif() + +if(MITK_USE_SimpleITK OR MITK_USE_Python) + set(MITK_USE_SWIG 1) + if(UNIX) + set(MITK_USE_PCRE 1) + endif() +endif() + # A list of "nice" external projects, playing well together with CMake set(nice_external_projects ${external_projects}) list(REMOVE_ITEM nice_external_projects Boost) foreach(proj ${nice_external_projects}) if(MITK_USE_${proj}) set(EXTERNAL_${proj}_DIR "${${proj}_DIR}" CACHE PATH "Path to ${proj} build directory") mark_as_advanced(EXTERNAL_${proj}_DIR) if(EXTERNAL_${proj}_DIR) set(${proj}_DIR ${EXTERNAL_${proj}_DIR}) endif() endif() endforeach() if(MITK_USE_Boost) set(EXTERNAL_BOOST_ROOT "${BOOST_ROOT}" CACHE PATH "Path to Boost directory") mark_as_advanced(EXTERNAL_BOOST_ROOT) if(EXTERNAL_BOOST_ROOT) set(BOOST_ROOT ${EXTERNAL_BOOST_ROOT}) endif() endif() # Setup file for setting custom ctest vars configure_file( CMake/SuperbuildCTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) if(BUILD_TESTING) set(EXTERNAL_MITK_DATA_DIR "${MITK_DATA_DIR}" CACHE PATH "Path to the MITK data directory") mark_as_advanced(EXTERNAL_MITK_DATA_DIR) if(EXTERNAL_MITK_DATA_DIR) set(MITK_DATA_DIR ${EXTERNAL_MITK_DATA_DIR}) endif() endif() # Look for git early on, if needed if((BUILD_TESTING AND NOT EXTERNAL_MITK_DATA_DIR) OR (MITK_USE_CTK AND NOT EXTERNAL_CTK_DIR)) find_package(Git REQUIRED) endif() #----------------------------------------------------------------------------- # External project settings #----------------------------------------------------------------------------- include(ExternalProject) set(ep_base "${CMAKE_BINARY_DIR}/CMakeExternals") set_property(DIRECTORY PROPERTY EP_BASE ${ep_base}) set(ep_install_dir ${ep_base}/Install) #set(ep_build_dir ${ep_base}/Build) set(ep_source_dir ${ep_base}/Source) #set(ep_parallelism_level) set(ep_build_shared_libs ON) set(ep_build_testing OFF) if(NOT MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL) set(MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL http://mitk.org/download/thirdparty) endif() # Compute -G arg for configuring external projects with the same CMake generator: if(CMAKE_EXTRA_GENERATOR) set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") else() set(gen "${CMAKE_GENERATOR}") endif() # Use this value where semi-colons are needed in ep_add args: set(sep "^^") ## if(MSVC_VERSION) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP") endif() set(ep_common_args -DBUILD_TESTING:BOOL=${ep_build_testing} -DCMAKE_INSTALL_PREFIX:PATH=${ep_install_dir} -DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH} -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} -DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} #debug flags -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} #release flags -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} #relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} #link flags -DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ) # Pass the CMAKE_OSX variables to external projects if(APPLE) set(MAC_OSX_ARCHITECTURE_ARGS -DCMAKE_OSX_ARCHITECTURES:PATH=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET:PATH=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} ) set(ep_common_args ${MAC_OSX_ARCHITECTURE_ARGS} ${ep_common_args} ) endif() # Include external projects foreach(p ${external_projects}) include(CMakeExternals/${p}.cmake) endforeach() #----------------------------------------------------------------------------- # Set superbuild boolean args #----------------------------------------------------------------------------- set(mitk_cmake_boolean_args BUILD_SHARED_LIBS WITH_COVERAGE BUILD_TESTING MITK_USE_QT MITK_BUILD_ALL_PLUGINS MITK_BUILD_ALL_APPS MITK_BUILD_TUTORIAL # Deprecated. Use MITK_BUILD_EXAMPLES instead MITK_BUILD_EXAMPLES MITK_USE_ACVD MITK_USE_CppUnit MITK_USE_GLEW MITK_USE_Boost MITK_USE_SYSTEM_Boost MITK_USE_BLUEBERRY MITK_USE_CTK MITK_USE_DCMTK MITK_USE_OpenCV MITK_USE_Poco MITK_USE_SOFA MITK_USE_Python MITK_USE_OpenCL MITK_ENABLE_PIC_READER ) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(mitk_superbuild_boolean_args) foreach(mitk_cmake_arg ${mitk_cmake_boolean_args}) list(APPEND mitk_superbuild_boolean_args -D${mitk_cmake_arg}:BOOL=${${mitk_cmake_arg}}) endforeach() if(MITK_BUILD_ALL_PLUGINS) list(APPEND mitk_superbuild_boolean_args -DBLUEBERRY_BUILD_ALL_PLUGINS:BOOL=ON) endif() #----------------------------------------------------------------------------- # MITK Utilities #----------------------------------------------------------------------------- set(proj MITK-Utilities) ExternalProject_Add(${proj} DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS # Mandatory dependencies ${tinyxml_DEPENDS} ${ANN_DEPENDS} ${VTK_DEPENDS} ${ITK_DEPENDS} # Optionnal dependencies ${ACVD_DEPENDS} ${CppUnit_DEPENDS} ${GLUT_DEPENDS} ${GLEW_DEPENDS} ${Boost_DEPENDS} ${CTK_DEPENDS} ${DCMTK_DEPENDS} ${OpenCV_DEPENDS} ${Poco_DEPENDS} ${SOFA_DEPENDS} ${MITK-Data_DEPENDS} ${Qwt_DEPENDS} ${Qxt_DEPENDS} + ${SimpleITK_DEPENDS} + ${Numpy_DEPENDS} ) #----------------------------------------------------------------------------- # Additional MITK CXX/C Flags #----------------------------------------------------------------------------- set(MITK_ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_RELEASE "" CACHE STRING "Additional Release C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_DEBUG "" CACHE STRING "Additional Debug C Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_C_FLAGS MITK_ADDITIONAL_C_FLAGS_DEBUG MITK_ADDITIONAL_C_FLAGS_RELEASE) set(MITK_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_RELEASE "" CACHE STRING "Additional Release CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_DEBUG "" CACHE STRING "Additional Debug CXX Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_CXX_FLAGS MITK_ADDITIONAL_CXX_FLAGS_DEBUG MITK_ADDITIONAL_CXX_FLAGS_RELEASE) set(MITK_ADDITIONAL_EXE_LINKER_FLAGS "" CACHE STRING "Additional exe linker flags for MITK") set(MITK_ADDITIONAL_SHARED_LINKER_FLAGS "" CACHE STRING "Additional shared linker flags for MITK") set(MITK_ADDITIONAL_MODULE_LINKER_FLAGS "" CACHE STRING "Additional module linker flags for MITK") mark_as_advanced(MITK_ADDITIONAL_EXE_LINKER_FLAGS MITK_ADDITIONAL_SHARED_LINKER_FLAGS MITK_ADDITIONAL_MODULE_LINKER_FLAGS) #----------------------------------------------------------------------------- # MITK Configure #----------------------------------------------------------------------------- if(MITK_INITIAL_CACHE_FILE) set(mitk_initial_cache_arg -C "${MITK_INITIAL_CACHE_FILE}") endif() set(mitk_optional_cache_args ) foreach(type RUNTIME ARCHIVE LIBRARY) if(DEFINED CTK_PLUGIN_${type}_OUTPUT_DIRECTORY) list(APPEND mitk_optional_cache_args -DCTK_PLUGIN_${type}_OUTPUT_DIRECTORY:PATH=${CTK_PLUGIN_${type}_OUTPUT_DIRECTORY}) endif() endforeach() # Optional python variables if(MITK_USE_Python) + list(APPEND mitk_optional_cache_args + -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} + -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} + -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} + -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} + -DMITK_USE_SYSTEM_PYTHON:BOOL=${MITK_USE_SYSTEM_PYTHON} + -DMITK_BUILD_org.mitk.gui.qt.python:BOOL=ON + ) + if( NOT MITK_USE_SYSTEM_PYTHON ) list(APPEND mitk_optional_cache_args - -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} - -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} - -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} - -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} ) + # Folders are needed to create an installer + -DPython_DIR:PATH=${Python_DIR} + -DNumpy_DIR:PATH=${Numpy_DIR} + ) + endif() endif() set(proj MITK-Configure) ExternalProject_Add(${proj} LIST_SEPARATOR ^^ DOWNLOAD_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_CACHE_ARGS # --------------- Build options ---------------- -DBUILD_TESTING:BOOL=${ep_build_testing} -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/MITK-build/install -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} # --------------- Compile options ---------------- -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} ${MITK_ADDITIONAL_C_FLAGS}" "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${MITK_ADDITIONAL_CXX_FLAGS}" # debug flags "-DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} ${MITK_ADDITIONAL_CXX_FLAGS_DEBUG}" "-DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} ${MITK_ADDITIONAL_C_FLAGS_DEBUG}" # release flags "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} ${MITK_ADDITIONAL_CXX_FLAGS_RELEASE}" "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} ${MITK_ADDITIONAL_C_FLAGS_RELEASE}" # relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} # link flags "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} ${MITK_ADDITIONAL_EXE_LINKER_FLAGS}" "-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} ${MITK_ADDITIONAL_SHARED_LINKER_FLAGS}" "-DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ${MITK_ADDITIONAL_MODULE_LINKER_FLAGS}" # Output directories -DMITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY} -DMITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY} -DMITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY} # ------------- Boolean build options -------------- ${mitk_superbuild_boolean_args} ${mitk_optional_cache_args} -DMITK_USE_SUPERBUILD:BOOL=OFF -DMITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION} -DCTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} # ----------------- Miscellaneous --------------- -DMITK_CTEST_SCRIPT_MODE:STRING=${MITK_CTEST_SCRIPT_MODE} -DMITK_SUPERBUILD_BINARY_DIR:PATH=${MITK_BINARY_DIR} -DMITK_MODULES_TO_BUILD:INTERNAL=${MITK_MODULES_TO_BUILD} ${qt_project_args} -DMITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES} -DMITK_ACCESSBYITK_FLOATING_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES} -DMITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES} -DMITK_ACCESSBYITK_VECTOR_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} -DMITK_ACCESSBYITK_DIMENSIONS:STRING=${MITK_ACCESSBYITK_DIMENSIONS} # --------------- External project dirs --------------- -DMITK_KWSTYLE_EXECUTABLE:FILEPATH=${MITK_KWSTYLE_EXECUTABLE} -DCTK_DIR:PATH=${CTK_DIR} -DDCMTK_DIR:PATH=${DCMTK_DIR} -Dtinyxml_DIR:PATH=${tinyxml_DIR} -DGLUT_DIR:PATH=${GLUT_DIR} -DGLEW_DIR:PATH=${GLEW_DIR} -DANN_DIR:PATH=${ANN_DIR} -DCppUnit_DIR:PATH=${CppUnit_DIR} -DVTK_DIR:PATH=${VTK_DIR} # FindVTK expects VTK_DIR -DITK_DIR:PATH=${ITK_DIR} # FindITK expects ITK_DIR -DACVD_DIR:PATH=${ACVD_DIR} -DOpenCV_DIR:PATH=${OpenCV_DIR} -DPoco_DIR:PATH=${Poco_DIR} -DSOFA_DIR:PATH=${SOFA_DIR} -DGDCM_DIR:PATH=${GDCM_DIR} -DBOOST_ROOT:PATH=${BOOST_ROOT} -DMITK_USE_Boost_LIBRARIES:STRING=${MITK_USE_Boost_LIBRARIES} -DMITK_DATA_DIR:PATH=${MITK_DATA_DIR} -DQwt_DIR:PATH=${Qwt_DIR} -DQxt_DIR:PATH=${Qxt_DIR} + -DSimpleITK_DIR:PATH=${SimpleITK_DIR} + -DNumpy_DIR:PATH=${Numpy_DIR} CMAKE_ARGS ${mitk_initial_cache_arg} ${MAC_OSX_ARCHITECTURE_ARGS} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} BINARY_DIR ${CMAKE_BINARY_DIR}/MITK-build BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS MITK-Utilities ) #----------------------------------------------------------------------------- # MITK #----------------------------------------------------------------------------- if(CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(mitk_build_cmd "$(MAKE)") else() set(mitk_build_cmd ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/MITK-build --config ${CMAKE_CFG_INTDIR}) endif() if(NOT DEFINED SUPERBUILD_EXCLUDE_MITKBUILD_TARGET OR NOT SUPERBUILD_EXCLUDE_MITKBUILD_TARGET) set(MITKBUILD_TARGET_ALL_OPTION "ALL") else() set(MITKBUILD_TARGET_ALL_OPTION "") endif() add_custom_target(MITK-build ${MITKBUILD_TARGET_ALL_OPTION} COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build DEPENDS MITK-Configure ) #----------------------------------------------------------------------------- # Custom target allowing to drive the build of the MITK project itself #----------------------------------------------------------------------------- add_custom_target(MITK COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build )