python: support standalone Python bindings build
authorAlexander Alekhin <alexander.alekhin@intel.com>
Thu, 7 Jun 2018 09:32:48 +0000 (12:32 +0300)
committerAlexander Alekhin <alexander.alekhin@intel.com>
Thu, 7 Jun 2018 12:16:39 +0000 (15:16 +0300)
- requires OpenCV source directory
- requires OpenCV binary directory with built modules and 'python_bindings_generator' target

cmake/OpenCVDetectPython.cmake
modules/python/CMakeLists.txt
modules/python/bindings/CMakeLists.txt
modules/python/common.cmake
modules/python/python2/CMakeLists.txt
modules/python/python3/CMakeLists.txt
modules/python/standalone.cmake [new file with mode: 0644]

index 6dec76f..b6c7a25 100644 (file)
@@ -27,6 +27,12 @@ function(find_python preferred_version min_version library_env include_dir_env
          debug_library include_path include_dir include_dir2 packages_path
          numpy_include_dirs numpy_version)
 if(NOT ${found})
+  if(" ${executable}" STREQUAL " PYTHON_EXECUTABLE")
+    set(__update_python_vars 0)
+  else()
+    set(__update_python_vars 1)
+  endif()
+
   ocv_check_environment_variables(${executable})
   if(${executable})
     set(PYTHON_EXECUTABLE "${${executable}}")
@@ -47,7 +53,7 @@ if(NOT ${found})
     endforeach()
   endif()
 
-  string(REGEX MATCH "^[0-9]+" _preferred_version_major ${preferred_version})
+  string(REGEX MATCH "^[0-9]+" _preferred_version_major "${preferred_version}")
 
   find_host_package(PythonInterp "${preferred_version}")
   if(NOT PYTHONINTERP_FOUND)
@@ -56,7 +62,7 @@ if(NOT ${found})
 
   if(PYTHONINTERP_FOUND)
     # Check if python major version is correct
-    if(${_preferred_version_major} EQUAL ${PYTHON_VERSION_MAJOR})
+    if("${_preferred_version_major}" STREQUAL "" OR "${_preferred_version_major}" STREQUAL "${PYTHON_VERSION_MAJOR}")
       # Copy outputs
       set(_found ${PYTHONINTERP_FOUND})
       set(_executable ${PYTHON_EXECUTABLE})
@@ -65,7 +71,9 @@ if(NOT ${found})
       set(_version_minor ${PYTHON_VERSION_MINOR})
       set(_version_patch ${PYTHON_VERSION_PATCH})
     endif()
+  endif()
 
+  if(__update_python_vars)
     # Clear find_host_package side effects
     unset(PYTHONINTERP_FOUND)
     unset(PYTHON_EXECUTABLE CACHE)
@@ -109,7 +117,8 @@ if(NOT ${found})
         set(_library_release ${PYTHON_LIBRARY_RELEASE})
         set(_include_dir ${PYTHON_INCLUDE_DIR})
         set(_include_dir2 ${PYTHON_INCLUDE_DIR2})
-
+      endif()
+      if(__update_python_vars)
         # Clear find_package side effects
         unset(PYTHONLIBS_FOUND)
         unset(PYTHON_LIBRARIES)
@@ -160,7 +169,7 @@ if(NOT ${found})
         unset(_path)
       endif()
 
-      set(_numpy_include_dirs ${${numpy_include_dirs}})
+      set(_numpy_include_dirs "${${numpy_include_dirs}}")
 
       if(NOT _numpy_include_dirs)
         if(CMAKE_CROSSCOMPILING)
@@ -222,6 +231,10 @@ if(NOT ${found})
 endif()
 endfunction(find_python)
 
+if(OPENCV_PYTHON_SKIP_DETECTION)
+  return()
+endif()
+
 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
index dffe9a7..bcaa7d9 100644 (file)
@@ -1,6 +1,7 @@
 # ----------------------------------------------------------------------------
 #  CMake file for python support
 # ----------------------------------------------------------------------------
+if(DEFINED OPENCV_INITIAL_PASS)  # OpenCV build
 
 add_subdirectory(bindings)
 
@@ -28,3 +29,10 @@ endif()
 
 add_subdirectory(python2)
 add_subdirectory(python3)
