Unverified Commit 1729aae9 authored by Henry Schreiner's avatar Henry Schreiner Committed by GitHub
Browse files

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
parent 69821d9e
...@@ -31,11 +31,13 @@ jobs: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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
......
...@@ -14,19 +14,22 @@ jobs: ...@@ -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: ...@@ -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
...@@ -32,7 +32,7 @@ MANIFEST ...@@ -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
......
...@@ -5,9 +5,9 @@ ...@@ -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) ...@@ -41,11 +41,22 @@ include(GNUInstallDirs)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
include(CMakeDependentOption) 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 # 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() ...@@ -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() ...@@ -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
target_include_directories( # Build the headers-only target (no Python included):
pybind11 ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}> add_library(headers INTERFACE)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) add_library(pybind11::headers ALIAS headers) # to match exported target
# 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) include("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11Common.cmake")
target_compile_features(pybind11 INTERFACE cxx_inheriting_constructors cxx_user_literals
cxx_right_angle_brackets)
else()
# This was added in CMake 3.8, but we are keeping a consistent breaking
# point for the config file at 3.13. A config generated by CMake 3.13+
# can only be read in 3.13+ due to the SHELL usage later, so this is safe to do.
target_compile_features(pybind11 INTERFACE cxx_std_11)
endif()
add_library(module INTERFACE)
add_library(pybind11::module ALIAS module)
target_link_libraries(module INTERFACE pybind11::pybind11)
# See https://github.com/Kitware/CMake/blob/master/Modules/CMakePlatformId.h.in for platform IDs if(NOT PYBIND11_MASTER_PROJECT AND NOT pybind11_FIND_QUIETLY)
# Note: CMake 3.15 allows $<PLATFORM_ID:Windows,Cygwin> message(STATUS "Using pybind11: (version \"${pybind11_VERSION}\" ${pybind11_VERSION_TYPE})")
target_link_libraries( endif()
module
INTERFACE
"$<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Cygwin>>:$<BUILD_INTERFACE:${PYTHON_LIBRARIES}>>")
if(CMAKE_VERSION VERSION_LESS 3.13) # Relative directory setting
target_link_libraries(module INTERFACE "$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>") if(USE_PYTHON_INCLUDE_DIR AND DEFINED Python_INCLUDE_DIRS)
else() file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${Python_INCLUDE_DIRS})
# SHELL (3.12+) forces this to remain together, and link_options was added in 3.13+ elseif(USE_PYTHON_INCLUDE_DIR AND DEFINED PYTHON_INCLUDE_DIR)
# This is safer, because you are ensured the deduplication pass in CMake will not consider file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_INCLUDE_DIRS})
# these separate and remove one but not the other.
target_link_options(module INTERFACE "$<$<PLATFORM_ID:Darwin>:SHELL:-undefined dynamic_lookup>")
endif() endif()
# Workaround for Python 2.7 and C++17 (C++14 as a warning) incompatibility # Fill in headers target
# This adds the flags -Wno-register and -Wno-deprecated-register if the compiler target_include_directories(
# is Clang 3.9+ or AppleClang and the compile language is CXX, or /wd5033 for MSVC (all languages, headers ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
# since MSVC didn't recognize COMPILE_LANGUAGE until CMake 3.11+). $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
set(clang_4plus
"$<AND:$<CXX_COMPILER_ID:Clang>,$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,3.9>>>") target_compile_features(headers INTERFACE cxx_inheriting_constructors cxx_user_literals
set(no_register "$<OR:${clang_4plus},$<CXX_COMPILER_ID:AppleClang>>") cxx_right_angle_brackets)
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) ...@@ -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() ...@@ -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()
# 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() endif()
...@@ -18,7 +18,7 @@ information, see :doc:`/compiling`. ...@@ -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)`
......
...@@ -6,6 +6,39 @@ Changelog ...@@ -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 CMake’s C++ standard system replaces
``PYBIND11_CPP_STANDARD``.
* Generated config file is now portable to different Python/compiler/CMake
versions.
* Virtual environments prioritized if ``PYTHON_EXECUTABLE`` is not set
(``venv``, ``virtualenv``, and ``conda``) (similar to the new FindPython
mode).
* Other CMake features now natively supported, like
``CMAKE_INTERPROCEDURAL_OPTIMIZATION``, ``set(CMAKE_CXX_VISIBILITY_PRESET
hidden)``.
* Optional :ref:`find-python-mode` and :ref:`nopython-mode` with CMake.
`#2370 <https://github.com/pybind/pybind11/pull/2370>`_
* Uninstall target added.
`#2265 <https://github.com/pybind/pybind11/pull/2265>`_ and
`#2346 <https://github.com/pybind/pybind11/pull/2346>`_
v2.5.0 (Mar 31, 2020) v2.5.0 (Mar 31, 2020)
----------------------------------------------------- -----------------------------------------------------
......
...@@ -33,8 +33,8 @@ extension module can be created with just a few lines of code: ...@@ -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. ...@@ -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. ...@@ -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`` ...@@ -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: ...@@ -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. ...@@ -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 ...@@ -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`. ...@@ -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)
......
breathe == 4.5.0 breathe==4.13.1
sphinx<3
sphinx_rtd_theme
...@@ -8,6 +8,53 @@ to a new version. But it goes into more detail. This includes things like ...@@ -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
==== ====
......
...@@ -5,9 +5,9 @@ ...@@ -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() ...@@ -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) ...@@ -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) ...@@ -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() ...@@ -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}) ...@@ -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()
......
# 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 "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
set(build_options if(PYBIND11_FINDPYTHON)
"-DCMAKE_PREFIX_PATH=${pybind11_BINARY_DIR}/mock_install" list(APPEND build_options "-DPYBIND11_FINDPYTHON=${PYBIND11_FINDPYTHON}")
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}") 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() ...@@ -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) ...@@ -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()
......
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)
......
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( ...@@ -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})
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) ...@@ -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})
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)
......
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() ...@@ -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})
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 ...@@ -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( ...@@ -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})
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() ...@@ -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
......
...@@ -64,4 +64,7 @@ if(NOT CATCH_VERSION OR CATCH_VERSION VERSION_LESS ${Catch_FIND_VERSION}) ...@@ -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)
...@@ -55,15 +55,46 @@ if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION) ...@@ -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) ...@@ -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.
# #
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment