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 arch: x64
max-cxx-std: 17 max-cxx-std: 17
dev: false dev: false
args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: macos-latest - runs-on: macos-latest
python: 3.7 python: 3.7
arch: x64 arch: x64
max-cxx-std: 17 max-cxx-std: 17
dev: false dev: false
args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: windows-2016 - runs-on: windows-2016
python: 3.7 python: 3.7
arch: x86 arch: x86
@ -46,6 +48,7 @@ jobs:
arch: x64 arch: x64
max-cxx-std: 17 max-cxx-std: 17
dev: false dev: false
args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: windows-latest - runs-on: windows-latest
python: 3.7 python: 3.7
arch: x64 arch: x64
@ -89,7 +92,7 @@ jobs:
dev: false 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 }} runs-on: ${{ matrix.runs-on }}
continue-on-error: ${{ matrix.dev }} continue-on-error: ${{ matrix.dev }}
@ -106,6 +109,9 @@ jobs:
if: runner.os != 'macOS' if: runner.os != 'macOS'
run: echo "::set-env name=BOOST_ROOT::$BOOST_ROOT_1_72_0" 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 - name: Cache wheels
if: runner.os == 'macOS' if: runner.os == 'macOS'
uses: actions/cache@v2 uses: actions/cache@v2
@ -120,7 +126,7 @@ jobs:
- name: Prepare env - name: Prepare env
run: python -m pip install -r tests/requirements.txt run: python -m pip install -r tests/requirements.txt
- name: Configure C++11 - name: Configure C++11 ${{ matrix.args }}
shell: bash shell: bash
run: > run: >
cmake -S . -B build cmake -S . -B build
@ -128,7 +134,7 @@ jobs:
-DDOWNLOAD_CATCH=ON -DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON -DDOWNLOAD_EIGEN=ON
-DCMAKE_CXX_STANDARD=11 -DCMAKE_CXX_STANDARD=11
-DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") ${{ matrix.args }}
- name: Build C++11 - name: Build C++11
run: cmake --build build -j 2 run: cmake --build build -j 2
@ -140,9 +146,9 @@ jobs:
run: cmake --build build --target cpptest -j 2 run: cmake --build build --target cpptest -j 2
- name: Interface test C++11 - 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 shell: bash
run: > run: >
cmake -S . -B build2 cmake -S . -B build2
@ -150,7 +156,7 @@ jobs:
-DDOWNLOAD_CATCH=ON -DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON -DDOWNLOAD_EIGEN=ON
-DCMAKE_CXX_STANDARD=${{ matrix.max-cxx-std }} -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 }} - name: Build C++${{ matrix.max-cxx-std }}
run: cmake --build build2 -j 2 run: cmake --build build2 -j 2
@ -350,14 +356,14 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install requirements - name: Install system requirements
run: apk add doxygen python3-dev run: apk add doxygen python3-dev
- name: Ensure pip - name: Ensure pip
run: python3 -m ensurepip run: python3 -m ensurepip
- name: Install python docs requirements - name: Install docs & setup requirements
run: python3 -m pip install "sphinx<3" sphinx_rtd_theme breathe==4.13.1 pytest setuptools run: python3 -m pip install -r docs/requirements.txt pytest setuptools
- name: Build docs - name: Build docs
run: python3 -m sphinx -W -b html docs docs/.build run: python3 -m sphinx -W -b html docs docs/.build

View File

@ -14,19 +14,22 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
runs-on: [ubuntu-latest, macos-latest] runs-on: [ubuntu-latest, macos-latest, windows-latest]
arch: [x64] arch: [x64]
cmake: [3.7, 3.18] cmake: [3.18]
include: include:
- runs-on: windows-latest - runs-on: ubuntu-latest
arch: x64 arch: x64
cmake: 3.18 cmake: 3.4
- runs-on: macos-latest
arch: x64
cmake: 3.7
# TODO: 3.8
- runs-on: windows-2016 - runs-on: windows-2016
arch: x86 arch: x86
cmake: 3.11 cmake: 3.8
- runs-on: windows-2016 - runs-on: windows-2016
arch: x86 arch: x86
@ -63,3 +66,13 @@ jobs:
-DPYBIND11_WERROR=ON -DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON -DDOWNLOAD_CATCH=ON
-DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") -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 .*.swp
.DS_Store .DS_Store
/dist /dist
/build /build*
.cache/ .cache/
sosize-*.txt sosize-*.txt
pybind11Config*.cmake pybind11Config*.cmake

