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
This commit is contained in:
Henry Schreiner 2020-08-19 12:26:26 -04:00 committed by GitHub
parent 69821d9e75
commit 1729aae96f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1117 additions and 395 deletions

View File

@ -31,11 +31,13 @@ jobs:
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 @@ jobs:
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 @@ jobs:
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 @@ jobs:
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 @@ jobs:
- 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 @@ jobs:
-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 @@ jobs:
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 @@ jobs:
-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 @@ jobs:
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

View File

@ -14,19 +14,22 @@ jobs:
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
- runs-on: macos-latest
arch: x64
cmake: 3.7
# TODO: 3.8
- runs-on: windows-2016
arch: x86
cmake: 3.11
cmake: 3.8
- runs-on: windows-2016
arch: x86
@ -63,3 +66,13 @@ jobs:
-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

2
.gitignore vendored
View File

@ -32,7 +32,7 @@ MANIFEST
.*.swp
.DS_Store
/dist
/build
/build*
.cache/
sosize-*.txt
pybind11Config*.cmake

View File

@ -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(GNUInstallDirs)
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 @@ endif()
# 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 @@ endif()
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}>
headers ${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}>)
if(CMAKE_VERSION VERSION_LESS 3.13)
target_compile_features(pybind11 INTERFACE cxx_inheriting_constructors cxx_user_literals
target_compile_features(headers 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}>)
if(PYBIND11_INSTALL)
install(DIRECTORY ${PYBIND11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
@ -248,14 +202,17 @@ if(PYBIND11_INSTALL)
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 @@ endif()
# BUILD_TESTING takes priority, but only if this is the master project
if(PYBIND11_MASTER_PROJECT AND DEFINED BUILD_TESTING)
if(BUILD_TESTING)
if(_pybind11_nopython)
message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
else()
add_subdirectory(tests)
endif()
endif()
else()
if(PYBIND11_TEST)
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()

View File

@ -18,7 +18,7 @@ information, see :doc:`/compiling`.
.. 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)`

View File

@ -6,6 +6,39 @@ Changelog
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 CMakes 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)
-----------------------------------------------------

View File

@ -33,8 +33,8 @@ extension module can be created with just a few lines of code:
.. 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 @@ PyPI integration, can be found in the [cmake_example]_ repository.
.. [cmake_example] https://github.com/pybind/cmake_example
.. versionchanged:: 2.6
CMake 3.4+ is required.
pybind11_add_module
-------------------
@ -89,7 +92,9 @@ will result in code bloat and is generally not recommended.
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 @@ the ``-D<variable>=<value>`` flag. You can also manually set ``CXX_STANDARD``
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 @@ For example:
# 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 @@ See the `Config file`_ docstring for details of relevant CMake variables.
.. 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 @@ can refer to the same [cmake_example]_ repository for a full sample project
.. _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 @@ information about usage in C++, see :doc:`/advanced/embedding`.
.. 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)

View File

@ -1 +1,3 @@
breathe == 4.5.0
breathe==4.13.1
sphinx<3
sphinx_rtd_theme

View File

@ -8,6 +8,53 @@ to a new version. But it goes into more detail. This includes things like
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
====

View File

@ -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 @@ else()
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 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
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 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
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 @@ endif()
# 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 @@ foreach(target ${test_targets})
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_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()

View File

@ -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 @@ endfunction()
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 @@ if(PYBIND11_INSTALL)
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()

View File

@ -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)

View File

@ -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 @@ message(
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})

View File

@ -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 @@ add_library(test_installed_target MODULE ../main.cpp)
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})

View File

@ -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)

View File

@ -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 @@ endif()
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})

View File

@ -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 @@ set_target_properties(test_subdirectory_target PROPERTIES OUTPUT_NAME test_cmake
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 @@ add_custom_target(
-E
env
PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_target>
${PYTHON_EXECUTABLE}
${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME})

View File

@ -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 @@ else()
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

View File

@ -64,4 +64,7 @@ if(NOT CATCH_VERSION OR CATCH_VERSION VERSION_LESS ${Catch_FIND_VERSION})
endif()
endif()
add_library(Catch2::Catch2 IMPORTED INTERFACE)
set_property(TARGET Catch2::Catch2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CATCH_INCLUDE_DIR}")
set(CATCH_FOUND TRUE)

View File

@ -55,15 +55,46 @@ if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION)
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 @@ if(NOT PYTHONINTERP_FOUND)
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.
#

296
tools/pybind11Common.cmake Normal file
View File

@ -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()

View File

@ -8,6 +8,7 @@ This module sets the following variables in your project::
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 @@ interface library targets::
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 @@ The following variables can be set to guide the search for this package::
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 @@ set(pybind11_VERSION_TYPE "@pybind11_VERSION_TYPE@")
check_required_components(pybind11)
include("${CMAKE_CURRENT_LIST_DIR}/pybind11Tools.cmake")
#-----------------------------------------------------------------------------
# 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")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED)
list(REMOVE_AT CMAKE_MODULE_PATH -1)
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}>>"
)
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")
if(TARGET pybind11::python_link_helper)
# This has already been setup elsewhere, such as with a previous call or
# add_subdirectory
return()
endif()
include("${CMAKE_CURRENT_LIST_DIR}/pybind11Targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/pybind11Common.cmake")
if(NOT pybind11_FIND_QUIETLY)
message(
STATUS
"Found pybind11: ${pybind11_INCLUDE_DIR} (found version \"${pybind11_VERSION}\" ${pybind11_VERSION_TYPE})"
)
endif()

View File

@ -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()

View File

@ -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 @@ set(Python_ADDITIONAL_VERSIONS
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 @@ endfunction()
#
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 @@ function(pybind11_add_module target_name)
)
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})
if(NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
if(ARG_THIN_LTO)
target_link_libraries(${target_name} PRIVATE pybind11::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)
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()