+
+else()  # standalone build
+
+cmake_minimum_required(VERSION 2.8.12)
+include("./standalone.cmake")
+
+endif()
index 73c67aa..f7c86e0 100644 (file)
@@ -37,6 +37,7 @@ ocv_list_filterout(opencv_hdrs "modules/.+/utils/.*")
 ocv_list_filterout(opencv_hdrs "modules/.*\\\\.inl\\\\.h*")
 ocv_list_filterout(opencv_hdrs "modules/.*_inl\\\\.h*")
 ocv_list_filterout(opencv_hdrs "modules/.*\\\\.details\\\\.h*")
+ocv_list_filterout(opencv_hdrs "modules/.*\\\\.private\\\\.h*")
 ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker\\\\.hpp") # Conditional compilation
 
 set(cv2_generated_files
@@ -78,3 +79,32 @@ else()
   file(WRITE "${cv2_custom_hdr}" "${cv2_custom_hdr_str}")
 endif()
 unset(__content)
+
+
+#
+# Configuration for standalone build of Python bindings
+#
+set(PYTHON_CONFIG_SCRIPT "")
+ocv_cmake_script_append_var(PYTHON_CONFIG_SCRIPT
+    CMAKE_BUILD_TYPE
+    BUILD_SHARED_LIBS
+
+    CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+    CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+
+    CV_GCC CV_CLANG ENABLE_NOISY_WARNINGS
+
+    CMAKE_MODULE_LINKER_FLAGS
+    CMAKE_INSTALL_PREFIX
+
+    OpenCV_SOURCE_DIR
+
+    OPENCV_FORCE_PYTHON_LIBS
+    OPENCV_PYTHON_SKIP_LINKER_EXCLUDE_LIBS
+
+    OPENCV_PYTHON_BINDINGS_DIR
+    cv2_custom_hdr
+    cv2_generated_files
+)
+set(CMAKE_HELPER_SCRIPT "${CMAKE_BINARY_DIR}/opencv_python_config.cmake")
+file(GENERATE OUTPUT "${CMAKE_HELPER_SCRIPT}" CONTENT "${PYTHON_CONFIG_SCRIPT}")
index 80cd2b6..cbb79b8 100644 (file)
@@ -1,5 +1,5 @@
 # This file is included from a subdirectory
-set(PYTHON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../")
+set(PYTHON_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}")
 
 ocv_add_module(${MODULE_NAME} BINDINGS PRIVATE_REQUIRED opencv_python_bindings_generator)
 
@@ -20,7 +20,9 @@ if(NOT WIN32 AND NOT APPLE AND NOT OPENCV_PYTHON_SKIP_LINKER_EXCLUDE_LIBS)
 endif()
 
 ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs} ${opencv_userdef_hdrs} ${cv2_custom_hdr})
-add_dependencies(${the_module} gen_opencv_python_source)
+if(TARGET gen_opencv_python_source)
+  add_dependencies(${the_module} gen_opencv_python_source)
+endif()
 
 if(APPLE)
   set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
@@ -32,8 +34,10 @@ elseif(WIN32 OR OPENCV_FORCE_PYTHON_LIBS)
   endif()
 endif()
 
-set(deps ${OPENCV_MODULE_${the_module}_DEPS})
-list(REMOVE_ITEM deps opencv_python_bindings_generator) # don't add dummy module to target_link_libraries list
+if(TARGET gen_opencv_python_source)
+  set(deps ${OPENCV_MODULE_${the_module}_DEPS})
+  list(REMOVE_ITEM deps opencv_python_bindings_generator) # don't add dummy module to target_link_libraries list
+endif()
 ocv_target_link_libraries(${the_module} LINK_PRIVATE ${deps})
 
 if(DEFINED ${PYTHON}_CVPY_SUFFIX)
@@ -75,8 +79,16 @@ if(MSVC AND NOT ENABLE_NOISY_WARNINGS)
   string(REPLACE "/W4" "/W3" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 endif()
 
-ocv_warnings_disable(CMAKE_CXX_FLAGS -Woverloaded-virtual -Wunused-private-field)
-ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) # accurate guard via #pragma doesn't work (C++ preprocessor doesn't handle #pragma)
+
+if(MSVC)
+  ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996)
+else()
+  ocv_warnings_disable(CMAKE_CXX_FLAGS
+      -Wdeprecated-declarations
+      -Woverloaded-virtual -Wunused-private-field
+      -Wundef # accurate guard via #pragma doesn't work (C++ preprocessor doesn't handle #pragma)
+  )
+endif()
 
 if(MSVC AND NOT BUILD_SHARED_LIBS)
   set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG")
@@ -94,7 +106,9 @@ else()
   set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${${PYTHON}_PACKAGES_PATH} COMPONENT python)
 endif()
 