View File

@ -5,9 +5,9 @@
# All rights reserved. Use of this source code is governed by a # All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file. # 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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) if(${CMAKE_VERSION} VERSION_LESS 3.18)
@ -41,11 +41,22 @@ include(GNUInstallDirs)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
include(CMakeDependentOption) include(CMakeDependentOption)
if(NOT pybind11_FIND_QUIETLY)
message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}") message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}")
endif()
# Check if pybind11 is being used directly or via add_subdirectory # Check if pybind11 is being used directly or via add_subdirectory
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(PYBIND11_MASTER_PROJECT ON) 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}") message(STATUS "CMake ${CMAKE_VERSION}")
if(CMAKE_CXX_STANDARD) if(CMAKE_CXX_STANDARD)
@ -60,13 +71,16 @@ endif()
# Options # Options
option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT}) option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
option(PYBIND11_TEST "Build pybind11 test suite?" ${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( cmake_dependent_option(
USE_PYTHON_INCLUDE_DIR USE_PYTHON_INCLUDE_DIR
"Install pybind11 headers in Python include directory instead of default installation prefix" "Install pybind11 headers in Python include directory instead of default installation prefix"
OFF "PYBIND11_INSTALL" OFF) 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 # NB: when adding a header don't forget to also add it to setup.py
set(PYBIND11_HEADERS set(PYBIND11_HEADERS
include/pybind11/detail/class.h include/pybind11/detail/class.h
@ -118,101 +132,41 @@ endif()
string(REPLACE "include/" "${CMAKE_CURRENT_SOURCE_DIR}/include/" PYBIND11_HEADERS string(REPLACE "include/" "${CMAKE_CURRENT_SOURCE_DIR}/include/" PYBIND11_HEADERS
"${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 # Cache variables so pybind11_add_module can be used in parent projects
set(PYBIND11_INCLUDE_DIR set(PYBIND11_INCLUDE_DIR
"${CMAKE_CURRENT_LIST_DIR}/include" "${CMAKE_CURRENT_LIST_DIR}/include"
CACHE INTERNAL "") 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 - # 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 need generator expressions, because those will be placed in the target file.
# You can also place ifs *in* the Config.in, but not here. # You can also place ifs *in* the Config.in, but not here.
# Build an interface library target: # This section builds targets, but does *not* touch Python
add_library(pybind11 INTERFACE)
add_library(pybind11::pybind11 ALIAS pybind11) # to match exported target
# 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( 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}>) $<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(headers INTERFACE cxx_inheriting_constructors cxx_user_literals
target_compile_features(pybind11 INTERFACE cxx_inheriting_constructors cxx_user_literals
cxx_right_angle_brackets) 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) if(PYBIND11_INSTALL)
install(DIRECTORY ${PYBIND11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(DIRECTORY ${PYBIND11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
@ -248,14 +202,17 @@ if(PYBIND11_INSTALL)
install( install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.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}) DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
if(NOT PYBIND11_EXPORT_NAME) if(NOT PYBIND11_EXPORT_NAME)
set(PYBIND11_EXPORT_NAME "${PROJECT_NAME}Targets") set(PYBIND11_EXPORT_NAME "${PROJECT_NAME}Targets")
endif() endif()
install(TARGETS pybind11 module embed EXPORT "${PYBIND11_EXPORT_NAME}") install(TARGETS headers EXPORT "${PYBIND11_EXPORT_NAME}")
install( install(
EXPORT "${PYBIND11_EXPORT_NAME}" EXPORT "${PYBIND11_EXPORT_NAME}"
@ -275,10 +232,28 @@ endif()
# BUILD_TESTING takes priority, but only if this is the master project # BUILD_TESTING takes priority, but only if this is the master project
if(PYBIND11_MASTER_PROJECT AND DEFINED BUILD_TESTING) if(PYBIND11_MASTER_PROJECT AND DEFINED BUILD_TESTING)
if(BUILD_TESTING) if(BUILD_TESTING)
if(_pybind11_nopython)
message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
else()
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()
endif()
else() else()
if(PYBIND11_TEST) if(PYBIND11_TEST)
if(_pybind11_nopython)
message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
else()
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()
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 .. code-block:: cmake
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.4)
project(example) project(example)
find_package(pybind11 REQUIRED) # or `add_subdirectory(pybind11)` 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 Starting with version 1.8.0, pybind11 releases use a `semantic versioning
<http://semver.org>`_ policy. <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) 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 .. code-block:: cmake
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.4...3.18)
project(example) project(example LANGUAGES CXX)
add_subdirectory(pybind11) add_subdirectory(pybind11)
pybind11_add_module(example example.cpp) 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 .. [cmake_example] https://github.com/pybind/cmake_example
.. versionchanged:: 2.6
CMake 3.4+ is required.
pybind11_add_module 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 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 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 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 .. _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 on a target or use ``target_compile_features`` on your targets - anything that
CMake supports. CMake supports.
The target Python version can be selected by setting ``PYBIND11_PYTHON_VERSION`` Classic Python support: The target Python version can be selected by setting
or an exact Python installation can be specified with ``PYTHON_EXECUTABLE``. ``PYBIND11_PYTHON_VERSION`` or an exact Python installation can be specified
For example: with ``PYTHON_EXECUTABLE``. For example:
.. code-block:: bash .. code-block:: bash
@ -127,6 +132,7 @@ For example:
# This often is a good way to get the current Python, works in environments: # This often is a good way to get the current Python, works in environments:
cmake -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") .. cmake -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") ..
find_package vs. add_subdirectory find_package vs. add_subdirectory
--------------------------------- ---------------------------------
@ -136,8 +142,8 @@ See the `Config file`_ docstring for details of relevant CMake variables.
.. code-block:: cmake .. code-block:: cmake
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.4...3.18)
project(example) project(example LANGUAGES CXX)
find_package(pybind11 REQUIRED) find_package(pybind11 REQUIRED)
pybind11_add_module(example example.cpp) 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 .. _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 .. _find-python-mode:
be used as a special *interface library* . The target ``pybind11::module``
is available with pybind11 headers, Python headers and libraries as needed, FindPython mode
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. 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 .. code-block:: cmake
cmake_minimum_required(VERSION 3.7) cmake_minumum_required(VERSION 3.15...3.18)
project(example) 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) find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11)
add_library(example MODULE main.cpp) add_library(example MODULE main.cpp)
target_link_libraries(example PRIVATE pybind11::module)
set_target_properties(example PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}" target_link_libraries(example PRIVATE pybind11::module pybind11::lto pybind11::windows_extras)
SUFFIX "${PYTHON_MODULE_EXTENSION}")
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:: .. warning::
Since pybind11 is a metatemplate library, it is crucial that certain Since pybind11 is a metatemplate library, it is crucial that certain
compiler flags are provided to ensure high quality code generation. In compiler flags are provided to ensure high quality code generation. In
contrast to the ``pybind11_add_module()`` command, the CMake interface contrast to the ``pybind11_add_module()`` command, the CMake interface
library only provides the *minimal* set of parameters to ensure that the provides a *composable* set of targets to ensure that you retain flexibility.
code using pybind11 compiles, but it does **not** pass these extra compiler It can be expecially important to provide or set these properties; the
flags (i.e. this is up to you). :ref:`FAQ <faq:symhidden>` contains an explanation on why these are needed.
These include Link Time Optimization (``-flto`` on GCC/Clang/ICPC, ``/GL`` .. versionadded:: 2.6
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.
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) If you want complete control, you can set ``PYBIND11_NOPYTHON`` to completely
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) disable Python integration (this also happens if you run ``FindPython2`` and
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # CMake 3.9+ required ``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 .. versionadded:: 2.6
manually.
Embedding the Python interpreter Embedding the Python interpreter
-------------------------------- --------------------------------
@ -228,8 +313,8 @@ information about usage in C++, see :doc:`/advanced/embedding`.
.. code-block:: cmake .. code-block:: cmake
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.4...3.18)
project(example) project(example LANGUAGES CXX)
find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11) 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 deprecated APIs and their replacements, build system changes, general code
modernization and other useful information. 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 v2.2
==== ====

View File

@ -5,9 +5,9 @@
# All rights reserved. Use of this source code is governed by a # All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file. # 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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) if(${CMAKE_VERSION} VERSION_LESS 3.18)
@ -16,6 +16,12 @@ else()
cmake_policy(VERSION 3.18) cmake_policy(VERSION 3.18)
endif() 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 # There's no harm in including a project in a project
project(pybind11_tests CXX) 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_INCLUDE_DIR ${eigen_SOURCE_DIR})
set(EIGEN3_FOUND TRUE) set(EIGEN3_FOUND TRUE)
else() else()
find_package(Eigen3 3.2.7 QUIET CONFIG) 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) if(NOT EIGEN3_FOUND)
# Couldn't load via target, so fall back to allowing module mode finding, which will pick up # 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() endif()
if(EIGEN3_FOUND) 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 # 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 # rather than looking it up in the cmake script); older versions, and the
# tools/FindEigen3.cmake, set EIGEN3_VERSION instead. # 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) # Optional dependency for some tests (boost::variant is only supported with version >= 1.56)
find_package(Boost 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 # Compile with compiler warnings turned on
function(pybind11_enable_warnings target_name) function(pybind11_enable_warnings target_name)
if(MSVC) if(MSVC)
@ -233,16 +255,12 @@ foreach(target ${test_targets})
endif() endif()
if(EIGEN3_FOUND) if(EIGEN3_FOUND)
if(PYBIND11_EIGEN_VIA_TARGET)
target_link_libraries(${target} PRIVATE Eigen3::Eigen) 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) target_compile_definitions(${target} PRIVATE -DPYBIND11_TEST_EIGEN)
endif() endif()
if(Boost_FOUND) 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) target_compile_definitions(${target} PRIVATE -DPYBIND11_TEST_BOOST)
endif() endif()

