1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindPythonLibs
6--------------
7
8.. deprecated:: 3.12
9
10  Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` instead.
11
12Find python libraries
13
14This module finds if Python is installed and determines where the
15include files and libraries are.  It also determines what the name of
16the library is.  This code sets the following variables:
17
18::
19
20  PYTHONLIBS_FOUND           - have the Python libs been found
21  PYTHON_LIBRARIES           - path to the python library
22  PYTHON_INCLUDE_PATH        - path to where Python.h is found (deprecated)
23  PYTHON_INCLUDE_DIRS        - path to where Python.h is found
24  PYTHON_DEBUG_LIBRARIES     - path to the debug library (deprecated)
25  PYTHONLIBS_VERSION_STRING  - version of the Python libs found (since CMake 2.8.8)
26
27
28
29The Python_ADDITIONAL_VERSIONS variable can be used to specify a list
30of version numbers that should be taken into account when searching
31for Python.  You need to set this variable before calling
32find_package(PythonLibs).
33
34If you'd like to specify the installation of Python to use, you should
35modify the following cache variables:
36
37::
38
39  PYTHON_LIBRARY             - path to the python library
40  PYTHON_INCLUDE_DIR         - path to where Python.h is found
41
42If calling both ``find_package(PythonInterp)`` and
43``find_package(PythonLibs)``, call ``find_package(PythonInterp)`` first to
44get the currently active Python version by default with a consistent version
45of PYTHON_LIBRARIES.
46#]=======================================================================]
47
48# Use the executable's path as a hint
49set(_Python_LIBRARY_PATH_HINT)
50if(IS_ABSOLUTE "${PYTHON_EXECUTABLE}")
51  if(WIN32)
52    get_filename_component(_Python_PREFIX "${PYTHON_EXECUTABLE}" PATH)
53    if(_Python_PREFIX)
54      set(_Python_LIBRARY_PATH_HINT ${_Python_PREFIX}/libs)
55    endif()
56    unset(_Python_PREFIX)
57  else()
58    get_filename_component(_Python_PREFIX "${PYTHON_EXECUTABLE}" PATH)
59    get_filename_component(_Python_PREFIX "${_Python_PREFIX}" PATH)
60    if(_Python_PREFIX)
61      set(_Python_LIBRARY_PATH_HINT ${_Python_PREFIX}/lib)
62    endif()
63    unset(_Python_PREFIX)
64  endif()
65endif()
66
67include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake)
68# Search for the python framework on Apple.
69CMAKE_FIND_FRAMEWORKS(Python)
70
71# Save CMAKE_FIND_FRAMEWORK
72if(DEFINED CMAKE_FIND_FRAMEWORK)
73  set(_PythonLibs_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
74else()
75  unset(_PythonLibs_CMAKE_FIND_FRAMEWORK)
76endif()
77# To avoid picking up the system Python.h pre-maturely.
78set(CMAKE_FIND_FRAMEWORK LAST)
79
80set(_PYTHON1_VERSIONS 1.6 1.5)
81set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
82set(_PYTHON3_VERSIONS 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
83
84if(PythonLibs_FIND_VERSION)
85    if(PythonLibs_FIND_VERSION_COUNT GREATER 1)
86        set(_PYTHON_FIND_MAJ_MIN "${PythonLibs_FIND_VERSION_MAJOR}.${PythonLibs_FIND_VERSION_MINOR}")
87        unset(_PYTHON_FIND_OTHER_VERSIONS)
88        if(PythonLibs_FIND_VERSION_EXACT)
89            if(_PYTHON_FIND_MAJ_MIN STREQUAL PythonLibs_FIND_VERSION)
90                set(_PYTHON_FIND_OTHER_VERSIONS "${PythonLibs_FIND_VERSION}")
91            else()
92                set(_PYTHON_FIND_OTHER_VERSIONS "${PythonLibs_FIND_VERSION}" "${_PYTHON_FIND_MAJ_MIN}")
93            endif()
94        else()
95            foreach(_PYTHON_V ${_PYTHON${PythonLibs_FIND_VERSION_MAJOR}_VERSIONS})
96                if(NOT _PYTHON_V VERSION_LESS _PYTHON_FIND_MAJ_MIN)
97                    list(APPEND _PYTHON_FIND_OTHER_VERSIONS ${_PYTHON_V})
98                endif()
99             endforeach()
100        endif()
101        unset(_PYTHON_FIND_MAJ_MIN)
102    else()
103        set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON${PythonLibs_FIND_VERSION_MAJOR}_VERSIONS})
104    endif()
105else()
106    set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON3_VERSIONS} ${_PYTHON2_VERSIONS} ${_PYTHON1_VERSIONS})
107endif()
108
109# Set up the versions we know about, in the order we will search. Always add
110# the user supplied additional versions to the front.
111# If FindPythonInterp has already found the major and minor version,
112# insert that version between the user supplied versions and the stock
113# version list.
114set(_Python_VERSIONS ${Python_ADDITIONAL_VERSIONS})
115if(DEFINED PYTHON_VERSION_MAJOR AND DEFINED PYTHON_VERSION_MINOR)
116  list(APPEND _Python_VERSIONS ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
117endif()
118list(APPEND _Python_VERSIONS ${_PYTHON_FIND_OTHER_VERSIONS})
119
120unset(_PYTHON_FIND_OTHER_VERSIONS)
121unset(_PYTHON1_VERSIONS)
122unset(_PYTHON2_VERSIONS)
123unset(_PYTHON3_VERSIONS)
124
125# Python distribution: define which architectures can be used
126if (CMAKE_SIZEOF_VOID_P)
127  # In this case, search only for 64bit or 32bit
128  math (EXPR _PYTHON_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
129  set (_PYTHON_ARCH2 _PYTHON_PREFIX_ARCH})
130else()
131  if (PYTHON_EXECUTABLE)
132    # determine interpreter architecture
133    execute_process (COMMAND "${PYTHON_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)"
134                     RESULT_VARIABLE _PYTHON_RESULT
135                     OUTPUT_VARIABLE _PYTHON_IS64BIT
136                     ERROR_VARIABLE _PYTHON_IS64BIT)
137      if (NOT _PYTHON_RESULT)
138        if (_PYTHON_IS64BIT)
139          set (_PYTHON_ARCH 64)
140          set (_PYTHON_ARCH2 64)
141        else()
142          set (_PYTHON_ARCH 32)
143          set (_PYTHON_ARCH2 32)
144        endif()
145      endif()
146  else()
147    # architecture unknown, search for both 64bit and 32bit
148    set (_PYTHON_ARCH 64)
149    set (_PYTHON_ARCH2 32)
150  endif()
151endif()
152
153foreach(_CURRENT_VERSION ${_Python_VERSIONS})
154  string(REPLACE "." "" _CURRENT_VERSION_NO_DOTS ${_CURRENT_VERSION})
155  if(WIN32)
156    find_library(PYTHON_DEBUG_LIBRARY
157      NAMES python${_CURRENT_VERSION_NO_DOTS}_d python
158      NAMES_PER_DIR
159      HINTS ${_Python_LIBRARY_PATH_HINT}
160      PATHS
161      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug
162      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs/Debug
163      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs/Debug
164      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug
165      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs/Debug
166      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs/Debug
167      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
168      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
169      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
170      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
171      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
172      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
173      )
174  endif()
175
176  set(PYTHON_FRAMEWORK_LIBRARIES)
177  if(Python_FRAMEWORKS AND NOT PYTHON_LIBRARY)
178    foreach(dir ${Python_FRAMEWORKS})
179      list(APPEND PYTHON_FRAMEWORK_LIBRARIES
180           ${dir}/Versions/${_CURRENT_VERSION}/lib)
181    endforeach()
182  endif()
183  find_library(PYTHON_LIBRARY
184    NAMES
185      python${_CURRENT_VERSION_NO_DOTS}
186      python${_CURRENT_VERSION}mu
187      python${_CURRENT_VERSION}m
188      python${_CURRENT_VERSION}u
189      python${_CURRENT_VERSION}
190    NAMES_PER_DIR
191    HINTS
192      ${_Python_LIBRARY_PATH_HINT}
193    PATHS
194      ${PYTHON_FRAMEWORK_LIBRARIES}
195      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
196      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
197      [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
198      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
199      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
200      [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
201  )
202  # Look for the static library in the Python config directory
203  find_library(PYTHON_LIBRARY
204    NAMES python${_CURRENT_VERSION_NO_DOTS} python${_CURRENT_VERSION}
205    NAMES_PER_DIR
206    # This is where the static library is usually located
207    PATH_SUFFIXES python${_CURRENT_VERSION}/config
208  )
209
210  # Don't search for include dir until library location is known
211  if(PYTHON_LIBRARY)
212
213    # Use the library's install prefix as a hint
214    set(_Python_INCLUDE_PATH_HINT)
215    # PYTHON_LIBRARY may contain a list because of SelectLibraryConfigurations
216    # which may have been run previously. If it is the case, the list can be:
217    #   optimized;<FILEPATH_TO_RELEASE_LIBRARY>;debug;<FILEPATH_TO_DEBUG_LIBRARY>
218    foreach(lib ${PYTHON_LIBRARY} ${PYTHON_DEBUG_LIBRARY})
219      if(IS_ABSOLUTE "${lib}")
220        get_filename_component(_Python_PREFIX "${lib}" PATH)
221        get_filename_component(_Python_PREFIX "${_Python_PREFIX}" PATH)
222        if(_Python_PREFIX)
223          list(APPEND _Python_INCLUDE_PATH_HINT ${_Python_PREFIX}/include)
224        endif()
225        unset(_Python_PREFIX)
226      endif()
227    endforeach()
228
229    # Add framework directories to the search paths
230    set(PYTHON_FRAMEWORK_INCLUDES)
231    if(Python_FRAMEWORKS AND NOT PYTHON_INCLUDE_DIR)
232      foreach(dir ${Python_FRAMEWORKS})
233        list(APPEND PYTHON_FRAMEWORK_INCLUDES
234          ${dir}/Versions/${_CURRENT_VERSION}/include)
235      endforeach()
236    endif()
237
238    find_path(PYTHON_INCLUDE_DIR
239      NAMES Python.h
240      HINTS
241        ${_Python_INCLUDE_PATH_HINT}
242      PATHS
243        ${PYTHON_FRAMEWORK_INCLUDES}
244        [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include
245        [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/include
246        [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/include
247        [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include
248        [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/include
249        [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/include
250      PATH_SUFFIXES
251        python${_CURRENT_VERSION}mu
252        python${_CURRENT_VERSION}m
253        python${_CURRENT_VERSION}u
254        python${_CURRENT_VERSION}
255    )
256  endif()
257
258  # For backward compatibility, set PYTHON_INCLUDE_PATH.
259  set(PYTHON_INCLUDE_PATH "${PYTHON_INCLUDE_DIR}")
260
261  if(PYTHON_INCLUDE_DIR AND EXISTS "${PYTHON_INCLUDE_DIR}/patchlevel.h")
262    file(STRINGS "${PYTHON_INCLUDE_DIR}/patchlevel.h" python_version_str
263         REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"")
264    string(REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1"
265                         PYTHONLIBS_VERSION_STRING "${python_version_str}")
266    unset(python_version_str)
267  endif()
268
269  if(PYTHON_LIBRARY AND PYTHON_INCLUDE_DIR)
270    break()
271  endif()
272endforeach()
273
274unset(_Python_INCLUDE_PATH_HINT)
275unset(_Python_LIBRARY_PATH_HINT)
276
277mark_as_advanced(
278  PYTHON_DEBUG_LIBRARY
279  PYTHON_LIBRARY
280  PYTHON_INCLUDE_DIR
281)
282
283# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the
284# cache entries because they are meant to specify the location of a single
285# library. We now set the variables listed by the documentation for this
286# module.
287set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
288set(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}")
289
290# These variables have been historically named in this module different from
291# what SELECT_LIBRARY_CONFIGURATIONS() expects.
292set(PYTHON_LIBRARY_DEBUG "${PYTHON_DEBUG_LIBRARY}")
293set(PYTHON_LIBRARY_RELEASE "${PYTHON_LIBRARY}")
294include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
295SELECT_LIBRARY_CONFIGURATIONS(PYTHON)
296# SELECT_LIBRARY_CONFIGURATIONS() sets ${PREFIX}_FOUND if it has a library.
297# Unset this, this prefix doesn't match the module prefix, they are different
298# for historical reasons.
299unset(PYTHON_FOUND)
300
301# Restore CMAKE_FIND_FRAMEWORK
302if(DEFINED _PythonLibs_CMAKE_FIND_FRAMEWORK)
303  set(CMAKE_FIND_FRAMEWORK ${_PythonLibs_CMAKE_FIND_FRAMEWORK})
304  unset(_PythonLibs_CMAKE_FIND_FRAMEWORK)
305else()
306  unset(CMAKE_FIND_FRAMEWORK)
307endif()
308
309include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
310FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibs
311                                  REQUIRED_VARS PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS
312                                  VERSION_VAR PYTHONLIBS_VERSION_STRING)
313
314# PYTHON_ADD_MODULE(<name> src1 src2 ... srcN) is used to build modules for python.
315# PYTHON_WRITE_MODULES_HEADER(<filename>) writes a header file you can include
316# in your sources to initialize the static python modules
317function(PYTHON_ADD_MODULE _NAME )
318  get_property(_TARGET_SUPPORTS_SHARED_LIBS
319    GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
320  option(PYTHON_ENABLE_MODULE_${_NAME} "Add module ${_NAME}" TRUE)
321  option(PYTHON_MODULE_${_NAME}_BUILD_SHARED
322    "Add module ${_NAME} shared" ${_TARGET_SUPPORTS_SHARED_LIBS})
323
324  # Mark these options as advanced
325  mark_as_advanced(PYTHON_ENABLE_MODULE_${_NAME}
326    PYTHON_MODULE_${_NAME}_BUILD_SHARED)
327
328  if(PYTHON_ENABLE_MODULE_${_NAME})
329    if(PYTHON_MODULE_${_NAME}_BUILD_SHARED)
330      set(PY_MODULE_TYPE MODULE)
331    else()
332      set(PY_MODULE_TYPE STATIC)
333      set_property(GLOBAL  APPEND  PROPERTY  PY_STATIC_MODULES_LIST ${_NAME})
334    endif()
335
336    set_property(GLOBAL  APPEND  PROPERTY  PY_MODULES_LIST ${_NAME})
337    add_library(${_NAME} ${PY_MODULE_TYPE} ${ARGN})
338#    target_link_libraries(${_NAME} ${PYTHON_LIBRARIES})
339
340    if(PYTHON_MODULE_${_NAME}_BUILD_SHARED)
341      set_target_properties(${_NAME} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}")
342      if(WIN32 AND NOT CYGWIN)
343        set_target_properties(${_NAME} PROPERTIES SUFFIX ".pyd")
344      endif()
345    endif()
346
347  endif()
348endfunction()
349
350function(PYTHON_WRITE_MODULES_HEADER _filename)
351
352  get_property(PY_STATIC_MODULES_LIST  GLOBAL  PROPERTY PY_STATIC_MODULES_LIST)
353
354  get_filename_component(_name "${_filename}" NAME)
355  string(REPLACE "." "_" _name "${_name}")
356  string(TOUPPER ${_name} _nameUpper)
357  set(_filename ${CMAKE_CURRENT_BINARY_DIR}/${_filename})
358
359  set(_filenameTmp "${_filename}.in")
360  file(WRITE ${_filenameTmp} "/*Created by cmake, do not edit, changes will be lost*/\n")
361  file(APPEND ${_filenameTmp}
362"#ifndef ${_nameUpper}
363#define ${_nameUpper}
364
365#include <Python.h>
366
367#ifdef __cplusplus
368extern \"C\" {
369#endif /* __cplusplus */
370
371")
372
373  foreach(_currentModule ${PY_STATIC_MODULES_LIST})
374    file(APPEND ${_filenameTmp} "extern void init${PYTHON_MODULE_PREFIX}${_currentModule}(void);\n\n")
375  endforeach()
376
377  file(APPEND ${_filenameTmp}
378"#ifdef __cplusplus
379}
380#endif /* __cplusplus */
381
382")
383
384
385  foreach(_currentModule ${PY_STATIC_MODULES_LIST})
386    file(APPEND ${_filenameTmp} "int ${_name}_${_currentModule}(void) \n{\n  static char name[]=\"${PYTHON_MODULE_PREFIX}${_currentModule}\"; return PyImport_AppendInittab(name, init${PYTHON_MODULE_PREFIX}${_currentModule});\n}\n\n")
387  endforeach()
388
389  file(APPEND ${_filenameTmp} "void ${_name}_LoadAllPythonModules(void)\n{\n")
390  foreach(_currentModule ${PY_STATIC_MODULES_LIST})
391    file(APPEND ${_filenameTmp} "  ${_name}_${_currentModule}();\n")
392  endforeach()
393  file(APPEND ${_filenameTmp} "}\n\n")
394  file(APPEND ${_filenameTmp} "#ifndef EXCLUDE_LOAD_ALL_FUNCTION\nvoid CMakeLoadAllPythonModules(void)\n{\n  ${_name}_LoadAllPythonModules();\n}\n#endif\n\n#endif\n")
395
396# with configure_file() cmake complains that you may not use a file created using file(WRITE) as input file for configure_file()
397  execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_filenameTmp}" "${_filename}" OUTPUT_QUIET ERROR_QUIET)
398
399endfunction()
400