diff --git a/CMake/FindNumpy.cmake b/CMake/FindNumpy.cmake index 23f58bc0ae..548ece47c8 100644 --- a/CMake/FindNumpy.cmake +++ b/CMake/FindNumpy.cmake @@ -1,38 +1,31 @@ # Variables set by this script # NUMPY_FOUND # NUMPY_INCLUDE_DIR find_package(PackageHandleStandardArgs) -if(DEFINED Numpy_DIR AND EXISTS ${Numpy_DIR}) - set(NUMPY_INCLUDE_DIR ${Numpy_DIR}/core/include) - MESSAGE("NUMPY_DIR: " ${Numpy_DIR}) - MESSAGE("NUMPY_INCLUDE_DIR: " ${NUMPY_INCLUDE_DIR}) - MESSAGE("PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) -else() - # search for the runtime if it's not already set - if( NOT DEFINED PYTHON_EXECUTABLE ) - FIND_PACKAGE(PythonLibs REQUIRED) - FIND_PACKAGE(PythonInterp REQUIRED) - endif() +# search for the runtime if it's not already set +if( NOT DEFINED PYTHON_EXECUTABLE ) + FIND_PACKAGE(PythonLibs REQUIRED) + FIND_PACKAGE(PythonInterp REQUIRED) +endif() - set(_python ${PYTHON_EXECUTABLE}) - if(UNIX) - STRING(REPLACE " " "\ " _python ${PYTHON_EXECUTABLE}) - endif() +set(_python ${PYTHON_EXECUTABLE}) +if(UNIX) + STRING(REPLACE " " "\ " _python ${PYTHON_EXECUTABLE}) +endif() - execute_process ( - COMMAND ${_python} -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 +execute_process ( + COMMAND ${_python} -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() +if(DEFINED output AND EXISTS ${output} ) + set (NUMPY_INCLUDE_DIR ${output}) endif() FIND_PACKAGE_HANDLE_STANDARD_ARGS(Numpy DEFAULT_MSG NUMPY_INCLUDE_DIR) MARK_AS_ADVANCED ( NUMPY_INCLUDE_DIR ) diff --git a/CMake/PackageDepends/MITK_Numpy_Config.cmake b/CMake/PackageDepends/MITK_Numpy_Config.cmake index f75fdca6bc..d9a3c21c51 100644 --- a/CMake/PackageDepends/MITK_Numpy_Config.cmake +++ b/CMake/PackageDepends/MITK_Numpy_Config.cmake @@ -1,2 +1 @@ list(APPEND ALL_INCLUDE_DIRECTORIES ${NUMPY_INCLUDE_DIR}) - diff --git a/CMake/PackageDepends/MITK_PythonLibs_Config.cmake b/CMake/PackageDepends/MITK_PythonLibs_Config.cmake index 373feb7aef..bbf23330e3 100644 --- a/CMake/PackageDepends/MITK_PythonLibs_Config.cmake +++ b/CMake/PackageDepends/MITK_PythonLibs_Config.cmake @@ -1,3 +1,5 @@ list(APPEND ALL_LIBRARIES ${PYTHON_LIBRARIES}) list(APPEND ALL_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_DIRS}) - +if(MITK_USE_Numpy) + include(${CMAKE_CURRENT_LIST_DIR}/MITK_Numpy_Config.cmake) +endif() diff --git a/CMake/mitkFunctionExternalPythonBuildStep.cmake b/CMake/mitkFunctionExternalPythonBuildStep.cmake index 303429bca3..3c96507c61 100644 --- a/CMake/mitkFunctionExternalPythonBuildStep.cmake +++ b/CMake/mitkFunctionExternalPythonBuildStep.cmake @@ -1,49 +1,54 @@ #! 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}") set(_workdir "${_bin_dir}/ep/src/${proj}") set(_prefixdir "${_bin_dir}/ep/tmp") set(_python "${_python_executable}") foreach(_dir "${_workdir}" "${_prefixdir}") if(NOT EXISTS "${_dir}") message(SEND_ERROR "The directory ${_dir} does not exist") endif() endforeach() # escape spaces if(UNIX) STRING(REPLACE " " "\ " _workdir ${_workdir}) STRING(REPLACE " " "\ " _prefixdir ${_prefixdir}) STRING(REPLACE " " "\ " _python ${_python}) endif() execute_process( COMMAND ${_python} ${_command} WORKING_DIRECTORY ${_workdir} RESULT_VARIABLE result + #ERROR_QUIET + ERROR_VARIABLE error + OUTPUT_VARIABLE output + #OUTPUT_QUIET ) if(NOT ${result} EQUAL 0) - message(FATAL_ERROR "Error in: ${proj}: ${error}") + message("Error in: ${proj}: ${error}") + message("Output in: ${proj}: ${output}") endif() endfunction() diff --git a/CMake/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake index ba00cc5fde..81e3704f79 100644 --- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake +++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake @@ -1,168 +1,169 @@ macro(_find_package package_name) find_package(${package_name} REQUIRED PATHS ${${package_name}_DIR} PATH_SUFFIXES ${package_name} NO_DEFAULT_PATH NO_MODULE QUIET) if(NOT ${package_name}_FOUND) find_package(${package_name} REQUIRED) endif() endmacro() function(mitkFunctionGetLibrarySearchPaths search_path intermediate_dir) set(_dir_candidates "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins" ) if(MITK_EXTERNAL_PROJECT_PREFIX) list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}/bin" "${MITK_EXTERNAL_PROJECT_PREFIX}/lib" ) endif() # 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(MITK_USE_HDF5) _find_package(HDF5) get_target_property(_location hdf5 LOCATION) get_filename_component(_location ${_location} PATH) list(APPEND _additional_paths ${_location}) # This is a work-around. The hdf5-config.cmake file is not robust enough # to be included several times via find_pakcage calls. set(HDF5_LIBRARIES ${HDF5_LIBRARIES} PARENT_SCOPE) endif() if(MITK_USE_Vigra) # we cannot use _find_package(Vigra) here because the vigra-config.cmake file # always includes the target-exports files without using an include guard. This # would lead to errors when another find_package(Vigra) call is processed. The # (bad) assumption here is that for the time being, only the Classification module # is using Vigra. if(UNIX) list(APPEND _additional_paths ${Vigra_DIR}/lib) else() list(APPEND _additional_paths ${Vigra_DIR}/bin) endif() endif() if(_additional_paths) list(APPEND _dir_candidates ${_additional_paths}) 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(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/bin") endif() else() if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/lib") endif() endif() if(OpenCV_DIR) set(_opencv_link_directories "${OpenCV_LIB_DIR_DBG}" "${OpenCV_LIB_DIR_OPT}" "${OpenCV_3RDPARTY_LIB_DIR_DBG}" "${OpenCV_3RDPARTY_LIB_DIR_OPT}") list(REMOVE_DUPLICATES _opencv_link_directories) if(WIN32) foreach(_opencv_link_directory ${_opencv_link_directories}) list(APPEND _dir_candidates "${_opencv_link_directory}/../bin") endforeach() else() list(APPEND _dir_candidates ${_opencv_link_directories}) endif() endif() - if(MITK_USE_Python AND CTK_PYTHONQT_INSTALL_DIR) - list(APPEND _dir_candidates "${CTK_PYTHONQT_INSTALL_DIR}/bin") + if(MITK_USE_Python) + list(APPEND _dir_candidates "${CTK_DIR}/CMakeExternals/Install/bin") + list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}/lib/python2.7/bin") 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 index ded4b5b238..605553b324 100644 --- a/CMake/mitkFunctionInstallPython.cmake +++ b/CMake/mitkFunctionInstallPython.cmake @@ -1,158 +1,68 @@ #! 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) +function(mitkFunctionInstallPython _python_libs_out _search_path_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 AND EXISTS "${OpenCV_DIR}/lib/cv2${PYTHON_LIB_SUFFIX}") - # we currently only support installing in release mode - 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}Python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}D) - list(APPEND _VTK_PYTHON_TARGETS ${_lib}Python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}D) - endif() - endif() - endforeach() + # install the python runtime from the superbuild + if(NOT MITK_USE_SYSTEM_PYTHON) - # 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}" IMPORTED_LOCATION_DEBUG) - else() - get_target_property(_target_lib "${_target}" IMPORTED_LOCATION_RELEASE) - endif() - get_filename_component(_filepath "${_target_lib}" PATH) - get_filename_component(_filename "${_target_lib}" NAME) + # find package sets the python version numbers + find_package(PythonLibs REQUIRED) + find_package(PythonInterp REQUIRED) - install(FILES "${_target_lib}" DESTINATION ${_destination}) + set(_python_libs ) + set(_search_path ) - if(UNIX AND NOT APPLE ) - install(CODE "file(RPATH_REMOVE - FILE \"\${CMAKE_INSTALL_PREFIX}/bin/${_filename}\")") + # set the destination bundle + set(_destination bin) + if(APPLE) + set(_destination ${_app_bundle}) endif() - list(APPEND _python_libs "${_filename}") - 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") + list(APPEND _python_dirs "${MITK_EXTERNAL_PROJECT_PREFIX}/lib") + set(PYTHON_LIB_SUFFIX ".so") + set(_py_include_postfix python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/) # add the slash here so windows and unix will work with same code + set(_python_runtime_dir python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/) else() #WIN32 - list(APPEND _python_dirs "${Python_DIR}/libs") - list(APPEND _python_dirs "${Python_DIR}/bin") + list(APPEND _python_dirs "${MITK_EXTERNAL_PROJECT_PREFIX}/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/Lib") + #list(APPEND _python_dirs "${Python_DIR}/bin") + set(PYTHON_LIB_SUFFIX .pyd) + set(_py_include_postfix ) + set(_python_runtime_dir ) + set(_search_path "${MITK_EXTERNAL_PROJECT_PREFIX}/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/bin") endif() - file(GLOB_RECURSE item RELATIVE "${Python_DIR}/${_python_runtime_dir}" "${Python_DIR}/${_python_runtime_dir}/*") + file(GLOB_RECURSE item RELATIVE "${_python_dirs}/${_python_runtime_dir}" "${_python_dirs}/${_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_INCLUDE_DIR}/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) + #message("f: " ${f}) + #message("filepath: " ${_filepath}) + install(FILES "${_python_dirs}/${_python_runtime_dir}${f}" DESTINATION "${_destination}/Python/lib/${_python_runtime_dir}${_filepath}") + + #MESSAGE("in: " "${_python_dirs}/${_python_runtime_dir}${f}") + #MESSAGE("out: " "${_destination}/Python/lib/${_python_runtime_dir}${_filepath}") + if(${f} MATCHES "(${PYTHON_LIB_SUFFIX})$") + #MESSAGE("F: " "Python/lib/${_python_runtime_dir}${f}") + list(APPEND _python_libs "Python/lib/${_python_runtime_dir}${f}") + if(UNIX AND NOT APPLE) install(CODE "file(RPATH_REMOVE - FILE \"\${CMAKE_INSTALL_PREFIX}/bin/Python/${_python_runtime_dir}/${f}\")") + FILE \"\${CMAKE_INSTALL_PREFIX}/bin/Python/lib/${_python_runtime_dir}${f}\")") + endif() 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() + # config will by read out at runtime + install(FILES "${PYTHON_INCLUDE_DIR}/pyconfig.h" DESTINATION ${_destination}/Python/include/${_py_include_postfix}) - # 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() + set(${_python_libs_out} ${_python_libs} PARENT_SCOPE) + set(${_search_path_out} ${_search_path} PARENT_SCOPE) 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 e9cbcea951..980874457b 100644 --- a/CMake/mitkMacroInstall.cmake +++ b/CMake/mitkMacroInstall.cmake @@ -1,192 +1,191 @@ # # 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) + set(_python_libs) + set(_python_search_paths) include(mitkFunctionInstallPython) - mitkFunctionInstallPython(_python_libs _python_dirs "${_bundle_dest_dir}") + mitkFunctionInstallPython(_python_libs _python_search_paths "${_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_core_runtime\") 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_runtime_lib \"\${_bin_path}/liborg_blueberry_core_runtime${CMAKE_SHARED_LIBRARY_SUFFIX}\") if(EXISTS \"\${_bb_runtime_lib}\") list(APPEND GLOBBED_PLUGINS \"\${_bb_runtime_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() + if(_python_search_paths) + set(DIRS \"\${DIRS};\${_python_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/Numpy.cmake b/CMakeExternals/Numpy.cmake index f495e8d933..8b9b4760c5 100644 --- a/CMakeExternals/Numpy.cmake +++ b/CMakeExternals/Numpy.cmake @@ -1,102 +1,103 @@ #----------------------------------------------------------------------------- # 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} \"${MITK_CXX11_FLAG} ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\") set(ENV{LDFLAGS} \"${CMAKE_LINKER_FLAGS} ${CMAKE_LINKER_FLAGS_RELEASE} ${_install_rpath_linkflag}\") ") set(_numpy_build_step ${MITK_SOURCE_DIR}/CMake/mitkFunctionExternalPythonBuildStep.cmake) set(_configure_step ${ep_prefix}/tmp/${proj}_configure_step.cmake) file(WRITE ${_configure_step} "${_numpy_env} include(\"${_numpy_build_step}\") file(WRITE \"${ep_prefix}/src/${proj}/site.cfg\" \"\") mitkFunctionExternalPythonBuildStep(${proj} configure \"${PYTHON_EXECUTABLE}\" \"${CMAKE_BINARY_DIR}\" setup.py config) ") + set(_numpy_compiler ) + if(WIN32) + set(_numpy_compiler --compiler=msvc) + endif() + # build step set(_build_step ${ep_prefix}/tmp/${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) + mitkFunctionExternalPythonBuildStep(${proj} build \"${PYTHON_EXECUTABLE}\" \"${CMAKE_BINARY_DIR}\" setup.py build ${_numpy_compiler}) ") # install step set(_install_step ${ep_prefix}/tmp/${proj}_install_step.cmake) file(WRITE ${_install_step} "${_numpy_env} include(\"${_numpy_build_step}\") # escape characters in install path - set(_install_dir \"\${CMAKE_INSTALL_PREFIX}\") + set(_install_dir \"${Python_DIR}\") if(WIN32) string(REPLACE \"/\" \"\\\\\" _install_dir \${_install_dir}) endif() string(REPLACE \" \" \"\\ \" _install_dir \${_install_dir}) 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") + set(Numpy_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/numpy-1.9.2.tar.gz) + #set(Numpy_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/numpy-1.4.1.tar.gz) + #set(Numpy_MD5 "5c7b5349dc3161763f7f366ceb96516b") + set(Numpy_MD5 "a1ed53432dbcd256398898d35bc8e645") # escape spaces if(UNIX) STRING(REPLACE " " "\ " _configure_step ${_configure_step}) STRING(REPLACE " " "\ " _build_step ${_build_step}) STRING(REPLACE " " "\ " _install_step ${_install_step}) endif() - set(NUMPY_PATCH_COMMAND ) - if(WIN32) - set(NUMPY_PATCH_COMMAND PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/Numpy-1.4.1-win32.patch) - endif() - ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${Numpy_URL} URL_MD5 ${Numpy_MD5} - ${NUMPY_PATCH_COMMAND} BUILD_IN_SOURCE 1 CONFIGURE_COMMAND ${CMAKE_COMMAND} -P ${_configure_step} BUILD_COMMAND ${CMAKE_COMMAND} -P ${_build_step} INSTALL_COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX:PATH= -P ${_install_step} DEPENDS ${${proj}_DEPENDENCIES} ) set(Numpy_DIR ${MITK_PYTHON_SITE_DIR}/numpy) install(SCRIPT ${_install_step}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/Python-2.7.3.patch b/CMakeExternals/Python-2.7.3.patch index 61f1930738..f865570d50 100644 --- a/CMakeExternals/Python-2.7.3.patch +++ b/CMakeExternals/Python-2.7.3.patch @@ -1,26 +1,28 @@ diff -urNb Python-2.7.3/Lib/distutils/cygwinccompiler.py Python-src/Lib/distutils/cygwinccompiler.py --- Python-2.7.3/Lib/distutils/cygwinccompiler.py 2012-04-10 01:07:29.000000000 +0200 +++ Python-src/Lib/distutils/cygwinccompiler.py 2015-01-13 21:03:33.025871739 +0100 -@@ -75,6 +75,10 @@ +@@ -75,6 +75,12 @@ elif msc_ver == '1500': # VS2008 / MSVC 9.0 return ['msvcr90'] + elif msc_ver == '1600': + return ['msvcr100'] + elif msc_ver == '1700': ++ return ['msvcr110'] ++ elif msc_ver == '1800': + return ['msvcr120'] else: raise ValueError("Unknown MS Compiler version %s " % msc_ver) diff -urNb Python-2.7.3/Lib/distutils/msvc9compiler.py Python-src/Lib/distutils/msvc9compiler.py --- Python-2.7.3/Lib/distutils/msvc9compiler.py 2012-04-10 01:07:29.000000000 +0200 +++ Python-src/Lib/distutils/msvc9compiler.py 2015-01-13 21:03:33.021871739 +0100 @@ -658,7 +658,7 @@ # 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) + mfinfo = None if mfinfo is not None: mffilename, mfid = mfinfo out_arg = '-outputresource:%s;%s' % (output_filename, mfid) diff --git a/CMakeExternals/Python.cmake b/CMakeExternals/Python.cmake index bfdde38afd..4ac359e23b 100644 --- a/CMakeExternals/Python.cmake +++ b/CMakeExternals/Python.cmake @@ -1,208 +1,220 @@ #---------------------------------------------------------------------- # 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(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(proj ${PYTHON_SOURCE_PACKAGE}) # download the source code ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/${PYTHON_SOURCE_PACKAGE}.tgz URL_MD5 "2cf641732ac23b18d139be077bd906cd" # patch the VS compiler config PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/Python-2.7.3.patch CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) set(proj Python) set(Python_DEPENDENCIES ZLIB ${PYTHON_SOURCE_PACKAGE}) set(Python_DEPENDS ${proj}) 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 ) if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_cache_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() + # windows has to be installed to a seperate dir, or all py files will end up + # directly in the ep/lib folder + set(_python_install_dir ) + if(WIN32) + set(_python_install_dir -DCMAKE_INSTALL_PREFIX:PATH=${ep_prefix}/lib/python${MITK_PYTHON_MAJOR_VERSION}.${MITK_PYTHON_MINOR_VERSION}) + endif() + # CMake build environment for python from: # https://github.com/davidsansome/python-cmake-buildsystem ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/python-cmake-buildsystem-47845c55.tar.gz URL_MD5 "6e49d1ed93a5a0fff7621430c163d2d1" # fix to build python on i686 and i386 with the python cmake build system, # the x86 path must be set as default PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/python-cmake-buildsystem-47845c55.patch CMAKE_ARGS ${ep_common_args} CMAKE_CACHE_ARGS ${ep_common_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} + ${_python_install_dir} -DZLIB_INCLUDE_DIR:PATH=${ZLIB_INCLUDE_DIR} -DZLIB_LIBRARY:FILEPATH=${ZLIB_LIBRARY} # Python (and Numpy) do not like different shared library names -DCMAKE_DEBUG_POSTFIX:STRING= CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${Python_DEPENDENCIES} ) - set(Python_DIR "${ep_prefix}") + # set versions, override + set(PYTHON_VERSION_MAJOR ${MITK_PYTHON_MAJOR_VERSION}) + set(PYTHON_VERSION_MINOR ${MITK_PYTHON_MINOR_VERSION}) if(UNIX) + set(Python_DIR "${ep_prefix}") 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_INCLUDE_DIR2 "${PYTHON_INCLUDE_DIR}") 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") # linux custom compile step, set the environment variables and python home to the right # path. Other runtimes can mess up the paths of the installation and the stripped executable # used to compile links to the wrong library in /usr/lib set(_python_compile_step ${ep_prefix}/tmp/python_compile_step.sh) file(WRITE ${_python_compile_step} "#!/bin/bash export PYTHONHOME=${Python_DIR} export LD_LIBRARY_PATH=${Python_DIR}/lib ${PYTHON_EXECUTABLE} -m compileall ") # pre compile all *.py files in the runtime after install step ExternalProject_Add_Step(${proj} compile_step COMMAND sh ${_python_compile_step} WORKING_DIRECTORY ${Python_DIR} 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 #ExternalProject_Get_Property(${proj} binary_dir) #set(PYTHON_EXECUTABLE "${binary_dir}/bin/python${CMAKE_EXECUTABLE_SUFFIX}") else() + set(Python_DIR "${ep_prefix}/lib/python${MITK_PYTHON_MAJOR_VERSION}.${MITK_PYTHON_MINOR_VERSION}") set(PYTHON_EXECUTABLE "${Python_DIR}/bin/python${CMAKE_EXECUTABLE_SUFFIX}") set(PYTHON_INCLUDE_DIR "${Python_DIR}/include") set(PYTHON_INCLUDE_DIR2 "${PYTHON_INCLUDE_DIR}") 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") # pre compile all *.py files in the runtime after install step ExternalProject_Add_Step(${proj} compile_step COMMAND ${PYTHON_EXECUTABLE} -m compileall WORKING_DIRECTORY ${Python_DIR} DEPENDEES install ) endif() mitkFunctionInstallExternalCMakeProject(${proj}) install(DIRECTORY ${Python_DIR} DESTINATION . COMPONENT runtime FILES_MATCHING PATTERN "*.pyc" ) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/SimpleITK.cmake b/CMakeExternals/SimpleITK.cmake index 3f2f243c3c..972da24cd2 100644 --- a/CMakeExternals/SimpleITK.cmake +++ b/CMakeExternals/SimpleITK.cmake @@ -1,135 +1,136 @@ #----------------------------------------------------------------------------- # 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() if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() #TODO: Installer and testing works only with static libs on MAC set(_build_shared ON) if(APPLE) set(_build_shared OFF) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/SimpleITK-0.8.1.tar.gz URL_MD5 9126ab2eda9e88f598a962c02a705c43 PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/SimpleITK-0.8.1.patch CMAKE_ARGS ${ep_common_args} # -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON CMAKE_CACHE_ARGS ${ep_common_cache_args} ${additional_cmake_args} -DBUILD_SHARED_LIBS:BOOL=${_build_shared} -DSimpleITK_BUILD_DISTRIBUTE:BOOL=ON -DSimpleITK_PYTHON_THREADS:BOOL=ON -DUSE_SYSTEM_ITK:BOOL=ON -DBUILD_EXAMPLES:BOOL=OFF -DGDCM_DIR:PATH=${GDCM_DIR} -DITK_DIR:PATH=${ITK_DIR} -DSWIG_DIR:PATH=${SWIG_DIR} -DSWIG_EXECUTABLE:FILEPATH=${SWIG_EXECUTABLE} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) set(SimpleITK_DIR ${ep_prefix}) - if( MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON ) + if( MITK_USE_Python ) + set(_sitk_build_dir ${ep_prefix}/src/SimpleITK-build) + # Build python distribution with easy install. If a own runtime is used + # embedd the egg into the site-package folder of the runtime + + # Note: Userbase install could also be relevant in some cases Probably windows want's to + # install to Lib/python2.7/ + # 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 + # PYTHONUSERBASE=${_install_dir} ${PYTHON_EXECUTABLE} setup.py --user + # PythonDir needs to be fixed for the python interpreter by # changing dir delimiter for Windows - set(_install_dir ${Python_DIR}) + if(MITK_USE_SYSTEM_PYTHON) + set(_install_dir ${ep_prefix}) + else() + set(_install_dir ${Python_DIR}) + endif() if(WIN32) - STRING(REPLACE "/" "\\\\" _install_dir ${Python_DIR}) + STRING(REPLACE "/" "\\\\" _install_dir ${_install_dir}) else() # escape spaces in the install path for linux - STRING(REPLACE " " "\ " _install_dir ${Python_DIR}) + STRING(REPLACE " " "\ " _install_dir ${_install_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) + + if( 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 /Wrapping/PythonPackage + COMMAND PYTHONUSERBASE=${_install_dir} ${PYTHON_EXECUTABLE} setup.py install --prefix=${_install_dir} + DEPENDEES install + WORKING_DIRECTORY ${_sitk_build_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 /Wrapping/PythonPackage/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) - if(WIN32) - set(_userbase_install /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=/Wrapping/PythonPackage ${PYTHON_EXECUTABLE} setup.py install --user - DEPENDEES sitk_create_userbase_step - WORKING_DIRECTORY /Wrapping/PythonPackage + COMMAND ${PYTHON_EXECUTABLE} setup.py install --prefix=${_install_dir} + DEPENDEES install + WORKING_DIRECTORY ${_sitk_build_dir}/Wrapping/PythonPackage ) endif() endif() mitkFunctionInstallExternalCMakeProject(${proj}) # Still need to install the SimpleITK Python wrappings - else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake index 249d9036a0..d9abf3af59 100644 --- a/CMakeExternals/VTK.cmake +++ b/CMakeExternals/VTK.cmake @@ -1,122 +1,127 @@ #----------------------------------------------------------------------------- # 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(MITK_USE_HDF5) list(APPEND proj_DEPENDENCIES HDF5) endif() 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(WIN32) # see http://bugs.mitk.org/show_bug.cgi?id=17858 list(APPEND additional_cmake_args -DVTK_DO_NOT_DEFINE_OSTREAM_SLL:BOOL=ON -DVTK_DO_NOT_DEFINE_OSTREAM_ULL:BOOL=ON ) endif() # Optionally enable memory leak checks for any objects derived from vtkObject. This # will force unit tests to fail if they have any of these memory leaks. option(MITK_VTK_DEBUG_LEAKS OFF) mark_as_advanced(MITK_VTK_DEBUG_LEAKS) list(APPEND additional_cmake_args -DVTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS} ) if(MITK_USE_Python) if(NOT MITK_USE_SYSTEM_PYTHON) list(APPEND proj_DEPENDENCIES Python) + set(_vtk_install_python_dir -DVTK_INSTALL_PYTHON_MODULE_DIR:FILEPATH=${MITK_PYTHON_SITE_DIR}) + else() + set(_vtk_install_python_dir -DVTK_INSTALL_PYTHON_MODULE_DIR:FILEPATH=${ep_prefix}/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) 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} + ${_vtk_install_python_dir} ) 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() if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/VTK-6.2.0.tar.gz) set(VTK_URL_MD5 4790f8b3acdbc376997fbdc9d203f0b7) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${VTK_URL} URL_MD5 ${VTK_URL_MD5} PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/VTK-6.2.0.patch CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DVTK_WRAP_TCL:BOOL=OFF -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WRAP_JAVA:BOOL=OFF -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} CMAKE_CACHE_ARGS ${ep_common_cache_args} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) set(VTK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 61a4b6ff57..017077e02c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1382 +1,1380 @@ set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.2) cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION}) #----------------------------------------------------------------------------- # See http://www.cmake.org/cmake/help/v3.2/manual/cmake-policies.7.html for details #----------------------------------------------------------------------------- set(project_policies ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # 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 VERSION 2014.10.99) endif() #----------------------------------------------------------------------------- # 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) #----------------------------------------------------------------------------- # Standard CMake macros include(FeatureSummary) include(CTestUseLaunchers) include(CMakeParseArguments) include(FindPackageHandleStandardArgs) # MITK macros include(mitkFunctionGetGccVersion) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionEnableBuildConfiguration) include(mitkFunctionWhitelists) include(mitkFunctionAddExternalProject) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # 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() #----------------------------------------------------------------------------- # Check miminum Mac OS X version #----------------------------------------------------------------------------- # The minimum supported Mac OS X version is 10.9. If you use a version less than 10.9, there is no guarantee that the build still works. if(APPLE) exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE osx_version) if (osx_version VERSION_LESS "10.9") message(WARNING "Detected OS X version \"${osx_version}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") endif() if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.9) message(WARNING "Detected OS X deployment target \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") endif() endif() #----------------------------------------------------------------------------- # Check miminum compiler versions #----------------------------------------------------------------------------- if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # require at least gcc 4.7.3 as provided by ppa:ubuntu-toolchain-r/test for Ubuntu 12.04 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7.3) message(FATAL_ERROR "GCC version must be at least 4.7.3 If you are using Ubuntu 12.04, you can easily install gcc and g++ 4.7.3 (or any later version available) in addition to your version ${CMAKE_CXX_COMPILER_VERSION}: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-4.7 g++-4.7 Make sure to explicitly specify these compilers when configuring MITK: CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-4.7 CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-4.7 For more information on the proposed PPA see the Toolchain Updates section of https://wiki.ubuntu.com/ToolChain.") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least clang 3.4 as provided by Ubuntu 12.04 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) message(FATAL_ERROR "Clang version must be at least 3.4") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") # require at least clang 5.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) message(FATAL_ERROR "Apple Clang version must be at least 5.0") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # require at least Visual Studio 2012 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0.61030.0) message(FATAL_ERROR "Microsoft Visual Studio 2012 Update 4 or newer required (MSVC 17.0.61030.0)") endif() else() message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang (Linux or Apple), GCC and MSVC.") endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) else() set(GCC_VERSION 0) endif() set(MITK_CXX_STANDARD 11) set(CMAKE_CXX_EXTENSIONS 0) set(CMAKE_CXX_STANDARD ${MITK_CXX_STANDARD}) set(CMAKE_CXX_STANDARD_REQUIRED 1) # This is necessary to avoid problems with compile feature checks. # CMAKE_CXX_STANDARD seems to only set the -std=c++11 flag for targets. # However, compile flag checks also need to be done with -std=c++11. # The MITK_CXX11_FLAG variable is also used for external projects # build during the MITK super-build. mitkFunctionCheckCompilerFlags("-std=c++11" MITK_CXX11_FLAG) if(NOT MITK_CXX11_FLAG) # Older gcc compilers use -std=c++0x mitkFunctionCheckCompilerFlags("-std=c++0x" MITK_CXX11_FLAG) 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() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- macro(env_option name doc value) set(_value $ENV{${name}}) if("${_value}" STREQUAL "") set(_value ${value}) endif() option(${name} "${doc}" ${_value}) endmacro() # ----------------------------------------- # General build options option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" OFF) option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON) mark_as_advanced(MITK_BUILD_ALL_APPS MITK_ENABLE_PIC_READER ) # ----------------------------------------- # Qt version related variables if(APPLE) set(DESIRED_QT_VERSION 4 CACHE STRING "Pick a version of Qt to use: 4 or 5") else() set(DESIRED_QT_VERSION 5 CACHE STRING "Pick a version of Qt to use: 4 or 5") endif() env_option(MITK_USE_QT "Use the Qt Company'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(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" CACHE PATH "") set(MITK_QT5_COMPONENTS Concurrent OpenGL PrintSupport Script Sql Svg WebKitWidgets Xml XmlPatterns UiTools) find_package(Qt5 ${MITK_QT5_MINIMUM_VERSION} COMPONENTS ${MITK_QT5_COMPONENTS} REQUIRED) if(Qt5_DIR) get_filename_component(_Qt5_DIR "${Qt5_DIR}/../../../" ABSOLUTE) list(FIND CMAKE_PREFIX_PATH "${_Qt5_DIR}" _result) if(_result LESS 0) set(CMAKE_PREFIX_PATH "${_Qt5_DIR};${CMAKE_PREFIX_PATH}" CACHE PATH "" FORCE) endif() endif() endif() else() set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 FALSE) endif() # ------------------------------------------------------------------------ # Register external projects which can be build with the MITK superbuild # system. Each mitkFunctionAddExternalProject() call registers an external # project for which a CMakeExternals/.cmake file must exist. The # call also creates a MITK_USE_ variable (appearing in the CMake # UI if the NO_CACHE option is *not* given). # ----------------------------------------- # Optional external projects with no # inter-dependencies set_property(GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS "") mitkFunctionAddExternalProject(NAME Poco ON COMPONENTS Foundation Util XML Zip) mitkFunctionAddExternalProject(NAME Boost OFF DOC "Use the Boost C++ library") mitkFunctionAddExternalProject(NAME DCMTK ON DOC "EXPERIMENTAL, superbuild only: Use DCMTK in MITK") mitkFunctionAddExternalProject(NAME OpenIGTLink OFF) mitkFunctionAddExternalProject(NAME tinyxml ON ADVANCED) mitkFunctionAddExternalProject(NAME GDCM ON ADVANCED) mitkFunctionAddExternalProject(NAME GLUT OFF ADVANCED) mitkFunctionAddExternalProject(NAME Raptor2 OFF ADVANCED) mitkFunctionAddExternalProject(NAME Eigen ON ADVANCED DOC "Use the Eigen library") mitkFunctionAddExternalProject(NAME GLEW ON ADVANCED DOC "Use the GLEW library") mitkFunctionAddExternalProject(NAME ANN ON ADVANCED DOC "Use Approximate Nearest Neighbor Library") mitkFunctionAddExternalProject(NAME CppUnit ON ADVANCED DOC "Use CppUnit for unit tests") mitkFunctionAddExternalProject(NAME PCRE OFF ADVANCED NO_PACKAGE) mitkFunctionAddExternalProject(NAME ZLIB OFF ADVANCED NO_PACKAGE NO_CACHE) mitkFunctionAddExternalProject(NAME HDF5 OFF ADVANCED) # ----------------------------------------- # The following external projects must be # ordered according to their # inter-dependencies mitkFunctionAddExternalProject(NAME SWIG OFF ADVANCED NO_PACKAGE DEPENDS PCRE) mitkFunctionAddExternalProject(NAME Python OFF NO_PACKAGE DEPENDS SWIG DOC "Use Python wrapping in MITK") mitkFunctionAddExternalProject(NAME Numpy OFF ADVANCED NO_PACKAGE) mitkFunctionAddExternalProject(NAME OpenCV OFF) mitkFunctionAddExternalProject(NAME Vigra OFF DEPENDS HDF5) # These are "hard" dependencies and always set to ON mitkFunctionAddExternalProject(NAME ITK ON NO_CACHE) mitkFunctionAddExternalProject(NAME VTK ON NO_CACHE) mitkFunctionAddExternalProject(NAME SimpleITK OFF DEPENDS ITK GDCM SWIG) mitkFunctionAddExternalProject(NAME ACVD OFF DOC "Use Approximated Centroidal Voronoi Diagrams") mitkFunctionAddExternalProject(NAME CTK ON DEPENDS QT DCMTK DOC "Use CTK in MITK") mitkFunctionAddExternalProject(NAME Rasqal OFF DEPENDS Raptor2 PCRE ADVANCED) mitkFunctionAddExternalProject(NAME Redland OFF DEPENDS Rasqal DOC "Use the Redland RDF library") mitkFunctionAddExternalProject(NAME SOFA OFF DEPENDS GLUT Boost DOC "Use Simulation Open Framework Architecture") if(MITK_USE_QT) mitkFunctionAddExternalProject(NAME Qwt ON ADVANCED DEPENDS QT) endif() # ----------------------------------------- # Other MITK_USE_* options not related to # external projects build via the # MITK superbuild env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) #----------------------------------------------------------------------------- # Build configurations #----------------------------------------------------------------------------- set(_buildConfigs "Custom") file(GLOB _buildConfigFiles CMake/BuildConfigurations/*.cmake) foreach(_buildConfigFile ${_buildConfigFiles}) get_filename_component(_buildConfigFile ${_buildConfigFile} NAME_WE) list(APPEND _buildConfigs ${_buildConfigFile}) endforeach() set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations") mark_as_advanced(MITK_BUILD_CONFIGURATION) set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS ${_buildConfigs}) mitkFunctionEnableBuildConfiguration() mitkFunctionCreateWhitelistPaths(MITK) mitkFunctionFindWhitelists(MITK) # ----------------------------------------- # Custom dependency logic 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_SOFA) # 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() # Simulation plugin requires boost chrono library list(FIND MITK_USE_Boost_LIBRARIES chrono _result) if(_result LESS 0) message("> Adding 'chrono' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES chrono) 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() -if(MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON) +if(MITK_USE_Python) set(MITK_USE_ZLIB ON) if(NOT MITK_USE_Numpy) message("> Forcing MITK_USE_Numpy to ON because of MITK_USE_Python") set(MITK_USE_Numpy ON CACHE BOOL "Use Numpy" FORCE) endif() if(NOT MITK_USE_SimpleITK) message("> Forcing MITK_USE_SimpleITK to ON because of MITK_USE_Python") - set(MITK_USE_Numpy ON CACHE BOOL "Use Numpy" FORCE) + set(MITK_USE_SimpleITK ON CACHE BOOL "Use Numpy" FORCE) endif() - 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) - if(MITK_USE_SYSTEM_PYTHON) - find_package(PythonLibs REQUIRED) - find_package(PythonInterp REQUIRED) + option(MITK_USE_SYSTEM_PYTHON "Use the system python runtime" OFF) + if(MITK_USE_SYSTEM_PYTHON) + find_package(PythonLibs REQUIRED) + find_package(PythonInterp REQUIRED) endif() - endif() endif() 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() 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() #----------------------------------------------------------------------------- # Pixel type multiplexing #----------------------------------------------------------------------------- # 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(GenerateExportHeader) include(mitkFunctionOrganizeSources) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionCompileSnippets) include(mitkFunctionUseModules) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCreateModule) include(mitkMacroCreateExecutable) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) include(mitkMacroConfigureItkPixelTypes) #----------------------------------------------------------------------------- # Global CMake variables #----------------------------------------------------------------------------- # Required and enabled C++11 features for all MITK code. # These are added as PUBLIC compile features to all MITK modules. set(MITK_CXX_FEATURES cxx_auto_type cxx_decltype cxx_enum_forward_declarations cxx_extended_friend_declarations cxx_extern_templates cxx_final cxx_lambdas cxx_local_type_template_args cxx_long_long_type cxx_nullptr cxx_override cxx_range_for cxx_right_angle_brackets cxx_rvalue_references cxx_static_assert cxx_strong_enums cxx_template_template_parameters cxx_trailing_return_types cxx_variadic_macros ) if(NOT DEFINED CMAKE_DEBUG_POSTFIX) # We can't do this yet because the CTK Plugin Framework # cannot cope with a postfix yet. #set(CMAKE_DEBUG_POSTFIX d) endif() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- set(_default_LIBRARY_output_dir lib) set(_default_RUNTIME_output_dir bin) set(_default_ARCHIVE_output_dir lib) foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(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_CMAKE_${type}_OUTPUT_DIRECTORY) set(CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) else() set(CMAKE_${type}_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${_default_${type}_output_dir}) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY}) endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY} CACHE INTERNAL "Output directory for ${type} files.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # 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() # MITK_VERSION set(MITK_VERSION_STRING "${MITK_VERSION_MAJOR}.${MITK_VERSION_MINOR}.${MITK_VERSION_PATCH}") if(MITK_VERSION_PATCH STREQUAL "99") set(MITK_VERSION_STRING "${MITK_VERSION_STRING}-${MITK_REVISION_SHORTID}") endif() # Needed early on for redirecting the BlueBerry documentation output dir set(MITK_DOXYGEN_OUTPUT_DIR ${PROJECT_BINARY_DIR}/Documentation/Doxygen CACHE PATH "Output directory for doxygen generated documentation." ) if(NOT UNIX AND NOT MINGW) set(MITK_WIN32_FORCE_STATIC "STATIC" CACHE INTERNAL "Use this variable to always build static libraries on non-unix platforms") endif() if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() # Configure pixel types used for ITK image access multiplexing mitkMacroConfigureItkPixelTypes() # Configure module naming conventions set(MITK_MODULE_NAME_REGEX_MATCH "^[A-Z].*$") set(MITK_MODULE_NAME_REGEX_NOT_MATCH "^[Mm][Ii][Tt][Kk].*$") set(MITK_MODULE_NAME_PREFIX "Mitk") set(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME 1) #----------------------------------------------------------------------------- # 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 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 "${COVERAGE_CXX_FLAGS} ${MITK_CXX11_FLAG}") 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 -DNOMINMAX") mitkFunctionCheckCompilerFlags("/wd4005" MITK_CXX_FLAGS) # warning C4005: macro redefinition mitkFunctionCheckCompilerFlags("/wd4231" MITK_CXX_FLAGS) # 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) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) 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}) if(NOT MITK_USE_SYSTEM_Boost) set(Boost_NO_SYSTEM_PATHS 1) endif() set(Boost_USE_MULTITHREADED 1) set(Boost_USE_STATIC_LIBS 0) set(Boost_USE_STATIC_RUNTIME 0) # We need this later for a DCMTK workaround set(_dcmtk_dir_orig ${DCMTK_DIR}) # This property is populated at the top half of this file get_property(MITK_EXTERNAL_PROJECTS GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(MITK_USE_${ep} AND _package) if(_components) find_package(${_package} COMPONENTS ${_components} REQUIRED CONFIG) else() # Prefer config mode first because it finds external # Config.cmake files pointed at by _DIR variables. # Otherwise, existing Find.cmake files could fail. # (e.g. in the case of GLEW and the FindGLEW.cmake file shipped # with CMake). find_package(${_package} QUIET CONFIG) string(TOUPPER "${_package}" _package_uc) if(NOT (${_package}_FOUND OR ${_package_uc}_FOUND)) find_package(${_package} REQUIRED) endif() endif() endif() endforeach() # Ensure that the MITK CMake module path comes first set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) if(MITK_USE_DCMTK) # Due to the preferred CONFIG mode in find_package calls above, # the DCMTKConfig.cmake file is read, which does not provide useful # package information. We explictly need MODULE mode to find DCMTK. if(${_dcmtk_dir_orig} MATCHES "${MITK_EXTERNAL_PROJECT_PREFIX}.*") # Help our FindDCMTK.cmake script find our super-build DCMTK set(DCMTK_DIR ${MITK_EXTERNAL_PROJECT_PREFIX}) else() # Use the original value set(DCMTK_DIR ${_dcmtk_dir_orig}) endif() find_package(DCMTK REQUIRED MODULE) endif() if(MITK_USE_Python) find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) + if(MITK_USE_Numpy) + find_package(Numpy REQUIRED) + endif() endif() if(MITK_USE_SOFA) # The SOFAConfig.cmake file does not provide exported targets or # libraries with absolute paths, hence we need to make the link # directories globally available until the SOFAConfig.cmake file # supports a proper mechanism for handling targets. # The same code is needed in MITKConfig.cmake. link_directories(${SOFA_LIBRARY_DIRS}) endif() if(MITK_USE_Boost) # Same as SOFA above link_directories(${Boost_LIBRARY_DIRS}) endif() if(MITK_USE_OpenIGTLink) # Same as SOFA above link_directories(${OpenIGTLink_LIBRARY_DIRS}) endif() if(MITK_USE_SimpleITK) link_directories(${SimpleITK_LIBRARY_DIRS}) endif() if(MITK_USE_OpenCL) find_package(OpenCL REQUIRED) endif() # Qt support if(MITK_USE_QT) if(DESIRED_QT_VERSION MATCHES 4) find_package(Qt4 ${MITK_QT4_MINIMUM_VERSION} REQUIRED) elseif(DESIRED_QT_VERSION MATCHES 5) find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED) # at least Core required get_target_property(_qmake_exec Qt5::qmake LOCATION) execute_process(COMMAND ${_qmake_exec} -query QT_INSTALL_BINS RESULT_VARIABLE _result OUTPUT_VARIABLE QT_BINARY_DIR ERROR_VARIABLE _error ) string(STRIP "${QT_BINARY_DIR}" QT_BINARY_DIR) if(_result OR NOT EXISTS "${QT_BINARY_DIR}") message(FATAL_ERROR "Could not determine Qt binary directory: ${_result} ${QT_BINARY_DIR} ${_error}") endif() endif() endif() #----------------------------------------------------------------------------- # 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 ) # Initial cache for ProjectTemplate and PluginGenerator tests configure_file( CMake/mitkTestInitialCache.txt.in ${MITK_BINARY_DIR}/mitkTestInitialCache.txt @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() #----------------------------------------------------------------------------- # 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}") #----------------------------------------------------------------------------- # Compile Utilities and set-up MITK variables #----------------------------------------------------------------------------- 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_CXX_FLAGS "${MITK_CXX_FLAGS}") set(BLUEBERRY_CXX_FLAGS_RELEASE "${MITK_CXX_FLAGS_RELEASE}") set(BLUEBERRY_C_FLAGS "${MITK_C_FLAGS}") 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() #----------------------------------------------------------------------------- # 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(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") if(TARGET 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() endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") mitkFunctionWhitelistPlugins(MITK MITK_EXT_PLUGINS) 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}) string(FIND ${mitk_app} "MITK_BUILD_APP_" _index) string(SUBSTRING ${mitk_app} ${_index} -1 _var) if(${_var}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}") endif() 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() endif() #----------------------------------------------------------------------------- # 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 #----------------------------------------------------------------------------- # ---------------- Export targets ----------------- 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() get_target_property(deprecated_module ${target_to_export} MITK_MODULE_DEPRECATED_SINCE) if(deprecated_module) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_MODULE_DEPRECATED_SINCE \"${deprecated_module}\")") endif() endforeach() # ---------------- External projects ----------------- get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) set(MITK_CONFIG_EXTERNAL_PROJECTS ) #string(REPLACE "^^" ";" _mitk_external_projects ${MITK_EXTERNAL_PROJECTS}) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} set(MITK_USE_${ep} ${MITK_USE_${ep}}) set(MITK_${ep}_DIR \"${${ep}_DIR}\") set(MITK_${ep}_COMPONENTS ${_components}) ") endforeach() foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(_components) set(_components_arg COMPONENTS \${_components}) else() set(_components_arg) endif() if(_package) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} if(MITK_USE_${ep}) set(${ep}_DIR \${MITK_${ep}_DIR}) if(MITK_${ep}_COMPONENTS) mitkMacroFindDependency(${_package} COMPONENTS \${MITK_${ep}_COMPONENTS}) else() mitkMacroFindDependency(${_package}) endif() endif()") endif() endforeach() # ---------------- Tools ----------------- 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) # ---------------- Configure files ----------------- 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) 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") if(MITK_USE_HDF5) list(APPEND MITK_LIBRARY_DIRS ${HDF5_DIR}/install/bin) message(STATUS "MITK-Runtime " ${MITK_RUNTIME_PATH}) endif(MITK_USE_HDF5) 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/Modules/Python/CMakeLists.txt b/Modules/Python/CMakeLists.txt index acb47d61c7..e0323b505f 100644 --- a/Modules/Python/CMakeLists.txt +++ b/Modules/Python/CMakeLists.txt @@ -1,24 +1,24 @@ if(MITK_USE_Python) set(OpenCV_DEP ) if(MITK_USE_OpenCV) set(OpenCV_DEP OpenCV) endif() mitk_create_module( DEPENDS MitkCore MitkQtWidgets PACKAGE_DEPENDS PUBLIC Qt4|QtGui Qt5|Widgets CTK|CTKScriptingPythonCore+CTKScriptingPythonWidgets - PRIVATE PythonLibs VTK|vtkPython+vtkWrappingPythonCore Numpy ${OpenCV_DEP} + PRIVATE PythonLibs VTK|vtkPython+vtkWrappingPythonCore ${OpenCV_DEP} ) if(TARGET ${MODULE_TARGET}) configure_file(PythonPath.h.in "${CMAKE_CURRENT_BINARY_DIR}/PythonPath.h" @ONLY) if(NOT MITK_USE_SYSTEM_PYTHON) target_compile_definitions(${MODULE_TARGET} PRIVATE -DUSE_MITK_BUILTIN_PYTHON) endif() endif() add_subdirectory(Testing) endif() diff --git a/Modules/Python/PythonPath.h.in b/Modules/Python/PythonPath.h.in index d62c631f5a..6339dd9a52 100644 --- a/Modules/Python/PythonPath.h.in +++ b/Modules/Python/PythonPath.h.in @@ -1,19 +1,28 @@ #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('@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('@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 "')" +#ifdef WIN32 +//Todo: windows system python +#define EXTERNAL_SITE_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python2.7/Lib/site-packages" +#define EXTERNAL_DIST_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python2.7/Lib/dist-packages" +#define PYTHONHOME "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python2.7" +#else +#define EXTERNAL_SITE_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python2.7/site-packages" +#define EXTERNAL_DIST_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python2.7/dist-packages" +#define PYTHONHOME "@MITK_EXTERNAL_PROJECT_PREFIX@" +#endif -#define PYTHONHOME "@Python_DIR@" +//#define PYTHONPATH_COMMAND "import sys\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('@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 "')" diff --git a/Modules/Python/QmitkPythonSnippets.cpp b/Modules/Python/QmitkPythonSnippets.cpp index b0947c81af..e6543448eb 100644 --- a/Modules/Python/QmitkPythonSnippets.cpp +++ b/Modules/Python/QmitkPythonSnippets.cpp @@ -1,483 +1,496 @@ /*=================================================================== 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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( !QmitkPythonSnippets::LoadStringMap( d->m_AutoSaveFileName, 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 ) { 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 ) { 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/QmitkPythonTextEditor.cpp b/Modules/Python/QmitkPythonTextEditor.cpp index 2789143341..8027c90b94 100644 --- a/Modules/Python/QmitkPythonTextEditor.cpp +++ b/Modules/Python/QmitkPythonTextEditor.cpp @@ -1,184 +1,190 @@ /*=================================================================== 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 "QmitkPythonTextEditor.h" #include #include #include -#include +#include +#include +#include +#include +#include +#include + #include #include #include #include #include #include "QmitkPythonScriptEditorHighlighter.h" struct QmitkPythonTextEditorData { QString m_FilePath; QAction* m_LoadScript; QAction* m_SaveScript; QAction* m_RunScript; QToolBar* m_Toolbar; QTextEdit* m_Content; QGridLayout* m_Layout; mitk::IPythonService* m_PythonService; us::ServiceReference m_PythonServiceRef; QString m_FileName; }; QmitkPythonTextEditor::QmitkPythonTextEditor(QWidget *parent) :QWidget(parent), d(new QmitkPythonTextEditorData) { us::ModuleContext* context = us::GetModuleContext(); d->m_PythonServiceRef = context->GetServiceReference(); d->m_PythonService = context->GetService( d->m_PythonServiceRef ); d->m_LoadScript = new QAction(this); d->m_LoadScript->setToolTip("Load script from disk."); d->m_LoadScript->setObjectName(QString::fromUtf8("LoadScript")); QIcon icon2; icon2.addFile(QString::fromUtf8(":/mitkPython/document-open.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_LoadScript->setIcon(icon2); d->m_SaveScript = new QAction(this); d->m_SaveScript->setToolTip("Save script to disk."); d->m_SaveScript->setObjectName(QString::fromUtf8("SaveScript")); QIcon icon3; icon3.addFile(QString::fromUtf8(":/mitkPython/document-save.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_SaveScript->setIcon(icon3); d->m_RunScript = new QAction(this); d->m_RunScript->setToolTip("Run the current script."); d->m_RunScript->setObjectName(QString::fromUtf8("RunScript")); QIcon icon4; icon4.addFile(QString::fromUtf8(":/mitkPython/media-playback-start.png"), QSize(), QIcon::Normal, QIcon::Off); d->m_RunScript->setIcon(icon4); d->m_Toolbar = new QToolBar; d->m_Toolbar->addAction( d->m_LoadScript ); d->m_Toolbar->addAction( d->m_SaveScript ); d->m_Toolbar->addAction( d->m_RunScript ); d->m_Content = new QTextEdit(this); d->m_Content->setObjectName(QString::fromUtf8("Content")); 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_Content, 1, 0, 1, 1 ); d->m_Layout->setContentsMargins(2,2,2,2); this->setLayout(d->m_Layout); QMetaObject::connectSlotsByName(this); } QmitkPythonTextEditor::~QmitkPythonTextEditor() { us::ModuleContext* context = us::GetModuleContext(); context->UngetService( d->m_PythonServiceRef ); delete d; } void QmitkPythonTextEditor::dragEnterEvent(QDragEnterEvent *event) { event->accept(); } void QmitkPythonTextEditor::dropEvent(QDropEvent *event) { QList urls = event->mimeData()->urls(); for(int i = 0; i < urls.size(); i++) { this->Paste( urls[i].toString() ); } } /* bool QmitkPythonTextEditor::canInsertFromMimeData( const QMimeData * ) const { return true; } */ void QmitkPythonTextEditor::Paste(const QString &command) { if( this->isVisible() ) { d->m_Content->insertPlainText(command + "\n"); } } QString QmitkPythonTextEditor::ReadFile(const QString& filename) { QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { MITK_ERROR << "Could not open file " << filename.toStdString(); return NULL; } QByteArray total; QByteArray line; while (!file.atEnd()) { line = file.read(1024); total.append(line); } return QString(total); } void QmitkPythonTextEditor::on_SaveScript_triggered( bool ) { d->m_FileName = QFileDialog::getSaveFileName(this,tr("Save File"), d->m_FileName,tr("*.py")); if( d->m_FileName.compare("") != 0) { std::ofstream myfile; myfile.open(d->m_FileName.toLocal8Bit().data()); myfile << d->m_Content->toPlainText().toLocal8Bit().data(); myfile.close(); } } void QmitkPythonTextEditor::on_LoadScript_triggered( bool ) { d->m_FileName = QFileDialog::getOpenFileName( this, "Load Script", d->m_FileName, tr("*.py")); if( !d->m_FileName.isEmpty() ) { QString contents = this->ReadFile( d->m_FileName ); d->m_Content->setText(contents); } } void QmitkPythonTextEditor::on_RunScript_triggered( bool ) { if( !d->m_PythonService ) { MITK_ERROR << "Python service not available."; return; } d->m_PythonService->Execute( d->m_Content->toPlainText().toStdString(), mitk::IPythonService::MULTI_LINE_COMMAND ); } diff --git a/Modules/Python/QmitkPythonVariableStackTableModel.h b/Modules/Python/QmitkPythonVariableStackTableModel.h index 204f110c3d..8403716c06 100755 --- a/Modules/Python/QmitkPythonVariableStackTableModel.h +++ b/Modules/Python/QmitkPythonVariableStackTableModel.h @@ -1,63 +1,63 @@ /*=================================================================== 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 QmitkPythonVariableStackTableModel_h #define QmitkPythonVariableStackTableModel_h #include #include #include #include "mitkIPythonService.h" #include #include /// /// implements a table model to show the variables of the Python "__main__" dictionary /// furthermore implements dragging and dropping of datanodes (conversion from and to python) /// class MITKPYTHON_EXPORT QmitkPythonVariableStackTableModel : public QAbstractTableModel, public mitk::PythonCommandObserver { Q_OBJECT public: static const QString MITK_IMAGE_VAR_NAME; static const QString MITK_SURFACE_VAR_NAME; QmitkPythonVariableStackTableModel(QObject *parent = 0); virtual ~QmitkPythonVariableStackTableModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; Qt::ItemFlags flags( const QModelIndex& index ) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; QStringList mimeTypes() const; bool dropMimeData ( const QMimeData *, Qt::DropAction, int, int, const QModelIndex & ); Qt::DropActions supportedDropActions() const; - Qt::DropActions supportedDragActions() const; + //Qt::DropActions supportedDragActions() const; void CommandExecuted(const std::string& pythonCommand); std::vector GetVariableStack() const; private: std::vector m_VariableStack; mitk::IPythonService* m_PythonService; us::ServiceReference m_PythonServiceRef; }; #endif // QmitkPythonVariableStackTableModel_h diff --git a/Modules/Python/Testing/CMakeLists.txt b/Modules/Python/Testing/CMakeLists.txt index 255140ee09..d54e8505ed 100644 --- a/Modules/Python/Testing/CMakeLists.txt +++ b/Modules/Python/Testing/CMakeLists.txt @@ -1,6 +1,5 @@ set(package_deps PACKAGE_DEPENDS PRIVATE) -if(NOT APPLE) - list(APPEND package_deps SimpleITK) -endif() +list(APPEND package_deps SimpleITK) + MITK_CREATE_MODULE_TESTS(${package_deps}) diff --git a/Modules/Python/documentation/mitkPython.dox b/Modules/Python/documentation/mitkPython.dox index 52f27b2c52..8084fab6c6 100644 --- a/Modules/Python/documentation/mitkPython.dox +++ b/Modules/Python/documentation/mitkPython.dox @@ -1,49 +1,80 @@ /** \page mitkPython_Overview The MITK Python Module -\section sec1 Brief description -The MITK Python Module provides a service class for interactively run python code (passed as C++ strings) and +\section python_sec1 Brief description +The MITK Python Module provides a service class to 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 +\section python_sec2 Build Instructions -The following build options are available: +Currently MITK-Python is only supported with Qt4. Qt5 support is in an experimental stage. +Have a look at \ref python_ssec3 on how to build MITK-Python with Qt5. +The following CMake build options are available:
  • MITK_USE_Python
  • MITK_USE_SYSTEM_PYTHON
