1# - Find python libraries 2# This module finds the libraries corresponding to the Python interpreter 3# FindPythonInterp provides. 4# This code sets the following variables: 5# 6# PYTHONLIBS_FOUND - have the Python libs been found 7# PYTHON_PREFIX - path to the Python installation 8# PYTHON_LIBRARIES - path to the python library 9# PYTHON_INCLUDE_DIRS - path to where Python.h is found 10# PYTHON_MODULE_EXTENSION - lib extension, e.g. '.so' or '.pyd' 11# PYTHON_MODULE_PREFIX - lib name prefix: usually an empty string 12# PYTHON_SITE_PACKAGES - path to installation site-packages 13# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build 14# 15# Thanks to talljimbo for the patch adding the 'LDVERSION' config 16# variable usage. 17 18#============================================================================= 19# Copyright 2001-2009 Kitware, Inc. 20# Copyright 2012 Continuum Analytics, Inc. 21# 22# All rights reserved. 23# 24# Redistribution and use in source and binary forms, with or without 25# modification, are permitted provided that the following conditions 26# are met: 27# 28# * Redistributions of source code must retain the above copyright 29# notice, this list of conditions and the following disclaimer. 30# 31# * Redistributions in binary form must reproduce the above copyright 32# notice, this list of conditions and the following disclaimer in the 33# documentation and/or other materials provided with the distribution. 34# 35# * Neither the names of Kitware, Inc., the Insight Software Consortium, 36# nor the names of their contributors may be used to endorse or promote 37# products derived from this software without specific prior written 38# permission. 39# 40# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43# # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51#============================================================================= 52 53# Checking for the extension makes sure that `LibsNew` was found and not just `Libs`. 54if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION) 55 return() 56endif() 57 58if(PythonLibsNew_FIND_QUIETLY) 59 set(_pythonlibs_quiet QUIET) 60else() 61 set(_pythonlibs_quiet "") 62endif() 63 64if(PythonLibsNew_FIND_REQUIRED) 65 set(_pythonlibs_required REQUIRED) 66endif() 67 68# Check to see if the `python` command is present and from a virtual 69# environment, conda, or GHA activation - if it is, try to use that. 70 71if(NOT DEFINED PYTHON_EXECUTABLE) 72 if(DEFINED ENV{VIRTUAL_ENV}) 73 find_program( 74 PYTHON_EXECUTABLE python 75 PATHS "$ENV{VIRTUAL_ENV}" "$ENV{VIRTUAL_ENV}/bin" 76 NO_DEFAULT_PATH) 77 elseif(DEFINED ENV{CONDA_PREFIX}) 78 find_program( 79 PYTHON_EXECUTABLE python 80 PATHS "$ENV{CONDA_PREFIX}" "$ENV{CONDA_PREFIX}/bin" 81 NO_DEFAULT_PATH) 82 elseif(DEFINED ENV{pythonLocation}) 83 find_program( 84 PYTHON_EXECUTABLE python 85 PATHS "$ENV{pythonLocation}" "$ENV{pythonLocation}/bin" 86 NO_DEFAULT_PATH) 87 endif() 88 if(NOT PYTHON_EXECUTABLE) 89 unset(PYTHON_EXECUTABLE) 90 endif() 91endif() 92 93# Use the Python interpreter to find the libs. 94if(NOT PythonLibsNew_FIND_VERSION) 95 set(PythonLibsNew_FIND_VERSION "") 96endif() 97 98find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required} 99 ${_pythonlibs_quiet}) 100 101if(NOT PYTHONINTERP_FOUND) 102 set(PYTHONLIBS_FOUND FALSE) 103 set(PythonLibsNew_FOUND FALSE) 104 return() 105endif() 106 107# According to https://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter 108# testing whether sys has the gettotalrefcount function is a reliable, cross-platform 109# way to detect a CPython debug interpreter. 110# 111# The library suffix is from the config var LDVERSION sometimes, otherwise 112# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows. 113execute_process( 114 COMMAND 115 "${PYTHON_EXECUTABLE}" "-c" "from distutils import sysconfig as s;import sys;import struct; 116print('.'.join(str(v) for v in sys.version_info)); 117print(sys.prefix); 118print(s.get_python_inc(plat_specific=True)); 119print(s.get_python_lib(plat_specific=True)); 120print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO')); 121print(hasattr(sys, 'gettotalrefcount')+0); 122print(struct.calcsize('@P')); 123print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION')); 124print(s.get_config_var('LIBDIR') or ''); 125print(s.get_config_var('MULTIARCH') or ''); 126" 127 RESULT_VARIABLE _PYTHON_SUCCESS 128 OUTPUT_VARIABLE _PYTHON_VALUES 129 ERROR_VARIABLE _PYTHON_ERROR_VALUE) 130 131if(NOT _PYTHON_SUCCESS MATCHES 0) 132 if(PythonLibsNew_FIND_REQUIRED) 133 message(FATAL_ERROR "Python config failure:\n${_PYTHON_ERROR_VALUE}") 134 endif() 135 set(PYTHONLIBS_FOUND FALSE) 136 set(PythonLibsNew_FOUND FALSE) 137 return() 138endif() 139 140# Convert the process output into a list 141if(WIN32) 142 string(REGEX REPLACE "\\\\" "/" _PYTHON_VALUES ${_PYTHON_VALUES}) 143endif() 144string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES}) 145string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES}) 146list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST) 147list(GET _PYTHON_VALUES 1 PYTHON_PREFIX) 148list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR) 149list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES) 150list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION) 151list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG) 152list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P) 153list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX) 154list(GET _PYTHON_VALUES 8 PYTHON_LIBDIR) 155list(GET _PYTHON_VALUES 9 PYTHON_MULTIARCH) 156 157# Make sure the Python has the same pointer-size as the chosen compiler 158# Skip if CMAKE_SIZEOF_VOID_P is not defined 159if(CMAKE_SIZEOF_VOID_P AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}")) 160 if(PythonLibsNew_FIND_REQUIRED) 161 math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8") 162 math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8") 163 message(FATAL_ERROR "Python config failure: Python is ${_PYTHON_BITS}-bit, " 164 "chosen compiler is ${_CMAKE_BITS}-bit") 165 endif() 166 set(PYTHONLIBS_FOUND FALSE) 167 set(PythonLibsNew_FOUND FALSE) 168 return() 169endif() 170 171# The built-in FindPython didn't always give the version numbers 172string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST}) 173list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR) 174list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR) 175list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH) 176set(PYTHON_VERSION "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}") 177 178# Make sure all directory separators are '/' 179string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX "${PYTHON_PREFIX}") 180string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}") 181string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES "${PYTHON_SITE_PACKAGES}") 182 183if(CMAKE_HOST_WIN32) 184 set(PYTHON_LIBRARY "${PYTHON_PREFIX}/libs/python${PYTHON_LIBRARY_SUFFIX}.lib") 185 186 # when run in a venv, PYTHON_PREFIX points to it. But the libraries remain in the 187 # original python installation. They may be found relative to PYTHON_INCLUDE_DIR. 188 if(NOT EXISTS "${PYTHON_LIBRARY}") 189 get_filename_component(_PYTHON_ROOT ${PYTHON_INCLUDE_DIR} DIRECTORY) 190 set(PYTHON_LIBRARY "${_PYTHON_ROOT}/libs/python${PYTHON_LIBRARY_SUFFIX}.lib") 191 endif() 192 193 # if we are in MSYS & MINGW, and we didn't find windows python lib, look for system python lib 194 if(DEFINED ENV{MSYSTEM} 195 AND MINGW 196 AND NOT EXISTS "${PYTHON_LIBRARY}") 197 if(PYTHON_MULTIARCH) 198 set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}") 199 else() 200 set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}") 201 endif() 202 unset(PYTHON_LIBRARY) 203 find_library( 204 PYTHON_LIBRARY 205 NAMES "python${PYTHON_LIBRARY_SUFFIX}" 206 PATHS ${_PYTHON_LIBS_SEARCH} 207 NO_DEFAULT_PATH) 208 endif() 209 210 # raise an error if the python libs are still not found. 211 if(NOT EXISTS "${PYTHON_LIBRARY}") 212 message(FATAL_ERROR "Python libraries not found") 213 endif() 214 215else() 216 if(PYTHON_MULTIARCH) 217 set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}") 218 else() 219 set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}") 220 endif() 221 #message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}") 222 # Probably this needs to be more involved. It would be nice if the config 223 # information the python interpreter itself gave us were more complete. 224 find_library( 225 PYTHON_LIBRARY 226 NAMES "python${PYTHON_LIBRARY_SUFFIX}" 227 PATHS ${_PYTHON_LIBS_SEARCH} 228 NO_DEFAULT_PATH) 229 230 # If all else fails, just set the name/version and let the linker figure out the path. 231 if(NOT PYTHON_LIBRARY) 232 set(PYTHON_LIBRARY python${PYTHON_LIBRARY_SUFFIX}) 233 endif() 234endif() 235 236mark_as_advanced(PYTHON_LIBRARY PYTHON_INCLUDE_DIR) 237 238# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the 239# cache entries because they are meant to specify the location of a single 240# library. We now set the variables listed by the documentation for this 241# module. 242set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") 243set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") 244if(NOT PYTHON_DEBUG_LIBRARY) 245 set(PYTHON_DEBUG_LIBRARY "") 246endif() 247set(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}") 248 249find_package_message(PYTHON "Found PythonLibs: ${PYTHON_LIBRARY}" 250 "${PYTHON_EXECUTABLE}${PYTHON_VERSION_STRING}") 251 252set(PYTHONLIBS_FOUND TRUE) 253set(PythonLibsNew_FOUND TRUE) 254 255if(NOT PYTHON_MODULE_PREFIX) 256 set(PYTHON_MODULE_PREFIX "") 257endif() 258