From cac1218eef7ebbd07951e961d547234d5c910bd2 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 29 Jun 2014 16:45:24 -0400 Subject: [PATCH 1/7] Build both Python 2 and Python 3 bindings If both Python 2 and Python 3 are found, then build bindings for both of them during the build process. Currently, one version of Python is detected automatically, and building for the other requires changes the CMake config. The largest chunk of this change generalizes OpenCVDetectPython.cmake to find both a Python 2 and Python 3 version of Python. Secondly, the opencv_python module is split into two modules, opencv_python2 and opencv_python3. Both are built from the same source. but for different versions of Python. --- CMakeLists.txt | 32 ++- cmake/OpenCVDetectPython.cmake | 321 ++++++++++++++++------- cmake/OpenCVMinDepVersions.cmake | 3 +- doc/CMakeLists.txt | 4 +- modules/java/CMakeLists.txt | 8 +- modules/java/android_test/CMakeLists.txt | 4 +- modules/matlab/CMakeLists.txt | 12 +- modules/python/CMakeLists.txt | 132 +--------- modules/python/common.cmake | 128 +++++++++ modules/python/python2/CMakeLists.txt | 26 ++ modules/python/python3/CMakeLists.txt | 26 ++ 11 files changed, 454 insertions(+), 242 deletions(-) create mode 100644 modules/python/common.cmake create mode 100644 modules/python/python2/CMakeLists.txt create mode 100644 modules/python/python3/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 5abf44980..b9ff7bec1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -991,18 +991,34 @@ endif() # ========================== python ========================== status("") -status(" Python:") -status(" Interpreter:" PYTHONINTERP_FOUND THEN "${PYTHON_EXECUTABLE} (ver ${PYTHON_VERSION_STRING})" ELSE NO) -if(BUILD_opencv_python) - if(PYTHONLIBS_VERSION_STRING) - status(" Libraries:" HAVE_opencv_python THEN "${PYTHON_LIBRARIES} (ver ${PYTHONLIBS_VERSION_STRING})" ELSE NO) +status(" Python 2:") +status(" Interpreter:" PYTHON2INTERP_FOUND THEN "${PYTHON2_EXECUTABLE} (ver ${PYTHON2_VERSION_STRING})" ELSE NO) +if(BUILD_opencv_python2) + if(PYTHON2LIBS_VERSION_STRING) + status(" Libraries:" HAVE_opencv_python2 THEN "${PYTHON2_LIBRARIES} (ver ${PYTHON2LIBS_VERSION_STRING})" ELSE NO) else() - status(" Libraries:" HAVE_opencv_python THEN "${PYTHON_LIBRARIES}" ELSE NO) + status(" Libraries:" HAVE_opencv_python2 THEN "${PYTHON2_LIBRARIES}" ELSE NO) endif() - status(" numpy:" PYTHON_NUMPY_INCLUDE_DIRS THEN "${PYTHON_NUMPY_INCLUDE_DIRS} (ver ${PYTHON_NUMPY_VERSION})" ELSE "NO (Python wrappers can not be generated)") - status(" packages path:" PYTHON_EXECUTABLE THEN "${PYTHON_PACKAGES_PATH}" ELSE "-") + status(" numpy:" PYTHON2_NUMPY_INCLUDE_DIRS THEN "${PYTHON2_NUMPY_INCLUDE_DIRS} (ver ${PYTHON2_NUMPY_VERSION})" ELSE "NO (Python wrappers can not be generated)") + status(" packages path:" PYTHON2_EXECUTABLE THEN "${PYTHON2_PACKAGES_PATH}" ELSE "-") endif() +status("") +status(" Python 3:") +status(" Interpreter:" PYTHON3INTERP_FOUND THEN "${PYTHON3_EXECUTABLE} (ver ${PYTHON3_VERSION_STRING})" ELSE NO) +if(BUILD_opencv_python3) + if(PYTHON3LIBS_VERSION_STRING) + status(" Libraries:" HAVE_opencv_python3 THEN "${PYTHON3_LIBRARIES} (ver ${PYTHON3LIBS_VERSION_STRING})" ELSE NO) + else() + status(" Libraries:" HAVE_opencv_python3 THEN "${PYTHON3_LIBRARIES}" ELSE NO) + endif() + status(" numpy:" PYTHON3_NUMPY_INCLUDE_DIRS THEN "${PYTHON3_NUMPY_INCLUDE_DIRS} (ver ${PYTHON3_NUMPY_VERSION})" ELSE "NO (Python3 wrappers can not be generated)") + status(" packages path:" PYTHON3_EXECUTABLE THEN "${PYTHON3_PACKAGES_PATH}" ELSE "-") +endif() + +status("") +status(" Python (for build):" PYTHON_DEFAULT_AVAILABLE THEN "${PYTHON_DEFAULT_EXECUTABLE}" ELSE NO) + # ========================== java ========================== status("") status(" Java:") diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index 95a26dbf3..4b7105268 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -1,101 +1,234 @@ -if(WIN32 AND NOT PYTHON_EXECUTABLE) - # search for executable with the same bitness as resulting binaries - # standard FindPythonInterp always prefers executable from system path - # this is really important because we are using the interpreter for numpy search and for choosing the install location - foreach(_CURRENT_VERSION ${Python_ADDITIONAL_VERSIONS} 2.7 "${MIN_VER_PYTHON}") - find_host_program(PYTHON_EXECUTABLE - NAMES python${_CURRENT_VERSION} python - PATHS - [HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Python\\\\PythonCore\\\\${_CURRENT_VERSION}\\\\InstallPath] - [HKEY_CURRENT_USER\\\\SOFTWARE\\\\Python\\\\PythonCore\\\\${_CURRENT_VERSION}\\\\InstallPath] - NO_SYSTEM_ENVIRONMENT_PATH - ) - endforeach() -endif() -find_host_package(PythonInterp 2.7) -if(NOT PYTHONINTERP_FOUND) -find_host_package(PythonInterp "${MIN_VER_PYTHON}") +# Find specified Python version +# Arguments: +# preferred_version (value): Version to check for first +# min_version (value): Minimum supported version +# library_env (value): Name of Python library ENV variable to check +# include_dir_env (value): Name of Python include directory ENV variable to check +# found (variable): Set if interpreter found +# executable (variable): Output of executable found +# version_string (variable): Output of found version +# version_major (variable): Output of found major version +# version_minor (variable): Output of found minor version +# libs_found (variable): Set if libs found +# libs_version_string (variable): Output of found libs version +# libraries (variable): Output of found Python libraries +# library (variable): Output of found Python library +# debug_libraries (variable): Output of found Python debug libraries +# debug_library (variable): Output of found Python debug library +# include_path (variable): Output of found Python include path +# include_dir (variable): Output of found Python include dir +# include_dir2 (variable): Output of found Python include dir2 +# packages_path (variable): Output of found Python packages path +# numpy_include_dirs (variable): Output of found Python Numpy include dirs +# numpy_version (variable): Output of found Python Numpy version +function(find_python preferred_version min_version library_env include_dir_env + found executable version_string version_major version_minor + libs_found libs_version_string libraries library debug_libraries + debug_library include_path include_dir include_dir2 packages_path + numpy_include_dirs numpy_version) + if(WIN32 AND NOT ${executable}) + # search for executable with the same bitness as resulting binaries + # standard FindPythonInterp always prefers executable from system path + # this is really important because we are using the interpreter for numpy search and for choosing the install location + foreach(_CURRENT_VERSION ${Python_ADDITIONAL_VERSIONS} "${preferred_version}" "${min_version}") + find_host_program(executable + NAMES python${_CURRENT_VERSION} python + PATHS + [HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Python\\\\PythonCore\\\\${_CURRENT_VERSION}\\\\InstallPath] + [HKEY_CURRENT_USER\\\\SOFTWARE\\\\Python\\\\PythonCore\\\\${_CURRENT_VERSION}\\\\InstallPath] + NO_SYSTEM_ENVIRONMENT_PATH + ) + endforeach() + endif() + + find_host_package(PythonInterp "${preferred_version}") + if(NOT PYTHONINTERP_FOUND) + find_host_package(PythonInterp "${min_version}") + endif() + + if(PYTHONINTERP_FOUND) + # Copy outputs + set(_found ${PYTHONINTERP_FOUND}) + set(_executable ${PYTHON_EXECUTABLE}) + set(_version_string ${PYTHON_VERSION_STRING}) + set(_version_major ${PYTHON_VERSION_MAJOR}) + set(_version_minor ${PYTHON_VERSION_MINOR}) + set(_version_patch ${PYTHON_VERSION_PATCH}) + + # Clear find_host_package side effects + unset(PYTHONINTERP_FOUND) + unset(PYTHON_EXECUTABLE CACHE) + unset(PYTHON_VERSION_STRING) + unset(PYTHON_VERSION_MAJOR) + unset(PYTHON_VERSION_MINOR) + unset(PYTHON_VERSION_PATCH) + endif() + + if(_found) + set(_version_major_minor "${_version_major}.${_version_minor}") + + if(NOT ANDROID AND NOT IOS) + ocv_check_environment_variables(${library_env} ${include_dir_env}) + if(${library}) + set(PYTHON_LIBRARY "${${library_env}}") + endif() + if(${include_dir}) + set(PYTHON_INCLUDE_DIR "${${include_dir_env}}") + endif() + + # not using _version_string here, because it might not conform to the CMake version format + find_host_package(PythonLibs "${_version_major_minor}.${_version_patch}" EXACT) + + if(PYTHONLIBS_FOUND) + # Copy outputs + set(_libs_found ${PYTHONLIBS_FOUND}) + set(_libraries ${PYTHON_LIBRARIES}) + set(_include_path ${PYTHON_INCLUDE_PATH}) + set(_include_dirs ${PYTHON_INCLUDE_DIRS}) + set(_debug_libraries ${PYTHON_DEBUG_LIBRARIES}) + set(_libs_version_string ${PYTHONLIBS_VERSION_STRING}) + set(_debug_library ${PYTHON_DEBUG_LIBRARY}) + set(_library ${PYTHON_LIBRARY}) + set(_library_debug ${PYTHON_LIBRARY_DEBUG}) + set(_library_release ${PYTHON_LIBRARY_RELEASE}) + set(_include_dir ${PYTHON_INCLUDE_DIR}) + set(_include_dir2 ${PYTHON_INCLUDE_DIR2}) + + # Clear find_host_package side effects + unset(PYTHONLIBS_FOUND) + unset(PYTHON_LIBRARIES) + unset(PYTHON_INCLUDE_PATH) + unset(PYTHON_INCLUDE_DIRS) + unset(PYTHON_DEBUG_LIBRARIES) + unset(PYTHONLIBS_VERSION_STRING) + unset(PYTHON_DEBUG_LIBRARY CACHE) + unset(PYTHON_LIBRARY) + unset(PYTHON_LIBRARY_DEBUG) + unset(PYTHON_LIBRARY_RELEASE) + unset(PYTHON_LIBRARY CACHE) + unset(PYTHON_LIBRARY_DEBUG CACHE) + unset(PYTHON_LIBRARY_RELEASE CACHE) + unset(PYTHON_INCLUDE_DIR CACHE) + unset(PYTHON_INCLUDE_DIR2 CACHE) + endif() + endif() + + if(NOT ANDROID AND NOT IOS) + if(CMAKE_HOST_UNIX) + execute_process(COMMAND ${_executable} -c "from distutils.sysconfig import *; print(get_python_lib())" + RESULT_VARIABLE _cvpy_process + OUTPUT_VARIABLE _std_packages_path + OUTPUT_STRIP_TRAILING_WHITESPACE) + if("${_std_packages_path}" MATCHES "site-packages") + set(_packages_path "python${_version_major_minor}/site-packages") + else() #debian based assumed, install to the dist-packages. + set(_packages_path "python${_version_major_minor}/dist-packages") + endif() + if(EXISTS "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/${${packages_path}}") + set(_packages_path "lib${LIB_SUFFIX}/${_packages_path}") + else() + set(_packages_path "lib/${_packages_path}") + endif() + elseif(CMAKE_HOST_WIN32) + get_filename_component(_path "${_executable}" PATH) + file(TO_CMAKE_PATH "${_path}" _path) + if(NOT EXISTS "${_path}/Lib/site-packages") + unset(_path) + get_filename_component(_path "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_version_major_minor}\\InstallPath]" ABSOLUTE) + if(NOT _path) + get_filename_component(_path "[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_version_major_minor}\\InstallPath]" ABSOLUTE) + endif() + file(TO_CMAKE_PATH "${_path}" _path) + endif() + set(_packages_path "${_path}/Lib/site-packages") + unset(_path) + endif() + + set(_numpy_include_dirs ${${numpy_include_dirs}}) + + if(NOT _numpy_include_dirs) + if(CMAKE_CROSSCOMPILING) + message(STATUS "Cannot probe for Python/Numpy support (because we are cross-compiling OpenCV)") + message(STATUS "If you want to enable Python/Numpy support, set the following variables:") + message(STATUS " PYTHON2_INCLUDE_PATH") + message(STATUS " PYTHON2_LIBRARIES") + message(STATUS " PYTHON2_NUMPY_INCLUDE_DIRS") + message(STATUS " PYTHON3_INCLUDE_PATH") + message(STATUS " PYTHON3_LIBRARIES") + message(STATUS " PYTHON3_NUMPY_INCLUDE_DIRS") + else() + # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy + execute_process(COMMAND "${_executable}" -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))" + RESULT_VARIABLE _numpy_process + OUTPUT_VARIABLE _numpy_include_dirs + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(NOT _numpy_process EQUAL 0) + unset(_numpy_include_dirs) + endif() + endif() + endif() + + if(_numpy_include_dirs) + file(TO_CMAKE_PATH "${_numpy_include_dirs}" _numpy_include_dirs) + if(CMAKE_CROSSCOMPILING) + if(NOT _numpy_version) + set(_numpy_version "undefined - cannot be probed because of the cross-compilation") + endif() + else() + execute_process(COMMAND "${_executable}" -c "import numpy; print(numpy.version.version)" + RESULT_VARIABLE _numpy_process + OUTPUT_VARIABLE _numpy_version + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + endif() + endif(NOT ANDROID AND NOT IOS) + endif() + + # Export return values + set(${found} "${_found}" PARENT_SCOPE) + set(${executable} "${_executable}" CACHE FILEPATH "Path to Python interpretor") + set(${version_string} "${_version_string}" PARENT_SCOPE) + set(${version_major} "${_version_major}" PARENT_SCOPE) + set(${version_minor} "${_version_minor}" PARENT_SCOPE) + set(${libs_found} "${_libs_found}" PARENT_SCOPE) + set(${libs_version_string} "${_libs_version_string}" PARENT_SCOPE) + set(${libraries} "${_libraries}" PARENT_SCOPE) + set(${library} "${_library}" CACHE FILEPATH "Path to Python library") + set(${debug_libraries} "${_debug_libraries}" PARENT_SCOPE) + set(${debug_library} "${_debug_library}" CACHE FILEPATH "Path to Python debug") + set(${include_path} "${_include_path}" PARENT_SCOPE) + set(${include_dir} "${_include_dir}" CACHE PATH "Python include dir") + set(${include_dir2} "${_include_dir2}" CACHE PATH "Python include dir 2") + set(${packages_path} "${_packages_path}" CACHE PATH "Where to install the python packages.") + set(${numpy_include_dirs} ${_numpy_include_dirs} CACHE PATH "Path to numpy headers") + set(${numpy_version} "${_numpy_version}" PARENT_SCOPE) +endfunction(find_python) + +find_python(2.7 "${MIN_VER_PYTHON2}" PYTHON2_LIBRARY PYTHON2_INCLUDE_DIR + PYTHON2INTERP_FOUND PYTHON2_EXECUTABLE PYTHON2_VERSION_STRING + PYTHON2_VERSION_MAJOR PYTHON2_VERSION_MINOR PYTHON2LIBS_FOUND + PYTHON2LIBS_VERSION_STRING PYTHON2_LIBRARIES PYTHON2_LIBRARY + PYTHON2_DEBUG_LIBRARIES PYTHON2_LIBRARY_DEBUG PYTHON2_INCLUDE_PATH + PYTHON2_INCLUDE_DIR PYTHON2_INCLUDE_DIR2 PYTHON2_PACKAGES_PATH + PYTHON2_NUMPY_INCLUDE_DIRS PYTHON2_NUMPY_VERSION) + +find_python(3.4 "${MIN_VER_PYTHON3}" PYTHON3_LIBRARY PYTHON3_INCLUDE_DIR + PYTHON3INTERP_FOUND PYTHON3_EXECUTABLE PYTHON3_VERSION_STRING + PYTHON3_VERSION_MAJOR PYTHON3_VERSION_MINOR PYTHON3LIBS_FOUND + PYTHON3LIBS_VERSION_STRING PYTHON3_LIBRARIES PYTHON3_LIBRARY + PYTHON3_DEBUG_LIBRARIES PYTHON3_LIBRARY_DEBUG PYTHON3_INCLUDE_PATH + PYTHON3_INCLUDE_DIR PYTHON3_INCLUDE_DIR2 PYTHON3_PACKAGES_PATH + PYTHON3_NUMPY_INCLUDE_DIRS PYTHON3_NUMPY_VERSION) + +# Use Python 2 as default Python interpreter +if(PYTHON2LIBS_FOUND) + set(PYTHON_DEFAULT_AVAILABLE "TRUE") + set(PYTHON_DEFAULT_EXECUTABLE "${PYTHON2_EXECUTABLE}") endif() unset(HAVE_SPHINX CACHE) -if(PYTHONINTERP_FOUND) - set(PYTHON_VERSION_MAJOR_MINOR "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") - - if(NOT ANDROID AND NOT IOS) - ocv_check_environment_variables(PYTHON_LIBRARY PYTHON_INCLUDE_DIR) - # not using PYTHON_VERSION_STRING here, because it might not conform to the CMake version format - find_host_package(PythonLibs "${PYTHON_VERSION_MAJOR_MINOR}.${PYTHON_VERSION_PATCH}" EXACT) - endif() - - if(NOT ANDROID AND NOT IOS) - if(CMAKE_HOST_UNIX) - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import *; print(get_python_lib())" - RESULT_VARIABLE PYTHON_CVPY_PROCESS - OUTPUT_VARIABLE PYTHON_STD_PACKAGES_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE) - if("${PYTHON_STD_PACKAGES_PATH}" MATCHES "site-packages") - set(_PYTHON_PACKAGES_PATH "python${PYTHON_VERSION_MAJOR_MINOR}/site-packages") - else() #debian based assumed, install to the dist-packages. - set(_PYTHON_PACKAGES_PATH "python${PYTHON_VERSION_MAJOR_MINOR}/dist-packages") - endif() - if(EXISTS "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/${PYTHON_PACKAGES_PATH}") - set(_PYTHON_PACKAGES_PATH "lib${LIB_SUFFIX}/${_PYTHON_PACKAGES_PATH}") - else() - set(_PYTHON_PACKAGES_PATH "lib/${_PYTHON_PACKAGES_PATH}") - endif() - elseif(CMAKE_HOST_WIN32) - get_filename_component(PYTHON_PATH "${PYTHON_EXECUTABLE}" PATH) - file(TO_CMAKE_PATH "${PYTHON_PATH}" PYTHON_PATH) - if(NOT EXISTS "${PYTHON_PATH}/Lib/site-packages") - unset(PYTHON_PATH) - get_filename_component(PYTHON_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${PYTHON_VERSION_MAJOR_MINOR}\\InstallPath]" ABSOLUTE) - if(NOT PYTHON_PATH) - get_filename_component(PYTHON_PATH "[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${PYTHON_VERSION_MAJOR_MINOR}\\InstallPath]" ABSOLUTE) - endif() - file(TO_CMAKE_PATH "${PYTHON_PATH}" PYTHON_PATH) - endif() - set(_PYTHON_PACKAGES_PATH "${PYTHON_PATH}/Lib/site-packages") - endif() - SET(PYTHON_PACKAGES_PATH "${_PYTHON_PACKAGES_PATH}" CACHE PATH "Where to install the python packages.") - - if(NOT PYTHON_NUMPY_INCLUDE_DIRS) - if(CMAKE_CROSSCOMPILING) - message(STATUS "Cannot probe for Python/Numpy support (because we are cross-compiling OpenCV)") - message(STATUS "If you want to enable Python/Numpy support, set the following variables:") - message(STATUS " PYTHON_INCLUDE_PATH") - message(STATUS " PYTHON_LIBRARIES") - message(STATUS " PYTHON_NUMPY_INCLUDE_DIRS") - else() - # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy - execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))" - RESULT_VARIABLE PYTHON_NUMPY_PROCESS - OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIRS - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(NOT PYTHON_NUMPY_PROCESS EQUAL 0) - unset(PYTHON_NUMPY_INCLUDE_DIRS) - endif() - endif() - endif() - - if(PYTHON_NUMPY_INCLUDE_DIRS) - file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIRS}" _PYTHON_NUMPY_INCLUDE_DIRS) - set(PYTHON_NUMPY_INCLUDE_DIRS ${_PYTHON_NUMPY_INCLUDE_DIRS} CACHE PATH "Path to numpy headers") - if(CMAKE_CROSSCOMPILING) - if(NOT PYTHON_NUMPY_VERSION) - set(PYTHON_NUMPY_VERSION "undefined - cannot be probed because of the cross-compilation") - endif() - else() - execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import numpy; print(numpy.version.version)" - RESULT_VARIABLE PYTHON_NUMPY_PROCESS - OUTPUT_VARIABLE PYTHON_NUMPY_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() - endif() - endif(NOT ANDROID AND NOT IOS) -endif() - if(BUILD_DOCS) find_host_program(SPHINX_BUILD sphinx-build) find_host_program(PLANTUML plantuml) diff --git a/cmake/OpenCVMinDepVersions.cmake b/cmake/OpenCVMinDepVersions.cmake index 9dae72548..e8591e26e 100644 --- a/cmake/OpenCVMinDepVersions.cmake +++ b/cmake/OpenCVMinDepVersions.cmake @@ -1,5 +1,6 @@ set(MIN_VER_CMAKE 2.8.7) set(MIN_VER_CUDA 4.2) -set(MIN_VER_PYTHON 2.6) +set(MIN_VER_PYTHON2 2.6) +set(MIN_VER_PYTHON3 3.2) set(MIN_VER_ZLIB 1.2.3) set(MIN_VER_GTK 2.18.0) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 1c284539e..7c641cc26 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -105,8 +105,8 @@ if(BUILD_DOCS AND HAVE_SPHINX) COMMAND ${SPHINX_BUILD} ${BUILD_PLANTUML} -b latex -c "${CMAKE_CURRENT_SOURCE_DIR}" "${DOC_FAKE_ROOT}" . COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/pics ${CMAKE_CURRENT_BINARY_DIR}/doc/opencv1/pics COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/mymath.sty ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/patch_refman_latex.py" opencv2refman.tex - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/patch_refman_latex.py" opencv2manager.tex + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/patch_refman_latex.py" opencv2refman.tex + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/patch_refman_latex.py" opencv2manager.tex COMMAND ${CMAKE_COMMAND} -E echo "Generating opencv2refman.pdf" COMMAND ${PDFLATEX_COMPILER} -interaction=batchmode opencv2refman.tex COMMAND ${PDFLATEX_COMPILER} -interaction=batchmode opencv2refman.tex diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 1948e2114..4db3847bd 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -1,7 +1,7 @@ # ---------------------------------------------------------------------------- # CMake file for java support # ---------------------------------------------------------------------------- -if(IOS OR NOT PYTHON_EXECUTABLE OR NOT ANT_EXECUTABLE OR NOT (JNI_FOUND OR (ANDROID AND ANDROID_NATIVE_API_LEVEL GREATER 7))) +if(IOS OR NOT PYTHON_DEFAULT_AVAILABLE OR NOT ANT_EXECUTABLE OR NOT (JNI_FOUND OR (ANDROID AND ANDROID_NATIVE_API_LEVEL GREATER 7))) ocv_module_disable(java) endif() @@ -100,7 +100,7 @@ foreach(module ${OPENCV_JAVA_MODULES}) # first run of gen_java.py (to get list of generated files) file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/gen_java_out/") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/gen_java_out") - execute_process(COMMAND ${PYTHON_EXECUTABLE} "${scripts_gen_java}" "${scripts_hdr_parser}" ${module} ${opencv_public_headers_${module}} + execute_process(COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${scripts_gen_java}" "${scripts_hdr_parser}" ${module} ${opencv_public_headers_${module}} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/gen_java_out" OUTPUT_QUIET ERROR_QUIET) unset(generated_java_sources_${module}) @@ -124,7 +124,7 @@ set(step1_depends "${scripts_gen_java}" "${scripts_hdr_parser}" ${opencv_public_ foreach(module ${OPENCV_JAVA_MODULES}) # second run of gen_java.py (at build time) add_custom_command(OUTPUT ${generated_java_sources_${module}} "${CMAKE_CURRENT_BINARY_DIR}/${module}.cpp" - COMMAND ${PYTHON_EXECUTABLE} "${scripts_gen_java}" "${scripts_hdr_parser}" ${module} ${opencv_public_headers_${module}} + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${scripts_gen_java}" "${scripts_hdr_parser}" ${module} ${opencv_public_headers_${module}} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS "${scripts_gen_java}" "${scripts_hdr_parser}" ${opencv_public_headers_${module}} ) @@ -134,7 +134,7 @@ endforeach() set(step2_depends ${step1_depends} ${scripts_gen_javadoc} ${scripts_rst_parser} ${javadoc_rst_sources} ${generated_java_sources} ${handwrittren_java_sources}) string(REPLACE ";" "," OPENCV_JAVA_MODULES_STR "${OPENCV_JAVA_MODULES}") add_custom_command(OUTPUT ${documented_java_files} - COMMAND ${PYTHON_EXECUTABLE} "${scripts_gen_javadoc}" --modules ${OPENCV_JAVA_MODULES_STR} "${CMAKE_CURRENT_SOURCE_DIR}/generator/src/java" "${CMAKE_CURRENT_BINARY_DIR}" 2> "${CMAKE_CURRENT_BINARY_DIR}/get_javadoc_errors.log" + COMMAND ${PYTHON_DEFUALT_EXECUTABLE} "${scripts_gen_javadoc}" --modules ${OPENCV_JAVA_MODULES_STR} "${CMAKE_CURRENT_SOURCE_DIR}/generator/src/java" "${CMAKE_CURRENT_BINARY_DIR}" 2> "${CMAKE_CURRENT_BINARY_DIR}/get_javadoc_errors.log" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${step2_depends} VERBATIM diff --git a/modules/java/android_test/CMakeLists.txt b/modules/java/android_test/CMakeLists.txt index 41f69e6ca..a92050889 100644 --- a/modules/java/android_test/CMakeLists.txt +++ b/modules/java/android_test/CMakeLists.txt @@ -59,9 +59,9 @@ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E add_dependencies(opencv_tests ${PROJECT_NAME}) -if(PYTHON_EXECUTABLE) +if(PYTHON_DEFAULT_AVAILABLE) set(CHECK_TEST_COVERAGE "${OPENCV_MODULE_opencv_java_LOCATION}/check-tests.py") add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${PYTHON_EXECUTABLE} ${CHECK_TEST_COVERAGE} "${CMAKE_CURRENT_SOURCE_DIR}/src" "${OpenCV_BINARY_DIR}/src" > "${CMAKE_CURRENT_BINARY_DIR}/tests_coverage.log" + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CHECK_TEST_COVERAGE} "${CMAKE_CURRENT_SOURCE_DIR}/src" "${OpenCV_BINARY_DIR}/src" > "${CMAKE_CURRENT_BINARY_DIR}/tests_coverage.log" ) endif() diff --git a/modules/matlab/CMakeLists.txt b/modules/matlab/CMakeLists.txt index a4c1c3b16..095db3649 100644 --- a/modules/matlab/CMakeLists.txt +++ b/modules/matlab/CMakeLists.txt @@ -51,7 +51,7 @@ endmacro() if (IOS OR ANDROID OR NOT MATLAB_FOUND) ocv_module_disable(matlab) return() -elseif (NOT PYTHONLIBS_FOUND) +elseif (NOT PYTHON_DEFAULT_AVAILABLE) message(WARNING "A required dependency of the matlab module (PythonLibs) was not found. Disabling Matlab bindings...") ocv_module_disable(matlab) return() @@ -152,7 +152,7 @@ if (NOT MEX_WORKS) # attempt to generate a gateway for a function message(STATUS "Trying to generate Matlab code") execute_process( - COMMAND ${PYTHON_EXECUTABLE} + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py --jinja2 ${JINJA2_PATH} --hdrparser ${HDR_PARSER_PATH} @@ -212,7 +212,7 @@ file(REMOVE ${GENERATE_PROXY} ${COMPILE_PROXY}) # call the python executable to generate the Matlab gateways add_custom_command( OUTPUT ${GENERATE_PROXY} - COMMAND ${PYTHON_EXECUTABLE} + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py --jinja2 ${JINJA2_PATH} --hdrparser ${HDR_PARSER_PATH} @@ -221,7 +221,7 @@ add_custom_command( --modules ${opencv_modules} --extra ${opencv_extra_hdrs} --outdir ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${PYTHON_EXECUTABLE} + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generator/build_info.py --jinja2 ${JINJA2_PATH} --os ${CMAKE_SYSTEM} @@ -235,7 +235,7 @@ add_custom_command( --modules ${opencv_modules} --configuration $ --outdir ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${PYTHON_EXECUTABLE} + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generator/cvmex.py --jinja2 ${JINJA2_PATH} --opts="${MEX_OPTS}" @@ -298,7 +298,7 @@ string(REPLACE " " "\\ " MEX_CXXFLAGS ${MEX_CXXFLAGS}) string(REPLACE ";" "\\ " MEX_INCLUDE_DIRS "${MEX_INCLUDE_DIRS}") install(CODE "execute_process( - COMMAND ${PYTHON_EXECUTABLE} + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generator/cvmex.py --jinja2 ${JINJA2_PATH} --opts=${MEX_OPTS} diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index a50e372cc..205562dad 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -3,132 +3,14 @@ # ---------------------------------------------------------------------------- if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug") - ocv_module_disable(python) + ocv_module_disable(python2) + ocv_module_disable(python3) endif() -if(ANDROID OR IOS OR NOT PYTHONLIBS_FOUND OR NOT PYTHON_NUMPY_INCLUDE_DIRS) - ocv_module_disable(python) +if(ANDROID OR IOS) + ocv_module_disable(python2) + ocv_module_disable(python3) endif() -set(the_description "The python bindings") -ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) - -ocv_module_include_directories( - "${PYTHON_INCLUDE_PATH}" - ${PYTHON_NUMPY_INCLUDE_DIRS} - "${CMAKE_CURRENT_SOURCE_DIR}/src2" - ) - -set(opencv_hdrs - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/base.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/types.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/persistence.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/utility.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/ocl.hpp" - "${OPENCV_MODULE_opencv_flann_LOCATION}/include/opencv2/flann/miniflann.hpp" - "${OPENCV_MODULE_opencv_imgproc_LOCATION}/include/opencv2/imgproc.hpp" - "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/background_segm.hpp" - "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/tracking.hpp" - "${OPENCV_MODULE_opencv_photo_LOCATION}/include/opencv2/photo.hpp" - "${OPENCV_MODULE_opencv_highgui_LOCATION}/include/opencv2/highgui.hpp" - "${OPENCV_MODULE_opencv_ml_LOCATION}/include/opencv2/ml.hpp" - "${OPENCV_MODULE_opencv_features2d_LOCATION}/include/opencv2/features2d.hpp" - "${OPENCV_MODULE_opencv_calib3d_LOCATION}/include/opencv2/calib3d.hpp" - "${OPENCV_MODULE_opencv_objdetect_LOCATION}/include/opencv2/objdetect.hpp" - ) - -if(HAVE_opencv_nonfree) - list(APPEND opencv_hdrs "${OPENCV_MODULE_opencv_nonfree_LOCATION}/include/opencv2/nonfree/features2d.hpp" - "${OPENCV_MODULE_opencv_nonfree_LOCATION}/include/opencv2/nonfree.hpp") -endif() - -set(cv2_generated_hdrs - "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h" - "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_funcs.h" - "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_func_tab.h" - "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_types.h" - "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_type_reg.h" - "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_const_reg.h") - -add_custom_command( - OUTPUT ${cv2_generated_hdrs} - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} ${opencv_hdrs} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src2/gen2.py - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src2/hdr_parser.py - DEPENDS ${opencv_hdrs}) - -add_library(${the_module} SHARED src2/cv2.cpp ${cv2_generated_hdrs}) -set_target_properties(${the_module} PROPERTIES COMPILE_DEFINITIONS OPENCV_NOSTL) - -if(PYTHON_DEBUG_LIBRARIES AND NOT PYTHON_LIBRARIES MATCHES "optimized.*debug") - target_link_libraries(${the_module} debug ${PYTHON_DEBUG_LIBRARIES} optimized ${PYTHON_LIBRARIES}) -else() - target_link_libraries(${the_module} ${PYTHON_LIBRARIES}) -endif() -target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS}) - -execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SO'))" - RESULT_VARIABLE PYTHON_CVPY_PROCESS - OUTPUT_VARIABLE CVPY_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) - -set_target_properties(${the_module} PROPERTIES - PREFIX "" - OUTPUT_NAME cv2 - SUFFIX ${CVPY_SUFFIX}) - -if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${the_module} PROPERTIES FOLDER "bindings") -endif() - -if(MSVC) - add_definitions(-DCVAPI_EXPORTS) -endif() - -if(CMAKE_COMPILER_IS_GNUCXX AND NOT ENABLE_NOISY_WARNINGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function") -endif() - -if(MSVC AND NOT ENABLE_NOISY_WARNINGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4100") #unreferenced formal parameter - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4127") #conditional expression is constant - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4505") #unreferenced local function has been removed - string(REPLACE "/W4" "/W3" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -endif() - -if(MSVC AND NOT BUILD_SHARED_LIBS) - set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") -endif() - -if(MSVC AND NOT PYTHON_DEBUG_LIBRARIES) - set(PYTHON_INSTALL_CONFIGURATIONS CONFIGURATIONS Release) -else() - set(PYTHON_INSTALL_CONFIGURATIONS "") -endif() - -if(WIN32) - set(PYTHON_INSTALL_ARCHIVE "") -else() - set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python) -endif() - -if(NOT INSTALL_CREATE_DISTRIB) - install(TARGETS ${the_module} - ${PYTHON_INSTALL_CONFIGURATIONS} - RUNTIME DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python - LIBRARY DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python - ${PYTHON_INSTALL_ARCHIVE} - ) -else() - if(DEFINED PYTHON_VERSION_MAJOR) - set(__ver "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") - else() - set(__ver "unknown") - endif() - install(TARGETS ${the_module} - CONFIGURATIONS Release - RUNTIME DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT python - LIBRARY DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT python - ) -endif() +add_subdirectory(python2) +add_subdirectory(python3) diff --git a/modules/python/common.cmake b/modules/python/common.cmake new file mode 100644 index 000000000..edac17f20 --- /dev/null +++ b/modules/python/common.cmake @@ -0,0 +1,128 @@ +# This file is included from a subdirectory +set(PYTHON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../") + +ocv_module_include_directories( + "${PYTHON_INCLUDE_PATH}" + ${PYTHON_NUMPY_INCLUDE_DIRS} + "${PYTHON_SOURCE_DIR}/src2" + ) + +set(opencv_hdrs + "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core.hpp" + "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/base.hpp" + "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/types.hpp" + "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/persistence.hpp" + "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/utility.hpp" + "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/ocl.hpp" + "${OPENCV_MODULE_opencv_flann_LOCATION}/include/opencv2/flann/miniflann.hpp" + "${OPENCV_MODULE_opencv_imgproc_LOCATION}/include/opencv2/imgproc.hpp" + "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/background_segm.hpp" + "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/tracking.hpp" + "${OPENCV_MODULE_opencv_photo_LOCATION}/include/opencv2/photo.hpp" + "${OPENCV_MODULE_opencv_highgui_LOCATION}/include/opencv2/highgui.hpp" + "${OPENCV_MODULE_opencv_ml_LOCATION}/include/opencv2/ml.hpp" + "${OPENCV_MODULE_opencv_features2d_LOCATION}/include/opencv2/features2d.hpp" + "${OPENCV_MODULE_opencv_calib3d_LOCATION}/include/opencv2/calib3d.hpp" + "${OPENCV_MODULE_opencv_objdetect_LOCATION}/include/opencv2/objdetect.hpp" + ) + +if(HAVE_opencv_nonfree) + list(APPEND opencv_hdrs "${OPENCV_MODULE_opencv_nonfree_LOCATION}/include/opencv2/nonfree/features2d.hpp" + "${OPENCV_MODULE_opencv_nonfree_LOCATION}/include/opencv2/nonfree.hpp") +endif() + +set(cv2_generated_hdrs + "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h" + "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_funcs.h" + "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_func_tab.h" + "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_types.h" + "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_type_reg.h" + "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_const_reg.h") + +add_custom_command( + OUTPUT ${cv2_generated_hdrs} + COMMAND ${PYTHON_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} ${opencv_hdrs} + DEPENDS ${PYTHON_SOURCE_DIR}/src2/gen2.py + DEPENDS ${PYTHON_SOURCE_DIR}/src2/hdr_parser.py + DEPENDS ${opencv_hdrs}) + +add_library(${the_module} SHARED ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs}) +set_target_properties(${the_module} PROPERTIES COMPILE_DEFINITIONS OPENCV_NOSTL) + +if(PYTHON_DEBUG_LIBRARIES AND NOT PYTHON_LIBRARIES MATCHES "optimized.*debug") + target_link_libraries(${the_module} debug ${PYTHON_DEBUG_LIBRARIES} optimized ${PYTHON_LIBRARIES}) +else() + target_link_libraries(${the_module} ${PYTHON_LIBRARIES}) +endif() +target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS}) + +execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SO'))" + RESULT_VARIABLE PYTHON_CVPY_PROCESS + OUTPUT_VARIABLE CVPY_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + +set_target_properties(${the_module} PROPERTIES + PREFIX "" + OUTPUT_NAME cv2 + SUFFIX ${CVPY_SUFFIX}) + +if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(${the_module} PROPERTIES FOLDER "bindings") +endif() + +if(MSVC) + add_definitions(-DCVAPI_EXPORTS) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX AND NOT ENABLE_NOISY_WARNINGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function") +endif() + +if(MSVC AND NOT ENABLE_NOISY_WARNINGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4100") #unreferenced formal parameter + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4127") #conditional expression is constant + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4505") #unreferenced local function has been removed + string(REPLACE "/W4" "/W3" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +endif() + +if(MSVC AND NOT BUILD_SHARED_LIBS) + set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") +endif() + +if(MSVC AND NOT PYTHON_DEBUG_LIBRARIES) + set(PYTHON_INSTALL_CONFIGURATIONS CONFIGURATIONS Release) +else() + set(PYTHON_INSTALL_CONFIGURATIONS "") +endif() + +if(WIN32) + set(PYTHON_INSTALL_ARCHIVE "") +else() + set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python) +endif() + +if(NOT INSTALL_CREATE_DISTRIB) + install(TARGETS ${the_module} + ${PYTHON_INSTALL_CONFIGURATIONS} + RUNTIME DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python + LIBRARY DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python + ${PYTHON_INSTALL_ARCHIVE} + ) +else() + if(DEFINED PYTHON_VERSION_MAJOR) + set(__ver "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") + else() + set(__ver "unknown") + endif() + install(TARGETS ${the_module} + CONFIGURATIONS Release + RUNTIME DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT python + LIBRARY DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT python + ) +endif() + +unset(PYTHON_SRC_DIR) +unset(PYTHON_CVPY_PROCESS) +unset(CVPY_SUFFIX) +unset(PYTHON_INSTALL_CONFIGURATIONS) +unset(PYTHON_INSTALL_ARCHIVE) diff --git a/modules/python/python2/CMakeLists.txt b/modules/python/python2/CMakeLists.txt new file mode 100644 index 000000000..875631600 --- /dev/null +++ b/modules/python/python2/CMakeLists.txt @@ -0,0 +1,26 @@ +if(NOT PYTHON2LIBS_FOUND OR NOT PYTHON2_NUMPY_INCLUDE_DIRS) + ocv_module_disable(python2) +endif() + +set(the_description "The python2 bindings") +ocv_add_module(python2 BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) + +set(PYTHON_INCLUDE_PATH ${PYTHON2_INCLUDE_PATH}) +set(PYTHON_NUMPY_INCLUDE_PATH ${PYTHON2_NUMPY_INCLUDE_PATH}) +set(PYTHON_EXECUTABLE ${PYTHON2_EXECUTABLE}) +set(PYTHON_DEBUG_LIBRARIES ${PYTHON2_DEBUG_LIBRARIES}) +set(PYTHON_LIBRARIES ${PYTHON2_LIBRARIES}) +set(PYTHON_PACKAGES_PATH ${PYTHON2_PACKAGES_PATH}) +set(PYTHON_VERSION_MAJOR ${PYTHON2_VERSION_MAJOR}) +set(PYTHON_VERSION_MINOR ${PYTHON2_VERSION_MINOR}) + +include(../common.cmake) + +unset(PYTHON_INCLUDE_PATH) +unset(PYTHON_NUMPY_INCLUDE_PATH) +unset(PYTHON_EXECUTABLE) +unset(PYTHON_DEBUG_LIBRARIES) +unset(PYTHON_LIBRARIES) +unset(PYTHON_PACKAGES_PATH) +unset(PYTHON_VERSION_MAJOR) +unset(PYTHON_VERSION_MINOR) diff --git a/modules/python/python3/CMakeLists.txt b/modules/python/python3/CMakeLists.txt new file mode 100644 index 000000000..b380bacc1 --- /dev/null +++ b/modules/python/python3/CMakeLists.txt @@ -0,0 +1,26 @@ +if(NOT PYTHON3LIBS_FOUND OR NOT PYTHON3_NUMPY_INCLUDE_DIRS) + ocv_module_disable(python3) +endif() + +set(the_description "The python3 bindings") +ocv_add_module(python3 BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) + +set(PYTHON_INCLUDE_PATH ${PYTHON3_INCLUDE_PATH}) +set(PYTHON_NUMPY_INCLUDE_PATH ${PYTHON3_NUMPY_INCLUDE_PATH}) +set(PYTHON_EXECUTABLE ${PYTHON3_EXECUTABLE}) +set(PYTHON_DEBUG_LIBRARIES ${PYTHON3_DEBUG_LIBRARIES}) +set(PYTHON_LIBRARIES ${PYTHON3_LIBRARIES}) +set(PYTHON_PACKAGES_PATH ${PYTHON3_PACKAGES_PATH}) +set(PYTHON_VERSION_MAJOR ${PYTHON3_VERSION_MAJOR}) +set(PYTHON_VERSION_MINOR ${PYTHON3_VERSION_MINOR}) + +include(../common.cmake) + +unset(PYTHON_INCLUDE_PATH) +unset(PYTHON_NUMPY_INCLUDE_PATH) +unset(PYTHON_EXECUTABLE) +unset(PYTHON_DEBUG_LIBRARIES) +unset(PYTHON_LIBRARIES) +unset(PYTHON_PACKAGES_PATH) +unset(PYTHON_VERSION_MAJOR) +unset(PYTHON_VERSION_MINOR) From 52df3b232d87e5b144c37f4c89af2e8e1f1ff5c7 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 31 Jul 2014 03:27:06 -0400 Subject: [PATCH 2/7] Reference PYTHON_NUMPY_INCLUDE_DIRS not PYTHON_NUMPY_INCLUDE_PATH PYTHON_NUMPY_INCLUDE_PATH was a typo, it should have been PYTHON_NUMPY_INCLUDE_DIRS. --- modules/python/python2/CMakeLists.txt | 2 +- modules/python/python3/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/python/python2/CMakeLists.txt b/modules/python/python2/CMakeLists.txt index f65c75d78..4881cb5ed 100644 --- a/modules/python/python2/CMakeLists.txt +++ b/modules/python/python2/CMakeLists.txt @@ -6,7 +6,7 @@ set(the_description "The python2 bindings") set(MODULE_NAME python2) set(PYTHON_INCLUDE_PATH ${PYTHON2_INCLUDE_PATH}) -set(PYTHON_NUMPY_INCLUDE_PATH ${PYTHON2_NUMPY_INCLUDE_PATH}) +set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON2_NUMPY_INCLUDE_DIRS}) set(PYTHON_EXECUTABLE ${PYTHON2_EXECUTABLE}) set(PYTHON_DEBUG_LIBRARIES ${PYTHON2_DEBUG_LIBRARIES}) set(PYTHON_LIBRARIES ${PYTHON2_LIBRARIES}) diff --git a/modules/python/python3/CMakeLists.txt b/modules/python/python3/CMakeLists.txt index 7c23bd9c7..3f6649205 100644 --- a/modules/python/python3/CMakeLists.txt +++ b/modules/python/python3/CMakeLists.txt @@ -6,7 +6,7 @@ set(the_description "The python3 bindings") set(MODULE_NAME python3) set(PYTHON_INCLUDE_PATH ${PYTHON3_INCLUDE_PATH}) -set(PYTHON_NUMPY_INCLUDE_PATH ${PYTHON3_NUMPY_INCLUDE_PATH}) +set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON3_NUMPY_INCLUDE_DIRS}) set(PYTHON_EXECUTABLE ${PYTHON3_EXECUTABLE}) set(PYTHON_DEBUG_LIBRARIES ${PYTHON3_DEBUG_LIBRARIES}) set(PYTHON_LIBRARIES ${PYTHON3_LIBRARIES}) From 976c727eec7b9bb3f4c12b7ed4ada8b3f664bf69 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 6 Aug 2014 02:30:35 -0400 Subject: [PATCH 3/7] Fix a few more PYTHON_NUMPY_INCLUDE_PATH The previous commit fixing references to PYTHON_NUMPY_INCLUDE_PATH missed a few unset()s. --- modules/python/python2/CMakeLists.txt | 2 +- modules/python/python3/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/python/python2/CMakeLists.txt b/modules/python/python2/CMakeLists.txt index 4881cb5ed..01a3b474d 100644 --- a/modules/python/python2/CMakeLists.txt +++ b/modules/python/python2/CMakeLists.txt @@ -18,7 +18,7 @@ include(../common.cmake) unset(MODULE_NAME) unset(PYTHON_INCLUDE_PATH) -unset(PYTHON_NUMPY_INCLUDE_PATH) +unset(PYTHON_NUMPY_INCLUDE_DIRS) unset(PYTHON_EXECUTABLE) unset(PYTHON_DEBUG_LIBRARIES) unset(PYTHON_LIBRARIES) diff --git a/modules/python/python3/CMakeLists.txt b/modules/python/python3/CMakeLists.txt index 3f6649205..14672d3c7 100644 --- a/modules/python/python3/CMakeLists.txt +++ b/modules/python/python3/CMakeLists.txt @@ -18,7 +18,7 @@ include(../common.cmake) unset(MODULE_NAME) unset(PYTHON_INCLUDE_PATH) -unset(PYTHON_NUMPY_INCLUDE_PATH) +unset(PYTHON_NUMPY_INCLUDE_DIRS) unset(PYTHON_EXECUTABLE) unset(PYTHON_DEBUG_LIBRARIES) unset(PYTHON_LIBRARIES) From 9d9411555fa87321a1e36a39c8993c224f66e2fd Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 6 Aug 2014 02:31:30 -0400 Subject: [PATCH 4/7] Place Python library out in dedicated folder Place the built Python module library in a dedicated folder inside of lib/. This ensures that even if the Python 2 and Python 3 module names conflict, they will not overwrite one another. --- modules/python/common.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/python/common.cmake b/modules/python/common.cmake index 7d964067a..c37ae6681 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -71,6 +71,7 @@ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig; pri OUTPUT_STRIP_TRAILING_WHITESPACE) set_target_properties(${the_module} PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${LIBRARY_OUTPUT_PATH}/${MODULE_NAME}" PREFIX "" OUTPUT_NAME cv2 SUFFIX ${CVPY_SUFFIX}) From d921cde4d2ee72533896ef971e8e30d2ce33806a Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 7 Aug 2014 00:16:49 -0400 Subject: [PATCH 5/7] Add opencv_matlab to Python ignored modules Requested by @vpisarev in #3047. --- modules/python/common.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/python/common.cmake b/modules/python/common.cmake index c37ae6681..581822e9d 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -15,6 +15,7 @@ endforeach(mp) # module blacklist ocv_list_filterout(candidate_deps "^opencv_cud(a|ev)") ocv_list_filterout(candidate_deps "^opencv_adas$") +ocv_list_filterout(candidate_deps "^opencv_matlab$") ocv_list_filterout(candidate_deps "^opencv_tracking$") From 7d41ce23a757b56d6b4c96d741f9a4b175606a70 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 7 Aug 2014 00:21:42 -0400 Subject: [PATCH 6/7] Build Python 3 bindings in subdirectory Build the Python 3 cv2 module in lib/python3/, to avoid potential naming conflicts with the Python 2 bindings. The Python 2 bindings are placed directly in lib/, where they are required for the Buildbot to successfully execute the Python tests. --- modules/python/common.cmake | 2 +- modules/python/python2/CMakeLists.txt | 3 +++ modules/python/python3/CMakeLists.txt | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/python/common.cmake b/modules/python/common.cmake index 581822e9d..30f6d2813 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -72,7 +72,7 @@ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig; pri OUTPUT_STRIP_TRAILING_WHITESPACE) set_target_properties(${the_module} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${LIBRARY_OUTPUT_PATH}/${MODULE_NAME}" + LIBRARY_OUTPUT_DIRECTORY "${LIBRARY_OUTPUT_PATH}/${MODULE_INSTALL_SUBDIR}" PREFIX "" OUTPUT_NAME cv2 SUFFIX ${CVPY_SUFFIX}) diff --git a/modules/python/python2/CMakeLists.txt b/modules/python/python2/CMakeLists.txt index 01a3b474d..158763ec5 100644 --- a/modules/python/python2/CMakeLists.txt +++ b/modules/python/python2/CMakeLists.txt @@ -4,6 +4,8 @@ endif() set(the_description "The python2 bindings") set(MODULE_NAME python2) +# Buildbot requires Python 2 to be in root lib dir +set(MODULE_INSTALL_SUBDIR "") set(PYTHON_INCLUDE_PATH ${PYTHON2_INCLUDE_PATH}) set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON2_NUMPY_INCLUDE_DIRS}) @@ -17,6 +19,7 @@ set(PYTHON_VERSION_MINOR ${PYTHON2_VERSION_MINOR}) include(../common.cmake) unset(MODULE_NAME) +unset(MODULE_INSTALL_SUBDIR) unset(PYTHON_INCLUDE_PATH) unset(PYTHON_NUMPY_INCLUDE_DIRS) unset(PYTHON_EXECUTABLE) diff --git a/modules/python/python3/CMakeLists.txt b/modules/python/python3/CMakeLists.txt index 14672d3c7..4b6fe4f14 100644 --- a/modules/python/python3/CMakeLists.txt +++ b/modules/python/python3/CMakeLists.txt @@ -4,6 +4,7 @@ endif() set(the_description "The python3 bindings") set(MODULE_NAME python3) +set(MODULE_INSTALL_SUBDIR python3) set(PYTHON_INCLUDE_PATH ${PYTHON3_INCLUDE_PATH}) set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON3_NUMPY_INCLUDE_DIRS}) @@ -17,6 +18,7 @@ set(PYTHON_VERSION_MINOR ${PYTHON3_VERSION_MINOR}) include(../common.cmake) unset(MODULE_NAME) +unset(MODULE_INSTALL_SUBDIR) unset(PYTHON_INCLUDE_PATH) unset(PYTHON_NUMPY_INCLUDE_DIRS) unset(PYTHON_EXECUTABLE) From e9ccadebed4a07626b2aa8108fde0634d96827d4 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 7 Aug 2014 00:51:48 -0400 Subject: [PATCH 7/7] Support Python 2 and 3 in test script Add Python 3 support to the Python test.py script. The print function is used in place of the print statement. The urlopen function has been moved to urllib.request in Python 3, so attempt to import it from either location. TestCase.assert_() has been deprecated in place of TestCase.assertTrue(). The tests all pass in both Python 2 and 3. --- modules/python/test/test.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/modules/python/test/test.py b/modules/python/test/test.py index 2da740de9..76f64fc52 100644 --- a/modules/python/test/test.py +++ b/modules/python/test/test.py @@ -1,12 +1,12 @@ #!/usr/bin/env python +from __future__ import print_function import unittest import random import time import math import sys import array -import urllib import tarfile import hashlib import os @@ -16,11 +16,17 @@ import functools import numpy as np import cv2 +# Python 3 moved urlopen to urllib.requests +try: + from urllib.request import urlopen +except ImportError: + from urllib import urlopen + class NewOpenCVTests(unittest.TestCase): def get_sample(self, filename, iscolor = cv2.IMREAD_COLOR): if not filename in self.image_cache: - filedata = urllib.urlopen("https://raw.github.com/Itseez/opencv/master/" + filename).read() + filedata = urlopen("https://raw.github.com/Itseez/opencv/master/" + filename).read() self.image_cache[filename] = cv2.imdecode(np.fromstring(filedata, dtype=np.uint8), iscolor) return self.image_cache[filename] @@ -51,7 +57,7 @@ class Hackathon244Tests(NewOpenCVTests): def test_int_array(self): a = np.array([-1, 2, -3, 4, -5]) absa0 = np.abs(a) - self.assert_(cv2.norm(a, cv2.NORM_L1) == 15) + self.assertTrue(cv2.norm(a, cv2.NORM_L1) == 15) absa1 = cv2.absdiff(a, 0) self.assertEqual(cv2.norm(absa1, absa0, cv2.NORM_INF), 0) @@ -90,13 +96,13 @@ class Hackathon244Tests(NewOpenCVTests): img = cv2.medianBlur(img, 3) imgc = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) keypoints = fd.detect(img) - self.assert_(600 <= len(keypoints) <= 700) + self.assertTrue(600 <= len(keypoints) <= 700) for kpt in keypoints: self.assertNotEqual(kpt.response, 0) def check_close_angles(self, a, b, angle_delta): - self.assert_(abs(a - b) <= angle_delta or - abs(360 - abs(a - b)) <= angle_delta) + self.assertTrue(abs(a - b) <= angle_delta or + abs(360 - abs(a - b)) <= angle_delta) def check_close_pairs(self, a, b, delta): self.assertLessEqual(abs(a[0] - b[0]), delta) @@ -127,6 +133,6 @@ class Hackathon244Tests(NewOpenCVTests): self.assertLessEqual(abs(mr - mr0), 5) if __name__ == '__main__': - print "Testing OpenCV", cv2.__version__ + print("Testing OpenCV", cv2.__version__) random.seed(0) unittest.main()