diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f5a08e2d..f2d8007d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -81,7 +81,7 @@ nox -s build ### Full setup To setup an ideal development environment, run the following commands on a -system with CMake 3.14+: +system with CMake 3.15+: ```bash python3 -m venv venv @@ -96,8 +96,8 @@ Tips: * You can use `virtualenv` (faster, from PyPI) instead of `venv`. * You can select any name for your environment folder; if it contains "env" it will be ignored by git. -* If you don't have CMake 3.14+, just add "cmake" to the pip install command. -* You can use `-DPYBIND11_FINDPYTHON=ON` to use FindPython on CMake 3.12+ +* If you don't have CMake 3.15+, just add "cmake" to the pip install command. +* You can use `-DPYBIND11_FINDPYTHON=ON` to use FindPython. * In classic mode, you may need to set `-DPYTHON_EXECUTABLE=/path/to/python`. FindPython uses `-DPython_ROOT_DIR=/path/to` or `-DPython_EXECUTABLE=/path/to/python`. @@ -149,8 +149,8 @@ To run the tests, you can "build" the check target: cmake --build build --target check ``` -`--target` can be spelled `-t` in CMake 3.15+. You can also run individual -tests with these targets: +`--target` can be spelled `-t`. You can also run individual tests with these +targets: * `pytest`: Python tests only, using the [pytest](https://docs.pytest.org/en/stable/) framework diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 8242db7b..8e89e6f3 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -32,7 +32,7 @@ jobs: include: - runs-on: ubuntu-20.04 arch: x64 - cmake: "3.5" + cmake: "3.15" - runs-on: ubuntu-20.04 arch: x64 @@ -40,7 +40,7 @@ jobs: - runs-on: macos-13 arch: x64 - cmake: "3.8" + cmake: "3.15" - runs-on: windows-2019 arch: x64 # x86 compilers seem to be missing on 2019 image diff --git a/CMakeLists.txt b/CMakeLists.txt index 0964e2ee..aa9634ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,16 +10,7 @@ if(NOT CMAKE_VERSION VERSION_LESS "3.27") cmake_policy(GET CMP0148 _pybind11_cmp0148) endif() -cmake_minimum_required(VERSION 3.5) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) if(_pybind11_cmp0148) cmake_policy(SET CMP0148 ${_pybind11_cmp0148}) @@ -27,9 +18,7 @@ if(_pybind11_cmp0148) endif() # Avoid infinite recursion if tests include this as a subdirectory -if(DEFINED PYBIND11_MASTER_PROJECT) - return() -endif() +include_guard(GLOBAL) # Extract project version from source file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/pybind11/detail/common.h" @@ -74,14 +63,6 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set(PYBIND11_MASTER_PROJECT ON) - if(OSX AND CMAKE_VERSION VERSION_LESS 3.7) - # Bug in macOS CMake < 3.7 is unable to download catch - message(WARNING "CMAKE 3.7+ needed on macOS to download catch, and newer HIGHLY recommended") - elseif(WINDOWS AND CMAKE_VERSION VERSION_LESS 3.8) - # Only tested with 3.8+ in CI. - message(WARNING "CMAKE 3.8+ tested on Windows, previous versions untested") - endif() - message(STATUS "CMake ${CMAKE_VERSION}") if(CMAKE_CXX_STANDARD) @@ -133,8 +114,7 @@ cmake_dependent_option( "Install pybind11 headers in Python include directory instead of default installation prefix" OFF "PYBIND11_INSTALL" OFF) -cmake_dependent_option(PYBIND11_FINDPYTHON "Force new FindPython" ${_pybind11_findpython_default} - "NOT CMAKE_VERSION VERSION_LESS 3.12" OFF) +option(PYBIND11_FINDPYTHON "Force new FindPython" ${_pybind11_findpython_default}) # Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests # (makes transition easier while we support both modes). @@ -188,7 +168,7 @@ set(PYBIND11_HEADERS include/pybind11/typing.h) # Compare with grep and warn if mismatched -if(PYBIND11_MASTER_PROJECT AND NOT CMAKE_VERSION VERSION_LESS 3.12) +if(PYBIND11_MASTER_PROJECT) file( GLOB_RECURSE _pybind11_header_check LIST_DIRECTORIES false @@ -206,10 +186,7 @@ if(PYBIND11_MASTER_PROJECT AND NOT CMAKE_VERSION VERSION_LESS 3.12) endif() endif() -# CMake 3.12 added list(TRANSFORM PREPEND -# But we can't use it yet -string(REPLACE "include/" "${CMAKE_CURRENT_SOURCE_DIR}/include/" PYBIND11_HEADERS - "${PYBIND11_HEADERS}") +list(TRANSFORM PYBIND11_HEADERS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") # Cache variable so this can be used in parent projects set(pybind11_INCLUDE_DIR @@ -279,25 +256,11 @@ if(PYBIND11_INSTALL) tools/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR}) - if(CMAKE_VERSION VERSION_LESS 3.14) - # Remove CMAKE_SIZEOF_VOID_P from ConfigVersion.cmake since the library does - # not depend on architecture specific settings or libraries. - set(_PYBIND11_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) - unset(CMAKE_SIZEOF_VOID_P) - - write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion) - - set(CMAKE_SIZEOF_VOID_P ${_PYBIND11_CMAKE_SIZEOF_VOID_P}) - else() - # CMake 3.14+ natively supports header-only libraries - write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion ARCH_INDEPENDENT) - endif() + # CMake natively supports header-only libraries + write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion ARCH_INDEPENDENT) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake diff --git a/docs/advanced/embedding.rst b/docs/advanced/embedding.rst index cbed8215..e78a8f4c 100644 --- a/docs/advanced/embedding.rst +++ b/docs/advanced/embedding.rst @@ -18,7 +18,7 @@ information, see :doc:`/compiling`. .. code-block:: cmake - cmake_minimum_required(VERSION 3.5...3.29) + cmake_minimum_required(VERSION 3.15...3.30) project(example) find_package(pybind11 REQUIRED) # or `add_subdirectory(pybind11)` diff --git a/docs/changelog.rst b/docs/changelog.rst index d19a9012..031d3158 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -20,7 +20,28 @@ New Features: * Support for Python 3.7 was removed. (Official end-of-life: 2023-06-27). `#5191 `_ -Support for CMake older than 3.15 and some older compilers will also be removed. +* stl.h ``list|set|map_caster`` were made more user friendly: it is no longer + necessary to explicitly convert Python iterables to ``tuple()``, ``set()``, + or ``map()`` in many common situations. + `#4686 `_ + +* Support for CMake older than 3.15 removed. CMake 3.15-3.30 supported. + `#5304 `_ + +Version 2.13.4 (August 14, 2024) +-------------------------------- + +Bug fixes: + +* Fix paths with spaces, including on Windows. + (Replaces regression from `#5302 `_) + `#4874 `_ + +Documentation: + +* Remove repetitive words. + `#5308 `_ + Version 2.13.3 (August 13, 2024) -------------------------------- diff --git a/docs/compiling.rst b/docs/compiling.rst index 65db93c8..94042c3e 100644 --- a/docs/compiling.rst +++ b/docs/compiling.rst @@ -18,7 +18,7 @@ A Python extension module can be created with just a few lines of code: .. code-block:: cmake - cmake_minimum_required(VERSION 3.15...3.29) + cmake_minimum_required(VERSION 3.15...3.30) project(example LANGUAGES CXX) set(PYBIND11_FINDPYTHON ON) @@ -319,11 +319,11 @@ Building with CMake For C++ codebases that have an existing CMake-based build system, a Python extension module can be created with just a few lines of code, as seen above in -the module section. Pybind11 currently supports a lower minimum if you don't -use the modern FindPython, though be aware that CMake 3.27 removed the old -mechanism, so pybind11 will automatically switch if the old mechanism is not -available. Please opt into the new mechanism if at all possible. Our default -may change in future versions. This is the minimum required: +the module section. Pybind11 currently defaults to the old mechanism, though be +aware that CMake 3.27 removed the old mechanism, so pybind11 will automatically +switch if the old mechanism is not available. Please opt into the new mechanism +if at all possible. Our default may change in future versions. This is the +minimum required: @@ -333,6 +333,9 @@ may change in future versions. This is the minimum required: .. versionchanged:: 2.11 CMake 3.5+ is required. +.. versionchanged:: 2.14 + CMake 3.15+ is required. + Further information can be found at :doc:`cmake/index`. @@ -444,7 +447,7 @@ See the `Config file`_ docstring for details of relevant CMake variables. .. code-block:: cmake - cmake_minimum_required(VERSION 3.4...3.18) + cmake_minimum_required(VERSION 3.15...3.30) project(example LANGUAGES CXX) find_package(pybind11 REQUIRED) @@ -483,14 +486,13 @@ can refer to the same [cmake_example]_ repository for a full sample project FindPython mode --------------- -CMake 3.12+ (3.15+ recommended, 3.18.2+ ideal) added a new module called -FindPython that had a highly improved search algorithm and modern targets -and tools. If you use FindPython, pybind11 will detect this and use the -existing targets instead: +Modern CMake (3.18.2+ ideal) added a new module called FindPython that had a +highly improved search algorithm and modern targets and tools. If you use +FindPython, pybind11 will detect this and use the existing targets instead: .. code-block:: cmake - cmake_minimum_required(VERSION 3.15...3.22) + cmake_minimum_required(VERSION 3.15...3.30) project(example LANGUAGES CXX) find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED) @@ -541,7 +543,7 @@ available in all modes. The targets provided are: Just the "linking" part of pybind11:module ``pybind11::module`` - Everything for extension modules - ``pybind11::pybind11`` + ``Python::Module`` (FindPython CMake 3.15+) or ``pybind11::python_link_helper`` + Everything for extension modules - ``pybind11::pybind11`` + ``Python::Module`` (FindPython) or ``pybind11::python_link_helper`` ``pybind11::embed`` Everything for embedding the Python interpreter - ``pybind11::pybind11`` + ``Python::Python`` (FindPython) or Python libs @@ -568,7 +570,7 @@ You can use these targets to build complex applications. For example, the .. code-block:: cmake - cmake_minimum_required(VERSION 3.5...3.29) + cmake_minimum_required(VERSION 3.15...3.30) project(example LANGUAGES CXX) find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11) @@ -626,7 +628,7 @@ information about usage in C++, see :doc:`/advanced/embedding`. .. code-block:: cmake - cmake_minimum_required(VERSION 3.5...3.29) + cmake_minimum_required(VERSION 3.15...3.30) project(example LANGUAGES CXX) find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11) diff --git a/docs/faq.rst b/docs/faq.rst index 1eb00efa..92777b5b 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -258,9 +258,9 @@ CMake configure line. (Replace ``$(which python)`` with a path to python if your prefer.) You can alternatively try ``-DPYBIND11_FINDPYTHON=ON``, which will activate the -new CMake FindPython support instead of pybind11's custom search. Requires -CMake 3.12+, and 3.15+ or 3.18.2+ are even better. You can set this in your -``CMakeLists.txt`` before adding or finding pybind11, as well. +new CMake FindPython support instead of pybind11's custom search. Newer CMake, +like, 3.18.2+, is recommended. You can set this in your ``CMakeLists.txt`` +before adding or finding pybind11, as well. Inconsistent detection of Python version in CMake and pybind11 ============================================================== @@ -281,11 +281,11 @@ There are three possible solutions: from CMake and rely on pybind11 in detecting Python version. If this is not possible, the CMake machinery should be called *before* including pybind11. 2. Set ``PYBIND11_FINDPYTHON`` to ``True`` or use ``find_package(Python - COMPONENTS Interpreter Development)`` on modern CMake (3.12+, 3.15+ better, - 3.18.2+ best). Pybind11 in these cases uses the new CMake FindPython instead - of the old, deprecated search tools, and these modules are much better at - finding the correct Python. If FindPythonLibs/Interp are not available - (CMake 3.27+), then this will be ignored and FindPython will be used. + COMPONENTS Interpreter Development)`` on modern CMake ( 3.18.2+ best). + Pybind11 in these cases uses the new CMake FindPython instead of the old, + deprecated search tools, and these modules are much better at finding the + correct Python. If FindPythonLibs/Interp are not available (CMake 3.27+), + then this will be ignored and FindPython will be used. 3. Set ``PYBIND11_NOPYTHON`` to ``TRUE``. Pybind11 will not search for Python. However, you will have to use the target-based system, and do more setup yourself, because it does not know about or include things that depend on diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 096301bc..6a148e74 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -11,11 +11,14 @@ #include "pybind11.h" #include "detail/common.h" +#include "detail/descr.h" +#include "detail/type_caster_base.h" #include #include #include #include +#include #include #include #include @@ -349,36 +352,65 @@ struct type_caster> : list_caster struct type_caster> : list_caster, Type> {}; +template +ArrayType vector_to_array_impl(V &&v, index_sequence) { + return {{std::move(v[I])...}}; +} + +// Based on https://en.cppreference.com/w/cpp/container/array/to_array +template +ArrayType vector_to_array(V &&v) { + return vector_to_array_impl(std::forward(v), make_index_sequence{}); +} + template struct array_caster { using value_conv = make_caster; private: - template - bool require_size(enable_if_t size) { - if (value.size() != size) { - value.resize(size); + std::unique_ptr value; + + template = 0> + bool convert_elements(handle seq, bool convert) { + auto l = reinterpret_borrow(seq); + value.reset(new ArrayType{}); + // Using `resize` to preserve the behavior exactly as it was before PR #5305 + // For the `resize` to work, `Value` must be default constructible. + // For `std::valarray`, this is a requirement: + // https://en.cppreference.com/w/cpp/named_req/NumericType + value->resize(l.size()); + size_t ctr = 0; + for (const auto &it : l) { + value_conv conv; + if (!conv.load(it, convert)) { + return false; + } + (*value)[ctr++] = cast_op(std::move(conv)); } return true; } - template - bool require_size(enable_if_t size) { - return size == Size; - } + template = 0> bool convert_elements(handle seq, bool convert) { auto l = reinterpret_borrow(seq); - if (!require_size(l.size())) { + if (l.size() != Size) { return false; } - size_t ctr = 0; - for (const auto &it : l) { + // The `temp` storage is needed to support `Value` types that are not + // default-constructible. + // Deliberate choice: no template specializations, for simplicity, and + // because the compile time overhead for the specializations is deemed + // more significant than the runtime overhead for the `temp` storage. + std::vector temp; + temp.reserve(l.size()); + for (auto it : l) { value_conv conv; if (!conv.load(it, convert)) { return false; } - value[ctr++] = cast_op(std::move(conv)); + temp.emplace_back(cast_op(std::move(conv))); } + value.reset(new ArrayType(vector_to_array(std::move(temp)))); return true; } @@ -416,12 +448,36 @@ struct array_caster { return l.release(); } - PYBIND11_TYPE_CASTER(ArrayType, - const_name(const_name(""), const_name("Annotated[")) - + const_name("list[") + value_conv::name + const_name("]") - + const_name(const_name(""), - const_name(", FixedSize(") - + const_name() + const_name(")]"))); + // Code copied from PYBIND11_TYPE_CASTER macro. + // Intentionally preserving the behavior exactly as it was before PR #5305 + template >::value, int> = 0> + static handle cast(T_ *src, return_value_policy policy, handle parent) { + if (!src) { + return none().release(); + } + if (policy == return_value_policy::take_ownership) { + auto h = cast(std::move(*src), policy, parent); + delete src; // WARNING: Assumes `src` was allocated with `new`. + return h; + } + return cast(*src, policy, parent); + } + + // NOLINTNEXTLINE(google-explicit-constructor) + operator ArrayType *() { return &(*value); } + // NOLINTNEXTLINE(google-explicit-constructor) + operator ArrayType &() { return *value; } + // NOLINTNEXTLINE(google-explicit-constructor) + operator ArrayType &&() && { return std::move(*value); } + + template + using cast_op_type = movable_cast_op_type; + + static constexpr auto name + = const_name(const_name(""), const_name("Annotated[")) + const_name("list[") + + value_conv::name + const_name("]") + + const_name( + const_name(""), const_name(", FixedSize(") + const_name() + const_name(")]")); }; template diff --git a/pybind11/__main__.py b/pybind11/__main__.py index dadf24f3..0abc7e21 100644 --- a/pybind11/__main__.py +++ b/pybind11/__main__.py @@ -2,13 +2,35 @@ from __future__ import annotations import argparse -import shlex +import re import sys import sysconfig from ._version import __version__ from .commands import get_cmake_dir, get_include, get_pkgconfig_dir +# This is the conditional used for os.path being posixpath +if "posix" in sys.builtin_module_names: + from shlex import quote +elif "nt" in sys.builtin_module_names: + # See https://github.com/mesonbuild/meson/blob/db22551ed9d2dd7889abea01cc1c7bba02bf1c75/mesonbuild/utils/universal.py#L1092-L1121 + # and the original documents: + # https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments and + # https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ + UNSAFE = re.compile("[ \t\n\r]") + + def quote(s: str) -> str: + if s and not UNSAFE.search(s): + return s + + # Paths cannot contain a '"' on Windows, so we don't need to worry + # about nuanced counting here. + return f'"{s}\\"' if s.endswith("\\") else f'"{s}"' +else: + + def quote(s: str) -> str: + return s + def print_includes() -> None: dirs = [ @@ -23,7 +45,7 @@ def print_includes() -> None: if d and d not in unique_dirs: unique_dirs.append(d) - print(" ".join(shlex.quote(f"-I{d}") for d in unique_dirs)) + print(" ".join(quote(f"-I{d}") for d in unique_dirs)) def main() -> None: @@ -55,9 +77,9 @@ def main() -> None: if args.includes: print_includes() if args.cmakedir: - print(shlex.quote(get_cmake_dir())) + print(quote(get_cmake_dir())) if args.pkgconfigdir: - print(shlex.quote(get_pkgconfig_dir())) + print(quote(get_pkgconfig_dir())) if __name__ == "__main__": diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8765a518..450b96df 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,16 +5,7 @@ # All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. -cmake_minimum_required(VERSION 3.5) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) # Filter out items; print an optional message if any items filtered. This ignores extensions. # @@ -76,8 +67,8 @@ project(pybind11_tests CXX) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../tools") option(PYBIND11_WERROR "Report all warnings as errors" OFF) -option(DOWNLOAD_EIGEN "Download EIGEN (requires CMake 3.11+)" OFF) -option(PYBIND11_CUDA_TESTS "Enable building CUDA tests (requires CMake 3.12+)" OFF) +option(DOWNLOAD_EIGEN "Download EIGEN" OFF) +option(PYBIND11_CUDA_TESTS "Enable building CUDA tests" OFF) set(PYBIND11_TEST_OVERRIDE "" CACHE STRING "Tests from ;-separated list of *.cpp files will be built instead of all tests") @@ -267,25 +258,21 @@ endif() if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1) # Try loading via newer Eigen's Eigen3Config first (bypassing tools/FindEigen3.cmake). # Eigen 3.3.1+ exports a cmake 3.0+ target for handling dependency requirements, but also - # produces a fatal error if loaded from a pre-3.0 cmake. if(DOWNLOAD_EIGEN) - if(CMAKE_VERSION VERSION_LESS 3.11) - message(FATAL_ERROR "CMake 3.11+ required when using DOWNLOAD_EIGEN") + if(CMAKE_VERSION VERSION_LESS 3.18) + set(_opts) + else() + set(_opts SOURCE_SUBDIR no-cmake-build) endif() - include(FetchContent) FetchContent_Declare( eigen GIT_REPOSITORY "${PYBIND11_EIGEN_REPO}" - GIT_TAG "${PYBIND11_EIGEN_VERSION_HASH}") - - FetchContent_GetProperties(eigen) - if(NOT eigen_POPULATED) - message( - STATUS - "Downloading Eigen ${PYBIND11_EIGEN_VERSION_STRING} (${PYBIND11_EIGEN_VERSION_HASH}) from ${PYBIND11_EIGEN_REPO}" - ) - FetchContent_Populate(eigen) + GIT_TAG "${PYBIND11_EIGEN_VERSION_HASH}" + ${_opts}) + FetchContent_MakeAvailable(eigen) + if(NOT CMAKE_VERSION VERSION_LESS 3.18) + set(EIGEN3_INCLUDE_DIR "${eigen_SOURCE_DIR}") endif() set(EIGEN3_INCLUDE_DIR ${eigen_SOURCE_DIR}) @@ -333,8 +320,7 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1) if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1) list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_EIGEN_I}) endif() - message( - STATUS "Building tests WITHOUT Eigen, use -DDOWNLOAD_EIGEN=ON on CMake 3.11+ to download") + message(STATUS "Building tests WITHOUT Eigen, use -DDOWNLOAD_EIGEN=ON to download") endif() endif() @@ -519,12 +505,10 @@ foreach(target ${test_targets}) endforeach() # Provide nice organisation in IDEs -if(NOT CMAKE_VERSION VERSION_LESS 3.8) - source_group( - TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" - PREFIX "Header Files" - FILES ${PYBIND11_HEADERS}) -endif() +source_group( + TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" + PREFIX "Header Files" + FILES ${PYBIND11_HEADERS}) # Make sure pytest is found or produce a warning pybind11_find_import(pytest VERSION 3.1) diff --git a/tests/extra_python_package/test_files.py b/tests/extra_python_package/test_files.py index 5c970537..e6602ad7 100644 --- a/tests/extra_python_package/test_files.py +++ b/tests/extra_python_package/test_files.py @@ -9,7 +9,6 @@ import zipfile # These tests must be run explicitly -# They require CMake 3.15+ (--install) DIR = os.path.abspath(os.path.dirname(__file__)) MAIN_DIR = os.path.dirname(os.path.dirname(DIR)) diff --git a/tests/pyproject.toml b/tests/pyproject.toml index 044bf15c..469c145d 100644 --- a/tests/pyproject.toml +++ b/tests/pyproject.toml @@ -10,10 +10,6 @@ name = "pybind11_tests" version = "0.0.1" dependencies = ["pytest", "pytest-timeout", "numpy", "scipy"] -[tool.scikit-build] -# Hide a warning while we also support CMake < 3.15 -cmake.version = ">=3.15" - [tool.scikit-build.cmake.define] PYBIND11_FINDPYTHON = true diff --git a/tests/test_cmake_build/installed_embed/CMakeLists.txt b/tests/test_cmake_build/installed_embed/CMakeLists.txt index 2be0aa65..5c6267c7 100644 --- a/tests/test_cmake_build/installed_embed/CMakeLists.txt +++ b/tests/test_cmake_build/installed_embed/CMakeLists.txt @@ -1,13 +1,4 @@ -cmake_minimum_required(VERSION 3.5) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) project(test_installed_embed CXX) diff --git a/tests/test_cmake_build/installed_function/CMakeLists.txt b/tests/test_cmake_build/installed_function/CMakeLists.txt index fa7795e1..2945b3d2 100644 --- a/tests/test_cmake_build/installed_function/CMakeLists.txt +++ b/tests/test_cmake_build/installed_function/CMakeLists.txt @@ -1,14 +1,4 @@ -cmake_minimum_required(VERSION 3.5) -project(test_installed_module CXX) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) project(test_installed_function CXX) diff --git a/tests/test_cmake_build/installed_target/CMakeLists.txt b/tests/test_cmake_build/installed_target/CMakeLists.txt index 7e73f424..344c8bc6 100644 --- a/tests/test_cmake_build/installed_target/CMakeLists.txt +++ b/tests/test_cmake_build/installed_target/CMakeLists.txt @@ -1,13 +1,4 @@ -cmake_minimum_required(VERSION 3.5) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) project(test_installed_target CXX) diff --git a/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt b/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt index 33a36647..d0ae0798 100644 --- a/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt +++ b/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt @@ -1,13 +1,4 @@ -cmake_minimum_required(VERSION 3.5) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) project(test_subdirectory_embed CXX) diff --git a/tests/test_cmake_build/subdirectory_function/CMakeLists.txt b/tests/test_cmake_build/subdirectory_function/CMakeLists.txt index 76418a71..a521f33d 100644 --- a/tests/test_cmake_build/subdirectory_function/CMakeLists.txt +++ b/tests/test_cmake_build/subdirectory_function/CMakeLists.txt @@ -1,13 +1,4 @@ -cmake_minimum_required(VERSION 3.5) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) project(test_subdirectory_function CXX) diff --git a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt index 28e90318..4a5a7f2b 100644 --- a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt +++ b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt @@ -1,13 +1,4 @@ -cmake_minimum_required(VERSION 3.5) - -# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with -# some versions of VS that have a patched CMake 3.11. This forces us to emulate -# the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.29) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -else() - cmake_policy(VERSION 3.29) -endif() +cmake_minimum_required(VERSION 3.15...3.30) project(test_subdirectory_target CXX) diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index c35f0d4c..6240524a 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -201,6 +201,23 @@ TEST_SUBMODULE(stl, m) { m.def("cast_array", []() { return std::array{{1, 2}}; }); m.def("load_array", [](const std::array &a) { return a[0] == 1 && a[1] == 2; }); + struct NoDefaultCtor { + explicit constexpr NoDefaultCtor(int val) : val{val} {} + int val; + }; + + struct NoDefaultCtorArray { + explicit constexpr NoDefaultCtorArray(int i) + : arr{{NoDefaultCtor(10 + i), NoDefaultCtor(20 + i)}} {} + std::array arr; + }; + + // test_array_no_default_ctor + py::class_(m, "NoDefaultCtor").def_readonly("val", &NoDefaultCtor::val); + py::class_(m, "NoDefaultCtorArray") + .def(py::init()) + .def_readwrite("arr", &NoDefaultCtorArray::arr); + // test_valarray m.def("cast_valarray", []() { return std::valarray{1, 4, 9}; }); m.def("load_valarray", [](const std::valarray &v) { diff --git a/tests/test_stl.py b/tests/test_stl.py index 1896c322..6f548789 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -48,6 +48,13 @@ def test_array(doc): ) +def test_array_no_default_ctor(): + lst = m.NoDefaultCtorArray(3) + assert [e.val for e in lst.arr] == [13, 23] + lst.arr = m.NoDefaultCtorArray(4).arr + assert [e.val for e in lst.arr] == [14, 24] + + def test_valarray(doc): """std::valarray <-> list""" lst = m.cast_valarray() diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake index 7d8d94b1..450a1415 100644 --- a/tools/pybind11Common.cmake +++ b/tools/pybind11Common.cmake @@ -18,11 +18,7 @@ Adds the following functions:: #]======================================================] -# CMake 3.10 has an include_guard command, but we can't use that yet -# include_guard(global) (pre-CMake 3.10) -if(TARGET pybind11::pybind11) - return() -endif() +include_guard(GLOBAL) # If we are in subdirectory mode, all IMPORTED targets must be GLOBAL. If we # are in CONFIG mode, they should be "normal" targets instead. @@ -80,48 +76,32 @@ set_property( # Please open an issue if you need to use it; it will be removed if no one # needs it. if(CMAKE_SYSTEM_NAME MATCHES Emscripten AND NOT _pybind11_no_exceptions) - if(CMAKE_VERSION VERSION_LESS 3.13) - message(WARNING "CMake 3.13+ is required to build for Emscripten. Some flags will be missing") + if(is_config) + set(_tmp_config_target pybind11::pybind11_headers) else() - if(is_config) - set(_tmp_config_target pybind11::pybind11_headers) - else() - set(_tmp_config_target pybind11_headers) - endif() - - set_property( - TARGET ${_tmp_config_target} - APPEND - PROPERTY INTERFACE_LINK_OPTIONS -fexceptions) - set_property( - TARGET ${_tmp_config_target} - APPEND - PROPERTY INTERFACE_COMPILE_OPTIONS -fexceptions) - unset(_tmp_config_target) + set(_tmp_config_target pybind11_headers) endif() -endif() - -# --------------------------- link helper --------------------------- - -add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global}) -if(CMAKE_VERSION VERSION_LESS 3.13) - # In CMake 3.11+, you can set INTERFACE properties via the normal methods, and - # this would be simpler. set_property( - TARGET pybind11::python_link_helper + TARGET ${_tmp_config_target} APPEND - PROPERTY INTERFACE_LINK_LIBRARIES "$<$:-undefined dynamic_lookup>") -else() - # link_options was added in 3.13+ - # This is safer, because you are ensured the deduplication pass in CMake will not consider - # these separate and remove one but not the other. + PROPERTY INTERFACE_LINK_OPTIONS -fexceptions) set_property( - TARGET pybind11::python_link_helper + TARGET ${_tmp_config_target} APPEND - PROPERTY INTERFACE_LINK_OPTIONS "$<$:LINKER:-undefined,dynamic_lookup>") + PROPERTY INTERFACE_COMPILE_OPTIONS -fexceptions) + unset(_tmp_config_target) endif() +# --------------------------- link helper --------------------------- + +add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global}) + +set_property( + TARGET pybind11::python_link_helper + APPEND + PROPERTY INTERFACE_LINK_OPTIONS "$<$:LINKER:-undefined,dynamic_lookup>") + # ------------------------ Windows extras ------------------------- add_library(pybind11::windows_extras IMPORTED INTERFACE ${optional_global}) @@ -136,22 +116,14 @@ if(MSVC) # That's also clang-cl # /MP enables multithreaded builds (relevant when there are many files) for MSVC if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # no Clang no Intel - if(CMAKE_VERSION VERSION_LESS 3.11) - set_property( - TARGET pybind11::windows_extras - APPEND - PROPERTY INTERFACE_COMPILE_OPTIONS $<$>:/MP>) - else() - # Only set these options for C++ files. This is important so that, for - # instance, projects that include other types of source files like CUDA - # .cu files don't get these options propagated to nvcc since that would - # cause the build to fail. - set_property( - TARGET pybind11::windows_extras - APPEND - PROPERTY INTERFACE_COMPILE_OPTIONS - $<$>:$<$:/MP>>) - endif() + # Only set these options for C++ files. This is important so that, for + # instance, projects that include other types of source files like CUDA + # .cu files don't get these options propagated to nvcc since that would + # cause the build to fail. + set_property( + TARGET pybind11::windows_extras + APPEND + PROPERTY INTERFACE_COMPILE_OPTIONS $<$>:$<$:/MP>>) endif() endif() @@ -397,11 +369,7 @@ function(_pybind11_generate_lto target prefer_thin_lto) set(is_debug "$,$>") set(not_debug "$") set(cxx_lang "$") - if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11) - set(genex "${not_debug}") - else() - set(genex "$") - endif() + set(genex "$") set_property( TARGET ${target} APPEND @@ -416,17 +384,10 @@ function(_pybind11_generate_lto target prefer_thin_lto) endif() if(PYBIND11_LTO_LINKER_FLAGS) - if(CMAKE_VERSION VERSION_LESS 3.11) - set_property( - TARGET ${target} - APPEND - PROPERTY INTERFACE_LINK_LIBRARIES "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") - else() - set_property( - TARGET ${target} - APPEND - PROPERTY INTERFACE_LINK_OPTIONS "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") - endif() + set_property( + TARGET ${target} + APPEND + PROPERTY INTERFACE_LINK_OPTIONS "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") endif() endfunction() diff --git a/tools/pybind11GuessPythonExtSuffix.cmake b/tools/pybind11GuessPythonExtSuffix.cmake index c5fb3b42..b550f393 100644 --- a/tools/pybind11GuessPythonExtSuffix.cmake +++ b/tools/pybind11GuessPythonExtSuffix.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.15...3.30) function(pybind11_guess_python_module_extension python) diff --git a/tools/pybind11NewTools.cmake b/tools/pybind11NewTools.cmake index 444f3aaf..d3e938fa 100644 --- a/tools/pybind11NewTools.cmake +++ b/tools/pybind11NewTools.cmake @@ -5,10 +5,6 @@ # All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. -if(CMAKE_VERSION VERSION_LESS 3.12) - message(FATAL_ERROR "You cannot use the new FindPython module with CMake < 3.12") -endif() - include_guard(DIRECTORY) get_property( @@ -236,7 +232,6 @@ if(TARGET ${_Python}::Python) PROPERTY INTERFACE_LINK_LIBRARIES ${_Python}::Python) endif() -# CMake 3.15+ has this if(TARGET ${_Python}::Module) set_property( TARGET pybind11::module diff --git a/tools/pybind11Tools.cmake b/tools/pybind11Tools.cmake index 021038d9..d91e7670 100644 --- a/tools/pybind11Tools.cmake +++ b/tools/pybind11Tools.cmake @@ -5,13 +5,7 @@ # 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(global) (pre-CMake 3.10) -if(TARGET pybind11::python_headers) - return() -endif() - -# Built-in in CMake 3.5+ -include(CMakeParseArguments) +include_guard(GLOBAL) if(pybind11_FIND_QUIETLY) set(_pybind11_quiet QUIET) @@ -116,36 +110,19 @@ if(PYTHON_IS_DEBUG) PROPERTY INTERFACE_COMPILE_DEFINITIONS Py_DEBUG) endif() -# The <3.11 code here does not support release/debug builds at the same time, like on vcpkg -if(CMAKE_VERSION VERSION_LESS 3.11) - set_property( - TARGET pybind11::module - APPEND - PROPERTY - INTERFACE_LINK_LIBRARIES - pybind11::python_link_helper - "$<$,$>:$>" - ) - - set_property( - TARGET pybind11::embed - APPEND - PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11 $) -else() - # 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 - "$<$,$>:pybind11::_ClassicPythonLibraries>") - - target_link_libraries(pybind11::embed INTERFACE pybind11::pybind11 - pybind11::_ClassicPythonLibraries) -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 + "$<$,$>: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 diff --git a/tools/test-pybind11GuessPythonExtSuffix.cmake b/tools/test-pybind11GuessPythonExtSuffix.cmake index 0de2c016..ac90e039 100644 --- a/tools/test-pybind11GuessPythonExtSuffix.cmake +++ b/tools/test-pybind11GuessPythonExtSuffix.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.15...3.30) # Tests for pybind11_guess_python_module_extension # Run using `cmake -P tools/test-pybind11GuessPythonExtSuffix.cmake`