-\subsection ssec1 MITK_USE_Python +\subsection python_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. +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 +\subsection python_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 +Only Python 2.7.x is supported. +The user can also specify it's own runtime by modifying the variables added by the FindPythonLib.cmake script. Note: A Python runtime with numpy is needed to use the MITK Python wrapping. +When using this options all additional libraries installed in the python runtime will be available within the MITK-Python console. -\section sec3 Suported Data Types +\subsection python_ssec3 Qt5 Support + +In order to build MITK-Python with Qt5 support an external build of CTK and PythonQt 3.0 is necessary. +The current MITK CTK superbuild only supports PythonQt 2.0 that has no Qt 5 support. This will most likely +only work with the MITK_USE_SYSTEM_PYTHON option due to dependencies of each external project. +It can be build with the following steps: + +\subsubsection python_Step1 Step1 - Build PythonQt +PythonQt 3 has no CMake build system and has to be build by hand with qmake. +Download and build PythonQt 3 from sourceforge. + +\subsubsection python_Step2 Step2 - Build CTK +Build the current CTK master with the external PythonQt 3 binaries. +The external PythonQt 3 binaries can be added in CTK by adding the following +CMake variable that points to the PythonQt build directory: +\code +-DPYTHONQT_INSTALL_DIR:PATH=/your/PythonQt3Build +\endcode +More information about the changes added in CTK for PythonQt are available on Github. + +\subsubsection python_Step3 Step3 - Build MITK +In the last step MITK has to be build with the CTK from the previous step \ref python_Step2. +This is done by setting the CTK_Dir to the CTK build directory: +\code +-DCTK_DIR:PATH=/some_path +\endcode + +\section python_sec3 Suported Data Types The following data types in MITK are supported in the MITK Python Wrapping:
  • Image
  • Surface
