diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index 64054d1efa02e3c8a43b6424a4701cb2171df938..f304a50a422354cd390a4a85b9e0cf8388405238 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -75,10 +75,10 @@ if(NOT ${found}) if(NOT ANDROID AND NOT APPLE_FRAMEWORK) ocv_check_environment_variables(${library_env} ${include_dir_env}) - if(NOT ${${library_env}} EQUAL "") + if(NOT ${${library_env}} STREQUAL "") set(PYTHON_LIBRARY "${${library_env}}") endif() - if(NOT ${${include_dir_env}} EQUAL "") + if(NOT ${${include_dir_env}} STREQUAL "") set(PYTHON_INCLUDE_DIR "${${include_dir_env}}") endif() @@ -162,10 +162,10 @@ if(NOT ${found}) 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_LIBRARIES (optional on Unix-like systems)") message(STATUS " PYTHON2_NUMPY_INCLUDE_DIRS") message(STATUS " PYTHON3_INCLUDE_PATH") - message(STATUS " PYTHON3_LIBRARIES") + message(STATUS " PYTHON3_LIBRARIES (optional on Unix-like systems)") message(STATUS " PYTHON3_NUMPY_INCLUDE_DIRS") else() # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy diff --git a/modules/python/common.cmake b/modules/python/common.cmake index cf74f8dd953fda76793faeb947b6090422de496a..c33f6a9101d9e1f9bb27a0bbfa1367f0400ef22c 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -1,11 +1,15 @@ # This file is included from a subdirectory set(PYTHON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../") +# try to use dynamic symbols linking with libpython.so +set(OPENCV_FORCE_PYTHON_LIBS OFF CACHE BOOL "") +string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") + ocv_add_module(${MODULE_NAME} BINDINGS) ocv_module_include_directories( - "${PYTHON_INCLUDE_PATH}" - ${PYTHON_NUMPY_INCLUDE_DIRS} + "${${PYTHON}_INCLUDE_PATH}" + ${${PYTHON}_NUMPY_INCLUDE_DIRS} "${PYTHON_SOURCE_DIR}/src2" ) @@ -41,7 +45,7 @@ set(cv2_generated_hdrs file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}") add_custom_command( OUTPUT ${cv2_generated_hdrs} - COMMAND ${PYTHON_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${PYTHON}" DEPENDS ${PYTHON_SOURCE_DIR}/src2/gen2.py DEPENDS ${PYTHON_SOURCE_DIR}/src2/hdr_parser.py DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt @@ -49,21 +53,28 @@ add_custom_command( ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs}) -if(PYTHON_DEBUG_LIBRARIES AND NOT PYTHON_LIBRARIES MATCHES "optimized.*debug") - ocv_target_link_libraries(${the_module} debug ${PYTHON_DEBUG_LIBRARIES} optimized ${PYTHON_LIBRARIES}) -else() - if(APPLE) - set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") +if(APPLE) + set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") +elseif(WIN32 OR OPENCV_FORCE_PYTHON_LIBS) + if(${PYTHON}_DEBUG_LIBRARIES AND NOT ${PYTHON}_LIBRARIES MATCHES "optimized.*debug") + ocv_target_link_libraries(${the_module} debug ${${PYTHON}_DEBUG_LIBRARIES} optimized ${${PYTHON}_LIBRARIES}) else() - ocv_target_link_libraries(${the_module} ${PYTHON_LIBRARIES}) + ocv_target_link_libraries(${the_module} ${${PYTHON}_LIBRARIES}) endif() endif() ocv_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) +if(DEFINED ${PYTHON}_CVPY_SUFFIX) + set(CVPY_SUFFIX "${${PYTHON}_CVPY_SUFFIX}") +else() + 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) + if(NOT PYTHON_CVPY_PROCESS EQUAL 0) + set(CVPY_SUFFIX ".so") + endif() +endif() set_target_properties(${the_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${LIBRARY_OUTPUT_PATH}/${MODULE_INSTALL_SUBDIR}" @@ -95,7 +106,7 @@ 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) +if(MSVC AND NOT ${PYTHON}_DEBUG_LIBRARIES) set(PYTHON_INSTALL_CONFIGURATIONS CONFIGURATIONS Release) else() set(PYTHON_INSTALL_CONFIGURATIONS "") @@ -104,19 +115,22 @@ endif() if(WIN32) set(PYTHON_INSTALL_ARCHIVE "") else() - set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python) + set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${${PYTHON}_PACKAGES_PATH} COMPONENT python) endif() -if(NOT INSTALL_CREATE_DISTRIB) +if(NOT INSTALL_CREATE_DISTRIB AND DEFINED ${PYTHON}_PACKAGES_PATH) + set(__dst "${${PYTHON}_PACKAGES_PATH}") install(TARGETS ${the_module} OPTIONAL ${PYTHON_INSTALL_CONFIGURATIONS} - RUNTIME DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python - LIBRARY DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python + RUNTIME DESTINATION "${__dst}" COMPONENT python + LIBRARY DESTINATION "${__dst}" COMPONENT python ${PYTHON_INSTALL_ARCHIVE} ) else() - if(DEFINED PYTHON_VERSION_MAJOR) - set(__ver "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") + if(DEFINED ${PYTHON}_VERSION_MAJOR) + set(__ver "${${PYTHON}_VERSION_MAJOR}.${${PYTHON}_VERSION_MINOR}") + elseif(DEFINED ${PYTHON}_VERSION_STRING) + set(__ver "${${PYTHON}_VERSION_STRING}") else() set(__ver "unknown") endif() diff --git a/modules/python/python2/CMakeLists.txt b/modules/python/python2/CMakeLists.txt index 158763ec50b6728503dd7d1d1c7f8c8f385152c0..37e20fe33074d260182536846214f201039d2b0c 100644 --- a/modules/python/python2/CMakeLists.txt +++ b/modules/python/python2/CMakeLists.txt @@ -1,4 +1,4 @@ -if(NOT PYTHON2LIBS_FOUND OR NOT PYTHON2_NUMPY_INCLUDE_DIRS) +if(NOT PYTHON2_INCLUDE_PATH OR NOT PYTHON2_NUMPY_INCLUDE_DIRS) ocv_module_disable(python2) endif() @@ -7,24 +7,9 @@ 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}) -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}) +set(PYTHON PYTHON2) include(../common.cmake) unset(MODULE_NAME) unset(MODULE_INSTALL_SUBDIR) -unset(PYTHON_INCLUDE_PATH) -unset(PYTHON_NUMPY_INCLUDE_DIRS) -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 index 4b6fe4f141f0ad9e96dde9d560d8a735f042ded3..da86ba5c5eaec7a63e9313492ef0642dbf594154 100644 --- a/modules/python/python3/CMakeLists.txt +++ b/modules/python/python3/CMakeLists.txt @@ -1,4 +1,4 @@ -if(NOT PYTHON3LIBS_FOUND OR NOT PYTHON3_NUMPY_INCLUDE_DIRS) +if(NOT PYTHON3_INCLUDE_PATH OR NOT PYTHON3_NUMPY_INCLUDE_DIRS) ocv_module_disable(python3) endif() @@ -6,24 +6,9 @@ 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}) -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}) +set(PYTHON PYTHON3) include(../common.cmake) unset(MODULE_NAME) unset(MODULE_INSTALL_SUBDIR) -unset(PYTHON_INCLUDE_PATH) -unset(PYTHON_NUMPY_INCLUDE_DIRS) -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/src2/gen2.py b/modules/python/src2/gen2.py index 20c1007deeb55d002551eb3669165a59eb6e8fae..0175f1e6db521693a7ef1a6a24a4dbc57eec7623 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -44,6 +44,14 @@ gen_template_func_body = Template("""$code_decl """) py_major_version = sys.version_info[0] +if __name__ == "__main__": + if len(sys.argv) > 3: + if sys.argv[3] == 'PYTHON3': + py_major_version = 3 + elif sys.argv[3] == 'PYTHON2': + py_major_version = 2 + else: + raise Exception('Incorrect argument: expected PYTHON2 or PYTHON3, received: ' + sys.argv[3]) if py_major_version >= 3: head_init_str = "PyVarObject_HEAD_INIT(&PyType_Type, 0)" else: