feat: new FindPython support (#2370)
* feat: FindPython support
* refactor: rename to PYBIND11_FINDPYTHON
* docs: Caps fixes
* feat: NOPYTHON mode
* test: check simple call
* docs: add changelog/upgrade guide
* feat: Support Python3 and Python2
* refactor: Use targets in tests
* fix: support CMake 3.4+
* feat: classic search also finds virtual environments
* docs: some updates from @wjakob's review
* fix: wrong name for QUIET mode variable, reported by @skoslowski
* refactor: cleaner output messaging
* fix: support debug Python's in FindPython mode too
* fixup! refactor: cleaner output messaging
* fix: missing pybind11_FOUND and pybind11_INCLUDE_DIR restored to subdir mode
* fix: nicer reporting of Python / PyPy
* fix: out-of-order variable fix
* docs: minor last-minute cleanup
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3082963..4f9ebac 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,11 +31,13 @@
arch: x64
max-cxx-std: 17
dev: false
+ args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: macos-latest
python: 3.7
arch: x64
max-cxx-std: 17
dev: false
+ args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: windows-2016
python: 3.7
arch: x86
@@ -46,6 +48,7 @@
arch: x64
max-cxx-std: 17
dev: false
+ args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: windows-latest
python: 3.7
arch: x64
@@ -89,7 +92,7 @@
dev: false
- name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • ${{ matrix.arch }}"
+ name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • ${{ matrix.arch }} ${{ matrix.args }}"
runs-on: ${{ matrix.runs-on }}
continue-on-error: ${{ matrix.dev }}
@@ -106,6 +109,9 @@
if: runner.os != 'macOS'
run: echo "::set-env name=BOOST_ROOT::$BOOST_ROOT_1_72_0"
+ - name: Update CMake
+ uses: jwlawson/actions-setup-cmake@v1.3
+
- name: Cache wheels
if: runner.os == 'macOS'
uses: actions/cache@v2
@@ -120,7 +126,7 @@
- name: Prepare env
run: python -m pip install -r tests/requirements.txt
- - name: Configure C++11
+ - name: Configure C++11 ${{ matrix.args }}
shell: bash
run: >
cmake -S . -B build
@@ -128,7 +134,7 @@
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
-DCMAKE_CXX_STANDARD=11
- -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)")
+ ${{ matrix.args }}
- name: Build C++11
run: cmake --build build -j 2
@@ -140,9 +146,9 @@
run: cmake --build build --target cpptest -j 2
- name: Interface test C++11
- run: cmake --build build --target test_cmake_build
+ run: cmake --build build --target test_cmake_build -v
- - name: Configure C++${{ matrix.max-cxx-std }}
+ - name: Configure C++${{ matrix.max-cxx-std }} ${{ matrix.args }}
shell: bash
run: >
cmake -S . -B build2
@@ -150,7 +156,7 @@
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
-DCMAKE_CXX_STANDARD=${{ matrix.max-cxx-std }}
- -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)")
+ ${{ matrix.args }}
- name: Build C++${{ matrix.max-cxx-std }}
run: cmake --build build2 -j 2
@@ -350,14 +356,14 @@
steps:
- uses: actions/checkout@v2
- - name: Install requirements
+ - name: Install system requirements
run: apk add doxygen python3-dev
- name: Ensure pip
run: python3 -m ensurepip
- - name: Install python docs requirements
- run: python3 -m pip install "sphinx<3" sphinx_rtd_theme breathe==4.13.1 pytest setuptools
+ - name: Install docs & setup requirements
+ run: python3 -m pip install -r docs/requirements.txt pytest setuptools
- name: Build docs
run: python3 -m sphinx -W -b html docs docs/.build
diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml
index 934b2d7..d472f4b 100644
--- a/.github/workflows/configure.yml
+++ b/.github/workflows/configure.yml
@@ -14,19 +14,22 @@
strategy:
fail-fast: false
matrix:
- runs-on: [ubuntu-latest, macos-latest]
+ runs-on: [ubuntu-latest, macos-latest, windows-latest]
arch: [x64]
- cmake: [3.7, 3.18]
+ cmake: [3.18]
include:
- - runs-on: windows-latest
+ - runs-on: ubuntu-latest
arch: x64
- cmake: 3.18
+ cmake: 3.4
- # TODO: 3.8
+ - runs-on: macos-latest
+ arch: x64
+ cmake: 3.7
+
- runs-on: windows-2016
arch: x86
- cmake: 3.11
+ cmake: 3.8
- runs-on: windows-2016
arch: x86
@@ -63,3 +66,13 @@
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)")
+
+ - name: Build
+ working-directory: build dir
+ if: github.event_name == 'workflow_dispatch'
+ run: cmake --build . --config Release
+
+ - name: Test
+ working-directory: build dir
+ if: github.event_name == 'workflow_dispatch'
+ run: cmake --build . --config Release --target check
diff --git a/.gitignore b/.gitignore
index 54a1f92..6d65838 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,7 +32,7 @@
.*.swp
.DS_Store
/dist
-/build
+/build*
.cache/
sosize-*.txt
pybind11Config*.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f38a8f8..4279752 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,9 +5,9 @@
# 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.7)
+cmake_minimum_required(VERSION 3.4)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
@@ -41,11 +41,22 @@
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
-message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}")
+if(NOT pybind11_FIND_QUIETLY)
+ message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}")
+endif()
# Check if pybind11 is being used directly or via add_subdirectory
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_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)
@@ -60,13 +71,16 @@
# Options
option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
-option(PYBIND11_CLASSIC_LTO "Use the classic LTO flag algorithm, even on CMake 3.9+" OFF)
+option(PYBIND11_NOPYTHON "Disable search for Python" OFF)
cmake_dependent_option(
USE_PYTHON_INCLUDE_DIR
"Install pybind11 headers in Python include directory instead of default installation prefix"
OFF "PYBIND11_INSTALL" OFF)
+cmake_dependent_option(PYBIND11_FINDPYTHON "Force new FindPython" OFF
+ "NOT CMAKE_VERSION VERSION_LESS 3.12" OFF)
+
# NB: when adding a header don't forget to also add it to setup.py
set(PYBIND11_HEADERS
include/pybind11/detail/class.h
@@ -118,101 +132,41 @@
string(REPLACE "include/" "${CMAKE_CURRENT_SOURCE_DIR}/include/" PYBIND11_HEADERS
"${PYBIND11_HEADERS}")
-# Classic mode
-
-include("${CMAKE_CURRENT_LIST_DIR}/tools/pybind11Tools.cmake")
-
# Cache variables so pybind11_add_module can be used in parent projects
set(PYBIND11_INCLUDE_DIR
"${CMAKE_CURRENT_LIST_DIR}/include"
CACHE INTERNAL "")
-set(PYTHON_INCLUDE_DIRS
- ${PYTHON_INCLUDE_DIRS}
- CACHE INTERNAL "")
-set(PYTHON_LIBRARIES
- ${PYTHON_LIBRARIES}
- CACHE INTERNAL "")
-set(PYTHON_MODULE_PREFIX
- ${PYTHON_MODULE_PREFIX}
- CACHE INTERNAL "")
-set(PYTHON_MODULE_EXTENSION
- ${PYTHON_MODULE_EXTENSION}
- CACHE INTERNAL "")
-set(PYTHON_VERSION_MAJOR
- ${PYTHON_VERSION_MAJOR}
- CACHE INTERNAL "")
-set(PYTHON_VERSION_MINOR
- ${PYTHON_VERSION_MINOR}
- CACHE INTERNAL "")
-set(PYTHON_IS_DEBUG
- "${PYTHON_IS_DEBUG}"
- CACHE INTERNAL "")
-
-if(USE_PYTHON_INCLUDE_DIR)
- file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_INCLUDE_DIRS})
-endif()
# Note: when creating targets, you cannot use if statements at configure time -
# you need generator expressions, because those will be placed in the target file.
# You can also place ifs *in* the Config.in, but not here.
-# Build an interface library target:
-add_library(pybind11 INTERFACE)
-add_library(pybind11::pybind11 ALIAS pybind11) # to match exported target
+# This section builds targets, but does *not* touch Python
+# Build the headers-only target (no Python included):
+add_library(headers INTERFACE)
+add_library(pybind11::headers ALIAS headers) # to match exported target
+
+include("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11Common.cmake")
+
+if(NOT PYBIND11_MASTER_PROJECT AND NOT pybind11_FIND_QUIETLY)
+ message(STATUS "Using pybind11: (version \"${pybind11_VERSION}\" ${pybind11_VERSION_TYPE})")
+endif()
+
+# Relative directory setting
+if(USE_PYTHON_INCLUDE_DIR AND DEFINED Python_INCLUDE_DIRS)
+ file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${Python_INCLUDE_DIRS})
+elseif(USE_PYTHON_INCLUDE_DIR AND DEFINED PYTHON_INCLUDE_DIR)
+ file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_INCLUDE_DIRS})
+endif()
+
+# Fill in headers target
target_include_directories(
- pybind11 ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
-# Only add Python for build - must be added during the import for config since it has to be re-discovered.
-target_include_directories(pybind11 SYSTEM INTERFACE $<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>)
+ headers ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
-if(CMAKE_VERSION VERSION_LESS 3.13)
- target_compile_features(pybind11 INTERFACE cxx_inheriting_constructors cxx_user_literals
- cxx_right_angle_brackets)
-else()
- # This was added in CMake 3.8, but we are keeping a consistent breaking
- # point for the config file at 3.13. A config generated by CMake 3.13+
- # can only be read in 3.13+ due to the SHELL usage later, so this is safe to do.
- target_compile_features(pybind11 INTERFACE cxx_std_11)
-endif()
-
-add_library(module INTERFACE)
-add_library(pybind11::module ALIAS module)
-
-target_link_libraries(module INTERFACE pybind11::pybind11)
-
-# See https://github.com/Kitware/CMake/blob/master/Modules/CMakePlatformId.h.in for platform IDs
-# Note: CMake 3.15 allows $<PLATFORM_ID:Windows,Cygwin>
-target_link_libraries(
- module
- INTERFACE
- "$<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Cygwin>>:$<BUILD_INTERFACE:${PYTHON_LIBRARIES}>>")
-
-if(CMAKE_VERSION VERSION_LESS 3.13)
- target_link_libraries(module INTERFACE "$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>")
-else()
- # SHELL (3.12+) forces this to remain together, and 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.
- target_link_options(module INTERFACE "$<$<PLATFORM_ID:Darwin>:SHELL:-undefined dynamic_lookup>")
-endif()
-
-# Workaround for Python 2.7 and C++17 (C++14 as a warning) incompatibility
-# This adds the flags -Wno-register and -Wno-deprecated-register if the compiler
-# is Clang 3.9+ or AppleClang and the compile language is CXX, or /wd5033 for MSVC (all languages,
-# since MSVC didn't recognize COMPILE_LANGUAGE until CMake 3.11+).
-set(clang_4plus
- "$<AND:$<CXX_COMPILER_ID:Clang>,$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,3.9>>>")
-set(no_register "$<OR:${clang_4plus},$<CXX_COMPILER_ID:AppleClang>>")
-set(cxx_no_register "$<AND:$<COMPILE_LANGUAGE:CXX>,${no_register}>")
-set(msvc "$<CXX_COMPILER_ID:MSVC>")
-target_compile_options(
- pybind11 INTERFACE "$<${cxx_no_register}:-Wno-register;-Wno-deprecated-register>"
- "$<${msvc}:/wd5033>")
-
-add_library(embed INTERFACE)
-add_library(pybind11::embed ALIAS embed)
-target_link_libraries(embed INTERFACE pybind11::pybind11 $<BUILD_INTERFACE:${PYTHON_LIBRARIES}>)
+target_compile_features(headers INTERFACE cxx_inheriting_constructors cxx_user_literals
+ cxx_right_angle_brackets)
if(PYBIND11_INSTALL)
install(DIRECTORY ${PYBIND11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
@@ -248,14 +202,17 @@
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
- tools/FindPythonLibsNew.cmake tools/pybind11Tools.cmake
+ tools/FindPythonLibsNew.cmake
+ tools/pybind11Common.cmake
+ tools/pybind11Tools.cmake
+ tools/pybind11NewTools.cmake
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
if(NOT PYBIND11_EXPORT_NAME)
set(PYBIND11_EXPORT_NAME "${PROJECT_NAME}Targets")
endif()
- install(TARGETS pybind11 module embed EXPORT "${PYBIND11_EXPORT_NAME}")
+ install(TARGETS headers EXPORT "${PYBIND11_EXPORT_NAME}")
install(
EXPORT "${PYBIND11_EXPORT_NAME}"
@@ -275,10 +232,28 @@
# BUILD_TESTING takes priority, but only if this is the master project
if(PYBIND11_MASTER_PROJECT AND DEFINED BUILD_TESTING)
if(BUILD_TESTING)
- add_subdirectory(tests)
+ if(_pybind11_nopython)
+ message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
+ else()
+ add_subdirectory(tests)
+ endif()
endif()
else()
if(PYBIND11_TEST)
- add_subdirectory(tests)
+ if(_pybind11_nopython)
+ message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
+ else()
+ add_subdirectory(tests)
+ endif()
endif()
endif()
+
+# Better symmetry with find_package(pybind11 CONFIG) mode.
+if(NOT PYBIND11_MASTER_PROJECT)
+ set(pybind11_FOUND
+ TRUE
+ CACHE INTERNAL "true if pybind11 and all required components found on the system")
+ set(pybind11_INCLUDE_DIR
+ "${PYBIND11_INCLUDE_DIR}"
+ CACHE INTERNAL "Directory where pybind11 headers are located")
+endif()
diff --git a/docs/advanced/embedding.rst b/docs/advanced/embedding.rst
index 3930316..98a5c52 100644
--- a/docs/advanced/embedding.rst
+++ b/docs/advanced/embedding.rst
@@ -18,7 +18,7 @@
.. code-block:: cmake
- cmake_minimum_required(VERSION 3.0)
+ cmake_minimum_required(VERSION 3.4)
project(example)
find_package(pybind11 REQUIRED) # or `add_subdirectory(pybind11)`
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 2def2b0..fbb3667 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -6,6 +6,39 @@
Starting with version 1.8.0, pybind11 releases use a `semantic versioning
<http://semver.org>`_ policy.
+v2.6.0 (IN PROGRESS)
+--------------------
+
+See :ref:`upgrade-guide-2.6` for help upgrading to the new version.
+
+* Minimum CMake required increased to 3.4.
+ `#2338 <https://github.com/pybind/pybind11/pull/2338>`_ and
+ `#2370 <https://github.com/pybind/pybind11/pull/2370>`_
+
+ * Full integration with CMake’s C++ standard system replaces
+ ``PYBIND11_CPP_STANDARD``.
+
+ * Generated config file is now portable to different Python/compiler/CMake
+ versions.
+
+ * Virtual environments prioritized if ``PYTHON_EXECUTABLE`` is not set
+ (``venv``, ``virtualenv``, and ``conda``) (similar to the new FindPython
+ mode).
+
+ * Other CMake features now natively supported, like
+ ``CMAKE_INTERPROCEDURAL_OPTIMIZATION``, ``set(CMAKE_CXX_VISIBILITY_PRESET
+ hidden)``.
+
+* Optional :ref:`find-python-mode` and :ref:`nopython-mode` with CMake.
+ `#2370 <https://github.com/pybind/pybind11/pull/2370>`_
+
+* Uninstall target added.
+ `#2265 <https://github.com/pybind/pybind11/pull/2265>`_ and
+ `#2346 <https://github.com/pybind/pybind11/pull/2346>`_
+
+
+
+
v2.5.0 (Mar 31, 2020)
-----------------------------------------------------
diff --git a/docs/compiling.rst b/docs/compiling.rst
index 3935dda..72b0c1e 100644
--- a/docs/compiling.rst
+++ b/docs/compiling.rst
@@ -33,8 +33,8 @@
.. code-block:: cmake
- cmake_minimum_required(VERSION 3.7)
- project(example)
+ cmake_minimum_required(VERSION 3.4...3.18)
+ project(example LANGUAGES CXX)
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
@@ -50,6 +50,9 @@
.. [cmake_example] https://github.com/pybind/cmake_example
+.. versionchanged:: 2.6
+ CMake 3.4+ is required.
+
pybind11_add_module
-------------------
@@ -89,7 +92,9 @@
As stated above, LTO is enabled by default. Some newer compilers also support
different flavors of LTO such as `ThinLTO`_. Setting ``THIN_LTO`` will cause
the function to prefer this flavor if available. The function falls back to
-regular LTO if ``-flto=thin`` is not available.
+regular LTO if ``-flto=thin`` is not available. If
+``CMAKE_INTERPROCEDURAL_OPTIMIZATION`` is set (either ON or OFF), then that
+will be respected instead of the built-in flag search.
.. _ThinLTO: http://clang.llvm.org/docs/ThinLTO.html
@@ -113,9 +118,9 @@
on a target or use ``target_compile_features`` on your targets - anything that
CMake supports.
-The target Python version can be selected by setting ``PYBIND11_PYTHON_VERSION``
-or an exact Python installation can be specified with ``PYTHON_EXECUTABLE``.
-For example:
+Classic Python support: The target Python version can be selected by setting
+``PYBIND11_PYTHON_VERSION`` or an exact Python installation can be specified
+with ``PYTHON_EXECUTABLE``. For example:
.. code-block:: bash
@@ -127,6 +132,7 @@
# This often is a good way to get the current Python, works in environments:
cmake -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") ..
+
find_package vs. add_subdirectory
---------------------------------
@@ -136,8 +142,8 @@
.. code-block:: cmake
- cmake_minimum_required(VERSION 3.7)
- project(example)
+ cmake_minimum_required(VERSION 3.4...3.18)
+ project(example LANGUAGES CXX)
find_package(pybind11 REQUIRED)
pybind11_add_module(example example.cpp)
@@ -169,52 +175,131 @@
.. _Config file: https://github.com/pybind/pybind11/blob/master/tools/pybind11Config.cmake.in
-Advanced: interface library target
-----------------------------------
-When using a version of CMake greater than 3.0, pybind11 can additionally
-be used as a special *interface library* . The target ``pybind11::module``
-is available with pybind11 headers, Python headers and libraries as needed,
-and C++ compile features attached. This target is suitable for linking
-to an independently constructed (through ``add_library``, not
-``pybind11_add_module``) target in the consuming project.
+.. _find-python-mode:
+
+FindPython mode
+---------------
+
+CMake 3.12+ (3.15+ recommended) 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.7)
- project(example)
+ cmake_minumum_required(VERSION 3.15...3.18)
+ project(example LANGUAGES CXX)
+
+ find_package(Python COMPONENTS Interpreter Development REQUIRED)
+ find_package(pybind11 CONFIG REQUIRED)
+ # or add_subdirectory(pybind11)
+
+ pybind11_add_module(example example.cpp)
+
+You can also use the targets (as listed below) with FindPython. If you define
+``PYBIND11_FINDPYTHON``, pybind11 will perform the FindPython step for you
+(mostly useful when building pybind11's own tests, or as a way to change search
+algorithms from the CMake invocation, with ``-DPYBIND11_FINDPYTHON=ON``.
+
+.. warning::
+
+ If you use FindPython2 and FindPython3 to dual-target Python, use the
+ individual targets listed below, and avoid targets that directly include
+ Python parts.
+
+There are `many ways to hint or force a discovery of a specific Python
+installation <https://cmake.org/cmake/help/latest/module/FindPython.html>`_),
+setting ``Python_ROOT_DIR`` may be the most common one (though with
+virtualenv/venv support, and Conda support, this tends to find the correct
+Python version more often than the old system did).
+
+.. versionadded:: 2.6
+
+Advanced: interface library targets
+-----------------------------------
+
+Pybind11 supports modern CMake usage patterns with a set of interface targets,
+available in all modes. The targets provided are:
+
+ ``pybind11::headers``
+ Just the pybind11 headers and minimum compile requirements
+
+ ``pybind11::python2_no_register``
+ Quiets the warning/error when mixing C++14 or higher and Python 2
+
+ ``pybind11::pybind11``
+ Python headers + ``pybind11::headers`` + ``pybind11::python2_no_register`` (Python 2 only)
+
+ ``pybind11::python_link_helper``
+ 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``
+
+ ``pybind11::embed``
+ Everything for embedding the Python interpreter - ``pybind11::pybind11`` + ``Python::Embed`` (FindPython) or Python libs
+
+ ``pybind11::lto`` / ``pybind11::thin_lto``
+ An alternative to `INTERPROCEDURAL_OPTIMIZATION` for adding link-time optimization.
+
+ ``pybind11::windows_extras``
+ ``/bigobj`` and ``/mp`` for MSVC.
+
+Two helper functions are also provided:
+
+ ``pybind11_strip(target)``
+ Strips a target (uses ``CMAKE_STRIP`` after the target is built)
+
+ ``pybind11_extension(target)``
+ Sets the correct extension (with SOABI) for a target.
+
+You can use these targets to build complex applications. For example, the
+``add_python_module`` function is identical to:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.4)
+ project(example LANGUAGES CXX)
find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11)
add_library(example MODULE main.cpp)
- target_link_libraries(example PRIVATE pybind11::module)
- set_target_properties(example PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
- SUFFIX "${PYTHON_MODULE_EXTENSION}")
+
+ target_link_libraries(example PRIVATE pybind11::module pybind11::lto pybind11::windows_extras)
+
+ pybind11_extension(example)
+ pybind11_strip(example)
+
+ set_target_properties(example PROPERTIES CXX_VISIBILITY_PRESET "hidden"
+ CUDA_VISIBILITY_PRESET "hidden")
+
+Instead of setting properties, you can set ``CMAKE_*`` variables to initialize these correctly.
.. warning::
Since pybind11 is a metatemplate library, it is crucial that certain
compiler flags are provided to ensure high quality code generation. In
contrast to the ``pybind11_add_module()`` command, the CMake interface
- library only provides the *minimal* set of parameters to ensure that the
- code using pybind11 compiles, but it does **not** pass these extra compiler
- flags (i.e. this is up to you).
+ provides a *composable* set of targets to ensure that you retain flexibility.
+ It can be expecially important to provide or set these properties; the
+ :ref:`FAQ <faq:symhidden>` contains an explanation on why these are needed.
- These include Link Time Optimization (``-flto`` on GCC/Clang/ICPC, ``/GL``
- and ``/LTCG`` on Visual Studio) and .OBJ files with many sections on Visual
- Studio (``/bigobj``). The :ref:`FAQ <faq:symhidden>` contains an
- explanation on why these are needed.
+.. versionadded:: 2.6
- If you want to add these in yourself, you can use:
+.. _nopython-mode:
- .. code-block:: cmake
+Advanced: NOPYTHON mode
+-----------------------
- set(CMAKE_CXX_VISIBILITY_PRESET hidden)
- set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
- set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # CMake 3.9+ required
+If you want complete control, you can set ``PYBIND11_NOPYTHON`` to completely
+disable Python integration (this also happens if you run ``FindPython2`` and
+``FindPython3`` without running ``FindPython``). This gives you complete
+freedom to integrate into an existing system (like `Scikit-Build's
+<https://scikit-build.readthedocs.io>`_ ``PythonExtensions``).
+``pybind11_add_module`` and ``pybind11_extension`` will be unavailable, and the
+targets will be missing any Python specific behavior.
- or set the corresponding property (without the ``CMAKE_``) on the targets
- manually.
+.. versionadded:: 2.6
Embedding the Python interpreter
--------------------------------
@@ -228,8 +313,8 @@
.. code-block:: cmake
- cmake_minimum_required(VERSION 3.7)
- project(example)
+ cmake_minimum_required(VERSION 3.4...3.18)
+ project(example LANGUAGES CXX)
find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11)
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 3818fe8..2eb7f20 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1 +1,3 @@
-breathe == 4.5.0
+breathe==4.13.1
+sphinx<3
+sphinx_rtd_theme
diff --git a/docs/upgrade.rst b/docs/upgrade.rst
index 3f56973..98285eb 100644
--- a/docs/upgrade.rst
+++ b/docs/upgrade.rst
@@ -8,6 +8,53 @@
deprecated APIs and their replacements, build system changes, general code
modernization and other useful information.
+.. _upgrade-guide-2.6:
+
+v2.6
+====
+
+CMake support:
+--------------
+
+The minimum required version of CMake is now 3.4. Several details of the CMake
+support have been deprecated; warnings will be shown if you need to change
+something. The changes are:
+
+* ``PYBIND11_CPP_STANDARD=<platform-flag>`` is deprecated, please use
+ ``CMAKE_CXX_STANDARD=<number>`` instead, or any other valid CMake CXX or CUDA
+ standard selection method, like ``target_compile_features``.
+
+* If you do not request a standard, PyBind11 targets will compile with the
+ compiler default, but not less than C++11, instead of forcing C++14 always.
+ If you depend on the old behavior, please use ``set(CMAKE_CXX_STANDARD 14)``
+ instead.
+
+* Direct ``pybind11::module`` usage should always be accompanied by at least
+ ``set(CMAKE_CXX_VISIBILITY_PRESET hidden)`` or similar - it used to try to
+ manually force this compiler flag (but not correctly on all compilers or with
+ CUDA).
+
+* ``pybind11_add_module``'s ``SYSTEM`` argument is deprecated and does nothing;
+ linking now behaves like other imported libraries consistently in both
+ config and submodule mode, and behaves like a ``SYSTEM`` library by
+ default.
+
+* If ``PYTHON_EXECUTABLE`` is not set, virtual environments (``venv``,
+ ``virtualenv``, and ``conda``) are prioritized over the standard search
+ (similar to the new FindPython mode).
+
+In addition, the following changes may be of interest:
+
+* ``CMAKE_INTERPROCEDURAL_OPTIMIZATION`` will be respected by
+ ``pybind11_add_module`` if set instead of linking to ``pybind11::lto`` or
+ ``pybind11::thin_lto``.
+
+* Using ``find_package(Python COMPONENTS Interpreter Development)`` before
+ pybind11 will cause pybind11 to use the new Python mechanisms instead of its
+ own custom search, based on a patched version of classic
+ FindPythonInterp/FindPythonLibs. In the future, this may become the default.
+
+
v2.2
====
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 9a97ec5..895cfe7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -5,9 +5,9 @@
# 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.7)
+cmake_minimum_required(VERSION 3.4)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
@@ -16,6 +16,12 @@
cmake_policy(VERSION 3.18)
endif()
+# New Python support
+if(DEFINED Python_EXECUTABLE)
+ set(PYTHON_EXECUTABLE "${Python_EXECUTABLE}")
+ set(PYTHON_VERSION "${Python_VERSION}")
+endif()
+
# There's no harm in including a project in a project
project(pybind11_tests CXX)
@@ -137,13 +143,9 @@
set(EIGEN3_INCLUDE_DIR ${eigen_SOURCE_DIR})
set(EIGEN3_FOUND TRUE)
+
else()
find_package(Eigen3 3.2.7 QUIET CONFIG)
- if(EIGEN3_FOUND)
- if(EIGEN3_VERSION_STRING AND NOT EIGEN3_VERSION_STRING VERSION_LESS 3.3.1)
- set(PYBIND11_EIGEN_VIA_TARGET TRUE)
- endif()
- endif()
if(NOT EIGEN3_FOUND)
# Couldn't load via target, so fall back to allowing module mode finding, which will pick up
@@ -153,6 +155,12 @@
endif()
if(EIGEN3_FOUND)
+ if(NOT TARGET Eigen3::Eigen)
+ add_library(Eigen3::Eigen IMPORTED INTERFACE)
+ set_property(TARGET Eigen3::Eigen PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+ "${EIGEN3_INCLUDE_DIR}")
+ endif()
+
# Eigen 3.3.1+ cmake sets EIGEN3_VERSION_STRING (and hard codes the version when installed
# rather than looking it up in the cmake script); older versions, and the
# tools/FindEigen3.cmake, set EIGEN3_VERSION instead.
@@ -169,6 +177,20 @@
# Optional dependency for some tests (boost::variant is only supported with version >= 1.56)
find_package(Boost 1.56)
+if(Boost_FOUND)
+ if(NOT TARGET Boost::headers)
+ if(TARGET Boost::boost)
+ # Classic FindBoost
+ add_library(Boost::headers ALIAS Boost::boost)
+ else()
+ # Very old FindBoost, or newer Boost than CMake in older CMakes
+ add_library(Boost::headers IMPORTED INTERFACE)
+ set_property(TARGET Boost::headers PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+ ${Boost_INCLUDE_DIRS})
+ endif()
+ endif()
+endif()
+
# Compile with compiler warnings turned on
function(pybind11_enable_warnings target_name)
if(MSVC)
@@ -233,16 +255,12 @@
endif()
if(EIGEN3_FOUND)
- if(PYBIND11_EIGEN_VIA_TARGET)
- target_link_libraries(${target} PRIVATE Eigen3::Eigen)
- else()
- target_include_directories(${target} SYSTEM PRIVATE ${EIGEN3_INCLUDE_DIR})
- endif()
+ target_link_libraries(${target} PRIVATE Eigen3::Eigen)
target_compile_definitions(${target} PRIVATE -DPYBIND11_TEST_EIGEN)
endif()
if(Boost_FOUND)
- target_include_directories(${target} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
+ target_link_libraries(${target} PRIVATE Boost::headers)
target_compile_definitions(${target} PRIVATE -DPYBIND11_TEST_BOOST)
endif()
diff --git a/tests/test_cmake_build/CMakeLists.txt b/tests/test_cmake_build/CMakeLists.txt
index 0be071f..0c0578a 100644
--- a/tests/test_cmake_build/CMakeLists.txt
+++ b/tests/test_cmake_build/CMakeLists.txt
@@ -1,12 +1,24 @@
+# Built-in in CMake 3.5+
+include(CMakeParseArguments)
+
add_custom_target(test_cmake_build)
function(pybind11_add_build_test name)
- cmake_parse_arguments(PARSE_ARGV 1 ARG "INSTALL" "" "")
+ cmake_parse_arguments(ARG "INSTALL" "" "" ${ARGN})
- set(build_options
- "-DCMAKE_PREFIX_PATH=${pybind11_BINARY_DIR}/mock_install"
- "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
- "-DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}")
+ set(build_options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
+
+ if(PYBIND11_FINDPYTHON)
+ list(APPEND build_options "-DPYBIND11_FINDPYTHON=${PYBIND11_FINDPYTHON}")
+
+ if(DEFINED Python_ROOT_DIR)
+ list(APPEND build_options "-DPython_ROOT_DIR=${Python_ROOT_DIR}")
+ endif()
+
+ list(APPEND build_options "-DPython_EXECUTABLE=${Python_EXECUTABLE}")
+ else()
+ list(APPEND build_options "-DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}")
+ endif()
if(DEFINED CMAKE_CXX_STANDARD)
list(APPEND build_options "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")
@@ -45,7 +57,9 @@
pybind11_add_build_test(subdirectory_function)
pybind11_add_build_test(subdirectory_target)
-if(NOT ${PYTHON_MODULE_EXTENSION} MATCHES "pypy")
+if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy")
+ message(STATUS "Skipping embed test on PyPy")
+else()
pybind11_add_build_test(subdirectory_embed)
endif()
@@ -56,7 +70,8 @@
pybind11_add_build_test(installed_function INSTALL)
pybind11_add_build_test(installed_target INSTALL)
- if(NOT ${PYTHON_MODULE_EXTENSION} MATCHES "pypy")
+ if(NOT ("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
+ ))
pybind11_add_build_test(installed_embed INSTALL)
endif()
endif()
diff --git a/tests/test_cmake_build/installed_embed/CMakeLists.txt b/tests/test_cmake_build/installed_embed/CMakeLists.txt
index 6b773c7..64ae5c4 100644
--- a/tests/test_cmake_build/installed_embed/CMakeLists.txt
+++ b/tests/test_cmake_build/installed_embed/CMakeLists.txt
@@ -1,6 +1,6 @@
-cmake_minimum_required(VERSION 3.7)
+cmake_minimum_required(VERSION 3.4)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
diff --git a/tests/test_cmake_build/installed_function/CMakeLists.txt b/tests/test_cmake_build/installed_function/CMakeLists.txt
index db8213c..1a50286 100644
--- a/tests/test_cmake_build/installed_function/CMakeLists.txt
+++ b/tests/test_cmake_build/installed_function/CMakeLists.txt
@@ -1,6 +1,7 @@
-cmake_minimum_required(VERSION 3.7)
+cmake_minimum_required(VERSION 3.4)
+project(test_installed_module CXX)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
@@ -18,12 +19,20 @@
pybind11_add_module(test_installed_function SHARED NO_EXTRAS ../main.cpp)
set_target_properties(test_installed_function PROPERTIES OUTPUT_NAME test_cmake_build)
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
+
add_custom_target(
check_installed_function
${CMAKE_COMMAND}
-E
env
PYTHONPATH=$<TARGET_FILE_DIR:test_installed_function>
- ${PYTHON_EXECUTABLE}
+ ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME})
diff --git a/tests/test_cmake_build/installed_target/CMakeLists.txt b/tests/test_cmake_build/installed_target/CMakeLists.txt
index 1a124b9..b38eb77 100644
--- a/tests/test_cmake_build/installed_target/CMakeLists.txt
+++ b/tests/test_cmake_build/installed_target/CMakeLists.txt
@@ -1,6 +1,6 @@
-cmake_minimum_required(VERSION 3.7)
+cmake_minimum_required(VERSION 3.4)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
@@ -19,20 +19,27 @@
target_link_libraries(test_installed_target PRIVATE pybind11::module)
set_target_properties(test_installed_target PROPERTIES OUTPUT_NAME test_cmake_build)
-# make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
-set_target_properties(test_installed_target PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
- SUFFIX "${PYTHON_MODULE_EXTENSION}")
+# Make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
+pybind11_extension(test_installed_target)
# Do not treat includes from IMPORTED target as SYSTEM (Python headers in pybind11::module).
# This may be needed to resolve header conflicts, e.g. between Python release and debug headers.
set_target_properties(test_installed_target PROPERTIES NO_SYSTEM_FROM_IMPORTED ON)
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
+
add_custom_target(
check_installed_target
${CMAKE_COMMAND}
-E
env
PYTHONPATH=$<TARGET_FILE_DIR:test_installed_target>
- ${PYTHON_EXECUTABLE}
+ ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME})
diff --git a/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt b/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt
index 4571e87..c7df0cf 100644
--- a/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt
+++ b/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt
@@ -1,6 +1,6 @@
-cmake_minimum_required(VERSION 3.7)
+cmake_minimum_required(VERSION 3.4)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
diff --git a/tests/test_cmake_build/subdirectory_function/CMakeLists.txt b/tests/test_cmake_build/subdirectory_function/CMakeLists.txt
index 697f881..624c600 100644
--- a/tests/test_cmake_build/subdirectory_function/CMakeLists.txt
+++ b/tests/test_cmake_build/subdirectory_function/CMakeLists.txt
@@ -1,6 +1,6 @@
-cmake_minimum_required(VERSION 3.7)
+cmake_minimum_required(VERSION 3.4)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
@@ -12,15 +12,23 @@
project(test_subdirectory_function CXX)
add_subdirectory("${PYBIND11_PROJECT_DIR}" pybind11)
-pybind11_add_module(test_subdirectory_function THIN_LTO ../main.cpp)
+pybind11_add_module(test_subdirectory_function ../main.cpp)
set_target_properties(test_subdirectory_function PROPERTIES OUTPUT_NAME test_cmake_build)
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
+
add_custom_target(
check_subdirectory_function
${CMAKE_COMMAND}
-E
env
PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_function>
- ${PYTHON_EXECUTABLE}
+ ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME})
diff --git a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
index 4f2312e..2471941 100644
--- a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
+++ b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
@@ -1,6 +1,6 @@
-cmake_minimum_required(VERSION 3.7)
+cmake_minimum_required(VERSION 3.4)
-# The `cmake_minimum_required(VERSION 3.7...3.18)` syntax does not work with
+# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
@@ -18,9 +18,16 @@
target_link_libraries(test_subdirectory_target PRIVATE pybind11::module)
-# make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
-set_target_properties(test_subdirectory_target PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
- SUFFIX "${PYTHON_MODULE_EXTENSION}")
+# Make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
+pybind11_extension(test_subdirectory_target)
+
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
add_custom_target(
check_subdirectory_target
@@ -28,6 +35,6 @@
-E
env
PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_target>
- ${PYTHON_EXECUTABLE}
+ ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME})
diff --git a/tests/test_embed/CMakeLists.txt b/tests/test_embed/CMakeLists.txt
index c358d33..1495c77 100644
--- a/tests/test_embed/CMakeLists.txt
+++ b/tests/test_embed/CMakeLists.txt
@@ -1,10 +1,11 @@
-if(${PYTHON_MODULE_EXTENSION} MATCHES "pypy")
+if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy")
add_custom_target(cpptest) # Dummy target on PyPy. Embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return()
endif()
find_package(Catch 2.13.0)
+
if(CATCH_FOUND)
message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}")
else()
@@ -13,14 +14,12 @@
return()
endif()
+find_package(Threads REQUIRED)
+
add_executable(test_embed catch.cpp test_interpreter.cpp)
-target_include_directories(test_embed SYSTEM PRIVATE "${CATCH_INCLUDE_DIR}")
pybind11_enable_warnings(test_embed)
-target_link_libraries(test_embed PRIVATE pybind11::embed)
-
-find_package(Threads REQUIRED)
-target_link_libraries(test_embed PUBLIC Threads::Threads)
+target_link_libraries(test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads)
add_custom_target(
cpptest
diff --git a/tools/FindCatch.cmake b/tools/FindCatch.cmake
index ade66c7..4d6bffc 100644
--- a/tools/FindCatch.cmake
+++ b/tools/FindCatch.cmake
@@ -64,4 +64,7 @@
endif()
endif()
+add_library(Catch2::Catch2 IMPORTED INTERFACE)
+set_property(TARGET Catch2::Catch2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CATCH_INCLUDE_DIR}")
+
set(CATCH_FOUND TRUE)
diff --git a/tools/FindPythonLibsNew.cmake b/tools/FindPythonLibsNew.cmake
index 822ec77..c1c72c7 100644
--- a/tools/FindPythonLibsNew.cmake
+++ b/tools/FindPythonLibsNew.cmake
@@ -55,15 +55,46 @@
return()
endif()
+if(PythonLibsNew_FIND_QUIETLY)
+ set(_pythonlibs_quiet QUIET)
+endif()
+
+if(PythonLibsNew_FIND_REQUIRED)
+ set(_pythonlibs_required REQUIRED)
+endif()
+
+# Check to see if the `python` command is present and from a virtual
+# environment, conda, or GHA activation - if it is, try to use that.
+
+if(NOT DEFINED PYTHON_EXECUTABLE)
+ if(DEFINED ENV{VIRTUAL_ENV})
+ find_program(
+ PYTHON_EXECUTABLE python
+ PATHS "$ENV{VIRTUAL_ENV}" "$ENV{VIRTUAL_ENV}/bin"
+ NO_DEFAULT_PATH)
+ elseif(DEFINED ENV{CONDA_PREFIX})
+ find_program(
+ PYTHON_EXECUTABLE python
+ PATHS "$ENV{CONDA_PREFIX}" "$ENV{CONDA_PREFIX}/bin"
+ NO_DEFAULT_PATH)
+ elseif(DEFINED ENV{pythonLocation})
+ find_program(
+ PYTHON_EXECUTABLE python
+ PATHS "$ENV{pythonLocation}" "$ENV{pythonLocation}/bin"
+ NO_DEFAULT_PATH)
+ endif()
+ if(NOT PYTHON_EXECUTABLE)
+ unset(PYTHON_EXECUTABLE)
+ endif()
+endif()
+
# Use the Python interpreter to find the libs.
if(NOT PythonLibsNew_FIND_VERSION)
set(PythonLibsNew_FIND_VERSION "")
endif()
-if(PythonLibsNew_FIND_REQUIRED)
- find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} REQUIRED)
-else()
- find_package(PythonInterp ${PythonLibsNew_FIND_VERSION})
-endif()
+
+find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required}
+ ${_pythonlibs_quiet})
if(NOT PYTHONINTERP_FOUND)
set(PYTHONLIBS_FOUND FALSE)
@@ -71,7 +102,7 @@
return()
endif()
-# According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
+# According to https://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
# testing whether sys has the gettotalrefcount function is a reliable, cross-platform
# way to detect a CPython debug interpreter.
#
diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake
new file mode 100644
index 0000000..f058451
--- /dev/null
+++ b/tools/pybind11Common.cmake
@@ -0,0 +1,296 @@
+#[======================================================[.rst
+
+Adds the following targets::
+
+ pybind11::pybind11 - link to headers and pybind11
+ pybind11::module - Adds module links
+ pybind11::embed - Adds embed links
+ pybind11::lto - Link time optimizations (manual selection)
+ pybind11::thin_lto - Link time optimizations (manual selection)
+ pybind11::python_link_helper - Adds link to Python libraries
+ pybind11::python2_no_register - Avoid warning/error with Python 2 + C++14/7
+ pybind11::windows_extras - MSVC bigobj and mp for building multithreaded
+
+Adds the following functions::
+
+ pybind11_strip(target) - strip target after building on linux/macOS
+
+
+#]======================================================]
+
+# CMake 3.10 has an include_guard command, but we can't use that yet
+if(TARGET pybind11::lto)
+ return()
+endif()
+
+# If we are in subdirectory mode, all IMPORTED targets must be GLOBAL. If we
+# are in CONFIG mode, they should be "normal" targets instead.
+# In CMake 3.11+ you can promote a target to global after you create it,
+# which might be simpler than this check.
+get_property(
+ is_config
+ TARGET pybind11::headers
+ PROPERTY IMPORTED)
+if(NOT is_config)
+ set(optional_global GLOBAL)
+endif()
+
+# --------------------- Shared targets ----------------------------
+
+# Build an interface library target:
+add_library(pybind11::pybind11 IMPORTED INTERFACE ${optional_global})
+set_property(
+ TARGET pybind11::pybind11
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES pybind11::headers)
+
+# Build a module target:
+add_library(pybind11::module IMPORTED INTERFACE ${optional_global})
+set_property(
+ TARGET pybind11::module
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11)
+
+# Build an embed library target:
+add_library(pybind11::embed IMPORTED INTERFACE ${optional_global})
+set_property(
+ TARGET pybind11::embed
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11)
+
+# ----------------------- no register ----------------------
+
+# Workaround for Python 2.7 and C++17 (C++14 as a warning) incompatibility
+# This adds the flags -Wno-register and -Wno-deprecated-register if the compiler
+# is Clang 3.9+ or AppleClang and the compile language is CXX, or /wd5033 for MSVC (all languages,
+# since MSVC didn't recognize COMPILE_LANGUAGE until CMake 3.11+).
+
+add_library(pybind11::python2_no_register INTERFACE IMPORTED ${optional_global})
+set(clang_4plus
+ "$<AND:$<CXX_COMPILER_ID:Clang>,$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,3.9>>>")
+set(no_register "$<OR:${clang_4plus},$<CXX_COMPILER_ID:AppleClang>>")
+
+if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11)
+ set(cxx_no_register "${no_register}")
+else()
+ set(cxx_no_register "$<AND:$<COMPILE_LANGUAGE:CXX>,${no_register}>")
+endif()
+
+set(msvc "$<CXX_COMPILER_ID:MSVC>")
+
+set_property(
+ TARGET pybind11::python2_no_register
+ PROPERTY INTERFACE_COMPILE_OPTIONS
+ "$<${cxx_no_register}:-Wno-register;-Wno-deprecated-register>" "$<${msvc}:/wd5033>")
+
+# --------------------------- 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
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES "$<$<PLATFORM_ID:Darwin>:-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.
+ set_property(
+ TARGET pybind11::python_link_helper
+ APPEND
+ PROPERTY INTERFACE_LINK_OPTIONS "$<$<PLATFORM_ID:Darwin>:LINKER:-undefined,dynamic_lookup>")
+endif()
+
+# ------------------------ Windows extras -------------------------
+
+add_library(pybind11::windows_extras IMPORTED INTERFACE ${optional_global})
+
+if(MSVC)
+ # /MP enables multithreaded builds (relevant when there are many files), /bigobj is
+ # needed for bigger binding projects due to the limit to 64k addressable sections
+ set_property(
+ TARGET pybind11::windows_extras
+ APPEND
+ PROPERTY INTERFACE_COMPILE_OPTIONS /bigobj)
+
+ if(CMAKE_VERSION VERSION_LESS 3.11)
+ set_property(
+ TARGET pybind11::windows_extras
+ APPEND
+ PROPERTY INTERFACE_COMPILE_OPTIONS $<$<NOT:$<CONFIG:Debug>>:/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 $<$<NOT:$<CONFIG:Debug>>:$<$<COMPILE_LANGUAGE:CXX>:/MP>>)
+ endif()
+endif()
+
+# ----------------------- Legacy option --------------------------
+
+# Warn or error if old variable name used
+if(PYBIND11_CPP_STANDARD)
+ string(REGEX MATCH [[..$]] VAL "${PYBIND11_CPP_STANDARD}")
+ if(CMAKE_CXX_STANDARD)
+ if(NOT CMAKE_CXX_STANDARD STREQUAL VAL)
+ message(WARNING "CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} does not match "
+ "PYBIND11_CPP_STANDARD=${PYBIND11_CPP_STANDARD}, "
+ "please remove PYBIND11_CPP_STANDARD from your cache")
+ endif()
+ else()
+ set(supported_standards 11 14 17 20)
+ if("${VAL}" IN_LIST supported_standards)
+ message(WARNING "USE -DCMAKE_CXX_STANDARD=${VAL} instead of PYBIND11_PYTHON_VERSION")
+ set(CMAKE_CXX_STANDARD
+ ${VAL}
+ CACHE STRING "From PYBIND11_CPP_STANDARD")
+ else()
+ message(FATAL_ERROR "PYBIND11_CPP_STANDARD should be replaced with CMAKE_CXX_STANDARD "
+ "(last two chars: ${VAL} not understood as a valid CXX std)")
+ endif()
+ endif()
+endif()
+
+# --------------------- Python specifics -------------------------
+
+# Check to see which Python mode we are in, new, old, or no python
+if(PYBIND11_NOPYTHON)
+ set(_pybind11_nopython ON)
+elseif(
+ PYBIND11_FINDPYTHON
+ OR Python_FOUND
+ OR Python2_FOUND
+ OR Python3_FOUND)
+ # New mode
+ include("${CMAKE_CURRENT_LIST_DIR}/pybind11NewTools.cmake")
+
+else()
+
+ # Classic mode
+ include("${CMAKE_CURRENT_LIST_DIR}/pybind11Tools.cmake")
+
+endif()
+
+# --------------------- LTO -------------------------------
+
+include(CheckCXXCompilerFlag)
+
+# Checks whether the given CXX/linker flags can compile and link a cxx file.
+# cxxflags and linkerflags are lists of flags to use. The result variable is a
+# unique variable name for each set of flags: the compilation result will be
+# cached base on the result variable. If the flags work, sets them in
+# cxxflags_out/linkerflags_out internal cache variables (in addition to
+# ${result}).
+function(_pybind11_return_if_cxx_and_linker_flags_work result cxxflags linkerflags cxxflags_out
+ linkerflags_out)
+ set(CMAKE_REQUIRED_LIBRARIES ${linkerflags})
+ check_cxx_compiler_flag("${cxxflags}" ${result})
+ if(${result})
+ set(${cxxflags_out}
+ "${cxxflags}"
+ PARENT_SCOPE)
+ set(${linkerflags_out}
+ "${linkerflags}"
+ PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(_pybind11_generate_lto target prefer_thin_lto)
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+ set(cxx_append "")
+ set(linker_append "")
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT APPLE)
+ # Clang Gold plugin does not support -Os; append -O3 to MinSizeRel builds to override it
+ set(linker_append ";$<$<CONFIG:MinSizeRel>:-O3>")
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+ set(cxx_append ";-fno-fat-lto-objects")
+ endif()
+
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND prefer_thin_lto)
+ _pybind11_return_if_cxx_and_linker_flags_work(
+ HAS_FLTO_THIN "-flto=thin${cxx_append}" "-flto=thin${linker_append}"
+ PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
+ endif()
+
+ if(NOT HAS_FLTO_THIN)
+ _pybind11_return_if_cxx_and_linker_flags_work(
+ HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS
+ PYBIND11_LTO_LINKER_FLAGS)
+ endif()
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
+ # Intel equivalent to LTO is called IPO
+ _pybind11_return_if_cxx_and_linker_flags_work(HAS_INTEL_IPO "-ipo" "-ipo"
+ PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
+ elseif(MSVC)
+ # cmake only interprets libraries as linker flags when they start with a - (otherwise it
+ # converts /LTCG to \LTCG as if it was a Windows path). Luckily MSVC supports passing flags
+ # with - instead of /, even if it is a bit non-standard:
+ _pybind11_return_if_cxx_and_linker_flags_work(HAS_MSVC_GL_LTCG "/GL" "-LTCG"
+ PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
+ endif()
+
+ # Enable LTO flags if found, except for Debug builds
+ if(PYBIND11_LTO_CXX_FLAGS)
+ set(not_debug "$<NOT:$<CONFIG:Debug>>")
+ set(cxx_lang "$<COMPILE_LANGUAGE:CXX>")
+ if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11)
+ set(genex "${not_debug}")
+ else()
+ set(genex "$<AND:${not_debug},${cxx_lang}>")
+ endif()
+ set_property(
+ TARGET ${target}
+ APPEND
+ PROPERTY INTERFACE_COMPILE_OPTIONS "$<${genex}:${PYBIND11_LTO_CXX_FLAGS}>")
+ if(CMAKE_PROJECT_NAME STREQUAL "pybind11")
+ message(STATUS "${target} enabled")
+ endif()
+ else()
+ if(CMAKE_PROJECT_NAME STREQUAL "pybind11")
+ message(STATUS "${target} disabled (not supported by the compiler and/or linker)")
+ endif()
+ 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()
+ endif()
+endfunction()
+
+add_library(pybind11::lto IMPORTED INTERFACE ${optional_global})
+_pybind11_generate_lto(pybind11::lto FALSE)
+
+add_library(pybind11::thin_lto IMPORTED INTERFACE ${optional_global})
+_pybind11_generate_lto(pybind11::thin_lto TRUE)
+
+# ---------------------- pybind11_strip -----------------------------
+
+function(pybind11_strip target_name)
+ # Strip unnecessary sections of the binary on Linux/Mac OS
+ if(CMAKE_STRIP)
+ if(APPLE)
+ set(x_opt -x)
+ endif()
+
+ add_custom_command(
+ TARGET ${target_name}
+ POST_BUILD
+ COMMAND ${CMAKE_STRIP} ${x_opt} $<TARGET_FILE:${target_name}>)
+ endif()
+endfunction()
diff --git a/tools/pybind11Config.cmake.in b/tools/pybind11Config.cmake.in
index c86e0de..4f0500a 100644
--- a/tools/pybind11Config.cmake.in
+++ b/tools/pybind11Config.cmake.in
@@ -8,6 +8,7 @@
pybind11_FOUND - true if pybind11 and all required components found on the system
pybind11_VERSION - pybind11 version in format Major.Minor.Release
+ pybind11_VERSION_TYPE - pybind11 version type (dev, release)
pybind11_INCLUDE_DIRS - Directories where pybind11 and python headers are located.
pybind11_INCLUDE_DIR - Directory where pybind11 headers are located.
pybind11_DEFINITIONS - Definitions necessary to use pybind11, namely USING_pybind11.
@@ -28,21 +29,61 @@
Python headers, libraries (as needed by platform), and the C++ standard
are attached to the target.
+
+Advanced targets are also supplied - these are primary for users building
+complex applications, and they are available in all modes::
+
+ pybind11::headers - Just the pybind11 headers and minimum compile requirements
+ pybind11::pybind11 - Python headers too
+ pybind11::python_link_helper - Just the "linking" part of pybind11:module, for CMake < 3.15
+ pybind11::python2_no_register - Quiets the warning/error when mixing C++14+ and Python 2, also included in pybind11::module
+ pybind11::thin_lto - An alternative to INTERPROCEDURAL_OPTIMIZATION
+ pybind11::lto - An alternative to INTERPROCEDURAL_OPTIMIZATION (also avoids thin LTO on clang)
+ pybind11::windows_extras - Adds bigobj and mp for MSVC
+
+Modes::
+
+There are two modes provided; classic, which is built on the old Python
+discovery packages in CMake, or the new FindPython mode, which uses FindPython
+from 3.12+ forward (3.15+ _highly_ recommended).
+
+New FindPython mode::
+
+To activate this mode, either call ``find_package(Python COMPONENTS Interpreter Development)``
+before finding this package, or set the ``PYBIND11_FINDPYTHON`` variable to ON. In this mode,
+you can either use the basic targets, or use the FindPython tools::
+
+ find_package(Python COMPONENTS Interpreter Development)
+ find_package(pybind11 CONFIG)
+
+ # pybind11 method:
+ pybind11_add_module(MyModule1 src1.cpp)
+
+ # Python method:
+ Python_add_library(MyModule2 src2.cpp)
+ target_link_libraries(MyModule2 pybind11::headers)
+ set_target_properties(MyModule2 PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION ON
+ CXX__VISIBILITY_PRESET ON
+ VISIBLITY_INLINES_HIDDEN ON)
+
+If you build targets yourself, you may be interested in stripping the output
+for reduced size; this is the one other feature that the helper function gives you.
+
Classic mode::
Set PythonLibsNew variables to influence python detection and
CMAKE_CXX_STANDARD to influence standard setting. ::
find_package(pybind11 CONFIG REQUIRED)
- message(STATUS "Found pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}: ${pybind11_INCLUDE_DIRS}")
# Create an extension module
add_library(mylib MODULE main.cpp)
- target_link_libraries(mylib pybind11::module)
+ target_link_libraries(mylib PUBLIC pybind11::module)
# Or embed the Python interpreter into an executable
add_executable(myexe main.cpp)
- target_link_libraries(myexe pybind11::embed)
+ target_link_libraries(myexe PUBLIC pybind11::embed)
Suggested usage::
@@ -59,8 +100,17 @@
PATH - environment variable, set to bin directory of this package
CMAKE_DISABLE_FIND_PACKAGE_pybind11 - CMake variable, disables
find_package(pybind11) when not REQUIRED, perhaps to force internal build
-#]=============================================================================]
+Helper functions::
+
+ pybind11_add_module(...) - Add a library and setup all helpers
+ pybind11_strip(target) - Strip a target after building it (linux/macOS)
+ pybind11_extension(target) - Injects the Python extension name
+
+See ``pybind11Tools.cmake`` or ``pybind11NewTools.cmake`` for details on
+``pybind11_add_module``.
+
+#]=============================================================================]
@PACKAGE_INIT@
# Location of pybind11/pybind11.h
@@ -72,50 +122,19 @@
check_required_components(pybind11)
-include("${CMAKE_CURRENT_LIST_DIR}/pybind11Tools.cmake")
+if(TARGET pybind11::python_link_helper)
+ # This has already been setup elsewhere, such as with a previous call or
+ # add_subdirectory
+ return()
+endif()
-#-----------------------------------------------------------------------------
-# Don't include targets if this file is being picked up by another
-# project which has already built this as a subproject
-#-----------------------------------------------------------------------------
-if(NOT TARGET pybind11::pybind11)
- include("${CMAKE_CURRENT_LIST_DIR}/pybind11Targets.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/pybind11Targets.cmake")
- list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
- find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED)
- list(REMOVE_AT CMAKE_MODULE_PATH -1)
+include("${CMAKE_CURRENT_LIST_DIR}/pybind11Common.cmake")
- set_property(
- TARGET pybind11::pybind11
- APPEND
- PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_DIRS})
- set_property(
- TARGET pybind11::pybind11
- APPEND
- PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_DIRS})
-
- set_property(
- TARGET pybind11::embed
- APPEND
- PROPERTY INTERFACE_LINK_LIBRARIES ${PYTHON_LIBRARIES})
- set_property(
- TARGET pybind11::module
- APPEND
- PROPERTY
- INTERFACE_LINK_LIBRARIES
- "$<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Cygwin>>:$<BUILD_INTERFACE:${PYTHON_LIBRARIES}>>"
+if(NOT pybind11_FIND_QUIETLY)
+ message(
+ STATUS
+ "Found pybind11: ${pybind11_INCLUDE_DIR} (found version \"${pybind11_VERSION}\" ${pybind11_VERSION_TYPE})"
)
-
- get_property(
- _iid
- TARGET pybind11::pybind11
- PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
- get_property(
- _ill
- TARGET pybind11::module
- PROPERTY INTERFACE_LINK_LIBRARIES)
- set(pybind11_INCLUDE_DIRS ${_iid})
- set(pybind11_LIBRARIES ${_ico} ${_ill})
-
- include("${CMAKE_CURRENT_LIST_DIR}/pybind11Tools.cmake")
endif()
diff --git a/tools/pybind11NewTools.cmake b/tools/pybind11NewTools.cmake
new file mode 100644
index 0000000..2e7a931
--- /dev/null
+++ b/tools/pybind11NewTools.cmake
@@ -0,0 +1,203 @@
+# tools/pybind11NewTools.cmake -- Build system for the pybind11 modules
+#
+# Copyright (c) 2020 Wenzel Jakob <wenzel@inf.ethz.ch> and Henry Schreiner
+#
+# All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+get_property(
+ is_config
+ TARGET pybind11::headers
+ PROPERTY IMPORTED)
+
+if(pybind11_FIND_QUIETLY)
+ set(_pybind11_quiet QUIET)
+endif()
+
+if(CMAKE_VERSION VERSION_LESS 3.12)
+ message(FATAL_ERROR "You cannot use the new FindPython module with CMake < 3.12")
+endif()
+
+if(NOT Python_FOUND
+ AND NOT Python3_FOUND
+ AND NOT Python2_FOUND)
+ if(NOT DEFINED Python_FIND_IMPLEMENTATIONS)
+ set(Python_FIND_IMPLEMENTATIONS CPython PyPy)
+ endif()
+
+ # GitHub Actions like activation
+ if(NOT DEFINED Python_ROOT_DIR AND DEFINED ENV{pythonLocation})
+ set(Python_ROOT_DIR "$ENV{pythonLocation}")
+ endif()
+
+ find_package(Python REQUIRED COMPONENTS Interpreter Development ${_pybind11_quiet})
+
+ # If we are in submodule mode, export the Python targets to global targets.
+ # If this behavior is not desired, FindPython _before_ pybind11.
+ if(NOT is_config)
+ set_property(TARGET Python::Python PROPERTY IMPORTED_GLOBAL TRUE)
+ set_property(TARGET Python::Interpreter PROPERTY IMPORTED_GLOBAL TRUE)
+ if(TARGET Python::Module)
+ set_property(TARGET Python::Module PROPERTY IMPORTED_GLOBAL TRUE)
+ endif()
+ endif()
+endif()
+
+if(Python_FOUND)
+ set(_Python
+ Python
+ CACHE INTERNAL "" FORCE)
+elseif(Python3_FOUND AND NOT Python2_FOUND)
+ set(_Python
+ Python3
+ CACHE INTERNAL "" FORCE)
+elseif(Python2_FOUND AND NOT Python3_FOUND)
+ set(_Python
+ Python2
+ CACHE INTERNAL "" FORCE)
+else()
+ message(AUTHOR_WARNING "Python2 and Python3 both present, pybind11 in "
+ "PYBIND11_NOPYTHON mode (manually activate to silence warning)")
+ set(_pybind11_nopython ON)
+ return()
+endif()
+
+if(PYBIND11_MASTER_PROJECT)
+ if(${_Python}_INTERPRETER_ID MATCHES "PyPy")
+ message(STATUS "PyPy ${${_Python}_PyPy_VERSION} (Py ${${_Python}_VERSION})")
+ else()
+ message(STATUS "${_Python} ${${_Python}_VERSION}")
+ endif()
+endif()
+
+# Debug check - see https://stackoverflow.com/questions/646518/python-how-to-detect-debug-Interpreter
+execute_process(COMMAND ${_Python}::Python -c "import sys; print(hasattr(sys, 'gettotalrefcount'))"
+ OUTPUT_VARIABLE PYTHON_IS_DEBUG)
+
+# Python debug libraries expose slightly different objects before 3.8
+# https://docs.python.org/3.6/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 pybind::pybind11
+ APPEND
+ PROPERTY INTERFACE_COMPILE_DEFINITIONS Py_DEBUG)
+endif()
+
+# Check on every access - since Python2 and Python3 could have been used - do nothing in that case.
+
+if(DEFINED ${_Python}_INCLUDE_DIRS)
+ set_property(
+ TARGET pybind11::pybind11
+ APPEND
+ PROPERTY INTERFACE_INCLUDE_DIRECTORIES $<BUILD_INTERFACE:${${_Python}_INCLUDE_DIRS}>)
+endif()
+
+if(DEFINED ${_Python}_VERSION AND ${_Python}_VERSION VERSION_LESS 3)
+ set_property(
+ TARGET pybind11::pybind11
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python2_no_register)
+endif()
+
+# In CMake 3.18+, you can find these separately, so include an if
+if(TARGET ${_Python}::${_Python})
+ set_property(
+ TARGET pybind11::embed
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES ${_Python}::${_Python})
+endif()
+
+# CMake 3.15+ has this
+if(TARGET ${_Python}::Module)
+ set_property(
+ TARGET pybind11::module
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES ${_Python}::Module)
+else()
+ set_property(
+ TARGET pybind11::module
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python_link_helper)
+endif()
+
+function(pybind11_add_module target_name)
+ cmake_parse_arguments(PARSE_ARGV 1 ARG "STATIC;SHARED;MODULE;THIN_LTO;NO_EXTRAS" "" "")
+
+ if(ARG_ADD_LIBRARY_STATIC)
+ set(type STATIC)
+ elseif(ARG_ADD_LIBRARY_SHARED)
+ set(type SHARED)
+ else()
+ set(type MODULE)
+ endif()
+
+ if("${_Python}" STREQUAL "Python")
+ python_add_library(${target_name} ${type} WITH_SOABI ${ARG_UNPARSED_ARGUMENTS})
+ elseif("${_Python}" STREQUAL "Python3")
+ python3_add_library(${target_name} ${type} WITH_SOABI ${ARG_UNPARSED_ARGUMENTS})
+ elseif("${_Python}" STREQUAL "Python2")
+ python2_add_library(${target_name} ${type} WITH_SOABI ${ARG_UNPARSED_ARGUMENTS})
+ else()
+ message(FATAL_ERROR "Cannot detect FindPython version: ${_Python}")
+ endif()
+
+ target_link_libraries(${target_name} PRIVATE pybind11::headers)
+
+ if(type STREQUAL "MODULE")
+ target_link_libraries(${target_name} PRIVATE pybind11::module)
+ else()
+ target_link_libraries(${target_name} PRIVATE pybind11::embed)
+ endif()
+
+ if(MSVC)
+ target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
+ endif()
+
+ if(DEFINED ${_Python}_VERSION AND ${_Python}_VERSION VERSION_LESS 3)
+ target_link_libraries(${target_name} PRIVATE pybind11::python2_no_register)
+ endif()
+
+ set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden"
+ CUDA_VISIBILITY_PRESET "hidden")
+
+ 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(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo)
+ # Strip unnecessary sections of the binary on Linux/Mac OS
+ pybind11_strip(${target_name})
+ endif()
+
+ if(MSVC)
+ target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
+ endif()
+endfunction()
+
+function(pybind11_extension name)
+ set_property(TARGET ${name} PROPERTY PREFIX "")
+
+ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set_property(TARGET ${name} PROPERTY SUFFIX ".pyd")
+ endif()
+
+ if(${_Python}_SOABI)
+ get_property(
+ suffix
+ TARGET ${name}
+ PROPERTY SUFFIX)
+ if(NOT suffix)
+ set(suffix "${CMAKE_SHARED_MODULE_SUFFIX}")
+ endif()
+ set_property(TARGET ${name} PROPERTY SUFFIX ".${${_Python}_SOABI}${suffix}")
+ endif()
+endfunction()
diff --git a/tools/pybind11Tools.cmake b/tools/pybind11Tools.cmake
index 6e66695..29885ae 100644
--- a/tools/pybind11Tools.cmake
+++ b/tools/pybind11Tools.cmake
@@ -5,6 +5,13 @@
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
+# Built-in in CMake 3.5+
+include(CMakeParseArguments)
+
+if(pybind11_FIND_QUIETLY)
+ set(_pybind11_quiet QUIET)
+endif()
+
# Add a CMake parameter for choosing a desired Python version
if(NOT PYBIND11_PYTHON_VERSION)
set(PYBIND11_PYTHON_VERSION
@@ -18,112 +25,91 @@
CACHE INTERNAL "")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
-find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED)
+find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED ${_pybind11_quiet})
list(REMOVE_AT CMAKE_MODULE_PATH -1)
-include(CheckCXXCompilerFlag)
+# Cache variables so pybind11_add_module can be used in parent projects
+set(PYTHON_INCLUDE_DIRS
+ ${PYTHON_INCLUDE_DIRS}
+ CACHE INTERNAL "")
+set(PYTHON_LIBRARIES
+ ${PYTHON_LIBRARIES}
+ CACHE INTERNAL "")
+set(PYTHON_MODULE_PREFIX
+ ${PYTHON_MODULE_PREFIX}
+ CACHE INTERNAL "")
+set(PYTHON_MODULE_EXTENSION
+ ${PYTHON_MODULE_EXTENSION}
+ CACHE INTERNAL "")
+set(PYTHON_VERSION_MAJOR
+ ${PYTHON_VERSION_MAJOR}
+ CACHE INTERNAL "")
+set(PYTHON_VERSION_MINOR
+ ${PYTHON_VERSION_MINOR}
+ CACHE INTERNAL "")
+set(PYTHON_VERSION
+ ${PYTHON_VERSION}
+ CACHE INTERNAL "")
+set(PYTHON_IS_DEBUG
+ "${PYTHON_IS_DEBUG}"
+ CACHE INTERNAL "")
-# Warn or error if old variable name used
-if(PYBIND11_CPP_STANDARD)
- string(REGEX MATCH [[..$]] VAL "${PYBIND11_CPP_STANDARD}")
- if(CMAKE_CXX_STANDARD)
- if(NOT CMAKE_CXX_STANDARD STREQUAL VAL)
- message(WARNING "CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} does not match "
- "PYBIND11_CPP_STANDARD=${PYBIND11_CPP_STANDARD}, "
- "please remove PYBIND11_CPP_STANDARD from your cache")
+if(PYBIND11_MASTER_PROJECT)
+ if(PYTHON_MODULE_EXTENSION MATCHES "pypy")
+ if(NOT DEFINED PYPY_VERSION)
+ execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -c
+ [=[import sys; print(".".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()
- set(supported_standards 11 14 17 20)
- if("${VAL}" IN_LIST supported_standards)
- message(WARNING "USE -DCMAKE_CXX_STANDARD=${VAL} instead of PYBIND11_PYTHON_VERSION")
- set(CMAKE_CXX_STANDARD
- ${VAL}
- CACHE STRING "From PYBIND11_CPP_STANDARD")
- else()
- message(FATAL_ERROR "PYBIND11_CPP_STANDARD should be replaced with CMAKE_CXX_STANDARD "
- "(last two chars: ${VAL} not understood as a valid CXX std)")
- endif()
+ message(STATUS "PYTHON ${PYTHON_VERSION}")
endif()
endif()
-# Checks whether the given CXX/linker flags can compile and link a cxx file. cxxflags and
-# linkerflags are lists of flags to use. The result variable is a unique variable name for each set
-# of flags: the compilation result will be cached base on the result variable. If the flags work,
-# sets them in cxxflags_out/linkerflags_out internal cache variables (in addition to ${result}).
-function(_pybind11_return_if_cxx_and_linker_flags_work result cxxflags linkerflags cxxflags_out
- linkerflags_out)
- set(CMAKE_REQUIRED_LIBRARIES ${linkerflags})
- check_cxx_compiler_flag("${cxxflags}" ${result})
- if(${result})
- set(${cxxflags_out}
- "${cxxflags}"
- CACHE INTERNAL "" FORCE)
- set(${linkerflags_out}
- "${linkerflags}"
- CACHE INTERNAL "" FORCE)
- endif()
-endfunction()
+# Only add Python for build - must be added during the import for config since it has to be re-discovered.
+set_property(
+ TARGET pybind11::pybind11
+ APPEND
+ PROPERTY INTERFACE_INCLUDE_DIRECTORIES $<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>)
-# Internal: find the appropriate link time optimization flags for this compiler
-function(_pybind11_add_lto_flags target_name prefer_thin_lto)
- if(NOT DEFINED PYBIND11_LTO_CXX_FLAGS)
- set(PYBIND11_LTO_CXX_FLAGS
- ""
- CACHE INTERNAL "")
- set(PYBIND11_LTO_LINKER_FLAGS
- ""
- CACHE INTERNAL "")
+# Python debug libraries expose slightly different objects before 3.8
+# https://docs.python.org/3.6/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 pybind::pybind11
+ APPEND
+ PROPERTY INTERFACE_COMPILE_DEFINITIONS Py_DEBUG)
+endif()
- if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
- set(cxx_append "")
- set(linker_append "")
- if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT APPLE)
- # Clang Gold plugin does not support -Os; append -O3 to MinSizeRel builds to override it
- set(linker_append ";$<$<CONFIG:MinSizeRel>:-O3>")
- elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
- set(cxx_append ";-fno-fat-lto-objects")
- endif()
+set_property(
+ TARGET pybind11::module
+ APPEND
+ PROPERTY
+ INTERFACE_LINK_LIBRARIES pybind11::python_link_helper
+ "$<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Cygwin>>:$<BUILD_INTERFACE:${PYTHON_LIBRARIES}>>")
- if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND prefer_thin_lto)
- _pybind11_return_if_cxx_and_linker_flags_work(
- HAS_FLTO_THIN "-flto=thin${cxx_append}" "-flto=thin${linker_append}"
- PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
- endif()
+if(PYTHON_VERSION VERSION_LESS 3)
+ set_property(
+ TARGET pybind11::pybind11
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python2_no_register)
+endif()
- if(NOT HAS_FLTO_THIN)
- _pybind11_return_if_cxx_and_linker_flags_work(
- HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS
- PYBIND11_LTO_LINKER_FLAGS)
- endif()
- elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
- # Intel equivalent to LTO is called IPO
- _pybind11_return_if_cxx_and_linker_flags_work(
- HAS_INTEL_IPO "-ipo" "-ipo" PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
- elseif(MSVC)
- # cmake only interprets libraries as linker flags when they start with a - (otherwise it
- # converts /LTCG to \LTCG as if it was a Windows path). Luckily MSVC supports passing flags
- # with - instead of /, even if it is a bit non-standard:
- _pybind11_return_if_cxx_and_linker_flags_work(
- HAS_MSVC_GL_LTCG "/GL" "-LTCG" PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
- endif()
+set_property(
+ TARGET pybind11::embed
+ APPEND
+ PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11 $<BUILD_INTERFACE:${PYTHON_LIBRARIES}>)
- if(PYBIND11_LTO_CXX_FLAGS)
- message(STATUS "LTO enabled")
- else()
- message(STATUS "LTO disabled (not supported by the compiler and/or linker)")
- endif()
- endif()
-
- # Enable LTO flags if found, except for Debug builds
- if(PYBIND11_LTO_CXX_FLAGS)
- set(not_debug "$<NOT:$<CONFIG:Debug>>")
- set(cxx_lang "$<COMPILE_LANGUAGE:CXX>")
- target_compile_options(${target_name}
- PRIVATE "$<$<AND:${not_debug},${cxx_lang}>:${PYBIND11_LTO_CXX_FLAGS}>")
- endif()
- if(PYBIND11_LTO_LINKER_FLAGS)
- target_link_libraries(${target_name} PRIVATE "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>")
- endif()
+function(pybind11_extension name)
+ # The prefix and extension are provided by FindPythonLibsNew.cmake
+ set_target_properties(${name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
+ SUFFIX "${PYTHON_MODULE_EXTENSION}")
endfunction()
# Build a Python extension module:
@@ -132,7 +118,7 @@
#
function(pybind11_add_module target_name)
set(options MODULE SHARED EXCLUDE_FROM_ALL NO_EXTRAS SYSTEM THIN_LTO)
- cmake_parse_arguments(PARSE_ARGV 1 ARG "${options}" "" "")
+ cmake_parse_arguments(ARG "${options}" "" "" ${ARGN})
if(ARG_MODULE AND ARG_SHARED)
message(FATAL_ERROR "Can't be both MODULE and SHARED")
@@ -159,74 +145,34 @@
)
endif()
- # Python debug libraries expose slightly different objects before 3.8
- # https://docs.python.org/3.6/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)
- target_compile_definitions(${target_name} PRIVATE Py_DEBUG)
- endif()
-
- # The prefix and extension are provided by FindPythonLibsNew.cmake
- set_target_properties(${target_name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}")
- set_target_properties(${target_name} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}")
+ 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.
- set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
- set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden")
+ set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden"
+ CUDA_VISIBILITY_PRESET "hidden")
if(ARG_NO_EXTRAS)
return()
endif()
- if(CMAKE_VERSION VERSION_LESS 3.9 OR PYBIND11_CLASSIC_LTO)
- _pybind11_add_lto_flags(${target_name} ${ARG_THIN_LTO})
- else()
- include(CheckIPOSupported)
- check_ipo_supported(
- RESULT supported
- OUTPUT error
- LANGUAGES CXX)
- if(supported)
- set_property(TARGET ${target_name} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+ if(NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
+ if(ARG_THIN_LTO)
+ target_link_libraries(${target_name} PRIVATE pybind11::thin_lto)
else()
- message(WARNING "IPO is not supported: ${output}")
+ target_link_libraries(${target_name} PRIVATE pybind11::lto)
endif()
endif()
if(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo)
- # Strip unnecessary sections of the binary on Linux/Mac OS
- if(CMAKE_STRIP)
- if(APPLE)
- add_custom_command(
- TARGET ${target_name}
- POST_BUILD
- COMMAND ${CMAKE_STRIP} -x $<TARGET_FILE:${target_name}>)
- else()
- add_custom_command(
- TARGET ${target_name}
- POST_BUILD
- COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${target_name}>)
- endif()
- endif()
+ pybind11_strip(${target_name})
endif()
if(MSVC)
- # /MP enables multithreaded builds (relevant when there are many files), /bigobj is
- # needed for bigger binding projects due to the limit to 64k addressable sections
- target_compile_options(${target_name} PRIVATE /bigobj)
- if(CMAKE_VERSION VERSION_LESS 3.11)
- target_compile_options(${target_name} PRIVATE $<$<NOT:$<CONFIG:Debug>>:/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.
- target_compile_options(${target_name}
- PRIVATE $<$<NOT:$<CONFIG:Debug>>:$<$<COMPILE_LANGUAGE:CXX>:/MP>>)
- endif()
+ target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
endif()
+
endfunction()