-\subsection ssec4 Image +\subsection python_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 +\subsection python_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/mitkIPythonService.cpp b/Modules/Python/mitkIPythonService.cpp index 3138baee1a..446636ddc2 100644 --- a/Modules/Python/mitkIPythonService.cpp +++ b/Modules/Python/mitkIPythonService.cpp @@ -1,21 +1,29 @@ /*=================================================================== 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 "mitkIPythonService.h" mitk::IPythonService::~IPythonService() { } + +std::string mitk::IPythonService::ForceLoadModule() +{ + std::string ret = "Load python module"; + MITK_INFO << ret; + return ret; +} + diff --git a/Modules/Python/mitkIPythonService.h b/Modules/Python/mitkIPythonService.h index 32539caf14..ba6a74884c 100644 --- a/Modules/Python/mitkIPythonService.h +++ b/Modules/Python/mitkIPythonService.h @@ -1,141 +1,144 @@ /*=================================================================== 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 MITKPYTHON_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 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 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 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 + + // force us module loading by linking + static std::string ForceLoadModule(); }; } MITK_DECLARE_SERVICE_INTERFACE(mitk::IPythonService, "org.mitk.services.IPythonService") #endif diff --git a/Modules/Python/mitkPythonService.cpp b/Modules/Python/mitkPythonService.cpp index da852eab10..0bc3b068d6 100644 --- a/Modules/Python/mitkPythonService.cpp +++ b/Modules/Python/mitkPythonService.cpp @@ -1,646 +1,652 @@ /*=================================================================== 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; + + // TODO: Check this in the modernization branch with an installer // 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 + //pythonCommand.append( QString("\nsite.addsitedir('%1/Python/python2.7/site-packages')").arg(programPath.c_str()) ); + //pythonCommand.append( QString("\nsite.addsitedir('%1/Python/python2.7/dist-packages')").arg(programPath.c_str()) ); + // development } else { - pythonCommand.append(PYTHONPATH_COMMAND); + pythonCommand.append( QString("import site, sys\n") ); + pythonCommand.append( QString("sys.path.append('')\n") ); + pythonCommand.append( QString("sys.path.append('%1')\n").arg(EXTERNAL_DIST_PACKAGES) ); + pythonCommand.append( QString("\nsite.addsitedir('%1')").arg(EXTERNAL_SITE_PACKAGES) ); } if( pythonInitialized ) m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut|PythonQt::PythonAlreadyInitialized); else m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut); // 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); if(pHome) delete[] pHome; pHome = new char[pythonHome.toStdString().length() + 1]; strcpy(pHome,pythonHome.toStdString().c_str()); Py_SetPythonHome(pHome); MITK_DEBUG("PythonService") << "PythonHome: " << pHome; #endif MITK_DEBUG("PythonService") << "initalizing python"; + m_PythonManager.initialize(); #ifdef USE_MITK_BUILTIN_PYTHON PyObject* dict = PyDict_New(); // Import builtin modules if (PyDict_GetItemString(dict, "__builtins__") == NULL) { 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("PythonService")<< "Python Search paths: " << Py_GetPath(); MITK_DEBUG("PythonService") << "python initalized"; - MITK_DEBUG("PythonService") << "registering python paths" << PYTHONPATH_COMMAND; + //MITK_DEBUG("PythonService") << "registering python paths" << PYTHONPATH_COMMAND; m_PythonManager.executeString( pythonCommand, ctkAbstractPythonManager::FileInput ); } catch (...) { MITK_DEBUG("PythonService") << "exception initalizing python"; } } } mitk::PythonService::~PythonService() { 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; } 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(commandIssued) { this->NotifyObserver(pythonCommand.toStdString()); m_ErrorOccured = PythonQt::self()->hadError(); } 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; 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; 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); } } return list; } bool mitk::PythonService::DoesVariableExist(const std::string& name) const { bool varExists = false; std::vector allVars = this->GetVariableStack(); 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( 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::CopyToPythonAsSimpleItkImage(mitk::Image *image, const std::string &stdvarName) { QString varName = QString::fromStdString( stdvarName ); 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 ) { 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; } // 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(); this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); return true; } 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 ); 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) ); 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); } 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]; } 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; } 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 ) { // 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 varName = QString::fromStdString( stdvarName ); 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 ); // get address of the object pyAddr = PyDict_GetItemString(pyDict,QString("%1_addr").arg(varName).toStdString().c_str()); // 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 surface; } bool mitk::PythonService::CopyToPythonAsVtkPolyData( mitk::Surface* surface, const std::string& stdvarName ) { QString varName = QString::fromStdString( stdvarName ); std::ostringstream oss; std::string addr = ""; QString command; QString address; oss << (void*) ( surface->GetVtkPolyData() ); // 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) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); return true; } bool mitk::PythonService::IsSimpleItkPythonWrappingAvailable() { 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 ); m_VtkWrappingAvailable = !this->PythonErrorOccured(); return m_VtkWrappingAvailable; } bool mitk::PythonService::PythonErrorOccured() const { return m_ErrorOccured; } diff --git a/Plugins/org.mitk.gui.qt.python/documentation/UserManual/MitkPythonPluginView.png b/Plugins/org.mitk.gui.qt.python/documentation/UserManual/MitkPythonPluginView.png index befab56719..cf671e2b38 100644 Binary files a/Plugins/org.mitk.gui.qt.python/documentation/UserManual/MitkPythonPluginView.png 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 f63444f960..114be980c4 100644 --- a/Plugins/org.mitk.gui.qt.python/documentation/UserManual/QmitkPython.dox +++ b/Plugins/org.mitk.gui.qt.python/documentation/UserManual/QmitkPython.dox @@ -1,33 +1,33 @@ /** \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 SimpleITK/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{MitkPythonPluginView.png,"Screenshot of the MITK Python Plugin",20} +\imageMacro{MitkPythonPluginView.png,"Screenshot of the MITK Python Plugin",6} \section org_mitk_gui_qt_PythonConsole Console 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 Snippets 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/Plugins/org.mitk.gui.qt.python/src/internal/QmitkPythonView.cpp b/Plugins/org.mitk.gui.qt.python/src/internal/QmitkPythonView.cpp index 32b6a104bc..ccce177567 100644 --- a/Plugins/org.mitk.gui.qt.python/src/internal/QmitkPythonView.cpp +++ b/Plugins/org.mitk.gui.qt.python/src/internal/QmitkPythonView.cpp @@ -1,98 +1,101 @@ /*=================================================================== 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 "QmitkPythonView.h" -#include #include #include "mitkPluginActivator.h" #include #include #include +#include +#include +#include + const std::string QmitkPythonView::VIEW_ID = "org.mitk.views.python"; struct QmitkPythonViewData { // widget QmitkPythonVariableStackTableView* m_PythonVariableStackTableView; QmitkPythonSnippets* m_PythonSnippets; QmitkCtkPythonShell* m_PythonShell; QmitkPythonTextEditor* m_TextEditor; }; QmitkPythonView::QmitkPythonView() : d( new QmitkPythonViewData ) { d->m_PythonVariableStackTableView = 0; d->m_PythonShell = 0; } QmitkPythonView::~QmitkPythonView() { delete d; } void QmitkPythonView::CreateQtPartControl(QWidget* parent) { d->m_PythonVariableStackTableView = new QmitkPythonVariableStackTableView; d->m_PythonVariableStackTableView->SetDataStorage(this->GetDataStorage()); - d->m_PythonVariableStackTableView->horizontalHeader()->setResizeMode(QHeaderView::Interactive); + //d->m_PythonVariableStackTableView->horizontalHeader()->setResizeMode(QHeaderView::Interactive); QString snippetsFilePath = mitk::PluginActivator::m_XmlFilePath; MITK_DEBUG("QmitkPythonView") << "got snippetsFilePath " << snippetsFilePath.toStdString(); d->m_PythonSnippets = new QmitkPythonSnippets(snippetsFilePath); MITK_DEBUG("QmitkPythonView") << "initializing varStackSnippetsTab"; QTabWidget* varStackSnippetsTab = new QTabWidget; varStackSnippetsTab->addTab( d->m_PythonVariableStackTableView, "Variable Stack" ); varStackSnippetsTab->addTab( d->m_PythonSnippets, "Snippets" ); varStackSnippetsTab->setTabPosition( QTabWidget::South ); MITK_DEBUG("QmitkPythonView") << "initializing m_PythonShell"; d->m_PythonShell = new QmitkCtkPythonShell; MITK_DEBUG("QmitkPythonView") << "initializing m_TextEditor"; d->m_TextEditor = new QmitkPythonTextEditor; MITK_DEBUG("QmitkPythonView") << "initializing tabWidgetConsoleEditor"; QTabWidget* tabWidgetConsoleEditor = new QTabWidget; tabWidgetConsoleEditor->addTab( d->m_PythonShell, "Console" ); tabWidgetConsoleEditor->addTab( d->m_TextEditor, "Text Editor" ); tabWidgetConsoleEditor->setTabPosition( QTabWidget::South ); QList sizes; sizes << 1 << 3; QSplitter* splitter = new QSplitter; splitter->addWidget(varStackSnippetsTab); splitter->addWidget(tabWidgetConsoleEditor); splitter->setStretchFactor ( 0, 1 ); splitter->setStretchFactor ( 1, 3 ); QGridLayout* layout = new QGridLayout; layout->addWidget( splitter, 0, 0 ); parent->setLayout(layout); MITK_DEBUG("QmitkPythonView") << "creating connections for m_PythonSnippets"; connect( d->m_PythonSnippets, SIGNAL(PasteCommandRequested(QString)), d->m_PythonShell, SLOT(Paste(QString)) ); connect( d->m_PythonSnippets, SIGNAL(PasteCommandRequested(QString)), d->m_TextEditor, SLOT(Paste(QString)) ); } void QmitkPythonView::SetFocus() { d->m_PythonShell->setFocus(); }