diff --git a/CMake/mitkMacroInstallPython.cmake b/CMake/mitkMacroInstallPython.cmake index b9976cb69f..1e6df4dc84 100644 --- a/CMake/mitkMacroInstallPython.cmake +++ b/CMake/mitkMacroInstallPython.cmake @@ -1,110 +1,124 @@ macro(MITK_INSTALL_PYTHON _python_libs _python_dirs) if(UNIX) set(PYTHON_LIB_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) else(WIN32) set(PYTHON_LIB_SUFFIX .pyd) endif() # SimpleITK if(MITK_USE_SimpleITK) install(FILES "${SimpleITK_DIR}/Wrapping/SimpleITK.py" DESTINATION bin/Python/SimpleITK ) install(FILES "${SimpleITK_DIR}/Wrapping/__init__.py" DESTINATION bin/Python/SimpleITK ) install(FILES "${SimpleITK_DIR}/Wrapping/_SimpleITK${PYTHON_LIB_SUFFIX}" DESTINATION bin/Python/SimpleITK ) if(UNIX AND NOT APPLE) install(CODE "file(RPATH_REMOVE FILE \"\${CMAKE_INSTALL_PREFIX}/bin/Python/SimpleITK/_SimpleITK${PYTHON_LIB_SUFFIX}\")") endif() list(APPEND _python_libs "Python/SimpleITK/_SimpleITK${PYTHON_LIB_SUFFIX}") list(APPEND _python_dirs "${SimpleITK_DIR}/../SimpleITK-install/lib") endif() # install OpenCV python wrapping if(MITK_USE_OpenCV) list(APPEND _python_libs "cv2${CMAKE_SHARED_LIBRARY_SUFFIX}") install(FILES "${OpenCV_DIR}/lib/cv2${CMAKE_SHARED_LIBRARY_SUFFIX}" DESTINATION bin) if(UNIX AND NOT APPLE) install(CODE "file(RPATH_REMOVE FILE \"\${CMAKE_INSTALL_PREFIX}/bin/cv2${CMAKE_SHARED_LIBRARY_SUFFIX}\")") endif() list(APPEND _python_dirs "${OpenCV_DIR}/lib") endif() # install VTK python wrapping find_package(VTK REQUIRED) set(_VTK_PYTHON_TARGETS ) # find all vtk python wrapped targets foreach(_lib ${VTK_LIBRARIES}) # exclude system libs if(${_lib} MATCHES "^vtk.+") # use only python wrapped modules ( targets end with PythonD ) if(TARGET ${_lib}PythonD) list(APPEND _VTK_PYTHON_TARGETS ${_lib}Python) endif() endif() endforeach() # install the python modules and loaders foreach(_target ${_VTK_PYTHON_TARGETS}) # get the properties of the python wrapped target if( CMAKE_BUILD_TYPE STREQUAL "Debug") get_target_property(_target_lib "${_target}D" IMPORTED_LOCATION_DEBUG) else() get_target_property(_target_lib "${_target}D" IMPORTED_LOCATION_RELEASE) endif() get_filename_component(_filepath "${_target_lib}" PATH) install(FILES "${_filepath}/${_target}${PYTHON_LIB_SUFFIX}" DESTINATION bin) if(UNIX AND NOT APPLE ) install(CODE "file(RPATH_REMOVE FILE \"\${CMAKE_INSTALL_PREFIX}/bin/${_target}${PYTHON_LIB_SUFFIX}\")") endif() list(APPEND _python_libs "${_target}${PYTHON_LIB_SUFFIX}") endforeach() # install vtk python. This folder contains all *.py files for VTK module loading. - install(DIRECTORY "${VTK_DIR}/Wrapping/Python/vtk" - DESTINATION bin/Python - USE_SOURCE_PERMISSIONS - COMPONENT Runtime) + # 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 bin/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") # install python stuff - install(DIRECTORY "${Python_DIR}/lib/python2.7" + install(DIRECTORY "${Python_DIR}/lib/python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}" DESTINATION bin/Python/lib USE_SOURCE_PERMISSIONS COMPONENT Runtime) - install(FILES "${Python_DIR}/include/python2.7/pyconfig.h" DESTINATION bin/Python/include/python2.7) - else(WIN32) + install(FILES "${Python_DIR}/include/python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}/pyconfig.h" + DESTINATION bin/Python/include/python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}) + else() list(APPEND _python_dirs "${Python_DIR}/libs") list(APPEND _python_dirs "${Python_DIR}/bin") - install(DIRECTORY "${Python_DIR}/Lib" - DESTINATION bin/Python - USE_SOURCE_PERMISSIONS - COMPONENT Runtime) - install(DIRECTORY "${Python_DIR}/include" - DESTINATION bin/Python - USE_SOURCE_PERMISSIONS - COMPONENT Runtime) + file(GLOB_RECURSE item RELATIVE "${Python_DIR}/Lib" "${Python_DIR}/Lib/*") + foreach(f ${item}) + get_filename_component(_filepath "${f}" PATH) + install(FILES "${Python_DIR}/Lib/${f}" DESTINATION bin/Python/Lib/${_filepath}) + endforeach() + file(GLOB_RECURSE item RELATIVE "${Python_DIR}/include" "${Python_DIR}/include/*") + foreach(f ${item}) + get_filename_component(_filepath "${f}" PATH) + install(FILES "${Python_DIR}/include/${f}" DESTINATION bin/Python/include/${_filepath}) + endforeach() endif() endif() + if(Numpy_DIR) + # glob through all files, NSIS can't use directories + file(GLOB_RECURSE item RELATIVE "${Numpy_DIR}/numpy" "${Numpy_DIR}/numpy/*") + foreach(f ${item}) + get_filename_component(_filepath "${f}" PATH) + install(FILES "${Numpy_DIR}/numpy/${f}" DESTINATION bin/Python/numpy/${_filepath}) + endforeach() + endif() + list(REMOVE_DUPLICATES _python_dirs) endmacro() diff --git a/CMakeExternals/CableSwig.cmake b/CMakeExternals/CableSwig.cmake deleted file mode 100644 index 0a70771456..0000000000 --- a/CMakeExternals/CableSwig.cmake +++ /dev/null @@ -1,44 +0,0 @@ -#----------------------------------------------------------------------------- -# CableSwig -#----------------------------------------------------------------------------- - -if(MITK_USE_Python AND UNIX) - -# Sanity checks -if(DEFINED CableSwig_DIR AND NOT EXISTS ${CableSwig_DIR}) - message(FATAL_ERROR "CableSwig_DIR variable is defined but corresponds to non-existing directory") -endif() - -set(proj CableSwig) -set(proj_DEPENDENCIES ) -set(CableSwig_DEPENDS ${proj}) - -if(NOT DEFINED CableSwig_DIR) - - set(additional_cmake_args ) - - ExternalProject_Add(${proj} - SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src - BINARY_DIR ${proj}-build - PREFIX ${proj}-cmake - URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/CableSwig-ITK-3.20.0-v2.tar.gz - URL_MD5 893882bf8b4fbfbae3fe8c747a75f7a0 - INSTALL_COMMAND "" - CMAKE_GENERATOR ${gen} - CMAKE_ARGS - ${ep_common_args} - ${additional_cmake_args} - -DBUILD_TESTING:BOOL=OFF - -DSWIG_BUILD_EXAMPLES:BOOL=OFF - DEPENDS ${proj_DEPENDENCIES} - ) - - set(CableSwig_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) - -else() - - mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") - -endif() - -endif() diff --git a/CMakeExternals/Numpy.cmake b/CMakeExternals/Numpy.cmake new file mode 100644 index 0000000000..f87207622c --- /dev/null +++ b/CMakeExternals/Numpy.cmake @@ -0,0 +1,127 @@ + +if( MITK_USE_Python ) + + option(MITK_USE_NUMPY "Use the numpy python library" OFF) + + # always build numpy in this case + if(NOT MITK_USE_SYSTEM_PYTHON) + set(MITK_USE_NUMPY ON CACHE BOOL "Use the numpy python library" FORCE) + endif() + + if(MITK_USE_NUMPY) + # 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 ) + set(Numpy_DEPENDS ${proj}) + + if(NOT MITK_USE_SYSTEM_PYTHON) + list(APPEND proj_DEPENDENCIES Python) + endif() + + 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(_external_python_project ${CMAKE_BINARY_DIR}/mitkExternalPythonProject.cmake) + file(WRITE ${_external_python_project} + " + ${_numpy_env} + set(ENV{VS_UNICODE_OUTPUT} \"\") + set(ENV{CC} \"${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}\") + set(ENV{CFLAGS} \"${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\") + set(ENV{CXX} \"${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}\") + set(ENV{CXXFLAGS} \"${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\") + set(ENV{LDFLAGS} \"${CMAKE_LINKER_FLAGS} ${CMAKE_LINKER_FLAGS_RELEASE}\") + + function(MITK_PYTHON_BUILD_STEP proj step) + set(_command \${ARGN}) + + message(\"Running \${proj} \${step}:${PYTHON_EXECUTABLE} \${_command}\") + + execute_process( + COMMAND ${PYTHON_EXECUTABLE} \${_command} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/\${proj}-src + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE error + ) + set(output_file \"${CMAKE_BINARY_DIR}/\${proj}_\${step}_step_output.txt\") + file(WRITE \${output_file} \${output}) + + set(error_file \"${CMAKE_BINARY_DIR}/\${proj}_\${step}_step_error.txt\") + file(WRITE \${error_file} \${error}) + + if(NOT \${result} EQUAL 0) + message(FATAL_ERROR \"Error in: \${proj}: \${error}\") + endif() + endfunction() + ") + # configure step + set(_configure_step ${CMAKE_BINARY_DIR}/${proj}_configure_step.cmake) + file(WRITE ${_configure_step} + "include(\"${_external_python_project}\") + file(WRITE \"${CMAKE_BINARY_DIR}/${proj}-src/site.cfg\" \"\") + MITK_PYTHON_BUILD_STEP(${proj} configure setup.py config) + ") + + # build step + set(_build_step ${CMAKE_BINARY_DIR}/${proj}_build_step.cmake) + file(WRITE ${_build_step} + "include(\"${_external_python_project}\") + MITK_PYTHON_BUILD_STEP(${proj} build setup.py build --fcompiler=none) + ") + + # install step + set(_install_dir "${CMAKE_BINARY_DIR}/${proj}-install") + if(WIN32) + STRING(REPLACE "/" "\\\\" _install_dir "${CMAKE_BINARY_DIR}/${proj}-install") + endif() + set(_install_step ${CMAKE_BINARY_DIR}/${proj}_install_step.cmake) + file(WRITE ${_install_step} + "include(\"${_external_python_project}\") + MITK_PYTHON_BUILD_STEP(${proj} install setup.py install --prefix=${_install_dir}) + ") + + #set(Numpy_URL "https://dl.dropboxusercontent.com/u/8367205/ExternalProjects/numpy-1.6.1.tar.gz") + #set(Numpy_MD5 "2bce18c08fc4fce461656f0f4dd9103e") + set(Numpy_URL "https://dl.dropboxusercontent.com/u/8367205/ExternalProjects/numpy-1.4.1.tar.gz") + set(Numpy_MD5 "5c7b5349dc3161763f7f366ceb96516b") + + ExternalProject_Add(${proj} + URL ${Numpy_URL} + URL_MD5 ${Numpy_MD5} + SOURCE_DIR ${proj}-src + PREFIX ${proj}-cmake + BUILD_IN_SOURCE 1 + INSTALL_DIR ${CMAKE_BINARY_DIR}/${proj}-install + CONFIGURE_COMMAND ${CMAKE_COMMAND} -P ${_configure_step} + BUILD_COMMAND ${CMAKE_COMMAND} -P ${_build_step} + INSTALL_COMMAND ${CMAKE_COMMAND} -P ${_install_step} + + DEPENDS + ${${proj}_DEPENDENCIES} + ) + + if(WIN32) + set(Numpy_DIR ${CMAKE_BINARY_DIR}/${proj}-install/Lib/site-packages) + else() + set(Numpy_DIR ${CMAKE_BINARY_DIR}/${proj}-install/lib/python2.7/site-packages) + endif() + else() + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + endif() + endif() +endif() + diff --git a/CMakeExternals/OpenCV.cmake b/CMakeExternals/OpenCV.cmake index 6d496139ce..6d53c7074a 100644 --- a/CMakeExternals/OpenCV.cmake +++ b/CMakeExternals/OpenCV.cmake @@ -1,93 +1,99 @@ #----------------------------------------------------------------------------- # OpenCV #----------------------------------------------------------------------------- if(MITK_USE_OpenCV) # Sanity checks if(DEFINED OpenCV_DIR AND NOT EXISTS ${OpenCV_DIR}) message(FATAL_ERROR "OpenCV_DIR variable is defined but corresponds to non-existing directory") endif() set(proj OpenCV) set(proj_DEPENDENCIES) set(OpenCV_DEPENDS ${proj}) if(NOT DEFINED OpenCV_DIR) set(additional_cmake_args -DBUILD_opencv_java:BOOL=OFF ) if(MITK_USE_Python) #message(STATUS "PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}") #message(STATUS "PYTHON_DEBUG_LIBRARY: ${PYTHON_DEBUG_LIBRARY}") #message(STATUS "PYTHON_INCLUDE_DIR: ${PYTHON_INCLUDE_DIR}") #message(STATUS "PYTHON_LIBRARY: ${PYTHON_LIBRARY}") - - if( NOT MITK_USE_Python) - list(APPEND proj_DEPENDENCIES Python_DEPENDS) - endif() list(APPEND additional_cmake_args -DBUILD_opencv_python:BOOL=ON -DBUILD_NEW_PYTHON_SUPPORT:BOOL=ON -DPYTHON_DEBUG_LIBRARY:FILEPATH=${PYTHON_DEBUG_LIBRARY} -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} + #-DPYTHON_LIBRARIES=${PYTHON_LIBRARY} #-DPYTHON_DEBUG_LIBRARIES=${PYTHON_DEBUG_LIBRARIES} ) + if(NOT MITK_USE_SYSTEM_PYTHON) + list(APPEND proj_DEPENDENCIES Python) + endif() + if(MITK_USE_NUMPY) + list(APPEND proj_DEPENDENCIES Numpy) + list(APPEND additional_cmake_args + -DPYTHON_NUMPY_INCLUDE_DIR:PATH=${Numpy_DIR}/numpy/core/include/numpy + ) + endif() else() list(APPEND additional_cmake_args -DBUILD_opencv_python:BOOL=OFF -DBUILD_NEW_PYTHON_SUPPORT:BOOL=OFF ) endif() # 12-05-02, muellerm, added QT usage by OpenCV if QT is used in MITK # 12-09-11, muellerm, removed automatic usage again, since this will struggle with the MITK Qt application object if(MITK_USE_QT) list(APPEND additional_cmake_args -DWITH_QT:BOOL=OFF -DWITH_QT_OPENGL:BOOL=OFF -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() set(OpenCV_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchOpenCV-2.4.8.2.cmake) set(opencv_url ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/OpenCV-2.4.8.2.tar.gz) set(opencv_url_md5 07fa7c1d225ea7fe8eeb1270a6b00e69) ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake URL ${opencv_url} URL_MD5 ${opencv_url_md5} INSTALL_COMMAND "" PATCH_COMMAND ${OpenCV_PATCH_COMMAND} CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DBUILD_DOCS:BOOL=OFF -DBUILD_TESTS:BOOL=OFF -DBUILD_EXAMPLES:BOOL=OFF -DBUILD_DOXYGEN_DOCS:BOOL=OFF -DWITH_CUDA:BOOL=ON ${additional_cmake_args} DEPENDS ${proj_DEPENDENCIES} ) set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/PatchPython.cmake b/CMakeExternals/PatchPython.cmake new file mode 100644 index 0000000000..a9e3587124 --- /dev/null +++ b/CMakeExternals/PatchPython.cmake @@ -0,0 +1,8 @@ +# +# Windows python 2.7.3 patches for the CMake build system +# https://github.com/davidsansome/python-cmake-buildsystem/tree/master/cmake/patches-win32 +# +set(in ${CMAKE_CURRENT_LIST_DIR}/msvc9compiler.py.patched) +set(out ${PYTHON_SOURCE_DIR}/Lib/distutils/msvc9compiler.py) + +execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${in} ${out}) diff --git a/CMakeExternals/Python.cmake b/CMakeExternals/Python.cmake index 1db60577ea..695be3b37d 100644 --- a/CMakeExternals/Python.cmake +++ b/CMakeExternals/Python.cmake @@ -1,136 +1,155 @@ if( MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON ) - if(NOT DEFINED Python_DIR) - set(proj Python) - set(proj_DEPENDENCIES ) - set(Python_DEPENDS ${proj}) - set(PYTHON_MAJOR_VERSION 2) - set(PYTHON_MINOR_VERSION 7) - set(PYTHON_PATCH_VERSION 3) + # Sanity checks + if(DEFINED Python_DIR AND NOT EXISTS ${Python_DIR}) + message(FATAL_ERROR "Python_DIR variable is defined but corresponds to non-existing directory") + endif() + + if(NOT DEFINED Python_DIR) + set(proj Python) + set(proj_DEPENDENCIES ) + set(Python_DEPENDS ${proj}) + + set(PYTHON_MAJOR_VERSION 2) + set(PYTHON_MINOR_VERSION 7) + set(PYTHON_PATCH_VERSION 3) + + set(PYTHON_SOURCE_PACKAGE Python-${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}.${PYTHON_PATCH_VERSION}) + set(PYTHON_SOURCE_DIR "${CMAKE_BINARY_DIR}/${PYTHON_SOURCE_PACKAGE}") + # patch the VS compiler config + + if(WIN32) + set(PYTHON_PATCH_COMMAND PATCH_COMMAND ${CMAKE_COMMAND} -DPYTHON_SOURCE_DIR:PATH=${PYTHON_SOURCE_DIR} -P ${CMAKE_CURRENT_LIST_DIR}/Patch${proj}.cmake) + endif() + + # download the source code + ExternalProject_Add(Python-src + URL "https://dl.dropboxusercontent.com/u/8367205/ExternalProjects/${PYTHON_SOURCE_PACKAGE}.tgz" + URL_MD5 "2cf641732ac23b18d139be077bd906cd" + PREFIX ${CMAKE_BINARY_DIR}/${PYTHON_SOURCE_PACKAGE}-cmake + SOURCE_DIR "${PYTHON_SOURCE_DIR}" + ${PYTHON_PATCH_COMMAND} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + set(additional_cmake_cache_args ) + list(APPEND additional_cmake_cache_args + -DBUILTIN_ARRAY:BOOL=ON + -DBUILTIN_AUDIOOP:BOOL=ON + -DBUILTIN_BINASCII:BOOL=ON + -DBUILTIN_BISECT:BOOL=ON + -DBUILTIN_BSDB:BOOL=ON + -DBUILTIN_BSSDB:BOOL=ON + -DBUILTIN_BZ2:BOOL=ON + -DBUILTIN_CMATH:BOOL=ON + -DBUILTIN_COLLECTIONS:BOOL=ON + -DBUILTIN_CODECS_CN:BOOL=ON + -DBUILTIN_CODECS_HK:BOOL=ON + -DBUILTIN_CODECS_ISO2022:BOOL=ON + -DBUILTIN_CODECS_JP:BOOL=ON + -DBUILTIN_CODECS_KR:BOOL=ON + -DBUILTIN_CODECS_TW:BOOL=ON + -DBUILTIN_CPICKLE:BOOL=ON + -DBUILTIN_CRYPT:BOOL=ON + -DBUILTIN_CSTRINGIO:BOOL=ON + -DBUILTIN_CSV:BOOL=ON + -DBUILTIN_CTYPES:BOOL=OFF + #-DBUILTIN_CTYPES_TEST:BOOL=OFF + #-DBUILTIN_CURSES:BOOL=ON + -DBUILTIN_DATETIME:BOOL=ON + -DBUILTIN_DBM:BOOL=ON + -DBUILTIN_ELEMENTTREE:BOOL=ON + -DBUILTIN_FCNTL:BOOL=ON + -DBUILTIN_FUNCTOOLS:BOOL=ON + -DBUILTIN_FUTURE_BUILTINS:BOOL=ON + -DBULTIN_GDBM:BOOL=ON + -DBUILTIN_GRP:BOOL=ON + -DBUILTIN_HASHLIB:BOOL=ON + -DBUILTIN_HEAPQ:BOOL=ON + -DBUILTIN_HOTSHOT:BOOL=ON + -DBUILTIN_IO:BOOL=ON + -DBUILTIN_ITERTOOLS:BOOL=ON + -DBUILTIN_JSON:BOOL=ON + -DBUILTIN_LOCALE:BOOL=ON + -DBUILTIN_LSPROF:BOOL=ON + -DBUILTIN_MATH:BOOL=ON + -DBUILTIN_MMAP:BOOL=ON + -DBUILTIN_MULTIBYTECODEC:BOOL=ON + -DBUILTIN_MD5:BOOL=ON + -DBUILTIN_MULTIPROCESSING:BOOL=ON + -DBUILTIN_NIS:BOOL=ON + -DBUILTIN_NIT:BOOL=ON + -DBUILTIN_OPERATOR:BOOL=ON + -DBUILTIN_PARSER:BOOL=ON + -DBUILTIN_POSIX:BOOL=ON + -DBUILTIN_PWD:BOOL=ON + -DBUILTIN_PYEXPAT:BOOL=ON + -DBUILTIN_READLINE:BOOL=ON + -DBUILTIN_RESOURCE:BOOL=ON + -DBULTIN_RANDOM:BOOL=ON + -DBUILTIN_SCPROXY:BOOL=ON + -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=ON + -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=ON + ) - # download the source code - ExternalProject_Add(Python-src - URL "https://www.python.org/ftp/python/${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}.${PYTHON_PATCH_VERSION}/Python-${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}.${PYTHON_PATCH_VERSION}.tgz" - #URL_MD5 "d41d8cd98f00b204e9800998ecf8427e" - #DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR} - SOURCE_DIR "${CMAKE_BINARY_DIR}/Python-${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}.${PYTHON_PATCH_VERSION}" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - ) + # CMake build environment for python + ExternalProject_Add(${proj} + URL "https://dl.dropboxusercontent.com/u/8367205/ExternalProjects/python-cmake-buildsystem.tar.gz" + URL_MD5 "171090922892acdaf1a155e22765d72d" + SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src + PREFIX ${proj}-cmake + BINARY_DIR ${proj}-build + INSTALL_DIR ${proj}-install + CMAKE_ARGS + ${ep_common_args} + -DCMAKE_INSTALL_PREFIX:PATH= + CMAKE_CACHE_ARGS + -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} + -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} + #-DBUILD_TESTING:BOOL=OFF + -DBUILD_SHARED:BOOL=ON + -DBUILD_STATIC:BOOL=OFF + -DUSE_SYSTEM_LIBRARIES:BOOL=ON + ${additional_cmake_cache_args} + DEPENDS + Python-src ${${proj}_DEPENDENCIES} + ) - 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=ON - -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=ON - -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=ON - ) + set(Python_DIR "${CMAKE_BINARY_DIR}/${proj}-install") + if(UNIX) + set(PYTHON_EXECUTABLE "${CMAKE_BINARY_DIR}/${proj}-build/bin/python${CMAKE_EXECUTABLE_SUFFIX}") + set(PYTHON_INCLUDE_DIR "${Python_DIR}/include/python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}") + set(PYTHON_LIBRARY "${CMAKE_BINARY_DIR}/${proj}-build/lib/${CMAKE_SHARED_LIBRARY_PREFIX}python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") + else() + set(PYTHON_EXECUTABLE "${Python_DIR}/bin/python${CMAKE_EXECUTABLE_SUFFIX}") + set(PYTHON_INCLUDE_DIR "${Python_DIR}/include") + set(PYTHON_LIBRARY "${Python_DIR}/libs/python${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION}.lib") + endif() - # CMake build environment for python - ExternalProject_Add(${proj} - GIT_REPOSITORY "git://github.com/davidsansome/python-cmake-buildsystem.git" - GIT_TAG "3c5864f210a8d0ae1196be7c691252e16e459f59" - SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src - PREFIX ${proj}-cmake - BINARY_DIR ${proj}-build - INSTALL_DIR ${proj}-install - CMAKE_ARGS - ${ep_common_args} - -DCMAKE_INSTALL_PREFIX:PATH= - CMAKE_CACHE_ARGS - -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} - -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} - #-DBUILD_TESTING:BOOL=OFF - -DBUILD_SHARED:BOOL=ON - -DBUILD_STATIC:BOOL=OFF - -DUSE_SYSTEM_LIBRARIES:BOOL=ON - ${additional_cmake_cache_args} - DEPENDS - Python-src ${${proj}_DEPENDENCIES} - ) + # get the name of the library + get_filename_component(PYTHON_LIBRARY_NAME "${PYTHON_LIBRARY}" NAME) - set(Python_DIR "${CMAKE_BINARY_DIR}/${proj}-install") - if(UNIX) - set(PYTHON_EXECUTABLE "${CMAKE_BINARY_DIR}/${proj}-build/bin/python${CMAKE_EXECUTABLE_SUFFIX}") - set(PYTHON_INCLUDE_DIR "${Python_DIR}/include/python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}") - set(PYTHON_LIBRARY "${CMAKE_BINARY_DIR}/${proj}-build/lib/${CMAKE_SHARED_LIBRARY_PREFIX}python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") - else(WIN32) - set(PYTHON_EXECUTABLE "${Python_DIR}/bin/python${CMAKE_EXECUTABLE_SUFFIX}") - set(PYTHON_INCLUDE_DIR "${Python_DIR}/include") - set(PYTHON_LIBRARY "${Python_DIR}/libs/python${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION}.lib") + else() + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() - else() - mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") - endif() endif() diff --git a/CMakeExternals/SimpleITK.cmake b/CMakeExternals/SimpleITK.cmake index 1e27334872..cf1a191f87 100644 --- a/CMakeExternals/SimpleITK.cmake +++ b/CMakeExternals/SimpleITK.cmake @@ -1,89 +1,89 @@ #----------------------------------------------------------------------------- # 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() + # 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() if(NOT MITK_USE_SYSTEM_PYTHON) list(APPEND proj_DEPENDENCIES Python) 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 ) if(MITK_USE_Python) list(APPEND additional_cmake_args -DWRAP_PYTHON:BOOL=ON ) endif(MITK_USE_Python) if(MITK_USE_OpenCV) list(APPEND additional_cmake_args -DOpenCV_DIR:PATH=${OpenCV_DIR} ) endif() set(SimpleITK_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchSimpleITK.cmake) ExternalProject_Add(${proj} + URL "https://dl.dropboxusercontent.com/u/8367205/ExternalProjects/SimpleITK.tar.gz" + URL_MD5 "7cfa5d0ff79a540f4bcfaf992abe44d2" + #GIT_TAG "493f15f5cfc620413d0aa7bb705ffe6d038a41b5" SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake - GIT_REPOSITORY "http://itk.org/SimpleITK.git" - GIT_TAG "493f15f5cfc620413d0aa7bb705ffe6d038a41b5" - #INSTALL_COMMAND "" INSTALL_DIR ${proj}-install PATCH_COMMAND ${SimpleITK_PATCH_COMMAND} CMAKE_ARGS ${ep_common_args} -DCMAKE_INSTALL_PREFIX:PATH= CMAKE_CACHE_ARGS ${additional_cmake_args} -DSimpleITK_BUILD_DISTRIBUTE:BOOL=ON -DSimpleITK_PYTHON_THREADS:BOOL=ON -DUSE_SYSTEM_ITK:BOOL=ON -DBUILD_TESTING:BOOL=OFF -DBUILD_EXAMPLES:BOOL=OFF -DGDCM_DIR:PATH=${GDCM_DIR} -DITK_DIR:PATH=${ITK_DIR} -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} -DSWIG_DIR:PATH=${SWIG_DIR} -DSWIG_EXECUTABLE:FILEPATH=${SWIG_EXECUTABLE} DEPENDS ${proj_DEPENDENCIES} ) set(SimpleITK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/Swig.cmake b/CMakeExternals/Swig.cmake index 683daa7eb4..1974f9a08c 100644 --- a/CMakeExternals/Swig.cmake +++ b/CMakeExternals/Swig.cmake @@ -1,72 +1,66 @@ -# Sanity checks -if(DEFINED Swig_DIR AND NOT EXISTS ${Swig_DIR}) - message(FATAL_ERROR "Swig_DIR variable is defined but corresponds to non-existing directory") -endif() - -if(NOT SWIG_DIR) - - set(SWIG_TARGET_VERSION 3.0.2) - set(SWIG_DOWNLOAD_SOURCE_HASH "62f9b0d010cef36a13a010dc530d0d41") - set(SWIG_DOWNLOAD_WIN_HASH "3f18de4fc09ab9abb0d3be37c11fbc8f") - set(proj Swig) - set(Swig_DEPENDENCIES ) - set(Swig_DEPENDS ) +if(MITK_USE_SWIG) + # Sanity checks + if(DEFINED Swig_DIR AND NOT EXISTS ${Swig_DIR}) + message(FATAL_ERROR "Swig_DIR variable is defined but corresponds to non-existing directory") + endif() + if(NOT SWIG_DIR) + set(SWIG_TARGET_VERSION 3.0.2) + set(proj Swig) + set(Swig_DEPENDENCIES ) + set(Swig_DEPENDS ) - if(WIN32) # binary SWIG for windows - #------------------------------------------------------------------------------ - set(swig_source_dir ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}) - - # swig.exe available as pre-built binary on Windows: - ExternalProject_Add(Swig - URL http://midas3.kitware.com/midas/api/rest?method=midas.bitstream.download&checksum=${SWIG_DOWNLOAD_WIN_HASH}&name=swigwin-${SWIG_TARGET_VERSION}.zip - URL_MD5 ${SWIG_DOWNLOAD_WIN_HASH} - SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION} - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - ) - - set(SWIG_DIR ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}) # path specified as source in ep - set(SWIG_EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}/swig.exe) - - else() - # compiled SWIG for others - #------------------------------------------------------------------------------ - - # swig uses bison find it by cmake and pass it down - find_package(BISON) - set(BISON_FLAGS "" CACHE STRING "Flags used by bison") - mark_as_advanced( BISON_FLAGS) - - - # follow the standard EP_PREFIX locations - set(swig_binary_dir ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src) - set(swig_source_dir ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src) - set(swig_install_dir ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install) - - # configure step - configure_file( - ${MITK_SOURCE_DIR}/CMakeExternals/swig_configure_step.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/swig_configure_step.cmake - @ONLY) - set(swig_CONFIGURE_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/swig_configure_step.cmake) - - ExternalProject_add(Swig - URL http://midas3.kitware.com/midas/api/rest?method=midas.bitstream.download&checksum=${SWIG_DOWNLOAD_SOURCE_HASH}&name=swig-${SWIG_TARGET_VERSION}.tar.gz - URL_MD5 ${SWIG_DOWNLOAD_SOURCE_HASH} - SOURCE_DIR ${swig_source_dir} - INSTALL_DIR ${swig_install_dir} - PREFIX ${proj}-cmake - BUILD_IN_SOURCE 1 - CONFIGURE_COMMAND ${swig_CONFIGURE_COMMAND} - ) - - set(SWIG_DIR ${swig_install_dir}/share/swig/${SWIG_TARGET_VERSION}) - set(SWIG_EXECUTABLE ${swig_install_dir}/bin/swig) - - endif() -endif(NOT SWIG_DIR) - + if(WIN32) + set(swig_source_dir ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}) + + # swig.exe available as pre-built binary on Windows: + ExternalProject_Add(Swig + URL https://dl.dropboxusercontent.com/u/8367205/ExternalProjects/swigwin-${SWIG_TARGET_VERSION}.zip + URL_MD5 "3f18de4fc09ab9abb0d3be37c11fbc8f" + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + set(SWIG_DIR ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}) # path specified as source in ep + set(SWIG_EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/swigwin-${SWIG_TARGET_VERSION}/swig.exe) + + else() + + # swig uses bison find it by cmake and pass it down + find_package(BISON) + set(BISON_FLAGS "" CACHE STRING "Flags used by bison") + mark_as_advanced( BISON_FLAGS) + + + # follow the standard EP_PREFIX locations + set(swig_binary_dir ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src) + set(swig_source_dir ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src) + set(swig_install_dir ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install) + + # configure step + configure_file( + ${MITK_SOURCE_DIR}/CMakeExternals/swig_configure_step.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/swig_configure_step.cmake + @ONLY) + set(swig_CONFIGURE_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/swig_configure_step.cmake) + + ExternalProject_add(Swig + URL https://dl.dropboxusercontent.com/u/8367205/ExternalProjects/swig-${SWIG_TARGET_VERSION}.tar.gz + URL_MD5 "62f9b0d010cef36a13a010dc530d0d41" + SOURCE_DIR ${swig_source_dir} + INSTALL_DIR ${swig_install_dir} + PREFIX ${proj}-cmake + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND ${swig_CONFIGURE_COMMAND} + ) + + set(SWIG_DIR ${swig_install_dir}/share/swig/${SWIG_TARGET_VERSION}) + set(SWIG_EXECUTABLE ${swig_install_dir}/bin/swig) + + endif() + endif(NOT SWIG_DIR) +endif() diff --git a/CMakeExternals/msvc9compiler.py.patched b/CMakeExternals/msvc9compiler.py.patched new file mode 100644 index 0000000000..daf78685a2 --- /dev/null +++ b/CMakeExternals/msvc9compiler.py.patched @@ -0,0 +1,924 @@ +"""distutils.msvc9compiler + +Contains MSVCCompiler, an implementation of the abstract CCompiler class +for the Microsoft Visual Studio 2008. + +The module is compatible with VS 2005 and VS 2008. You can find legacy support +for older versions of VS in distutils.msvccompiler. +""" + +# Written by Perry Stoll +# hacked by Robin Becker and Thomas Heller to do a better job of +# finding DevStudio (through the registry) +# ported to VS2005 and VS 2008 by Christian Heimes + +__revision__ = "$Id$" + +import os +import subprocess +import sys +import re + +from distutils.errors import (DistutilsExecError, DistutilsPlatformError, + CompileError, LibError, LinkError) +from distutils.ccompiler import CCompiler, gen_lib_options +from distutils import log +from distutils.util import get_platform + +import _winreg + +RegOpenKeyEx = _winreg.OpenKeyEx +RegEnumKey = _winreg.EnumKey +RegEnumValue = _winreg.EnumValue +RegError = _winreg.error + +HKEYS = (_winreg.HKEY_USERS, + _winreg.HKEY_CURRENT_USER, + _winreg.HKEY_LOCAL_MACHINE, + _winreg.HKEY_CLASSES_ROOT) + +NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32) +if NATIVE_WIN64: + # Visual C++ is a 32-bit application, so we need to look in + # the corresponding registry branch, if we're running a + # 64-bit Python on Win64 + VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f" + WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" + VC_SXS_KEY = r"Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7" + VS_SXS_KEY = r"Software\Wow6432Node\Microsoft\VisualStudio\SxS\VS7" +else: + VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f" + WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Microsoft\.NETFramework" + VC_SXS_KEY = r"Software\Microsoft\VisualStudio\SxS\VC7" + VS_SXS_KEY = r"Software\Microsoft\VisualStudio\SxS\VS7" + +# A map keyed by get_platform() return values to values accepted by +# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is +# the param to cross-compile on x86 targetting amd64.) +PLAT_TO_VCVARS = { + 'win32' : 'x86', + 'win-amd64' : 'amd64', + 'win-ia64' : 'ia64', +} + +# Add the first found value of InstallationFolder from this list of +# keys to %PATH% +KEY_BASE = r"Software\Microsoft\\" +WINSDK_KEYS = [KEY_BASE + "Microsoft SDKs\\Windows\\" + rest for rest in ( + r"v%s", + r"v%sA" +)] + +# A map from VC version to Windows SDK version, to be used as the format +# parameter for each element of WINSDK_KEYS. +# See the following page for more details: +# - http://en.wikipedia.org/wiki/Microsoft_Windows_SDK#Versions +# - http://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History +WINSDK_VERSION_MAP = { + '9.0': ['6.0', '7.0'], # VS2008 + '10.0': ['7.0', '7.1'], # VS2010 + '11.0': ['7.1', '8.0', '8.1'], # VS2012 +} + +class Reg: + """Helper class to read values from the registry + """ + + def get_value(cls, path, key): + for base in HKEYS: + d = cls.read_values(base, path) + if d and key in d: + return d[key] + raise KeyError(key) + get_value = classmethod(get_value) + + def read_keys(cls, base, key): + """Return list of registry keys.""" + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + L = [] + i = 0 + while True: + try: + k = RegEnumKey(handle, i) + except RegError: + break + L.append(k) + i += 1 + return L + read_keys = classmethod(read_keys) + + def read_values(cls, base, key): + """Return dict of registry keys and values. + + All names are converted to lowercase. + """ + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + d = {} + i = 0 + while True: + try: + name, value, type = RegEnumValue(handle, i) + except RegError: + break + name = name.lower() + d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) + i += 1 + return d + read_values = classmethod(read_values) + + def convert_mbcs(s): + dec = getattr(s, "decode", None) + if dec is not None: + try: + s = dec("mbcs") + except UnicodeError: + pass + return s + convert_mbcs = staticmethod(convert_mbcs) + +class MacroExpander: + + def __init__(self, version): + self.macros = {} + self.vsbase = VS_BASE % version + self.load_macros(version) + + def set_macro(self, macro, path, key): + self.macros["$(%s)" % macro] = Reg.get_value(path, key) + + def load_macros(self, version): + self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir") + self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir") + self.set_macro("FrameworkDir", NET_BASE, "installroot") + try: + if version >= 8.0: + self.set_macro("FrameworkSDKDir", NET_BASE, + "sdkinstallrootv2.0") + else: + raise KeyError("sdkinstallrootv2.0") + except KeyError: + raise DistutilsPlatformError( + """Python was built with Visual Studio 2008; +extensions must be built with a compiler than can generate compatible binaries. +Visual Studio 2008 was not found on this system. If you have Cygwin installed, +you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""") + + if version >= 9.0: + self.set_macro("FrameworkVersion", self.vsbase, "clr version") + self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder") + else: + p = r"Software\Microsoft\NET Framework Setup\Product" + for base in HKEYS: + try: + h = RegOpenKeyEx(base, p) + except RegError: + continue + key = RegEnumKey(h, 0) + d = Reg.get_value(base, r"%s\%s" % (p, key)) + self.macros["$(FrameworkVersion)"] = d["version"] + + def sub(self, s): + for k, v in self.macros.items(): + s = s.replace(k, v) + return s + +def get_build_version(): + """Return the version of MSVC that was used to build Python. + + For Python 2.3 and up, the version number is included in + sys.version. For earlier versions, assume the compiler is MSVC 6. + """ + prefix = "MSC v." + i = sys.version.find(prefix) + if i == -1: + return 6 + i = i + len(prefix) + s, rest = sys.version[i:].split(" ", 1) + majorVersion = int(s[:-2]) - 6 + minorVersion = int(s[2:3]) / 10.0 + # I don't think paths are affected by minor version in version 6 + if majorVersion == 6: + minorVersion = 0 + if majorVersion >= 6: + return majorVersion + minorVersion + # else we don't know what version of the compiler this is + return None + +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths + +def removeDuplicates(variable): + """Remove duplicate values of an environment variable. + """ + oldList = variable.split(os.pathsep) + newList = [] + for i in oldList: + if i not in newList: + newList.append(i) + newVariable = os.pathsep.join(newList) + return newVariable + +# deprecated +def find_vcvarsall(version): + """Find the vcvarsall.bat file + + At first it tries to find the productdir of VS 2008 in the registry. If + that fails it falls back to the VS90COMNTOOLS env var. + """ + vsbase = VS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + productdir = None + + # trying Express edition + if productdir is None: + vsbase = VSEXPRESS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + productdir = None + log.debug("Unable to find productdir in registry") + + if not productdir or not os.path.isdir(productdir): + toolskey = "VS%0.f0COMNTOOLS" % version + toolsdir = os.environ.get(toolskey, None) + + if toolsdir and os.path.isdir(toolsdir): + productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC") + productdir = os.path.abspath(productdir) + if not os.path.isdir(productdir): + log.debug("%s is not a valid directory" % productdir) + return None + else: + log.debug("Env var %s is not set or invalid" % toolskey) + if not productdir: + log.debug("No productdir found") + return None + vcvarsall = os.path.join(productdir, "vcvarsall.bat") + if os.path.isfile(vcvarsall): + return vcvarsall + log.debug("Unable to find vcvarsall.bat") + return None + +def query_vcvarsall(version, arch="x86"): + """Launch vcvarsall.bat and read the settings from its environment + """ + + paths = [] + includes = [] + libs = [] + + def _append_if_exists(list_, path): + if os.path.isdir(path): + list_.append(path) + + def _add_bin_paths(base, paths): + if arch.endswith("ia64"): + _append_if_exists(paths, base + r"\bin\ia64") + elif arch.endswith("64"): + _append_if_exists(paths, base + r"\bin\x64") + _append_if_exists(paths, base + r"\bin\amd64") + elif arch.endswith("x86"): + _append_if_exists(paths, base + r"\bin") + + def _get_include_lib_paths(base): + existing_includes = [] + existing_libs = [] + _append_if_exists(existing_includes, base + r"\include") + if arch.endswith("ia64"): + _append_if_exists(existing_libs, base + r"\lib\ia64") + elif arch.endswith("64"): + _append_if_exists(existing_libs, base + r"\lib\x64") + _append_if_exists(existing_libs, base + r"\lib\amd64") + elif arch.endswith("x86"): + _append_if_exists(existing_libs, base + r"\lib") + + return (existing_includes, existing_libs) + + result = [] + + versionstr = '%.1f' % version + + vcpaths = Reg.read_values(_winreg.HKEY_LOCAL_MACHINE, VC_SXS_KEY) + vcinstalldir = vcpaths[versionstr] + vsinstalldir = Reg.read_values(_winreg.HKEY_LOCAL_MACHINE, VS_SXS_KEY).get(versionstr, vcinstalldir + "..") + + # set PATH to include: + # %VCINSTALLDIR%\bin[\x64|\amd64|\ia64] + # %VCINSTALLDIR%\VCPackages + + if vcinstalldir: + _add_bin_paths(vcinstalldir, paths) + _append_if_exists(paths, "%s\\VCPackages" % (vcinstalldir)) + + # set PATH to include: + # %VSINSTALLDIR%\Common7\IDE + # %VSINSTALLDIR%\Common7\Tools + # %VSINSTALLDIR%\Common7\Tools\bin + + if vsinstalldir: + _append_if_exists(paths, "%s\\Common7\\IDE" % (vsinstalldir)) + _append_if_exists(paths, "%s\\Common7\\Tools" % (vsinstalldir)) + _append_if_exists(paths, "%s\\Common7\\Tools\\bin" % (vsinstalldir)) + + # set PATH to include: + # %FrameworkDir%\%Framework35Version% + # %FrameworkDir%\%FrameworkVersion% + + frameworkdir = vcpaths.get("frameworkdir64" if arch == "amd64" else "frameworkdir32") + if frameworkdir: + _append_if_exists(paths, frameworkdir + r"\v3.5") + frameworkver = vcpaths.get("frameworkver64" if arch == "amd64" else "frameworkdir32") + if frameworkver: + _append_if_exists(paths, r"%s\%s" % (frameworkdir, frameworkver)) + + def _get_sdk_installationfolder(sdkver): + for sdkkey in WINSDK_KEYS: + try: + sdk_install = Reg.get_value(sdkkey % sdkver, "installationfolder") + except KeyError: + pass + else: + return sdk_install + return None + + sdk_available = False + + for sdkver in WINSDK_VERSION_MAP[versionstr]: + + # set PATH to include: + # %WindowsSdkDir%bin[\x64|\amd64|\ia64] + # set INCLUDE to include: + # %WindowsSdkDir%include + # and LIB to include + # %WindowsSdkDir%lib[\x64|\amd64|\ia64] + + sdk_install = _get_sdk_installationfolder(sdkver) + if sdk_install is not None: + (sdk_includes, sdk_libs) = _get_include_lib_paths(sdk_install) + sdk_available = len(sdk_includes) > 0 and len(sdk_libs) > 0 + if sdk_available: + _add_bin_paths(sdk_install, paths) + includes += sdk_includes + libs += sdk_libs + print("Windows SDK %s complete" % sdkver) + break + else: + print("Windows SDK %s incomplete" % sdkver) + else: + print("Windows SDK %s not found" % sdkver) + + # set INCLUDE to include: + # %VCINSTALLDIR%\include + # and LIB to include + # %VCINSTALLDIR%\lib[\x64|\amd64|\ia64] + + if vcinstalldir: + (vc_includes, vc_libs) = _get_include_lib_paths(vcinstalldir) + includes += vc_includes + libs += vc_libs + + result = { + "path": ";".join(paths), + "include": ";".join(includes), + "lib": ";".join(libs), + } + + print("Start -----------------------------------------") + import pprint as pp + for k in result.keys(): + print(">>>>>> key:%s" % k) + pp.pprint(result[k].split(';')) + print("End -----------------------------------------") + + return result + +# More globals +VERSION = get_build_version() +if VERSION < 8.0: + raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION) +# MACROS = MacroExpander(VERSION) + +class MSVCCompiler(CCompiler) : + """Concrete class that implements an interface to Microsoft Visual C++, + as defined by the CCompiler abstract class.""" + + compiler_type = 'msvc' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + _rc_extensions = ['.rc'] + _mc_extensions = ['.mc'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = (_c_extensions + _cpp_extensions + + _rc_extensions + _mc_extensions) + res_extension = '.res' + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + def __init__(self, verbose=0, dry_run=0, force=0): + CCompiler.__init__ (self, verbose, dry_run, force) + self.__version = VERSION + self.__root = r"Software\Microsoft\VisualStudio" + # self.__macros = MACROS + self.__paths = [] + # target platform (.plat_name is consistent with 'bdist') + self.plat_name = None + self.__arch = None # deprecated name + self.initialized = False + + def initialize(self, plat_name=None): + # multi-init means we would need to check platform same each time... + assert not self.initialized, "don't init multiple times" + if plat_name is None: + plat_name = get_platform() + # sanity check for platforms to prevent obscure errors later. + ok_plats = 'win32', 'win-amd64', 'win-ia64' + if plat_name not in ok_plats: + raise DistutilsPlatformError("--plat-name must be one of %s" % + (ok_plats,)) + + if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): + # Assume that the SDK set up everything alright; don't try to be + # smarter + self.cc = "cl.exe" + self.linker = "link.exe" + self.lib = "lib.exe" + self.rc = "rc.exe" + self.mc = "mc.exe" + else: + # On x86, 'vcvars32.bat amd64' creates an env that doesn't work; + # to cross compile, you use 'x86_amd64'. + # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross + # compile use 'x86' (ie, it runs the x86 compiler directly) + # No idea how itanium handles this, if at all. + if plat_name == get_platform() or plat_name == 'win32': + # native build or cross-compile to win32 + plat_spec = PLAT_TO_VCVARS[plat_name] + else: + # cross compile from win32 -> some 64bit + plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \ + PLAT_TO_VCVARS[plat_name] + + vc_env = query_vcvarsall(VERSION, plat_spec) + + # take care to only use strings in the environment. + self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep) + os.environ['lib'] = vc_env['lib'].encode('mbcs') + os.environ['include'] = vc_env['include'].encode('mbcs') + + if len(self.__paths) == 0: + raise DistutilsPlatformError("Python was built with %s, " + "and extensions need to be built with the same " + "version of the compiler, but it isn't installed." + % self.__product) + + self.cc = self.find_exe("cl.exe") + self.linker = self.find_exe("link.exe") + self.lib = self.find_exe("lib.exe") + self.rc = self.find_exe("rc.exe") # resource compiler + self.mc = self.find_exe("mc.exe") # message compiler + #self.set_path_env_var('lib') + #self.set_path_env_var('include') + + # extend the MSVC path with the current path + try: + for p in os.environ['path'].split(';'): + self.__paths.append(p) + except KeyError: + pass + self.__paths = normalize_and_reduce_paths(self.__paths) + os.environ['path'] = ";".join(self.__paths) + + self.preprocess_options = None + if self.__arch == "x86": + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', + '/Z7', '/D_DEBUG'] + else: + # Win64 + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-', + '/Z7', '/D_DEBUG'] + + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] + if self.__version >= 10: + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO', '/Manifest'] + if self.__version >= 7: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + ] + if self.__version >= 10: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None', '/Manifest' + ] + self.ldflags_static = [ '/nologo'] + + self.initialized = True + + # -- Worker methods ------------------------------------------------ + + def object_filenames(self, + source_filenames, + strip_dir=0, + output_dir=''): + # Copied from ccompiler.py, extended to return .res as 'object'-file + # for .rc input file + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + (base, ext) = os.path.splitext (src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError ("Don't know how to compile %s" % src_name) + if strip_dir: + base = os.path.basename (base) + if ext in self._rc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + elif ext in self._mc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + if not self.initialized: + self.initialize() + compile_info = self._setup_compile(output_dir, macros, include_dirs, + sources, depends, extra_postargs) + macros, objects, extra_postargs, pp_opts, build = compile_info + + compile_opts = extra_preargs or [] + compile_opts.append ('/c') + if debug: + compile_opts.extend(self.compile_options_debug) + else: + compile_opts.extend(self.compile_options) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) + + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj + try: + self.spawn([self.rc] + pp_opts + + [output_opt] + [input_opt]) + except DistutilsExecError, msg: + raise CompileError(msg) + continue + elif ext in self._mc_extensions: + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + h_dir = os.path.dirname(src) + rc_dir = os.path.dirname(obj) + try: + # first compile .MC to .RC and .H file + self.spawn([self.mc] + + ['-h', h_dir, '-r', rc_dir] + [src]) + base, _ = os.path.splitext (os.path.basename (src)) + rc_file = os.path.join (rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn([self.rc] + + ["/fo" + obj] + [rc_file]) + + except DistutilsExecError, msg: + raise CompileError(msg) + continue + else: + # how to handle this file? + raise CompileError("Don't know how to compile %s to %s" + % (src, obj)) + + output_opt = "/Fo" + obj + try: + self.spawn([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError(msg) + + return objects + + + def create_static_lib(self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + output_filename = self.library_filename(output_libname, + output_dir=output_dir) + + if self._need_link(objects, output_filename): + lib_args = objects + ['/OUT:' + output_filename] + if debug: + pass # XXX what goes here? + try: + self.spawn([self.lib] + lib_args) + except DistutilsExecError, msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + + def link(self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + fixed_args = self._fix_lib_args(libraries, library_dirs, + runtime_library_dirs) + (libraries, library_dirs, runtime_library_dirs) = fixed_args + + if runtime_library_dirs: + self.warn ("I don't know what to do with 'runtime_library_dirs': " + + str (runtime_library_dirs)) + + lib_opts = gen_lib_options(self, + library_dirs, runtime_library_dirs, + libraries) + if output_dir is not None: + output_filename = os.path.join(output_dir, output_filename) + + if self._need_link(objects, output_filename): + if target_desc == CCompiler.EXECUTABLE: + if debug: + ldflags = self.ldflags_shared_debug[1:] + else: + ldflags = self.ldflags_shared[1:] + else: + if debug: + ldflags = self.ldflags_shared_debug + else: + ldflags = self.ldflags_shared + + export_opts = [] + for sym in (export_symbols or []): + export_opts.append("/EXPORT:" + sym) + + ld_args = (ldflags + lib_opts + export_opts + + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + build_temp = os.path.dirname(objects[0]) + if export_symbols is not None: + (dll_name, dll_ext) = os.path.splitext( + os.path.basename(output_filename)) + implib_file = os.path.join( + build_temp, + self.library_filename(dll_name)) + ld_args.append ('/IMPLIB:' + implib_file) + + self.manifest_setup_ldargs(output_filename, build_temp, ld_args) + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + self.mkpath(os.path.dirname(output_filename)) + try: + self.spawn([self.linker] + ld_args) + except DistutilsExecError, msg: + raise LinkError(msg) + + # embed the manifest + # XXX - this is somewhat fragile - if mt.exe fails, distutils + # will still consider the DLL up-to-date, but it will not have a + # manifest. Maybe we should link to a temp file? OTOH, that + # implies a build environment error that shouldn't go undetected. + mfinfo = self.manifest_get_embed_info(target_desc, ld_args) + if mfinfo is not None: + mffilename, mfid = mfinfo + out_arg = '-outputresource:%s;%s' % (output_filename, mfid) + try: + self.spawn(['mt.exe', '-nologo', '-manifest', + mffilename, out_arg]) + except DistutilsExecError, msg: + raise LinkError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): + # If we need a manifest at all, an embedded manifest is recommended. + # See MSDN article titled + # "How to: Embed a Manifest Inside a C/C++ Application" + # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) + # Ask the linker to generate the manifest in the temp dir, so + # we can check it, and possibly embed it, later. + temp_manifest = os.path.join( + build_temp, + os.path.basename(output_filename) + ".manifest") + ld_args.append('/MANIFESTFILE:' + temp_manifest) + + def manifest_get_embed_info(self, target_desc, ld_args): + # If a manifest should be embedded, return a tuple of + # (manifest_filename, resource_id). Returns None if no manifest + # should be embedded. See http://bugs.python.org/issue7833 for why + # we want to avoid any manifest for extension modules if we can) + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + temp_manifest = arg.split(":", 1)[1] + break + else: + # no /MANIFESTFILE so nothing to do. + return None + if target_desc == CCompiler.EXECUTABLE: + # by default, executables always get the manifest with the + # CRT referenced. + mfid = 1 + else: + # Extension modules try and avoid any manifest if possible. + mfid = 2 + temp_manifest = self._remove_visual_c_ref(temp_manifest) + if temp_manifest is None: + return None + return temp_manifest, mfid + + def _remove_visual_c_ref(self, manifest_file): + try: + # Remove references to the Visual C runtime, so they will + # fall through to the Visual C dependency of Python.exe. + # This way, when installed for a restricted user (e.g. + # runtimes are not in WinSxS folder, but in Python's own + # folder), the runtimes do not need to be in every folder + # with .pyd's. + # Returns either the filename of the modified manifest or + # None if no manifest should be embedded. + manifest_f = open(manifest_file) + try: + manifest_buf = manifest_f.read() + finally: + manifest_f.close() + pattern = re.compile( + r"""|)""", + re.DOTALL) + manifest_buf = re.sub(pattern, "", manifest_buf) + pattern = "\s*" + manifest_buf = re.sub(pattern, "", manifest_buf) + # Now see if any other assemblies are referenced - if not, we + # don't want a manifest embedded. + pattern = re.compile( + r"""|)""", re.DOTALL) + if re.search(pattern, manifest_buf) is None: + return None + + manifest_f = open(manifest_file, 'w') + try: + manifest_f.write(manifest_buf) + return manifest_file + finally: + manifest_f.close() + except IOError: + pass + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option(self, dir): + return "/LIBPATH:" + dir + + def runtime_library_dir_option(self, dir): + raise DistutilsPlatformError( + "don't know how to set runtime library search path for MSVC++") + + def library_option(self, lib): + return self.library_filename(lib) + + + def find_library_file(self, dirs, lib, debug=0): + # Prefer a debugging library if found (and requested), but deal + # with it if we don't have one. + if debug: + try_names = [lib + "_d", lib] + else: + try_names = [lib] + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename (name)) + if os.path.exists(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None + + # Helper methods for using the MSVC registry settings + + def find_exe(self, exe): + """Return path to an MSVC executable program. + + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + for p in self.__paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + + # didn't find it; try existing path + for p in os.environ['Path'].split(';'): + fn = os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): + return fn + + return exe diff --git a/CMakeLists.txt b/CMakeLists.txt index 869b9de7d5..655144734c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1046 +1,1050 @@ cmake_minimum_required(VERSION 2.8.9) #----------------------------------------------------------------------------- # Include ctest launchers for dashboard in case of makefile generator #----------------------------------------------------------------------------- if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") include(CTestUseLaunchers) endif() #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Build MITK and the projects it depends on via SuperBuild.cmake." ON) if(MITK_USE_SUPERBUILD) project(MITK-superbuild) set(MITK_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(MITK_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(MITK) endif() #----------------------------------------------------------------------------- # Warn if source or build path is too long #----------------------------------------------------------------------------- if(WIN32) set(_src_dir_length_max 50) set(_bin_dir_length_max 50) if(MITK_USE_SUPERBUILD) set(_src_dir_length_max 43) # _src_dir_length_max - strlen(ITK-src) set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build) endif() string(LENGTH "${MITK_SOURCE_DIR}" _src_n) string(LENGTH "${MITK_BINARY_DIR}" _bin_n) # The warnings should be converted to errors if(_src_n GREATER _src_dir_length_max) message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})." "Please move the MITK source code directory to a directory with a shorter path." ) endif() if(_bin_n GREATER _bin_dir_length_max) message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})." "Please move the MITK build directory to a directory with a shorter path." ) endif() endif() #----------------------------------------------------------------------------- # See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details #----------------------------------------------------------------------------- set(project_policies CMP0001 # NEW: CMAKE_BACKWARDS_COMPATIBILITY should no longer be used. CMP0002 # NEW: Logical target names must be globally unique. CMP0003 # NEW: Libraries linked via full path no longer produce linker search paths. CMP0004 # NEW: Libraries linked may NOT have leading or trailing whitespace. CMP0005 # NEW: Preprocessor definition values are now escaped automatically. CMP0006 # NEW: Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION. CMP0007 # NEW: List command no longer ignores empty elements. CMP0008 # NEW: Libraries linked by full-path must have a valid library file name. CMP0009 # NEW: FILE GLOB_RECURSE calls should not follow symlinks by default. CMP0010 # NEW: Bad variable reference syntax is an error. CMP0011 # NEW: Included scripts do automatic cmake_policy PUSH and POP. CMP0012 # NEW: if() recognizes numbers and boolean constants. CMP0013 # NEW: Duplicate binary directories are not allowed. CMP0014 # NEW: Input directories must have CMakeLists.txt CMP0020 # NEW: Automatically link Qt executables to qtmain target on Windows ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake) set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionSuppressWarnings) include(mitkFunctionEnableBuildConfiguration) include(FeatureSummary) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY AND NOT EXISTS ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) message("Creating directory MITK_CMAKE_${type}_OUTPUT_DIRECTORY: ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") file(MAKE_DIRECTORY "${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") endif() if(MITK_USE_SUPERBUILD) set(output_dir ${MITK_BINARY_DIR}/bin) if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_BINARY_DIR}/MITK-build/bin) endif() else() if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(output_dir ${MITK_BINARY_DIR}/bin) else() set(output_dir ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) endif() endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) macro(env_option name doc value) set(_value $ENV{${name}}) if("${_value}" STREQUAL "") set(_value ${value}) endif() option(${name} "${doc}" ${_value}) endmacro() # ----------------------------------------- # Qt version related variables env_option(MITK_USE_QT "Use Nokia's Qt library" ON) set(DESIRED_QT_VERSION 4 CACHE STRING "Pick a version of Qt to use: 4 or 5") 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(DESIRED_QT_VERSION MATCHES 4) if(DESIRED_QT_VERSION MATCHES 5) set(MITK_QT5_MINIMUM_VERSION 5.0.0) set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 TRUE) endif(DESIRED_QT_VERSION MATCHES 5) else() set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 FALSE) endif() # ----------------------------------------- # MITK_USE_* build variables env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) set(MITK_BUILD_TUTORIAL OFF CACHE INTERNAL "Deprecated! Use MITK_BUILD_EXAMPLES instead!") env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" ${MITK_BUILD_TUTORIAL}) env_option(MITK_USE_ACVD "Use Approximated Centroidal Voronoi Diagrams" OFF) env_option(MITK_USE_CppUnit "Use CppUnit for unit tests" ON) if(BUILD_TESTING AND NOT MITK_USE_CppUnit) message("> Forcing MITK_USE_CppUnit to ON because BUILD_TESTING=ON") set(MITK_USE_CppUnit ON CACHE BOOL "Use CppUnit for unit tests" FORCE) endif() env_option(MITK_USE_GLEW "Use the GLEW library" ON) env_option(MITK_USE_Boost "Use the Boost C++ library" OFF) env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ${MITK_USE_Qt4}) env_option(MITK_USE_CTK "Use CTK in MITK" ${MITK_USE_Qt4}) env_option(MITK_USE_DCMTK "EXPERIMENTAL, superbuild only: Use DCMTK in MITK" ${MITK_USE_CTK}) env_option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF) env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) env_option(MITK_USE_Poco "Use the Poco library" ON) env_option(MITK_USE_SOFA "Use Simulation Open Framework Architecture" OFF) env_option(MITK_USE_Python "Use Python wrapping in MITK" OFF) env_option(MITK_USE_SimpleITK "Use the SimpleITK library" OFF) set(MITK_USE_CableSwig ${MITK_USE_Python}) option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON) set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations") set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS Custom Default All) mitkFunctionEnableBuildConfiguration() mark_as_advanced(MITK_BUILD_ALL_APPS MITK_USE_CppUnit MITK_USE_GLEW MITK_USE_CTK MITK_USE_DCMTK MITK_ENABLE_PIC_READER MITK_BUILD_CONFIGURATION ) if(MITK_USE_Python) option(MITK_USE_SYSTEM_PYTHON "Use the system python runtime" ON) if(MITK_USE_SYSTEM_PYTHON) FIND_PACKAGE(PythonLibs REQUIRED) FIND_PACKAGE(PythonInterp REQUIRED) endif() set(MITK_USE_SimpleITK ON CACHE BOOL "Use the SimpleITK library" FORCE) endif() +if(MITK_USE_SimpleITK) + set(MITK_USE_SWIG 1) +endif() + if(MITK_USE_Boost) option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF) set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries") endif() if(MITK_USE_BLUEBERRY AND NOT MITK_USE_Qt4) message("> Forcing MITK_USE_BLUEBERRY to OFF because Qt4 is not used.") set(MITK_USE_BLUEBERRY OFF CACHE BOOL "Build the BlueBerry application platform" FORCE) endif() if(MITK_USE_CTK AND NOT MITK_USE_Qt4) message("> Forcing MITK_USE_CTK to OFF because Qt4 is not used.") set(MITK_USE_CTK OFF CACHE BOOL "Use CTK in MITK" FORCE) endif() if(MITK_USE_BLUEBERRY) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) mark_as_advanced(MITK_BUILD_ALL_PLUGINS) if(NOT MITK_USE_CTK) message("> Forcing MITK_USE_CTK to ON because of MITK_USE_BLUEBERRY") set(MITK_USE_CTK ON CACHE BOOL "Use CTK in MITK" FORCE) endif() endif() if(MITK_USE_CTK AND NOT MITK_USE_DCMTK) message("> Forcing MITK_USE_DCMTK to ON because of MITK_USE_CTK") set(MITK_USE_DCMTK ON CACHE BOOL "Use DCMTK in MITK" FORCE) endif() if(MITK_USE_SOFA) # SOFA requires at least CMake 2.8.8 set(SOFA_CMAKE_VERSION 2.8.8) if(${CMAKE_VERSION} VERSION_LESS ${SOFA_CMAKE_VERSION}) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n Minimum required CMake version: ${SOFA_CMAKE_VERSION}\n Installed CMake version: ${CMAKE_VERSION}") endif() # SOFA/ITK combination requires at least MSVC 2010 if(MSVC_VERSION AND MSVC_VERSION LESS 1600) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n MSVC versions less than 2010 are not supported.") endif() # SOFA requires boost library if(MITK_USE_SOFA AND NOT MITK_USE_Boost) message("Forcing MITK_USE_Boost to ON because of MITK_USE_SOFA") set(MITK_USE_Boost ON CACHE BOOL "" FORCE) endif() # SOFA requires boost system library list(FIND MITK_USE_Boost_LIBRARIES system _result) if(_result LESS 0) message("Adding 'system' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES system) endif() # SOFA requires boost thread library list(FIND MITK_USE_Boost_LIBRARIES thread _result) if(_result LESS 0) message("Adding 'thread' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES thread) endif() set(MITK_USE_Boost_LIBRARIES ${MITK_USE_Boost_LIBRARIES} CACHE STRING "" FORCE) # Allow setting external SOFA plugins directory and SOFA plugins set(MITK_USE_SOFA_PLUGINS_DIR ${MITK_USE_SOFA_PLUGINS_DIR} CACHE PATH "External SOFA plugins directory" FORCE) set(MITK_USE_SOFA_PLUGINS ${MITK_USE_SOFA_PLUGINS} CACHE PATH "List of semicolon-separated plugin names" FORCE) endif() # Customize the default pixel types for multiplex macros set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS ) # consistency checks if(NOT MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES) set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES) set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES) set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_DIMENSIONS) set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") endif() #----------------------------------------------------------------------------- # Project.xml #----------------------------------------------------------------------------- # A list of topologically ordered targets set(CTEST_PROJECT_SUBPROJECTS) if(MITK_USE_BLUEBERRY) list(APPEND CTEST_PROJECT_SUBPROJECTS BlueBerry) endif() list(APPEND CTEST_PROJECT_SUBPROJECTS MITK-Core MITK-CoreUI MITK-IGT MITK-ToF MITK-DTI MITK-Registration MITK-Modules # all modules not contained in a specific subproject MITK-Plugins # all plugins not contained in a specific subproject MITK-Examples Unlabeled # special "subproject" catching all unlabeled targets and tests ) # Configure CTestConfigSubProject.cmake that could be used by CTest scripts configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in ${MITK_BINARY_DIR}/CTestConfigSubProject.cmake) if(CTEST_PROJECT_ADDITIONAL_TARGETS) # those targets will be executed at the end of the ctest driver script # and they also get their own subproject label set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}") else() set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}") endif() # Generate Project.xml file expected by the CTest driver script mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD}) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(MITK_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") # Print configuration summary message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL) return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(WriteBasicConfigVersionFile) include(CheckCXXSourceCompiles) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(MacroParseArguments) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkFunctionOrganizeSources) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionCompileSnippets) include(mitkFunctionUseModules) include(mitkMacroCreateModuleConf) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCreateModule) include(mitkMacroCreateExecutable) include(mitkMacroCheckModule) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroUseModule) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON) mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW) # TODO: check if necessary option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON) mark_as_advanced(USE_ITKZLIB) if(NOT MITK_FAST_TESTING) if(DEFINED MITK_CTEST_SCRIPT_MODE AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") ) set(MITK_FAST_TESTING 1) endif() endif() #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on Mac OSX all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(MITK_USE_BLUEBERRY AND APPLE) include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) list(GET target_info_list 0 app_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} Mitk${app_name}) endif() endforeach() endif() #----------------------------------------------------------------------------- # Set symbol visibility Flags #----------------------------------------------------------------------------- # MinGW does not export all symbols automatically, so no need to set flags if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW) set(VISIBILITY_CXX_FLAGS ) #"-fvisibility=hidden -fvisibility-inlines-hidden") endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # MITK C/CXX Flags #----------------------------------------------------------------------------- set(MITK_C_FLAGS "${COVERAGE_C_FLAGS}") set(MITK_C_FLAGS_DEBUG ) set(MITK_C_FLAGS_RELEASE ) set(MITK_CXX_FLAGS "${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS}") set(MITK_CXX_FLAGS_DEBUG ) set(MITK_CXX_FLAGS_RELEASE ) set(MITK_EXE_LINKER_FLAGS ) set(MITK_SHARED_LINKER_FLAGS ) if(WIN32) set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -D_WIN32_WINNT=0x0501 -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN") set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} /wd4231") # warning C4231: nonstandard extension used : 'extern' before template explicit instantiation # the following line should be removed after fixing bug 17637 mitkFunctionCheckCompilerFlags("/wd4316" MITK_CXX_FLAGS) # warning C4316: object alignment on heap endif() if(NOT MSVC_VERSION) foreach(_flag -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Wno-error=gnu -Wno-error=unknown-pragmas # The strict-overflow warning is generated by ITK template code -Wno-error=strict-overflow -Woverloaded-virtual -Wstrict-null-sentinel #-Wold-style-cast #-Wsign-promo # the following two lines should be removed after ITK-3097 has # been resolved, see also MITK bug 15279 -Wno-unused-local-typedefs -Wno-array-bounds -fdiagnostics-show-option ) mitkFunctionCheckCAndCXXCompilerFlags(${_flag} MITK_C_FLAGS MITK_CXX_FLAGS) endforeach() endif() if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" MITK_SHARED_LINKER_FLAGS) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" MITK_SHARED_LINKER_FLAGS) endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) # With older version of gcc supporting the flag -fstack-protector-all, an extra dependency to libssp.so # is introduced. If gcc is smaller than 4.4.0 and the build type is Release let's not include the flag. # Doing so should allow to build package made for distribution using older linux distro. if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0")) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) endif() if(MINGW) # suppress warnings about auto imported symbols set(MITK_SHARED_LINKER_FLAGS "-Wl,--enable-auto-import ${MITK_SHARED_LINKER_FLAGS}") endif() set(MITK_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}") endif() set(MITK_MODULE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(MITK_EXE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_RENDERING_TESTING OFF "Enable the MITK rendering tests. Requires x-server in Linux.") #Rendering testing does not work for Linux nightlies, thus it is disabled per default #and activated for Mac and Windows. if(WIN32 OR APPLE) set(MITK_ENABLE_RENDERING_TESTING ON) endif() mark_as_advanced( MITK_ENABLE_RENDERING_TESTING ) # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output") if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR}) file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR}) endif() # Test the external project template if(MITK_USE_BLUEBERRY) include(mitkTestProjectTemplate) endif() # Test the package target include(mitkPackageTest) endif() configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h) #----------------------------------------------------------------------------- # MITK_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild. # In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR) set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Compile Utilities and set-up MITK variables #----------------------------------------------------------------------------- include(mitkSetupVariables) #----------------------------------------------------------------------------- # Cleanup #----------------------------------------------------------------------------- file(GLOB _MODULES_CONF_FILES ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) if(_MODULES_CONF_FILES) file(REMOVE ${_MODULES_CONF_FILES}) endif() add_subdirectory(Utilities) if(MITK_USE_BLUEBERRY) # We need to hack a little bit because MITK applications may need # to enable certain BlueBerry plug-ins. However, these plug-ins # are validated separately from the MITK plug-ins and know nothing # about potential MITK plug-in dependencies of the applications. Hence # we cannot pass the MITK application list to the BlueBerry # ctkMacroSetupPlugins call but need to extract the BlueBerry dependencies # from the applications and set them explicitly. include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled and if target_libraries.cmake exists if((${option_name} OR MITK_BUILD_ALL_APPS) AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") foreach(_target_dep ${target_libraries}) if(_target_dep MATCHES org_blueberry_) string(REPLACE _ . _app_bb_dep ${_target_dep}) # explicitly set the build option for the BlueBerry plug-in set(BLUEBERRY_BUILD_${_app_bb_dep} ON CACHE BOOL "Build the ${_app_bb_dep} plug-in") endif() endforeach() endif() endforeach() set(mbilog_DIR "${mbilog_BINARY_DIR}") if(MITK_BUILD_ALL_PLUGINS) set(BLUEBERRY_BUILD_ALL_PLUGINS ON) endif() set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/) add_subdirectory(BlueBerry) set(BlueBerry_DIR ${CMAKE_CURRENT_BINARY_DIR}/BlueBerry CACHE PATH "The directory containing a CMake configuration file for BlueBerry" FORCE) include(mitkMacroCreateCTKPlugin) endif() #----------------------------------------------------------------------------- # Set C/CXX and linker flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MITK_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MITK_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MITK_C_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MITK_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MITK_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MITK_MODULE_LINKER_FLAGS}") #----------------------------------------------------------------------------- # Add custom targets representing CDash subprojects #----------------------------------------------------------------------------- foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") add_custom_target(${subproject}) endif() endforeach() #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Core) add_subdirectory(Modules) if(MITK_USE_BLUEBERRY) find_package(BlueBerry REQUIRED) set(MITK_DEFAULT_SUBPROJECTS MITK-Plugins) # Plug-in testing (needs some work to be enabled again) if(BUILD_TESTING) include(berryTestingHelpers) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp") get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE) if(APPLE AND _is_macosx_bundle) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp") endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") set(mitk_plugins_fullpath ) foreach(mitk_plugin ${MITK_EXT_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake) include(${MITK_PRIVATE_MODULES}/PluginList.cmake) foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin}) endforeach() endif() if(MITK_BUILD_EXAMPLES) include("${CMAKE_CURRENT_SOURCE_DIR}/Examples/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) list(APPEND mitk_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) endforeach() endif() # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$") set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") set(mitk_apps_fullpath ) foreach(mitk_app ${MITK_APPS}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}") endforeach() if (mitk_plugins_fullpath) ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) endif() set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake") if(${PROJECT_NAME}_PLUGIN_LIBRARIES) ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE}) else() file(REMOVE ${MITK_PLUGIN_USE_FILE}) set(MITK_PLUGIN_USE_FILE ) endif() # 11.3.13, change, muellerm: activate python bundle if python and blueberry is active if( MITK_USE_Python ) set(MITK_BUILD_org.mitk.gui.qt.python ON) endif() endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(Documentation) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) # MITK_APPS is set in Applications/AppList.cmake (included somewhere above # if MITK_USE_BLUEBERRY is set to ON). if(MITK_APPS) set(activated_apps_no 0) list(LENGTH MITK_APPS app_count) # Check how many apps have been enabled # If more than one app has been activated, the we use the # default CPack configuration. Otherwise that apps configuration # will be used, if present. foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) MATH(EXPR activated_apps_no "${activated_apps_no} + 1") endif() endforeach() if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS)) # Corner case if there is only one app in total set(use_project_cpack ON) elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS) # Only one app is enabled (no "build all" flag set) set(use_project_cpack ON) else() # Less or more then one app is enabled set(use_project_cpack OFF) endif() foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) # check whether application specific configuration files will be used if(use_project_cpack) # use files if they exist if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") endif() if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in") set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake") configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in ${CPACK_PROJECT_CONFIG_FILE} @ONLY) set(use_default_config OFF) endif() endif() # add link to the list list(APPEND CPACK_CREATE_DESKTOP_LINKS "${target_dir}") endif() endforeach() endif() # if no application specific configuration file was used, use default if(use_default_config) configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") endif() # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake") file(REMOVE ${MITK_EXPORTS_FILE}) set(targets_to_export) get_property(module_targets GLOBAL PROPERTY MITK_MODULE_TARGETS) if(module_targets) list(APPEND targets_to_export ${module_targets}) endif() if(MITK_USE_BLUEBERRY) if(MITK_PLUGIN_LIBRARIES) list(APPEND targets_to_export ${MITK_PLUGIN_LIBRARIES}) endif() endif() export(TARGETS ${targets_to_export} APPEND FILE ${MITK_EXPORTS_FILE}) set(MITK_EXPORTED_TARGET_PROPERTIES ) foreach(target_to_export ${targets_to_export}) get_target_property(autoload_targets ${target_to_export} MITK_AUTOLOAD_TARGETS) if(autoload_targets) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_TARGETS \"${autoload_targets}\")") endif() get_target_property(autoload_dir ${target_to_export} MITK_AUTOLOAD_DIRECTORY) if(autoload_dir) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_DIRECTORY \"${autoload_dir}\")") endif() endforeach() get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY) set(VISIBILITY_AVAILABLE 0) set(visibility_test_flag "") mitkFunctionCheckCompilerFlags("-fvisibility=hidden" visibility_test_flag) if(visibility_test_flag) # The compiler understands -fvisiblity=hidden (probably gcc >= 4 or Clang) set(VISIBILITY_AVAILABLE 1) endif() configure_file(mitkExportMacros.h.in ${MITK_BINARY_DIR}/mitkExportMacros.h) configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) file(GLOB _MODULES_CONF_FILES RELATIVE ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME} ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) set(MITK_MODULE_NAMES) foreach(_module ${_MODULES_CONF_FILES}) string(REPLACE Config.cmake "" _module_name ${_module}) list(APPEND MITK_MODULE_NAMES ${_module_name}) endforeach() configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${MITK_VERSION_STRING} COMPATIBILITY AnyNewerVersion) # If we are under Windows, create two batch files which correctly # set up the environment for the application and for Visual Studio if(WIN32) include(mitkFunctionCreateWindowsBatchScript) set(VS_SOLUTION_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sln") foreach(VS_BUILD_TYPE debug release) mitkFunctionCreateWindowsBatchScript("${MITK_SOURCE_DIR}/CMake/StartVS.bat.in" ${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat ${VS_BUILD_TYPE}) endforeach() endif(WIN32) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) #----------------------------------------------------------------------------- # MITK Examples #----------------------------------------------------------------------------- if(MITK_BUILD_EXAMPLES) # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Examples) endif() #----------------------------------------------------------------------------- # Print configuration summary #----------------------------------------------------------------------------- message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL ) diff --git a/Modules/Python/CMakeLists.txt b/Modules/Python/CMakeLists.txt index ea94ccb62d..38d0f9217d 100644 --- a/Modules/Python/CMakeLists.txt +++ b/Modules/Python/CMakeLists.txt @@ -1,16 +1,21 @@ if( MITK_USE_Python ) if(NOT MITK_USE_SYSTEM_PYTHON) add_definitions( -DUSE_MITK_BUILTIN_PYTHON ) endif() + set(OpenCV_DEP ) + if(MITK_USE_OpenCV) + set(OpenCV_DEP OpenCV) + endif() + MITK_CREATE_MODULE( DEPENDS MitkCore EXPORT_DEFINE MITK_PYTHON_EXPORT - PACKAGE_DEPENDS Qt4|QtGui CTK PythonLibs SimpleITK VTK|vtkPython+vtkWrappingPythonCore + PACKAGE_DEPENDS Qt4|QtGui CTK PythonLibs SimpleITK VTK|vtkPython+vtkWrappingPythonCore ${OpenCV_DEP} ) configure_file(PythonPath.h.in "${CMAKE_CURRENT_BINARY_DIR}/PythonPath.h" @ONLY) add_subdirectory(Testing) endif() diff --git a/Modules/Python/PythonPath.h.in b/Modules/Python/PythonPath.h.in index 415a61beb9..87a61cfe35 100644 --- a/Modules/Python/PythonPath.h.in +++ b/Modules/Python/PythonPath.h.in @@ -1,26 +1,22 @@ #ifdef _DEBUG #define PYTHON_PATH_BUILD_TYPE "/Debug" #else #define PYTHON_PATH_BUILD_TYPE "/Release" #endif #define PYTHONPATH_COMMAND "import sys\n"\ -"sys.path.append('@ITK_LIBRARY_DIRS@')\n"\ -"sys.path.append('@ITK_DIR@/Wrapping/WrapITK/Python')\n"\ -"sys.path.append('@ITK_LIBRARY_DIRS@" PYTHON_PATH_BUILD_TYPE "')\n"\ -"sys.path.append('@ITK_DIR@/Wrapping/WrapITK/Python" PYTHON_PATH_BUILD_TYPE "')\n"\ -"sys.path.append('@ITK_DIR@/Wrapping/Generators/Python')\n"\ -"sys.path.append('@ITK_DIR@/lib')\n"\ +"sys.path.append('@Numpy_DIR@')\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_LIBRARY_DIRS@')\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 "')" #define PYTHONHOME "@Python_DIR@" + +#define PYTHON_LIBRARY_NAME "@PYTHON_LIBRARY_NAME@" diff --git a/Modules/Python/mitkPythonService.cpp b/Modules/Python/mitkPythonService.cpp index 81f6a07d6f..4633fd5899 100644 --- a/Modules/Python/mitkPythonService.cpp +++ b/Modules/Python/mitkPythonService.cpp @@ -1,555 +1,563 @@ /*=================================================================== 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 +#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 { +#ifndef WIN32 + dlopen(PYTHON_LIBRARY_NAME, RTLD_NOW | RTLD_NOLOAD | RTLD_GLOBAL); +#endif + std::string programPath = mitk::IOUtil::GetProgramPath(); QDir programmDir( QString( programPath.c_str() ).append("/Python") ); QString pythonCommand; // Set the pythonpath variable depending if // we have an installer or development environment if ( programmDir.exists() ) { // runtime directory used in installers pythonCommand.append( QString("import 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')\n").arg(programPath.c_str()) ); pythonCommand.append( QString("sys.path.append('%1/Python/SimpleITK')").arg(programPath.c_str()) ); // set python home if own runtime is deployed } else { pythonCommand.append(PYTHONPATH_COMMAND); } 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; m_PythonManager.executeString( pythonCommand, ctkAbstractPythonManager::FileInput ); /* //system("export LD_LIBRARY_PATH=/local/muellerm/mitk/bugsquashing/bin-debug/VTK-build/bin:$LD_LIBRARY_PATH"); //m_PythonManager.executeString( "print sys.path", ctkAbstractPythonManager::SingleInput ); //MITK_DEBUG("mitk::PythonService") << "result of 'sys.path': " << result.toString().toStdString(); //m_PythonManager.executeString( "sys.path.append('/usr/share/pyshared/numpy')", ctkAbstractPythonManager::SingleInput ); //m_PythonManager.executeString( "import numpy", ctkAbstractPythonManager::SingleInput ); MITK_DEBUG("mitk::PythonService") << "Trying to import ITK"; m_PythonManager.executeString( "import itk", ctkAbstractPythonManager::SingleInput ); m_ItkWrappingAvailable = !m_PythonManager.pythonErrorOccured(); MITK_DEBUG("mitk::PythonService") << "m_ItkWrappingAvailable: " << (m_ItkWrappingAvailable? "yes": "no"); if( !m_ItkWrappingAvailable ) { MITK_WARN << "ITK Python wrapping not available. Please check build settings or PYTHONPATH settings."; } { MITK_DEBUG("mitk::PythonService") << "Trying to import OpenCv"; PyRun_SimpleString("import cv2\n"); if (PyErr_Occurred()) { PyErr_Print(); } else m_OpenCVWrappingAvailable = true; //m_PythonManager.executeString( "import cv2", ctkAbstractPythonManager::SingleInput ); MITK_DEBUG("mitk::PythonService") << "Investigate if an error occured while importing cv2"; //m_OpenCVWrappingAvailable = !m_PythonManager.pythonErrorOccured(); MITK_DEBUG("mitk::PythonService") << "m_OpenCVWrappingAvailable: " << (m_OpenCVWrappingAvailable? "yes": "no"); if( !m_OpenCVWrappingAvailable ) { MITK_WARN << "OpenCV Python wrapping not available. Please check build settings or PYTHONPATH settings."; } } MITK_DEBUG("mitk::PythonService") << "Trying to import VTK"; m_PythonManager.executeString( "import vtk", ctkAbstractPythonManager::SingleInput ); m_VtkWrappingAvailable = !m_PythonManager.pythonErrorOccured(); MITK_DEBUG("mitk::PythonService") << "m_VtkWrappingAvailable: " << (m_VtkWrappingAvailable? "yes": "no"); if( !m_VtkWrappingAvailable ) { MITK_WARN << "VTK Python wrapping not available. Please check build settings or PYTHONPATH settings."; } */ } catch (...) { MITK_DEBUG("PythonService") << "exception initalizing python"; } } //m_PythonManager.executeString( "for path in sys.path:\n print path\n", ctkAbstractPythonManager::SingleInput ); //m_PythonManager.executeString( "for k, v in os.environ.items():\n print \"%s=%s\" % (k, v)", ctkAbstractPythonManager::SingleInput ); //m_PythonManager.executeFile("/local/muellerm/Dropbox/13-02-11-python-wrapping/interpreterInfo.py"); //std::string result = m_PythonManager.executeString( "5+5", ctkAbstractPythonManager::EvalInput ); //MITK_DEBUG("mitk::PythonService") << "result of '5+5': " << result.toString().toStdString(); } mitk::PythonService::~PythonService() { //QVariant result = m_PythonManager.executeString( "sys.getrefcount(cv2)", ctkAbstractPythonManager::EvalInput ); //MITK_DEBUG("mitk::PythonService") << "sys.getrefcount(cv2): " << result.toString().toStdString(); //m_PythonManager.executeString( "del sys.modules[\"cv2\"]", ctkAbstractPythonManager::SingleInput ); //m_PythonManager.executeString( "del cv2", ctkAbstractPythonManager::SingleInput ); MITK_DEBUG("mitk::PythonService") << "destructing PythonService"; #ifdef USE_MITK_BUILTIN_PYTHON if(pHome) delete[] pHome; #endif } std::string mitk::PythonService::Execute(const std::string &stdpythonCommand, int commandType) { QString pythonCommand = QString::fromStdString(stdpythonCommand); { MITK_DEBUG("mitk::PythonService") << "pythonCommand = " << pythonCommand.toStdString(); MITK_DEBUG("mitk::PythonService") << "commandType = " << commandType; } 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(int i = 0; i< allVars.size(); i++) { if( allVars.at(i).m_Name == name ) { varExists = true; break; } } return varExists; } void mitk::PythonService::AddPythonCommandObserver(mitk::PythonCommandObserver *observer) { if(!m_Observer.contains(observer)) m_Observer.append(observer); } void mitk::PythonService::RemovePythonCommandObserver(mitk::PythonCommandObserver *observer) { m_Observer.removeOne(observer); } void mitk::PythonService::NotifyObserver(const std::string &command) { MITK_DEBUG("mitk::PythonService") << "number of observer " << m_Observer.size(); for( size_t i=0; i< m_Observer.size(); ++i ) { 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 ); // save image QString fileName = this->GetTempDataFileName( mitk::IOUtil::DEFAULTIMAGEEXTENSION ); fileName = QDir::fromNativeSeparators( fileName ); MITK_DEBUG("PythonService") << "Saving temporary file " << fileName.toStdString(); if( !mitk::IOUtil::SaveImage(image, fileName.toStdString()) ) { MITK_ERROR << "Temporary file could not be created."; } else { QString command; command.append( QString("reader = sitk.ImageFileReader()\n") ); command.append( QString("reader.SetFileName(\"%1\")\n").arg(fileName) ); command.append( QString("%1 = reader.Execute()\n").arg(varName) ); command.append( QString("del reader") ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); MITK_INFO << this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); QFile file( fileName ); MITK_DEBUG("PythonService") << "Removing file " << fileName.toStdString(); file.remove(); return true; } return false; } mitk::Image::Pointer mitk::PythonService::CopySimpleItkImageFromPython(const std::string &stdvarName) { QString varName = QString::fromStdString( stdvarName ); mitk::Image::Pointer mitkImage; QString command; QString fileName = GetTempDataFileName( mitk::IOUtil::DEFAULTIMAGEEXTENSION ); fileName = QDir::fromNativeSeparators( fileName ); MITK_DEBUG("PythonService") << "Saving temporary file with python itk code " << fileName.toStdString(); command.append( QString("writer = sitk.ImageFileWriter()\n") ); command.append( QString("writer.SetFileName(\"%1\")\n").arg(fileName) ); command.append( QString("writer.Execute(%1)\n").arg(varName) ); command.append( QString("del writer") ); 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; } 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("surface_addr_str = %1.GetAddressAsString(\"vtkPolyData\")\n").arg(varName) ); // remove 0x from the address command.append( QString("surface_addr = int(surface_addr_str[5:],16)\n") ); 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,"surface_addr"); // 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 surface_addr_str\n") ); command.append( QString("del surface_addr\n") ); 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" //addr = addr.substr(2); 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 ); //this->Execute( "import itk\n", IPythonService::SINGLE_LINE_COMMAND ); //this->Execute( "print \"Using ITK version \" + itk.Version.GetITKVersion()\n", IPythonService::SINGLE_LINE_COMMAND ); 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/SuperBuild.cmake b/SuperBuild.cmake index 6eceea5c00..c3e8105b7c 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -1,483 +1,489 @@ #----------------------------------------------------------------------------- # Convenient macro allowing to download a file #----------------------------------------------------------------------------- macro(downloadFile url dest) file(DOWNLOAD ${url} ${dest} STATUS status) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") endif() endmacro() #----------------------------------------------------------------------------- # MITK Prerequisites #----------------------------------------------------------------------------- if(UNIX AND NOT APPLE) include(mitkFunctionCheckPackageHeader) # Check for libxt-dev mitkFunctionCheckPackageHeader(StringDefs.h libxt-dev /usr/include/X11/) # Check for libtiff4-dev mitkFunctionCheckPackageHeader(tiff.h libtiff4-dev) # Check for libwrap0-dev mitkFunctionCheckPackageHeader(tcpd.h libwrap0-dev) endif() #----------------------------------------------------------------------------- # Qt options for external projects and MITK #----------------------------------------------------------------------------- if(MITK_USE_QT) set(qt_project_args -DDESIRED_QT_VERSION:STRING=${DESIRED_QT_VERSION}) else() set(qt_project_args ) endif() if(MITK_USE_Qt4) list(APPEND qt_project_args -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() if(MITK_USE_Qt5) find_program(QT_QMAKE_EXECUTABLE qmake) if(NOT QT_QMAKE_EXECUTABLE) message(FATAL_ERROR "Qt qmake executable not found.") endif() execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_VERSION OUTPUT_VARIABLE _qt_version OUTPUT_STRIP_TRAILING_WHITESPACE) set(_qt_version_minimum "5.0.0") if(_qt_version VERSION_LESS _qt_version_minimum) message(SEND_ERROR "Qt version ${_qt_version} too old. At least Qt ${_qt_version_minimum} is required") endif() execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_PREFIX OUTPUT_VARIABLE _qt_install_prefix OUTPUT_STRIP_TRAILING_WHITESPACE) file(TO_CMAKE_PATH "${_qt_install_prefix}" _qt_install_prefix) list(APPEND qt_project_args -DCMAKE_PREFIX_PATH:PATH=${_qt_install_prefix}) endif() #----------------------------------------------------------------------------- # ExternalProjects #----------------------------------------------------------------------------- set(external_projects Python + Numpy tinyxml GLUT ANN CppUnit GLEW VTK ACVD GDCM OpenCV Poco ITK Boost DCMTK CTK SOFA MITKData Qwt Swig SimpleITK ) # Qxt supports Qt5. We need to also support it in QxtCMakeLists.txt if(MITK_USE_Qt4) list(APPEND external_projects Qxt) endif() # These are "hard" dependencies and always set to ON set(MITK_USE_tinyxml 1) set(MITK_USE_ANN 1) set(MITK_USE_GLEW 1) set(MITK_USE_GDCM 1) set(MITK_USE_ITK 1) set(MITK_USE_VTK 1) # Semi-hard dependencies, enabled by user-controlled variables if(MITK_USE_QT) if(MITK_USE_Qt4) set(MITK_USE_Qwt 1) set(MITK_USE_Qxt 1) #TODO: Check how Qxt builds with Qt 5 endif() endif() if(MITK_USE_SOFA) set(MITK_USE_GLUT 1) endif() # A list of "nice" external projects, playing well together with CMake set(nice_external_projects ${external_projects}) list(REMOVE_ITEM nice_external_projects Boost) foreach(proj ${nice_external_projects}) if(MITK_USE_${proj}) set(EXTERNAL_${proj}_DIR "${${proj}_DIR}" CACHE PATH "Path to ${proj} build directory") mark_as_advanced(EXTERNAL_${proj}_DIR) if(EXTERNAL_${proj}_DIR) set(${proj}_DIR ${EXTERNAL_${proj}_DIR}) endif() endif() endforeach() if(MITK_USE_Boost) set(EXTERNAL_BOOST_ROOT "${BOOST_ROOT}" CACHE PATH "Path to Boost directory") mark_as_advanced(EXTERNAL_BOOST_ROOT) if(EXTERNAL_BOOST_ROOT) set(BOOST_ROOT ${EXTERNAL_BOOST_ROOT}) endif() endif() # Setup file for setting custom ctest vars configure_file( CMake/SuperbuildCTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) if(BUILD_TESTING) set(EXTERNAL_MITK_DATA_DIR "${MITK_DATA_DIR}" CACHE PATH "Path to the MITK data directory") mark_as_advanced(EXTERNAL_MITK_DATA_DIR) if(EXTERNAL_MITK_DATA_DIR) set(MITK_DATA_DIR ${EXTERNAL_MITK_DATA_DIR}) endif() endif() # Look for git early on, if needed if((BUILD_TESTING AND NOT EXTERNAL_MITK_DATA_DIR) OR (MITK_USE_CTK AND NOT EXTERNAL_CTK_DIR)) find_package(Git REQUIRED) endif() #----------------------------------------------------------------------------- # External project settings #----------------------------------------------------------------------------- include(ExternalProject) set(ep_base "${CMAKE_BINARY_DIR}/CMakeExternals") set_property(DIRECTORY PROPERTY EP_BASE ${ep_base}) set(ep_install_dir ${ep_base}/Install) #set(ep_build_dir ${ep_base}/Build) set(ep_source_dir ${ep_base}/Source) #set(ep_parallelism_level) set(ep_build_shared_libs ON) set(ep_build_testing OFF) if(NOT MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL) set(MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL http://mitk.org/download/thirdparty) endif() # Compute -G arg for configuring external projects with the same CMake generator: if(CMAKE_EXTRA_GENERATOR) set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") else() set(gen "${CMAKE_GENERATOR}") endif() # Use this value where semi-colons are needed in ep_add args: set(sep "^^") ## if(MSVC_VERSION) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP") endif() set(ep_common_args -DBUILD_TESTING:BOOL=${ep_build_testing} -DCMAKE_INSTALL_PREFIX:PATH=${ep_install_dir} -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} -DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} #debug flags -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} #release flags -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} #relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} #link flags -DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ) # Pass the CMAKE_OSX variables to external projects if(APPLE) set(MAC_OSX_ARCHITECTURE_ARGS -DCMAKE_OSX_ARCHITECTURES:PATH=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET:PATH=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} ) set(ep_common_args ${MAC_OSX_ARCHITECTURE_ARGS} ${ep_common_args} ) endif() # Include external projects foreach(p ${external_projects}) include(CMakeExternals/${p}.cmake) endforeach() #----------------------------------------------------------------------------- # Set superbuild boolean args #----------------------------------------------------------------------------- set(mitk_cmake_boolean_args BUILD_SHARED_LIBS WITH_COVERAGE BUILD_TESTING MITK_USE_QT MITK_BUILD_ALL_PLUGINS MITK_BUILD_ALL_APPS MITK_BUILD_TUTORIAL # Deprecated. Use MITK_BUILD_EXAMPLES instead MITK_BUILD_EXAMPLES MITK_USE_ACVD MITK_USE_CppUnit MITK_USE_GLEW MITK_USE_Boost MITK_USE_SYSTEM_Boost MITK_USE_BLUEBERRY MITK_USE_CTK MITK_USE_DCMTK MITK_USE_OpenCV MITK_USE_Poco MITK_USE_SOFA MITK_USE_Python MITK_USE_OpenCL MITK_ENABLE_PIC_READER ) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(mitk_superbuild_boolean_args) foreach(mitk_cmake_arg ${mitk_cmake_boolean_args}) list(APPEND mitk_superbuild_boolean_args -D${mitk_cmake_arg}:BOOL=${${mitk_cmake_arg}}) endforeach() if(MITK_BUILD_ALL_PLUGINS) list(APPEND mitk_superbuild_boolean_args -DBLUEBERRY_BUILD_ALL_PLUGINS:BOOL=ON) endif() #----------------------------------------------------------------------------- # MITK Utilities #----------------------------------------------------------------------------- set(proj MITK-Utilities) ExternalProject_Add(${proj} DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS # Mandatory dependencies ${tinyxml_DEPENDS} ${ANN_DEPENDS} ${VTK_DEPENDS} ${ITK_DEPENDS} # Optionnal dependencies ${ACVD_DEPENDS} ${CppUnit_DEPENDS} ${GLUT_DEPENDS} ${GLEW_DEPENDS} ${Boost_DEPENDS} ${CTK_DEPENDS} ${DCMTK_DEPENDS} ${OpenCV_DEPENDS} ${Poco_DEPENDS} ${SOFA_DEPENDS} ${MITK-Data_DEPENDS} ${Qwt_DEPENDS} ${Qxt_DEPENDS} ${SimpleITK_DEPENDS} + ${Numpy_DEPENDS} ) #----------------------------------------------------------------------------- # Additional MITK CXX/C Flags #----------------------------------------------------------------------------- set(MITK_ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_RELEASE "" CACHE STRING "Additional Release C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_DEBUG "" CACHE STRING "Additional Debug C Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_C_FLAGS MITK_ADDITIONAL_C_FLAGS_DEBUG MITK_ADDITIONAL_C_FLAGS_RELEASE) set(MITK_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_RELEASE "" CACHE STRING "Additional Release CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_DEBUG "" CACHE STRING "Additional Debug CXX Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_CXX_FLAGS MITK_ADDITIONAL_CXX_FLAGS_DEBUG MITK_ADDITIONAL_CXX_FLAGS_RELEASE) set(MITK_ADDITIONAL_EXE_LINKER_FLAGS "" CACHE STRING "Additional exe linker flags for MITK") set(MITK_ADDITIONAL_SHARED_LINKER_FLAGS "" CACHE STRING "Additional shared linker flags for MITK") set(MITK_ADDITIONAL_MODULE_LINKER_FLAGS "" CACHE STRING "Additional module linker flags for MITK") mark_as_advanced(MITK_ADDITIONAL_EXE_LINKER_FLAGS MITK_ADDITIONAL_SHARED_LINKER_FLAGS MITK_ADDITIONAL_MODULE_LINKER_FLAGS) #----------------------------------------------------------------------------- # MITK Configure #----------------------------------------------------------------------------- if(MITK_INITIAL_CACHE_FILE) set(mitk_initial_cache_arg -C "${MITK_INITIAL_CACHE_FILE}") endif() set(mitk_optional_cache_args ) foreach(type RUNTIME ARCHIVE LIBRARY) if(DEFINED CTK_PLUGIN_${type}_OUTPUT_DIRECTORY) list(APPEND mitk_optional_cache_args -DCTK_PLUGIN_${type}_OUTPUT_DIRECTORY:PATH=${CTK_PLUGIN_${type}_OUTPUT_DIRECTORY}) endif() endforeach() # Optional python variables if(MITK_USE_Python) list(APPEND mitk_optional_cache_args -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DMITK_USE_SYSTEM_PYTHON:BOOL=${MITK_USE_SYSTEM_PYTHON} + -DPYTHON_LIBRARY_NAME:STRING=${PYTHON_LIBRARY_NAME} -DMITK_BUILD_org.mitk.gui.qt.python:BOOL=ON ) if( NOT MITK_USE_SYSTEM_PYTHON ) list(APPEND mitk_optional_cache_args - -DPython_DIR:PATH=${Python_DIR}) + -DPython_DIR:PATH=${Python_DIR} + -DPYTHON_MAJOR_VERSION:STRING=${PYTHON_MAJOR_VERSION} + -DPYTHON_MINOR_VERSION:STRING=${PYTHON_MINOR_VERSION} + ) endif() - endif() set(proj MITK-Configure) ExternalProject_Add(${proj} LIST_SEPARATOR ^^ DOWNLOAD_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_CACHE_ARGS # --------------- Build options ---------------- -DBUILD_TESTING:BOOL=${ep_build_testing} -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/MITK-build/install -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} # --------------- Compile options ---------------- -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} ${MITK_ADDITIONAL_C_FLAGS}" "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${MITK_ADDITIONAL_CXX_FLAGS}" # debug flags "-DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} ${MITK_ADDITIONAL_CXX_FLAGS_DEBUG}" "-DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} ${MITK_ADDITIONAL_C_FLAGS_DEBUG}" # release flags "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} ${MITK_ADDITIONAL_CXX_FLAGS_RELEASE}" "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} ${MITK_ADDITIONAL_C_FLAGS_RELEASE}" # relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} # link flags "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} ${MITK_ADDITIONAL_EXE_LINKER_FLAGS}" "-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} ${MITK_ADDITIONAL_SHARED_LINKER_FLAGS}" "-DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ${MITK_ADDITIONAL_MODULE_LINKER_FLAGS}" # Output directories -DMITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY} -DMITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY} -DMITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY} # ------------- Boolean build options -------------- ${mitk_superbuild_boolean_args} ${mitk_optional_cache_args} -DMITK_USE_SUPERBUILD:BOOL=OFF -DMITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION} -DCTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} # ----------------- Miscellaneous --------------- -DMITK_CTEST_SCRIPT_MODE:STRING=${MITK_CTEST_SCRIPT_MODE} -DMITK_SUPERBUILD_BINARY_DIR:PATH=${MITK_BINARY_DIR} -DMITK_MODULES_TO_BUILD:INTERNAL=${MITK_MODULES_TO_BUILD} ${qt_project_args} -DMITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES} -DMITK_ACCESSBYITK_FLOATING_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES} -DMITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES} -DMITK_ACCESSBYITK_DIMENSIONS:STRING=${MITK_ACCESSBYITK_DIMENSIONS} # --------------- External project dirs --------------- -DMITK_KWSTYLE_EXECUTABLE:FILEPATH=${MITK_KWSTYLE_EXECUTABLE} -DCTK_DIR:PATH=${CTK_DIR} -DDCMTK_DIR:PATH=${DCMTK_DIR} -Dtinyxml_DIR:PATH=${tinyxml_DIR} -DGLUT_DIR:PATH=${GLUT_DIR} -DGLEW_DIR:PATH=${GLEW_DIR} -DANN_DIR:PATH=${ANN_DIR} -DCppUnit_DIR:PATH=${CppUnit_DIR} -DVTK_DIR:PATH=${VTK_DIR} # FindVTK expects VTK_DIR -DITK_DIR:PATH=${ITK_DIR} # FindITK expects ITK_DIR -DACVD_DIR:PATH=${ACVD_DIR} -DOpenCV_DIR:PATH=${OpenCV_DIR} -DPoco_DIR:PATH=${Poco_DIR} -DSOFA_DIR:PATH=${SOFA_DIR} -DGDCM_DIR:PATH=${GDCM_DIR} -DBOOST_ROOT:PATH=${BOOST_ROOT} -DMITK_USE_Boost_LIBRARIES:STRING=${MITK_USE_Boost_LIBRARIES} -DMITK_DATA_DIR:PATH=${MITK_DATA_DIR} -DQwt_DIR:PATH=${Qwt_DIR} -DQxt_DIR:PATH=${Qxt_DIR} -DSimpleITK_DIR:PATH=${SimpleITK_DIR} + -DNumpy_DIR:PATH=${Numpy_DIR} CMAKE_ARGS ${mitk_initial_cache_arg} ${MAC_OSX_ARCHITECTURE_ARGS} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} BINARY_DIR ${CMAKE_BINARY_DIR}/MITK-build BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS MITK-Utilities ) #----------------------------------------------------------------------------- # MITK #----------------------------------------------------------------------------- if(CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(mitk_build_cmd "$(MAKE)") else() set(mitk_build_cmd ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/MITK-build --config ${CMAKE_CFG_INTDIR}) endif() if(NOT DEFINED SUPERBUILD_EXCLUDE_MITKBUILD_TARGET OR NOT SUPERBUILD_EXCLUDE_MITKBUILD_TARGET) set(MITKBUILD_TARGET_ALL_OPTION "ALL") else() set(MITKBUILD_TARGET_ALL_OPTION "") endif() add_custom_target(MITK-build ${MITKBUILD_TARGET_ALL_OPTION} COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build DEPENDS MITK-Configure ) #----------------------------------------------------------------------------- # Custom target allowing to drive the build of the MITK project itself #----------------------------------------------------------------------------- add_custom_target(MITK COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build )