View File

@ -1,12 +1,24 @@
# Built-in in CMake 3.5+
include(CMakeParseArguments)
add_custom_target(test_cmake_build) add_custom_target(test_cmake_build)
function(pybind11_add_build_test name) function(pybind11_add_build_test name)
cmake_parse_arguments(PARSE_ARGV 1 ARG "INSTALL" "" "") cmake_parse_arguments(ARG "INSTALL" "" "" ${ARGN})
set(build_options set(build_options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
"-DCMAKE_PREFIX_PATH=${pybind11_BINARY_DIR}/mock_install"
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" if(PYBIND11_FINDPYTHON)
"-DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}") 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) if(DEFINED CMAKE_CXX_STANDARD)
list(APPEND build_options "-DCMAKE_CXX_STANDARD=${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_function)
pybind11_add_build_test(subdirectory_target) 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) pybind11_add_build_test(subdirectory_embed)
endif() endif()
@ -56,7 +70,8 @@ if(PYBIND11_INSTALL)
pybind11_add_build_test(installed_function INSTALL) pybind11_add_build_test(installed_function INSTALL)
pybind11_add_build_test(installed_target 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) pybind11_add_build_test(installed_embed INSTALL)
endif() endif()
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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) 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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) if(${CMAKE_VERSION} VERSION_LESS 3.18)
@ -18,12 +19,20 @@ message(
pybind11_add_module(test_installed_function SHARED NO_EXTRAS ../main.cpp) pybind11_add_module(test_installed_function SHARED NO_EXTRAS ../main.cpp)
set_target_properties(test_installed_function PROPERTIES OUTPUT_NAME test_cmake_build) 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( add_custom_target(
check_installed_function check_installed_function
${CMAKE_COMMAND} ${CMAKE_COMMAND}
-E -E
env env
PYTHONPATH=$<TARGET_FILE_DIR:test_installed_function> PYTHONPATH=$<TARGET_FILE_DIR:test_installed_function>
${PYTHON_EXECUTABLE} ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME}) ${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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) 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) target_link_libraries(test_installed_target PRIVATE pybind11::module)
set_target_properties(test_installed_target PROPERTIES OUTPUT_NAME test_cmake_build) 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 # 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}" pybind11_extension(test_installed_target)
SUFFIX "${PYTHON_MODULE_EXTENSION}")
# Do not treat includes from IMPORTED target as SYSTEM (Python headers in pybind11::module). # 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. # 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) 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( add_custom_target(
check_installed_target check_installed_target
${CMAKE_COMMAND} ${CMAKE_COMMAND}
-E -E
env env
PYTHONPATH=$<TARGET_FILE_DIR:test_installed_target> PYTHONPATH=$<TARGET_FILE_DIR:test_installed_target>
${PYTHON_EXECUTABLE} ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME}) ${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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) 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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) if(${CMAKE_VERSION} VERSION_LESS 3.18)
@ -12,15 +12,23 @@ endif()
project(test_subdirectory_function CXX) project(test_subdirectory_function CXX)
add_subdirectory("${PYBIND11_PROJECT_DIR}" pybind11) 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) 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( add_custom_target(
check_subdirectory_function check_subdirectory_function
${CMAKE_COMMAND} ${CMAKE_COMMAND}
-E -E
env env
PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_function> PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_function>
${PYTHON_EXECUTABLE} ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME}) ${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 # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) 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) target_link_libraries(test_subdirectory_target PRIVATE pybind11::module)
# make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib # 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}" pybind11_extension(test_subdirectory_target)
SUFFIX "${PYTHON_MODULE_EXTENSION}")
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( add_custom_target(
check_subdirectory_target check_subdirectory_target
@ -28,6 +35,6 @@ add_custom_target(
-E -E
env env
PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_target> PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_target>
${PYTHON_EXECUTABLE} ${_Python_EXECUTABLE}
${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_SOURCE_DIR}/../test.py
${PROJECT_NAME}) ${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. add_custom_target(cpptest) # Dummy target on PyPy. Embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}") set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return() return()
endif() endif()
find_package(Catch 2.13.0) find_package(Catch 2.13.0)
if(CATCH_FOUND) if(CATCH_FOUND)
message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}") message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}")
else() else()
@ -13,14 +14,12 @@ else()
return() return()
endif() endif()
find_package(Threads REQUIRED)
add_executable(test_embed catch.cpp test_interpreter.cpp) add_executable(test_embed catch.cpp test_interpreter.cpp)
target_include_directories(test_embed SYSTEM PRIVATE "${CATCH_INCLUDE_DIR}")
pybind11_enable_warnings(test_embed) pybind11_enable_warnings(test_embed)
target_link_libraries(test_embed PRIVATE pybind11::embed) target_link_libraries(test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads)
find_package(Threads REQUIRED)
target_link_libraries(test_embed PUBLIC Threads::Threads)
add_custom_target( add_custom_target(
cpptest cpptest

View File

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

View File

@ -55,15 +55,46 @@ if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION)
return() return()
endif() 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. # Use the Python interpreter to find the libs.
if(NOT PythonLibsNew_FIND_VERSION) if(NOT PythonLibsNew_FIND_VERSION)
set(PythonLibsNew_FIND_VERSION "") set(PythonLibsNew_FIND_VERSION "")
endif() endif()
if(PythonLibsNew_FIND_REQUIRED)
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} REQUIRED) find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required}
else() ${_pythonlibs_quiet})
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION})
endif()
if(NOT PYTHONINTERP_FOUND) if(NOT PYTHONINTERP_FOUND)
set(PYTHONLIBS_FOUND FALSE) set(PYTHONLIBS_FOUND FALSE)
@ -71,7 +102,7 @@ if(NOT PYTHONINTERP_FOUND)
return() return()
endif() 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 # testing whether sys has the gettotalrefcount function is a reliable, cross-platform
# way to detect a CPython debug interpreter. # 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_FOUND - true if pybind11 and all required components found on the system
pybind11_VERSION - pybind11 version in format Major.Minor.Release 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_DIRS - Directories where pybind11 and python headers are located.
pybind11_INCLUDE_DIR - Directory where pybind11 headers are located. pybind11_INCLUDE_DIR - Directory where pybind11 headers are located.
pybind11_DEFINITIONS - Definitions necessary to use pybind11, namely USING_pybind11. 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 Python headers, libraries (as needed by platform), and the C++ standard
are attached to the target. 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:: Classic mode::
Set PythonLibsNew variables to influence python detection and Set PythonLibsNew variables to influence python detection and
CMAKE_CXX_STANDARD to influence standard setting. :: CMAKE_CXX_STANDARD to influence standard setting. ::
find_package(pybind11 CONFIG REQUIRED) find_package(pybind11 CONFIG REQUIRED)
message(STATUS "Found pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}: ${pybind11_INCLUDE_DIRS}")
# Create an extension module # Create an extension module
add_library(mylib MODULE main.cpp) 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 # Or embed the Python interpreter into an executable
add_executable(myexe main.cpp) add_executable(myexe main.cpp)
target_link_libraries(myexe pybind11::embed) target_link_libraries(myexe PUBLIC pybind11::embed)
Suggested usage:: 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 PATH - environment variable, set to bin directory of this package
CMAKE_DISABLE_FIND_PACKAGE_pybind11 - CMake variable, disables CMAKE_DISABLE_FIND_PACKAGE_pybind11 - CMake variable, disables
find_package(pybind11) when not REQUIRED, perhaps to force internal build 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@ @PACKAGE_INIT@
# Location of pybind11/pybind11.h # Location of pybind11/pybind11.h
@ -72,50 +122,19 @@ set(pybind11_VERSION_TYPE "@pybind11_VERSION_TYPE@")
check_required_components(pybind11) 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}") include("${CMAKE_CURRENT_LIST_DIR}/pybind11Common.cmake")
find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED)
list(REMOVE_AT CMAKE_MODULE_PATH -1)
set_property( if(NOT pybind11_FIND_QUIETLY)
TARGET pybind11::pybind11 message(
APPEND STATUS
PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_DIRS}) "Found pybind11: ${pybind11_INCLUDE_DIR} (found version \"${pybind11_VERSION}\" ${pybind11_VERSION_TYPE})"
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")
endif() 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 # All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file. # 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 # Add a CMake parameter for choosing a desired Python version
if(NOT PYBIND11_PYTHON_VERSION) if(NOT PYBIND11_PYTHON_VERSION)
set(PYBIND11_PYTHON_VERSION set(PYBIND11_PYTHON_VERSION
@ -18,112 +25,91 @@ set(Python_ADDITIONAL_VERSIONS
CACHE INTERNAL "") CACHE INTERNAL "")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 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) 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
# Warn or error if old variable name used ${PYTHON_INCLUDE_DIRS}
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()
# 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()
# 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 "") CACHE INTERNAL "")
set(PYBIND11_LTO_LINKER_FLAGS 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 "") CACHE INTERNAL "")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") if(PYBIND11_MASTER_PROJECT)
set(cxx_append "") if(PYTHON_MODULE_EXTENSION MATCHES "pypy")
set(linker_append "") if(NOT DEFINED PYPY_VERSION)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT APPLE) execute_process(
# Clang Gold plugin does not support -Os; append -O3 to MinSizeRel builds to override it COMMAND ${PYTHON_EXECUTABLE} -c
set(linker_append ";$<$<CONFIG:MinSizeRel>:-O3>") [=[import sys; print(".".join(map(str, sys.pypy_version_info[:3])))]=]
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") OUTPUT_VARIABLE pypy_version)
set(cxx_append ";-fno-fat-lto-objects") set(PYPY_VERSION
${pypy_version}
CACHE INTERNAL "")
endif() endif()
message(STATUS "PYPY ${PYPY_VERSION} (Py ${PYTHON_VERSION})")
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()
if(PYBIND11_LTO_CXX_FLAGS)
message(STATUS "LTO enabled")
else() else()
message(STATUS "LTO disabled (not supported by the compiler and/or linker)") message(STATUS "PYTHON ${PYTHON_VERSION}")
endif() endif()
endif() endif()
# Enable LTO flags if found, except for Debug builds # Only add Python for build - must be added during the import for config since it has to be re-discovered.
if(PYBIND11_LTO_CXX_FLAGS) set_property(
set(not_debug "$<NOT:$<CONFIG:Debug>>") TARGET pybind11::pybind11
set(cxx_lang "$<COMPILE_LANGUAGE:CXX>") APPEND
target_compile_options(${target_name} PROPERTY INTERFACE_INCLUDE_DIRECTORIES $<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>)
PRIVATE "$<$<AND:${not_debug},${cxx_lang}>:${PYBIND11_LTO_CXX_FLAGS}>")
# 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() endif()
if(PYBIND11_LTO_LINKER_FLAGS)
target_link_libraries(${target_name} PRIVATE "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") 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(PYTHON_VERSION VERSION_LESS 3)
set_property(
TARGET pybind11::pybind11
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python2_no_register)
endif() endif()
set_property(
TARGET pybind11::embed
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11 $<BUILD_INTERFACE:${PYTHON_LIBRARIES}>)
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() endfunction()
# Build a Python extension module: # Build a Python extension module:
@ -132,7 +118,7 @@ endfunction()
# #
function(pybind11_add_module target_name) function(pybind11_add_module target_name)
set(options MODULE SHARED EXCLUDE_FROM_ALL NO_EXTRAS SYSTEM THIN_LTO) 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) if(ARG_MODULE AND ARG_SHARED)
message(FATAL_ERROR "Can't be both MODULE and SHARED") message(FATAL_ERROR "Can't be both MODULE and SHARED")
@ -159,74 +145,34 @@ function(pybind11_add_module target_name)
) )
endif() endif()
# Python debug libraries expose slightly different objects before 3.8 pybind11_extension(${target_name})
# 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}")
# -fvisibility=hidden is required to allow multiple modules compiled against # -fvisibility=hidden is required to allow multiple modules compiled against
# different pybind versions to work properly, and for some features (e.g. # different pybind versions to work properly, and for some features (e.g.
# py::module_local). We force it on everything inside the `pybind11` # py::module_local). We force it on everything inside the `pybind11`
# namespace; also turning it on for a pybind module compilation here avoids # namespace; also turning it on for a pybind module compilation here avoids
# potential warnings or issues from having mixed hidden/non-hidden types. # 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 CXX_VISIBILITY_PRESET "hidden"
set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden") CUDA_VISIBILITY_PRESET "hidden")
if(ARG_NO_EXTRAS) if(ARG_NO_EXTRAS)
return() return()
endif() endif()
if(CMAKE_VERSION VERSION_LESS 3.9 OR PYBIND11_CLASSIC_LTO) if(NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
_pybind11_add_lto_flags(${target_name} ${ARG_THIN_LTO}) if(ARG_THIN_LTO)
target_link_libraries(${target_name} PRIVATE pybind11::thin_lto)
else() else()
include(CheckIPOSupported) target_link_libraries(${target_name} PRIVATE pybind11::lto)
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}")
endif() endif()
endif() endif()
if(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo) 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})
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()
endif() endif()
if(MSVC) if(MSVC)
# /MP enables multithreaded builds (relevant when there are many files), /bigobj is target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
# 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()
endif() endif()
endfunction() endfunction()