-if(NOT INSTALL_CREATE_DISTRIB AND DEFINED ${PYTHON}_PACKAGES_PATH)
+if(DEFINED OPENCV_${PYTHON}_INSTALL_PATH)
+  set(__dst "${OPENCV_${PYTHON}_INSTALL_PATH}")
+elseif(NOT INSTALL_CREATE_DISTRIB AND DEFINED ${PYTHON}_PACKAGES_PATH)
   set(__dst "${${PYTHON}_PACKAGES_PATH}")
 endif()
 if(NOT __dst)
index bf55ef8..37e20fe 100644 (file)
@@ -13,9 +13,3 @@ include(../common.cmake)
 
 unset(MODULE_NAME)
 unset(MODULE_INSTALL_SUBDIR)
-
-if(MSVC)
-  ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996)
-else()
-  ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-declarations)
-endif()
index b3a7253..da86ba5 100644 (file)
@@ -12,9 +12,3 @@ include(../common.cmake)
 
 unset(MODULE_NAME)
 unset(MODULE_INSTALL_SUBDIR)
-
-if(MSVC)
-  ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996)
-else()
-  ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-declarations)
-endif()
diff --git a/modules/python/standalone.cmake b/modules/python/standalone.cmake
new file mode 100644 (file)
index 0000000..d21420a
--- /dev/null
@@ -0,0 +1,57 @@
+if(NOT DEFINED OpenCV_BINARY_DIR)
+  message(FATAL_ERROR "Define OpenCV_BINARY_DIR")
+endif()
+include("${OpenCV_BINARY_DIR}/opencv_python_config.cmake")
+if(NOT DEFINED OpenCV_SOURCE_DIR)
+  message(FATAL_ERROR "Missing define of OpenCV_SOURCE_DIR")
+endif()
+
+include("${OpenCV_SOURCE_DIR}/cmake/OpenCVUtils.cmake")
+
+set(OPENCV_PYTHON_SKIP_DETECTION ON)
+include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectPython.cmake")
+find_python("" "2.7" PYTHON_LIBRARY PYTHON_INCLUDE_DIR
+    PYTHONINTERP_FOUND PYTHON_EXECUTABLE PYTHON_VERSION_STRING
+    PYTHON_VERSION_MAJOR PYTHON_VERSION_MINOR PYTHONLIBS_FOUND
+    PYTHONLIBS_VERSION_STRING PYTHON_LIBRARIES PYTHON_LIBRARY
+    PYTHON_DEBUG_LIBRARIES PYTHON_LIBRARY_DEBUG PYTHON_INCLUDE_PATH
+    PYTHON_INCLUDE_DIR PYTHON_INCLUDE_DIR2 PYTHON_PACKAGES_PATH
+    PYTHON_NUMPY_INCLUDE_DIRS PYTHON_NUMPY_VERSION)
+if(NOT PYTHON_EXECUTABLE OR NOT PYTHON_INCLUDE_DIR)
+  message(FATAL_ERROR "Can't find Python development files")
+endif()
+if(NOT PYTHON_NUMPY_INCLUDE_DIRS)
+  message(FATAL_ERROR "Can't find Python 'numpy' development files")
+endif()
+
+status("-----------------------------------------------------------------")
+status("  Python:")
+status("    Interpreter:"   "${PYTHON_EXECUTABLE} (ver ${PYTHON_VERSION_STRING})")
+status("    Libraries:"     "${PYTHON_LIBRARIES} (ver ${PYTHONLIBS_VERSION_STRING})")
+status("    numpy:"         "${PYTHON_NUMPY_INCLUDE_DIRS} (ver ${PYTHON_NUMPY_VERSION})")
+status("")
+status("  Install to:" "${CMAKE_INSTALL_PREFIX}")
+status("-----------------------------------------------------------------")
+
+set(OpenCV_DIR "${OpenCV_BINARY_DIR}")
+find_package(OpenCV REQUIRED)
+
+set(PYTHON PYTHON)
+
+macro(ocv_add_module module_name)
+  set(the_module opencv_${module_name})
+  project(${the_module} CXX)
+endmacro()
+
+macro(ocv_module_include_directories module)
+  include_directories(${ARGN})
+endmacro()
+
+set(MODULE_NAME python)
+set(MODULE_INSTALL_SUBDIR "")
+set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib")
+set(deps ${OpenCV_LIBRARIES})
+include("${CMAKE_CURRENT_LIST_DIR}/common.cmake")  # generate python target
+
+# done, cleanup
+unset(OPENCV_BUILD_INFO_STR CACHE)  # remove from cache