* feat!: drop support for Python 3.8 The minimum supported version is now Python 3.9. pybind11 v3.0 was the last release that supports Python 3.8. The deprecation note said that support goes away in 3.1. Remove the code paths that this makes dead: - the `_PyObject_Vectorcall` fallback in `cast.h` - the `frame->f_code` and `frame->f_back` fallbacks in `pytypes.h` - the `PyFrame_FastToLocals` path in `get_type_override` - the conditional `Py_VISIT(Py_TYPE(self))` in `tp_traverse` - `PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX`, the pre-PyConfig interpreter init, and the `widen_chars` helpers in `embed.h` Assisted-by: ClaudeCode:claude-opus-5 * ci(appveyor): use Python 3.9 The AppVeyor job set `PYTHON: 38`, which makes the path `C:\Python38`. The image gives Python 3.9.13 as `C:\Python39`. Assisted-by: ClaudeCode:claude-opus-5 * feat!: require MSVC 2019 or newer Python 3.9 is the new minimum, so MSVC 2017 is no longer needed. Raise the compile-time floor to _MSC_VER 1920 and remove the workarounds that only applied below it: std::launder, fold expressions, weak_from_this, aligned new/delete, the C4100 warning helper, and the func_handle syntax error. AppVeyor now builds with Visual Studio 2019. Assisted-by: ClaudeCode:claude-opus-5 * fix(appveyor): build against the Python that has the test packages CMake 4 has no FindPythonLibs, so pybind11 uses FindPython. FindPython reads the registry before PATH and selected `C:\Python314-x64`, but the test packages go into the Python on PATH. Pass `Python_ROOT_DIR` to name the correct one. Also set `CMAKE_ARCH`. It was never set, so the architecture came from the generator. Visual Studio 2017 defaults to Win32, but Visual Studio 2019 defaults to x64, which made this x86 job build 64-bit code. Assisted-by: ClaudeCode:claude-opus-5 * fix(appveyor): give the linker Python's libs directory The build compiled but failed to link with LNK1104 on a bare `python39.lib`. That name comes from the `#pragma comment(lib, ...)` in pyconfig.h, so the linker needs the directory. CMake 4 has no FindPythonLibs, and FindPython does not add it for this Debug x86 build. Put it on LIB instead. The directory listing is temporary, to confirm the library is present. Assisted-by: ClaudeCode:claude-opus-5 * fix(appveyor): link the release Python library in Debug The image ships python39_d.lib next to python39.lib, so FindPython picks the debug import library for a Debug build. pybind11 undefines _DEBUG around Python.h, so pyconfig.h asks for python39.lib instead and the link failed with LNK1104. Name the release library for the debug slot. Setting LIB does not work, because MSBuild replaces it from the toolset, and it would link both import libraries. Assisted-by: ClaudeCode:claude-opus-5 * chore(appveyor): print link settings to debug LNK1104 Revert the two attempted fixes. Neither changed the failure: setting LIB does not survive MSBuild, and naming the release library for Python_LIBRARY_DEBUG had no effect. Print the Python cache entries and the link settings of a generated project file instead, to see what the linker really gets. Temporary. Assisted-by: ClaudeCode:claude-opus-5 * fix(appveyor): take the release Python library in Debug The generated project file linked C:\Python39\libs\python39_d.lib in the Debug configuration, because the image ships debug binaries next to the release ones. pybind11 undefines _DEBUG around Python.h, so pyconfig.h asks for python39.lib in a #pragma comment(lib), which nothing on the link line satisfies and no library directory holds. Map Debug to the release artifacts. Assisted-by: ClaudeCode:claude-opus-5 * chore(appveyor): drop the temporary link diagnostic Assisted-by: ClaudeCode:claude-opus-5 * fix(tests): guard the unraisable warning filter for pytest < 6 The distro pytest in the Clang and GCC Docker jobs has no PytestUnraisableExceptionWarning, so an unconditional filterwarnings mark makes pytest fail with an INTERNALERROR after the tests pass. Assisted-by: ClaudeCode:claude-opus-5 Claude-Session: https://claude.ai/code/session_01Aimf6HuSz1vLRwBnbxmCTc * docs: address review items on version hints, embed docs, and a PyPy xfail Extend Python_ADDITIONAL_VERSIONS through 3.15, describe the PyConfig behavior of initialize_interpreter, and drop the stale Python 3.8 wording from the PyPy xfail reason. Assisted-by: ClaudeCode:claude-opus-5 * Update README.rst Co-authored-by: Ralf W. Grosse-Kunstleve <rwgkio@gmail.com> --------- Co-authored-by: Ralf W. Grosse-Kunstleve <rwgkio@gmail.com>
218 lines
7.7 KiB
CMake
218 lines
7.7 KiB
CMake
# tools/pybind11Tools.cmake -- Build system for the pybind11 modules
|
|
#
|
|
# Copyright (c) 2020 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
|
#
|
|
# All rights reserved. Use of this source code is governed by a
|
|
# BSD-style license that can be found in the LICENSE file.
|
|
|
|
include_guard(DIRECTORY)
|
|
|
|
if(pybind11_FIND_QUIETLY)
|
|
set(_pybind11_quiet QUIET)
|
|
else()
|
|
set(_pybind11_quiet "")
|
|
endif()
|
|
|
|
# If this is the first run, PYTHON_VERSION can stand in for PYBIND11_PYTHON_VERSION
|
|
if(NOT DEFINED PYBIND11_PYTHON_VERSION AND DEFINED PYTHON_VERSION)
|
|
message(WARNING "Set PYBIND11_PYTHON_VERSION to search for a specific version, not "
|
|
"PYTHON_VERSION (which is an output). Assuming that is what you "
|
|
"meant to do and continuing anyway.")
|
|
set(PYBIND11_PYTHON_VERSION
|
|
"${PYTHON_VERSION}"
|
|
CACHE STRING "Python version to use for compiling modules")
|
|
unset(PYTHON_VERSION)
|
|
unset(PYTHON_VERSION CACHE)
|
|
elseif(DEFINED PYBIND11_PYTHON_VERSION)
|
|
# If this is set as a normal variable, promote it
|
|
set(PYBIND11_PYTHON_VERSION
|
|
"${PYBIND11_PYTHON_VERSION}"
|
|
CACHE STRING "Python version to use for compiling modules")
|
|
else()
|
|
# Make an empty cache variable.
|
|
set(PYBIND11_PYTHON_VERSION
|
|
""
|
|
CACHE STRING "Python version to use for compiling modules")
|
|
endif()
|
|
|
|
# A user can set versions manually too
|
|
set(Python_ADDITIONAL_VERSIONS
|
|
"3.15;3.14;3.13;3.12;3.11;3.10;3.9"
|
|
CACHE INTERNAL "")
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|
find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED ${_pybind11_quiet})
|
|
list(REMOVE_AT CMAKE_MODULE_PATH -1)
|
|
|
|
# Makes a normal variable a cached variable
|
|
macro(_PYBIND11_PROMOTE_TO_CACHE NAME)
|
|
set(_tmp_ptc "${${NAME}}")
|
|
# CMake 3.21 complains if a cached variable is shadowed by a normal one
|
|
unset(${NAME})
|
|
set(${NAME}
|
|
"${_tmp_ptc}"
|
|
CACHE INTERNAL "")
|
|
endmacro()
|
|
|
|
# Cache variables so pybind11_add_module can be used in parent projects
|
|
_pybind11_promote_to_cache(PYTHON_INCLUDE_DIRS)
|
|
_pybind11_promote_to_cache(PYTHON_LIBRARIES)
|
|
_pybind11_promote_to_cache(PYTHON_MODULE_PREFIX)
|
|
_pybind11_promote_to_cache(PYTHON_MODULE_EXTENSION)
|
|
_pybind11_promote_to_cache(PYTHON_MODULE_DEBUG_POSTFIX)
|
|
_pybind11_promote_to_cache(PYTHON_VERSION_MAJOR)
|
|
_pybind11_promote_to_cache(PYTHON_VERSION_MINOR)
|
|
_pybind11_promote_to_cache(PYTHON_VERSION)
|
|
_pybind11_promote_to_cache(PYTHON_IS_DEBUG)
|
|
|
|
if(PYBIND11_MASTER_PROJECT)
|
|
if(PYTHON_MODULE_EXTENSION MATCHES "pypy")
|
|
if(NOT DEFINED PYPY_VERSION)
|
|
execute_process(
|
|
COMMAND ${PYTHON_EXECUTABLE} -c
|
|
[=[import sys; sys.stdout.write(".".join(map(str, sys.pypy_version_info[:3])))]=]
|
|
OUTPUT_VARIABLE pypy_version)
|
|
set(PYPY_VERSION
|
|
${pypy_version}
|
|
CACHE INTERNAL "")
|
|
endif()
|
|
message(STATUS "PYPY ${PYPY_VERSION} (Py ${PYTHON_VERSION})")
|
|
else()
|
|
message(STATUS "PYTHON ${PYTHON_VERSION}")
|
|
endif()
|
|
endif()
|
|
|
|
# Only add Python for build - must be added during the import for config since
|
|
# it has to be re-discovered.
|
|
#
|
|
# This needs to be an target to it is included after the local pybind11
|
|
# directory, just in case there are multiple versions of pybind11, we want the
|
|
# one we expect.
|
|
add_library(pybind11::python_headers INTERFACE IMPORTED)
|
|
set_property(TARGET pybind11::python_headers PROPERTY INTERFACE_INCLUDE_DIRECTORIES
|
|
"$<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>")
|
|
set_property(
|
|
TARGET pybind11::pybind11
|
|
APPEND
|
|
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python_headers)
|
|
|
|
set(pybind11_INCLUDE_DIRS
|
|
"${pybind11_INCLUDE_DIR}" "${PYTHON_INCLUDE_DIRS}"
|
|
CACHE INTERNAL "Directories where pybind11 and possibly Python headers are located")
|
|
|
|
# A debug build of Python needs Py_DEBUG to select the matching ABI.
|
|
# https://docs.python.org/3/c-api/intro.html#debugging-builds
|
|
# https://stackoverflow.com/questions/39161202/how-to-work-around-missing-pymodule-create2-in-amd64-win-python35-d-lib
|
|
if(PYTHON_IS_DEBUG)
|
|
set_property(
|
|
TARGET pybind11::pybind11
|
|
APPEND
|
|
PROPERTY INTERFACE_COMPILE_DEFINITIONS Py_DEBUG)
|
|
endif()
|
|
|
|
# The IMPORTED INTERFACE library here is to ensure that "debug" and "release" get processed outside
|
|
# of a generator expression - https://gitlab.kitware.com/cmake/cmake/-/issues/18424, as they are
|
|
# target_link_library keywords rather than real libraries.
|
|
add_library(pybind11::_ClassicPythonLibraries IMPORTED INTERFACE)
|
|
target_link_libraries(pybind11::_ClassicPythonLibraries INTERFACE ${PYTHON_LIBRARIES})
|
|
target_link_libraries(
|
|
pybind11::module
|
|
INTERFACE
|
|
pybind11::python_link_helper
|
|
"$<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Cygwin>,$<PLATFORM_ID:Android>>:pybind11::_ClassicPythonLibraries>"
|
|
)
|
|
|
|
target_link_libraries(pybind11::embed INTERFACE pybind11::pybind11
|
|
pybind11::_ClassicPythonLibraries)
|
|
|
|
function(pybind11_extension name)
|
|
# The prefix and extension are provided by FindPythonLibsNew.cmake
|
|
set_target_properties(
|
|
${name}
|
|
PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
|
|
DEBUG_POSTFIX "${PYTHON_MODULE_DEBUG_POSTFIX}"
|
|
SUFFIX "${PYTHON_MODULE_EXTENSION}")
|
|
endfunction()
|
|
|
|
# Build a Python extension module:
|
|
# pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL]
|
|
# [NO_EXTRAS] [THIN_LTO] [OPT_SIZE] source1 [source2 ...])
|
|
#
|
|
function(pybind11_add_module target_name)
|
|
set(options "MODULE;SHARED;EXCLUDE_FROM_ALL;NO_EXTRAS;SYSTEM;THIN_LTO;OPT_SIZE")
|
|
cmake_parse_arguments(ARG "${options}" "" "" ${ARGN})
|
|
|
|
if(ARG_MODULE AND ARG_SHARED)
|
|
message(FATAL_ERROR "Can't be both MODULE and SHARED")
|
|
elseif(ARG_SHARED)
|
|
set(lib_type SHARED)
|
|
else()
|
|
set(lib_type MODULE)
|
|
endif()
|
|
|
|
if(ARG_EXCLUDE_FROM_ALL)
|
|
set(exclude_from_all EXCLUDE_FROM_ALL)
|
|
else()
|
|
set(exclude_from_all "")
|
|
endif()
|
|
|
|
add_library(${target_name} ${lib_type} ${exclude_from_all} ${ARG_UNPARSED_ARGUMENTS})
|
|
|
|
target_link_libraries(${target_name} PRIVATE pybind11::module)
|
|
|
|
if(ARG_SYSTEM)
|
|
message(
|
|
STATUS
|
|
"Warning: this does not have an effect - use NO_SYSTEM_FROM_IMPORTED if using imported targets"
|
|
)
|
|
endif()
|
|
|
|
pybind11_extension(${target_name})
|
|
|
|
# -fvisibility=hidden is required to allow multiple modules compiled against
|
|
# different pybind versions to work properly, and for some features (e.g.
|
|
# py::module_local). We force it on everything inside the `pybind11`
|
|
# namespace; also turning it on for a pybind module compilation here avoids
|
|
# potential warnings or issues from having mixed hidden/non-hidden types.
|
|
if(NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
|
|
set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
|
|
endif()
|
|
|
|
if(NOT DEFINED CMAKE_CUDA_VISIBILITY_PRESET)
|
|
set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden")
|
|
endif()
|
|
|
|
if(ARG_NO_EXTRAS)
|
|
return()
|
|
endif()
|
|
|
|
if(NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
|
if(ARG_THIN_LTO)
|
|
target_link_libraries(${target_name} PRIVATE pybind11::thin_lto)
|
|
else()
|
|
target_link_libraries(${target_name} PRIVATE pybind11::lto)
|
|
endif()
|
|
endif()
|
|
|
|
if(DEFINED CMAKE_BUILD_TYPE) # see https://github.com/pybind/pybind11/issues/4454
|
|
# Use case-insensitive comparison to match the result of $<CONFIG:cfgs>
|
|
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
|
|
if(NOT MSVC AND NOT "${uppercase_CMAKE_BUILD_TYPE}" MATCHES DEBUG|RELWITHDEBINFO|NONE)
|
|
pybind11_strip(${target_name})
|
|
endif()
|
|
endif()
|
|
|
|
if(MSVC)
|
|
target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
|
|
endif()
|
|
|
|
if(ARG_OPT_SIZE)
|
|
target_link_libraries(${target_name} PRIVATE pybind11::opt_size)
|
|
endif()
|
|
endfunction()
|
|
|
|
# Provide general way to call common Python commands in "common" file.
|
|
set(_Python
|
|
PYTHON
|
|
CACHE INTERNAL "" FORCE)
|