Add python3-setuptools dependency for python 3.12
[platform/upstream/opencv.git] / cmake / OpenCVDetectPython.cmake
1 # Find specified Python version
2 # Arguments:
3 #   preferred_version (value): Version to check for first
4 #   min_version (value): Minimum supported version
5 #   library_env (value): Name of Python library ENV variable to check
6 #   include_dir_env (value): Name of Python include directory ENV variable to check
7 #   found (variable): Set if interpreter found
8 #   executable (variable): Output of executable found
9 #   version_string (variable): Output of found version
10 #   version_major (variable): Output of found major version
11 #   version_minor (variable): Output of found minor version
12 #   libs_found (variable): Set if libs found
13 #   libs_version_string (variable): Output of found libs version
14 #   libraries (variable): Output of found Python libraries
15 #   library (variable): Output of found Python library
16 #   debug_libraries (variable): Output of found Python debug libraries
17 #   debug_library (variable): Output of found Python debug library
18 #   include_path (variable): Output of found Python include path
19 #   include_dir (variable): Output of found Python include dir
20 #   include_dir2 (variable): Output of found Python include dir2
21 #   packages_path (variable): Output of found Python packages path
22 #   numpy_include_dirs (variable): Output of found Python Numpy include dirs
23 #   numpy_version (variable): Output of found Python Numpy version
24 function(find_python preferred_version min_version library_env include_dir_env
25          found executable version_string version_major version_minor
26          libs_found libs_version_string libraries library debug_libraries
27          debug_library include_path include_dir include_dir2 packages_path
28          numpy_include_dirs numpy_version)
29 if(NOT ${found})
30   if(" ${executable}" STREQUAL " PYTHON_EXECUTABLE")
31     set(__update_python_vars 0)
32   else()
33     set(__update_python_vars 1)
34   endif()
35
36   ocv_check_environment_variables(${executable})
37   if(${executable})
38     set(PYTHON_EXECUTABLE "${${executable}}")
39   endif()
40
41   if(WIN32 AND NOT ${executable} AND OPENCV_PYTHON_PREFER_WIN32_REGISTRY)  # deprecated
42     # search for executable with the same bitness as resulting binaries
43     # standard FindPythonInterp always prefers executable from system path
44     # this is really important because we are using the interpreter for numpy search and for choosing the install location
45     foreach(_CURRENT_VERSION ${Python_ADDITIONAL_VERSIONS} "${preferred_version}" "${min_version}")
46       find_host_program(PYTHON_EXECUTABLE
47         NAMES python${_CURRENT_VERSION} python
48         PATHS
49           [HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Python\\\\PythonCore\\\\${_CURRENT_VERSION}\\\\InstallPath]
50           [HKEY_CURRENT_USER\\\\SOFTWARE\\\\Python\\\\PythonCore\\\\${_CURRENT_VERSION}\\\\InstallPath]
51         NO_SYSTEM_ENVIRONMENT_PATH
52       )
53     endforeach()
54   endif()
55
56   if(preferred_version)
57     set(__python_package_version "${preferred_version} EXACT")
58     find_host_package(PythonInterp "${preferred_version}" EXACT)
59     if(NOT PYTHONINTERP_FOUND)
60       message(STATUS "Python is not found: ${preferred_version} EXACT")
61     endif()
62   elseif(min_version)
63     set(__python_package_version "${min_version}")
64     find_host_package(PythonInterp "${min_version}")
65   else()
66     set(__python_package_version "")
67     find_host_package(PythonInterp)
68   endif()
69
70   string(REGEX MATCH "^[0-9]+" _python_version_major "${min_version}")
71
72   if(PYTHONINTERP_FOUND)
73     # Check if python major version is correct
74     if(" ${_python_version_major}" STREQUAL " ")
75       set(_python_version_major "${PYTHON_VERSION_MAJOR}")
76     endif()
77     if(NOT "${_python_version_major}" STREQUAL "${PYTHON_VERSION_MAJOR}"
78         AND NOT DEFINED ${executable}
79     )
80       if(NOT OPENCV_SKIP_PYTHON_WARNING)
81         message(WARNING "CMake's 'find_host_package(PythonInterp ${__python_package_version})' found wrong Python version:\n"
82                         "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}\n"
83                         "PYTHON_VERSION_STRING=${PYTHON_VERSION_STRING}\n"
84                         "Consider providing the '${executable}' variable via CMake command line or environment variables\n")
85       endif()
86       ocv_clear_vars(PYTHONINTERP_FOUND PYTHON_EXECUTABLE PYTHON_VERSION_STRING PYTHON_VERSION_MAJOR PYTHON_VERSION_MINOR PYTHON_VERSION_PATCH)
87       if(NOT CMAKE_VERSION VERSION_LESS "3.12")
88         if(_python_version_major STREQUAL "2")
89           set(__PYTHON_PREFIX Python2)
90         else()
91           set(__PYTHON_PREFIX Python3)
92         endif()
93         find_host_package(${__PYTHON_PREFIX} "${preferred_version}" COMPONENTS Interpreter)
94         if(${__PYTHON_PREFIX}_EXECUTABLE)
95           set(PYTHON_EXECUTABLE "${${__PYTHON_PREFIX}_EXECUTABLE}")
96           find_host_package(PythonInterp "${preferred_version}")  # Populate other variables
97         endif()
98       else()
99         message(STATUS "Consider using CMake 3.12+ for better Python support")
100       endif()
101     endif()
102     if(PYTHONINTERP_FOUND AND "${_python_version_major}" STREQUAL "${PYTHON_VERSION_MAJOR}")
103       # Copy outputs
104       set(_found ${PYTHONINTERP_FOUND})
105       set(_executable ${PYTHON_EXECUTABLE})
106       set(_version_string ${PYTHON_VERSION_STRING})
107       set(_version_major ${PYTHON_VERSION_MAJOR})
108       set(_version_minor ${PYTHON_VERSION_MINOR})
109       set(_version_patch ${PYTHON_VERSION_PATCH})
110     endif()
111   endif()
112
113   if(__update_python_vars)
114     # Clear find_host_package side effects
115     unset(PYTHONINTERP_FOUND)
116     unset(PYTHON_EXECUTABLE CACHE)
117     unset(PYTHON_VERSION_STRING)
118     unset(PYTHON_VERSION_MAJOR)
119     unset(PYTHON_VERSION_MINOR)
120     unset(PYTHON_VERSION_PATCH)
121   endif()
122
123   if(_found)
124     set(_version_major_minor "${_version_major}.${_version_minor}")
125
126     if(NOT ANDROID AND NOT APPLE_FRAMEWORK)
127       ocv_check_environment_variables(${library_env} ${include_dir_env})
128       if(NOT ${${library_env}} STREQUAL "")
129           set(PYTHON_LIBRARY "${${library_env}}")
130       endif()
131       if(NOT ${${include_dir_env}} STREQUAL "")
132           set(PYTHON_INCLUDE_DIR "${${include_dir_env}}")
133       endif()
134
135       # not using _version_string here, because it might not conform to the CMake version format
136       if(CMAKE_CROSSCOMPILING)
137         # builder version can differ from target, matching base version (e.g. 2.7)
138         find_package(PythonLibs "${_version_major_minor}")
139       else()
140         find_package(PythonLibs "${_version_major_minor}.${_version_patch}" EXACT)
141       endif()
142
143       if(PYTHONLIBS_FOUND)
144         # Copy outputs
145         set(_libs_found ${PYTHONLIBS_FOUND})
146         set(_libraries ${PYTHON_LIBRARIES})
147         set(_include_path ${PYTHON_INCLUDE_PATH})
148         set(_include_dirs ${PYTHON_INCLUDE_DIRS})
149         set(_debug_libraries ${PYTHON_DEBUG_LIBRARIES})
150         set(_libs_version_string ${PYTHONLIBS_VERSION_STRING})
151         set(_debug_library ${PYTHON_DEBUG_LIBRARY})
152         set(_library ${PYTHON_LIBRARY})
153         set(_library_debug ${PYTHON_LIBRARY_DEBUG})
154         set(_library_release ${PYTHON_LIBRARY_RELEASE})
155         set(_include_dir ${PYTHON_INCLUDE_DIR})
156         set(_include_dir2 ${PYTHON_INCLUDE_DIR2})
157       endif()
158       if(__update_python_vars)
159         # Clear find_package side effects
160         unset(PYTHONLIBS_FOUND)
161         unset(PYTHON_LIBRARIES)
162         unset(PYTHON_INCLUDE_PATH)
163         unset(PYTHON_INCLUDE_DIRS)
164         unset(PYTHON_DEBUG_LIBRARIES)
165         unset(PYTHONLIBS_VERSION_STRING)
166         unset(PYTHON_DEBUG_LIBRARY CACHE)
167         unset(PYTHON_LIBRARY)
168         unset(PYTHON_LIBRARY_DEBUG)
169         unset(PYTHON_LIBRARY_RELEASE)
170         unset(PYTHON_LIBRARY CACHE)
171         unset(PYTHON_LIBRARY_DEBUG CACHE)
172         unset(PYTHON_LIBRARY_RELEASE CACHE)
173         unset(PYTHON_INCLUDE_DIR CACHE)
174         unset(PYTHON_INCLUDE_DIR2 CACHE)
175       endif()
176     endif()
177
178     if(NOT ANDROID AND NOT IOS)
179       if(CMAKE_HOST_UNIX)
180         execute_process(COMMAND ${_executable} -c "from sysconfig import *; print(get_path('purelib'))"
181                         RESULT_VARIABLE _cvpy_process
182                         OUTPUT_VARIABLE _std_packages_path
183                         OUTPUT_STRIP_TRAILING_WHITESPACE)
184         if("${_std_packages_path}" MATCHES "site-packages")
185           set(_packages_path "python${_version_major_minor}/site-packages")
186         else() #debian based assumed, install to the dist-packages.
187           set(_packages_path "python${_version_major_minor}/dist-packages")
188         endif()
189         set(_packages_path "lib/${_packages_path}")
190       elseif(CMAKE_HOST_WIN32)
191         get_filename_component(_path "${_executable}" PATH)
192         file(TO_CMAKE_PATH "${_path}" _path)
193         if(NOT EXISTS "${_path}/Lib/site-packages")
194           unset(_path)
195           get_filename_component(_path "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_version_major_minor}\\InstallPath]" ABSOLUTE)
196           if(NOT _path)
197              get_filename_component(_path "[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_version_major_minor}\\InstallPath]" ABSOLUTE)
198           endif()
199           file(TO_CMAKE_PATH "${_path}" _path)
200         endif()
201         set(_packages_path "${_path}/Lib/site-packages")
202         unset(_path)
203       endif()
204
205       set(_numpy_include_dirs "${${numpy_include_dirs}}")
206
207       if(NOT _numpy_include_dirs)
208         if(CMAKE_CROSSCOMPILING)
209           message(STATUS "Cannot probe for Python/Numpy support (because we are cross-compiling OpenCV)")
210           message(STATUS "If you want to enable Python/Numpy support, set the following variables:")
211           message(STATUS "  PYTHON2_INCLUDE_PATH")
212           message(STATUS "  PYTHON2_LIBRARIES (optional on Unix-like systems)")
213           message(STATUS "  PYTHON2_NUMPY_INCLUDE_DIRS")
214           message(STATUS "  PYTHON3_INCLUDE_PATH")
215           message(STATUS "  PYTHON3_LIBRARIES (optional on Unix-like systems)")
216           message(STATUS "  PYTHON3_NUMPY_INCLUDE_DIRS")
217         else()
218           # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy
219           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()))"
220                           RESULT_VARIABLE _numpy_process
221                           OUTPUT_VARIABLE _numpy_include_dirs
222                           OUTPUT_STRIP_TRAILING_WHITESPACE)
223
224           if(NOT _numpy_process EQUAL 0)
225               unset(_numpy_include_dirs)
226           endif()
227         endif()
228       endif()
229
230       if(_numpy_include_dirs)
231         file(TO_CMAKE_PATH "${_numpy_include_dirs}" _numpy_include_dirs)
232         if(CMAKE_CROSSCOMPILING)
233           if(NOT _numpy_version)
234             set(_numpy_version "undefined - cannot be probed because of the cross-compilation")
235           endif()
236         else()
237           execute_process(COMMAND "${_executable}" -c "import numpy; print(numpy.version.version)"
238                           RESULT_VARIABLE _numpy_process
239                           OUTPUT_VARIABLE _numpy_version
240                           OUTPUT_STRIP_TRAILING_WHITESPACE)
241         endif()
242       endif()
243     endif(NOT ANDROID AND NOT IOS)
244   endif()
245
246   # Export return values
247   set(${found} "${_found}" CACHE INTERNAL "")
248   set(${executable} "${_executable}" CACHE FILEPATH "Path to Python interpreter")
249   set(${version_string} "${_version_string}" CACHE INTERNAL "")
250   set(${version_major} "${_version_major}" CACHE INTERNAL "")
251   set(${version_minor} "${_version_minor}" CACHE INTERNAL "")
252   set(${libs_found} "${_libs_found}" CACHE INTERNAL "")
253   set(${libs_version_string} "${_libs_version_string}" CACHE INTERNAL "")
254   set(${libraries} "${_libraries}" CACHE INTERNAL "Python libraries")
255   set(${library} "${_library}" CACHE FILEPATH "Path to Python library")
256   set(${debug_libraries} "${_debug_libraries}" CACHE INTERNAL "")
257   set(${debug_library} "${_debug_library}" CACHE FILEPATH "Path to Python debug")
258   set(${include_path} "${_include_path}" CACHE INTERNAL "")
259   set(${include_dir} "${_include_dir}" CACHE PATH "Python include dir")
260   set(${include_dir2} "${_include_dir2}" CACHE PATH "Python include dir 2")
261   set(${packages_path} "${_packages_path}" CACHE PATH "Where to install the python packages.")
262   set(${numpy_include_dirs} ${_numpy_include_dirs} CACHE PATH "Path to numpy headers")
263   set(${numpy_version} "${_numpy_version}" CACHE INTERNAL "")
264 endif()
265 endfunction(find_python)
266
267 if(OPENCV_PYTHON_SKIP_DETECTION)
268   return()
269 endif()
270
271 find_python("" "${MIN_VER_PYTHON2}" PYTHON2_LIBRARY PYTHON2_INCLUDE_DIR
272     PYTHON2INTERP_FOUND PYTHON2_EXECUTABLE PYTHON2_VERSION_STRING
273     PYTHON2_VERSION_MAJOR PYTHON2_VERSION_MINOR PYTHON2LIBS_FOUND
274     PYTHON2LIBS_VERSION_STRING PYTHON2_LIBRARIES PYTHON2_LIBRARY
275     PYTHON2_DEBUG_LIBRARIES PYTHON2_LIBRARY_DEBUG PYTHON2_INCLUDE_PATH
276     PYTHON2_INCLUDE_DIR PYTHON2_INCLUDE_DIR2 PYTHON2_PACKAGES_PATH
277     PYTHON2_NUMPY_INCLUDE_DIRS PYTHON2_NUMPY_VERSION)
278
279 option(OPENCV_PYTHON3_VERSION "Python3 version" "")
280 find_python("${OPENCV_PYTHON3_VERSION}" "${MIN_VER_PYTHON3}" PYTHON3_LIBRARY PYTHON3_INCLUDE_DIR
281     PYTHON3INTERP_FOUND PYTHON3_EXECUTABLE PYTHON3_VERSION_STRING
282     PYTHON3_VERSION_MAJOR PYTHON3_VERSION_MINOR PYTHON3LIBS_FOUND
283     PYTHON3LIBS_VERSION_STRING PYTHON3_LIBRARIES PYTHON3_LIBRARY
284     PYTHON3_DEBUG_LIBRARIES PYTHON3_LIBRARY_DEBUG PYTHON3_INCLUDE_PATH
285     PYTHON3_INCLUDE_DIR PYTHON3_INCLUDE_DIR2 PYTHON3_PACKAGES_PATH
286     PYTHON3_NUMPY_INCLUDE_DIRS PYTHON3_NUMPY_VERSION)
287
288
289 if(PYTHON_DEFAULT_EXECUTABLE)
290     set(PYTHON_DEFAULT_AVAILABLE "TRUE")
291 elseif(PYTHON2_EXECUTABLE AND PYTHON2INTERP_FOUND)
292     # Use Python 2 as default Python interpreter
293     set(PYTHON_DEFAULT_AVAILABLE "TRUE")
294     set(PYTHON_DEFAULT_EXECUTABLE "${PYTHON2_EXECUTABLE}")
295 elseif(PYTHON3_EXECUTABLE AND PYTHON3INTERP_FOUND)
296     # Use Python 3 as fallback Python interpreter (if there is no Python 2)
297     set(PYTHON_DEFAULT_AVAILABLE "TRUE")
298     set(PYTHON_DEFAULT_EXECUTABLE "${PYTHON3_EXECUTABLE}")
299 endif()