# - Try to find Python include dirs and libraries # # Usage of this module as follows: # # find_package(PythonDev) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # PYTHON_EXECUTABLE If this is set to a path to a Python interpreter # then this module attempts to infer the path to # python-config from it # PYTHON_CONFIG Set this variable to the location of python-config # if the module has problems finding the proper # installation path. # # Variables defined by this module: # # PYTHONDEV_FOUND System has Python dev headers/libraries # PYTHON_INCLUDE_DIR The Python include directories. # PYTHON_LIBRARIES The Python libraries and linker flags. include(FindPackageHandleStandardArgs) if (CMAKE_CROSSCOMPILING) find_package(PythonLibs) if (PYTHON_INCLUDE_PATH AND NOT PYTHON_INCLUDE_DIR) set(PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_PATH}") endif () find_package_handle_standard_args(PythonDev DEFAULT_MSG PYTHON_INCLUDE_DIR PYTHON_LIBRARIES) return() endif () if (PYTHON_EXECUTABLE) # Get the real path so that we can reliably find the correct python-config # (e.g. some systems may have a "python" symlink, but not a "python-config" # symlink). get_filename_component(PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}" REALPATH) get_filename_component(PYTHON_EXECUTABLE_DIR "${PYTHON_EXECUTABLE}" DIRECTORY) get_filename_component(PYTHON_EXECUTABLE_NAME "${PYTHON_EXECUTABLE}" NAME) if (EXISTS ${PYTHON_EXECUTABLE}-config) set(PYTHON_CONFIG ${PYTHON_EXECUTABLE}-config CACHE PATH "" FORCE) # Avoid assumption that python-config is associated with python3 if # python3 co-exists in a directory that also contains python2 stuff elseif ( EXISTS ${PYTHON_EXECUTABLE_DIR}/python-config AND NOT EXISTS ${PYTHON_EXECUTABLE_DIR}/python2 AND NOT EXISTS ${PYTHON_EXECUTABLE_DIR}/python2.7 AND NOT EXISTS ${PYTHON_EXECUTABLE_DIR}/python2-config AND NOT EXISTS ${PYTHON_EXECUTABLE_DIR}/python2.7-config) set(PYTHON_CONFIG ${PYTHON_EXECUTABLE_DIR}/python-config CACHE PATH "" FORCE) endif () else () find_program( PYTHON_CONFIG NAMES python3-config python3.11-config python3.10-config python3.9-config python3.8-config python3.7-config python-config) endif () # The OpenBSD python packages have python-config's that don't reliably # report linking flags that will work. if (PYTHON_CONFIG AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") # Try `--ldflags --embed` first and fallback to `--ldflags` if it fails. # Python 3.8+ introduced the `--embed` flag in relation to this: # https://docs.python.org/3.8/whatsnew/3.8.html#debug-build-uses-the-same-abi-as-release-build # Note that even if this FindPythonDev script could technically apply to # either embedded or extension use cases, the `--embed` flag only adds # a `-lpython` and it's generally safe to link libpython in both cases. # The only downside to doing that against an extension when it's not # strictly necessary is losing the ability to mix-and-match debug/release # modes between Python and extensions and that's not a feature to typically # care about. execute_process( COMMAND "${PYTHON_CONFIG}" --ldflags --embed RESULT_VARIABLE _python_config_result OUTPUT_VARIABLE PYTHON_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) if (NOT ${_python_config_result} EQUAL 0) execute_process( COMMAND "${PYTHON_CONFIG}" --ldflags RESULT_VARIABLE _python_config_result OUTPUT_VARIABLE PYTHON_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) endif () string(STRIP "${PYTHON_LIBRARIES}" PYTHON_LIBRARIES) execute_process(COMMAND "${PYTHON_CONFIG}" --includes OUTPUT_VARIABLE PYTHON_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) string(REGEX REPLACE "^[-I]" "" PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}") string(REGEX REPLACE "[ ]-I" " " PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}") separate_arguments(PYTHON_INCLUDE_DIR) find_package_handle_standard_args(PythonDev DEFAULT_MSG PYTHON_CONFIG PYTHON_INCLUDE_DIR PYTHON_LIBRARIES) else () if (${CMAKE_VERSION} VERSION_LESS "3.12.0") find_package(PythonLibs) if (PYTHON_INCLUDE_PATH AND NOT PYTHON_INCLUDE_DIR) set(PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_PATH}") endif () else () # Expect this branch to be used mostly in macOS where the system # default Python 3 installation is not easily/consistently detected # by CMake. CMake 3.12+ is required, but it's expected that macOS # users are getting a recent version from homebrew/etc anyway. find_package(Python3 COMPONENTS Development) if (Python3_INCLUDE_DIRS AND NOT PYTHON_INCLUDE_DIR) set(PYTHON_INCLUDE_DIR "${Python3_INCLUDE_DIRS}") endif () if (Python3_LIBRARIES AND NOT PYTHON_LIBRARIES) set(PYTHON_LIBRARIES "${Python3_LIBRARIES}") endif () endif () find_package_handle_standard_args(PythonDev DEFAULT_MSG PYTHON_INCLUDE_DIR PYTHON_LIBRARIES) endif ()