diff --git a/CMake/mitkFunctionExternalPythonBuildStep.cmake b/CMake/mitkFunctionExternalPythonBuildStep.cmake new file mode 100644 index 0000000000..0a6f55570d --- /dev/null +++ b/CMake/mitkFunctionExternalPythonBuildStep.cmake @@ -0,0 +1,39 @@ +#! CMake function that runs a python build step from a setup.py script, +#! e.g. python setup.py build. This is used to build external python +#! libraries like numpy. The function takes the necessary build steps, +#! python executable etc. as arguments. The specific build command executed +#! by the runtime is passed as ARGN. +#! +#! params: +#! proj - The name of the project +#! step - Buildstep used to label the generated outputs, e.g. configure;build;install +#! _python_executable - The python executable +#! _bin_dir - The current binary from where commands are executed relative to it +#! ARGN - Python command that will be run in the _bin_dir/proj-src folder +#! e.g. setup.py build --someflags +#! +function(mitkFunctionExternalPythonBuildStep proj step _python_executable _bin_dir) + + # the specific python build command run by this step + set(_command ${ARGN}) + + message("Running ${proj} ${step}:${PYTHON_EXECUTABLE} ${_command}") + + execute_process( + COMMAND ${_python_executable} ${_command} + WORKING_DIRECTORY ${_bin_dir}/${proj}-src + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE error + ) + set(output_file "${_bin_dir}/${proj}-cmake/${proj}_${step}_step_output.txt") + file(WRITE ${output_file} ${output}) + + set(error_file "${_bin_dir}/${proj}-cmake/${proj}_${step}_step_error.txt") + file(WRITE ${error_file} ${error}) + + if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "Error in: ${proj}: ${error}") + endif() +endfunction() + diff --git a/CMake/mitkMacroInstallPython.cmake b/CMake/mitkMacroInstallPython.cmake index 1dce8ce261..245b116ad0 100644 --- a/CMake/mitkMacroInstallPython.cmake +++ b/CMake/mitkMacroInstallPython.cmake @@ -1,144 +1,144 @@ #! This CMake macro installs the python runtime with #! all python related libraries and toolkits. Py files are #! searched one by one with a globbing expression to generate a list used #! by the mac and NSIS installer. #! #! params: #! _python_libs Returns a list of the installed libraries. Used to fixup the bundle. #! _python_dirs Returns a list with the directories containig the dependencies #! to the installed libs. #! _app_bundle App bundle name in case of a Apple bundle. #! macro(mitkMacroInstallPython _python_libs _python_dirs _app_bundle) set(_destination bin) if(APPLE) set(_destination ${_app_bundle}) endif() if(UNIX) # apple and linux only supports .so as loadable extension set(PYTHON_LIB_SUFFIX .so) else(WIN32) # windows only supports pyd as loadable extension set(PYTHON_LIB_SUFFIX .pyd) endif() # SimpleITK if(MITK_USE_SimpleITK) install(FILES "${SimpleITK_DIR}/Wrapping/SimpleITK.py" DESTINATION ${_destination}/Python/SimpleITK ) install(FILES "${SimpleITK_DIR}/Wrapping/__init__.py" DESTINATION ${_destination}/Python/SimpleITK ) install(FILES "${SimpleITK_DIR}/Wrapping/_SimpleITK${PYTHON_LIB_SUFFIX}" DESTINATION ${_destination}/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}/lib") endif() # install OpenCV python wrapping if(MITK_USE_OpenCV) list(APPEND _python_libs "cv2${PYTHON_LIB_SUFFIX}") if(UNIX) install(FILES "${OpenCV_DIR}/lib/cv2${PYTHON_LIB_SUFFIX}" DESTINATION ${_destination}) else() install(FILES "${OpenCV_DIR}/lib/Release/cv2${PYTHON_LIB_SUFFIX}" DESTINATION ${_destination}) endif() if(UNIX AND NOT APPLE) install(CODE "file(RPATH_REMOVE FILE \"\${CMAKE_INSTALL_PREFIX}/bin/cv2${CMAKE_SHARED_LIBRARY_SUFFIX}\")") endif() list(APPEND _python_dirs "${OpenCV_DIR}/lib") endif() # install VTK python wrapping find_package(VTK REQUIRED) set(_VTK_PYTHON_TARGETS ) # find all vtk python wrapped targets foreach(_lib ${VTK_LIBRARIES}) # exclude system libs if(${_lib} MATCHES "^vtk.+") # use only python wrapped modules ( targets end with PythonD ) if(TARGET ${_lib}PythonD) list(APPEND _VTK_PYTHON_TARGETS ${_lib}Python) endif() endif() endforeach() # install the python modules and loaders foreach(_target ${_VTK_PYTHON_TARGETS}) # get the properties of the python wrapped target if( CMAKE_BUILD_TYPE STREQUAL "Debug") get_target_property(_target_lib "${_target}D" IMPORTED_LOCATION_DEBUG) else() get_target_property(_target_lib "${_target}D" IMPORTED_LOCATION_RELEASE) endif() get_filename_component(_filepath "${_target_lib}" PATH) install(FILES "${_filepath}/${_target}${PYTHON_LIB_SUFFIX}" DESTINATION ${_destination}) if(UNIX AND NOT APPLE ) install(CODE "file(RPATH_REMOVE FILE \"\${CMAKE_INSTALL_PREFIX}/bin/${_target}${PYTHON_LIB_SUFFIX}\")") endif() list(APPEND _python_libs "${_target}${PYTHON_LIB_SUFFIX}") endforeach() # install vtk python. This folder contains all *.py files for VTK module loading. # glob through all files, NSIS can't use directories file(GLOB_RECURSE item RELATIVE "${VTK_DIR}/Wrapping/Python/vtk" "${VTK_DIR}/Wrapping/Python/vtk/*.py") foreach(f ${item}) get_filename_component(_filepath "${f}" PATH) install(FILES "${VTK_DIR}/Wrapping/Python/vtk/${f}" DESTINATION ${_destination}/Python/vtk/${_filepath}) endforeach() list(APPEND _python_dirs "${VTK_DIR}/lib") # install the python runtime from the superbuild if(NOT MITK_USE_SYSTEM_PYTHON) if(UNIX) set(_python_runtime_dir lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}) list(APPEND _python_dirs "${Python_DIR}/lib") else() #WIN32 set(_python_runtime_dir Lib) list(APPEND _python_dirs "${Python_DIR}/libs") list(APPEND _python_dirs "${Python_DIR}/bin") endif() file(GLOB_RECURSE item RELATIVE "${Python_DIR}/${_python_runtime_dir}" "${Python_DIR}/${_python_runtime_dir}/*") foreach(f ${item}) get_filename_component(_filepath "${f}" PATH) install(FILES "${Python_DIR}/${_python_runtime_dir}/${f}" DESTINATION ${_destination}/Python/${_python_runtime_dir}/${_filepath}) endforeach() 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 ${_destination}/Python/include/${_filepath}) endforeach() # Numpy is always build in an own runtime if(Numpy_DIR) # glob through all files, NSIS can't use directories - file(GLOB_RECURSE item RELATIVE "${Numpy_DIR}/numpy" "${Numpy_DIR}/numpy/*") + file(GLOB_RECURSE item RELATIVE "${Numpy_DIR}" "${Numpy_DIR}/*") foreach(f ${item}) get_filename_component(_filepath "${f}" PATH) - install(FILES "${Numpy_DIR}/numpy/${f}" DESTINATION ${_destination}/Python/numpy/${_filepath}) + install(FILES "${Numpy_DIR}/${f}" DESTINATION ${_destination}/Python/numpy/${_filepath}) endforeach() endif() endif() list(REMOVE_DUPLICATES _python_dirs) endmacro() diff --git a/CMakeExternals/Numpy.cmake b/CMakeExternals/Numpy.cmake index ebe5c8017c..969e197b4c 100644 --- a/CMakeExternals/Numpy.cmake +++ b/CMakeExternals/Numpy.cmake @@ -1,110 +1,88 @@ #----------------------------------------------------------------------------- # Numpy #----------------------------------------------------------------------------- if( MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON ) # Sanity checks if(DEFINED Numpy_DIR AND NOT EXISTS ${Numpy_DIR}) message(FATAL_ERROR "Numpy_DIR variable is defined but corresponds to non-existing directory") endif() if( NOT DEFINED Numpy_DIR ) set(proj Numpy) set(${proj}_DEPENDENCIES Python) set(Numpy_DEPENDS ${proj}) + # setup build environment and disable fortran, blas and lapack set(_numpy_env " set(ENV{F77} \"\") set(ENV{F90} \"\") set(ENV{FFLAGS} \"\") set(ENV{ATLAS} \"None\") set(ENV{BLAS} \"None\") set(ENV{LAPACK} \"None\") set(ENV{MKL} \"None\") - ") - - set(_external_python_project ${CMAKE_BINARY_DIR}/${proj}-cmake/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}) + set(_numpy_build_step ${MITK_SOURCE_DIR}/CMake/mitkFunctionExternalPythonBuildStep.cmake) - if(NOT \${result} EQUAL 0) - message(FATAL_ERROR \"Error in: \${proj}: \${error}\") - endif() - endfunction() - ") - # configure step set(_configure_step ${CMAKE_BINARY_DIR}/${proj}-cmake/${proj}_configure_step.cmake) file(WRITE ${_configure_step} - "include(\"${_external_python_project}\") + "${_numpy_env} + include(\"${_numpy_build_step}\") file(WRITE \"${CMAKE_BINARY_DIR}/${proj}-src/site.cfg\" \"\") - MITK_PYTHON_BUILD_STEP(${proj} configure setup.py config) + mitkFunctionExternalPythonBuildStep(${proj} configure ${PYTHON_EXECUTABLE} \"${CMAKE_BINARY_DIR}\" setup.py config) ") # build step set(_build_step ${CMAKE_BINARY_DIR}/${proj}-cmake/${proj}_build_step.cmake) file(WRITE ${_build_step} - "include(\"${_external_python_project}\") - MITK_PYTHON_BUILD_STEP(${proj} build setup.py build --fcompiler=none) + "${_numpy_env} + include(\"${_numpy_build_step}\") + mitkFunctionExternalPythonBuildStep(${proj} build ${PYTHON_EXECUTABLE} \"${CMAKE_BINARY_DIR}\" setup.py build --fcompiler=none) ") # install step set(_install_dir ${Python_BUILD_DIR}) if(WIN32) STRING(REPLACE "/" "\\\\" _install_dir ${Python_DIR}) endif() set(_install_step ${CMAKE_BINARY_DIR}/${proj}-cmake/${proj}_install_step.cmake) file(WRITE ${_install_step} - "include(\"${_external_python_project}\") - MITK_PYTHON_BUILD_STEP(${proj} install setup.py install --prefix=${_install_dir}) + "${_numpy_env} + include(\"${_numpy_build_step}\") + mitkFunctionExternalPythonBuildStep(${proj} install ${PYTHON_EXECUTABLE} \"${CMAKE_BINARY_DIR}\" setup.py install --prefix=${_install_dir}) ") 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 CONFIGURE_COMMAND ${CMAKE_COMMAND} -P ${_configure_step} BUILD_COMMAND ${CMAKE_COMMAND} -P ${_build_step} INSTALL_COMMAND ${CMAKE_COMMAND} -P ${_install_step} DEPENDS ${${proj}_DEPENDENCIES} ) set(Numpy_DIR ${MITK_PYTHON_SITE_DIR}/numpy) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif()