Add missing cmake

This commit is contained in:
Seth Hillbrand 2021-04-05 13:06:34 -07:00
parent bbcc840989
commit 24f6cc99fa
6 changed files with 1297 additions and 0 deletions

View File

@ -0,0 +1,70 @@
# - Find the Catch test framework or download it (single header)
#
# This is a quick module for internal use. It assumes that Catch is
# REQUIRED and that a minimum version is provided (not EXACT). If
# a suitable version isn't found locally, the single header file
# will be downloaded and placed in the build dir: PROJECT_BINARY_DIR.
#
# This code sets the following variables:
# CATCH_INCLUDE_DIR - path to catch.hpp
# CATCH_VERSION - version number
if(NOT Catch_FIND_VERSION)
message(FATAL_ERROR "A version number must be specified.")
elseif(Catch_FIND_REQUIRED)
message(FATAL_ERROR "This module assumes Catch is not required.")
elseif(Catch_FIND_VERSION_EXACT)
message(FATAL_ERROR "Exact version numbers are not supported, only minimum.")
endif()
# Extract the version number from catch.hpp
function(_get_catch_version)
file(
STRINGS "${CATCH_INCLUDE_DIR}/catch.hpp" version_line
REGEX "Catch v.*"
LIMIT_COUNT 1)
if(version_line MATCHES "Catch v([0-9]+)\\.([0-9]+)\\.([0-9]+)")
set(CATCH_VERSION
"${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}"
PARENT_SCOPE)
endif()
endfunction()
# Download the single-header version of Catch
function(_download_catch version destination_dir)
message(STATUS "Downloading catch v${version}...")
set(url https://github.com/philsquared/Catch/releases/download/v${version}/catch.hpp)
file(DOWNLOAD ${url} "${destination_dir}/catch.hpp" STATUS status)
list(GET status 0 error)
if(error)
message(FATAL_ERROR "Could not download ${url}")
endif()
set(CATCH_INCLUDE_DIR
"${destination_dir}"
CACHE INTERNAL "")
endfunction()
# Look for catch locally
find_path(
CATCH_INCLUDE_DIR
NAMES catch.hpp
PATH_SUFFIXES catch2)
if(CATCH_INCLUDE_DIR)
_get_catch_version()
endif()
# Download the header if it wasn't found or if it's outdated
if(NOT CATCH_VERSION OR CATCH_VERSION VERSION_LESS ${Catch_FIND_VERSION})
if(DOWNLOAD_CATCH)
_download_catch(${Catch_FIND_VERSION} "${PROJECT_BINARY_DIR}/catch/")
_get_catch_version()
else()
set(CATCH_FOUND FALSE)
return()
endif()
endif()
add_library(Catch2::Catch2 IMPORTED INTERFACE)
set_property(TARGET Catch2::Catch2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CATCH_INCLUDE_DIR}")
set(CATCH_FOUND TRUE)

View File

@ -0,0 +1,86 @@
# - Try to find Eigen3 lib
#
# This module supports requiring a minimum version, e.g. you can do
# find_package(Eigen3 3.1.2)
# to require version 3.1.2 or newer of Eigen3.
#
# Once done this will define
#
# EIGEN3_FOUND - system has eigen lib with correct version
# EIGEN3_INCLUDE_DIR - the eigen include directory
# EIGEN3_VERSION - eigen version
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@free.fr>
# Copyright (c) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
if(NOT Eigen3_FIND_VERSION)
if(NOT Eigen3_FIND_VERSION_MAJOR)
set(Eigen3_FIND_VERSION_MAJOR 2)
endif(NOT Eigen3_FIND_VERSION_MAJOR)
if(NOT Eigen3_FIND_VERSION_MINOR)
set(Eigen3_FIND_VERSION_MINOR 91)
endif(NOT Eigen3_FIND_VERSION_MINOR)
if(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION_PATCH 0)
endif(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION
"${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
endif(NOT Eigen3_FIND_VERSION)
macro(_eigen3_check_version)
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match
"${_eigen3_version_header}")
set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match
"${_eigen3_version_header}")
set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match
"${_eigen3_version_header}")
set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK FALSE)
else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK TRUE)
endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
if(NOT EIGEN3_VERSION_OK)
message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
"but at least version ${Eigen3_FIND_VERSION} is required")
endif(NOT EIGEN3_VERSION_OK)
endmacro(_eigen3_check_version)
if(EIGEN3_INCLUDE_DIR)
# in cache already
_eigen3_check_version()
set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
else(EIGEN3_INCLUDE_DIR)
if(NOT DEFINED KDE4_INCLUDE_DIR)
set(KDE4_INCLUDE_DIR "")
endif()
find_path(
EIGEN3_INCLUDE_DIR
NAMES signature_of_eigen3_matrix_library
PATHS ${CMAKE_INSTALL_PREFIX}/include ${KDE4_INCLUDE_DIR}
PATH_SUFFIXES eigen3 eigen)
if(EIGEN3_INCLUDE_DIR)
_eigen3_check_version()
endif(EIGEN3_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
mark_as_advanced(EIGEN3_INCLUDE_DIR)
endif(EIGEN3_INCLUDE_DIR)

View File

@ -0,0 +1,257 @@
# - Find python libraries
# This module finds the libraries corresponding to the Python interpreter
# FindPythonInterp provides.
# This code sets the following variables:
#
# PYTHONLIBS_FOUND - have the Python libs been found
# PYTHON_PREFIX - path to the Python installation
# PYTHON_LIBRARIES - path to the python library
# PYTHON_INCLUDE_DIRS - path to where Python.h is found
# PYTHON_MODULE_EXTENSION - lib extension, e.g. '.so' or '.pyd'
# PYTHON_MODULE_PREFIX - lib name prefix: usually an empty string
# PYTHON_SITE_PACKAGES - path to installation site-packages
# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build
#
# Thanks to talljimbo for the patch adding the 'LDVERSION' config
# variable usage.
#=============================================================================
# Copyright 2001-2009 Kitware, Inc.
# Copyright 2012 Continuum Analytics, Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
# nor the names of their contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================
# Checking for the extension makes sure that `LibsNew` was found and not just `Libs`.
if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION)
return()
endif()
if(PythonLibsNew_FIND_QUIETLY)
set(_pythonlibs_quiet QUIET)
else()
set(_pythonlibs_quiet "")
endif()
if(PythonLibsNew_FIND_REQUIRED)
set(_pythonlibs_required REQUIRED)
endif()
# Check to see if the `python` command is present and from a virtual
# environment, conda, or GHA activation - if it is, try to use that.
if(NOT DEFINED PYTHON_EXECUTABLE)
if(DEFINED ENV{VIRTUAL_ENV})
find_program(
PYTHON_EXECUTABLE python
PATHS "$ENV{VIRTUAL_ENV}" "$ENV{VIRTUAL_ENV}/bin"
NO_DEFAULT_PATH)
elseif(DEFINED ENV{CONDA_PREFIX})
find_program(
PYTHON_EXECUTABLE python
PATHS "$ENV{CONDA_PREFIX}" "$ENV{CONDA_PREFIX}/bin"
NO_DEFAULT_PATH)
elseif(DEFINED ENV{pythonLocation})
find_program(
PYTHON_EXECUTABLE python
PATHS "$ENV{pythonLocation}" "$ENV{pythonLocation}/bin"
NO_DEFAULT_PATH)
endif()
if(NOT PYTHON_EXECUTABLE)
unset(PYTHON_EXECUTABLE)
endif()
endif()
# Use the Python interpreter to find the libs.
if(NOT PythonLibsNew_FIND_VERSION)
set(PythonLibsNew_FIND_VERSION "")
endif()
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required}
${_pythonlibs_quiet})
if(NOT PYTHONINTERP_FOUND)
set(PYTHONLIBS_FOUND FALSE)
set(PythonLibsNew_FOUND FALSE)
return()
endif()
# According to https://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
# testing whether sys has the gettotalrefcount function is a reliable, cross-platform
# way to detect a CPython debug interpreter.
#
# The library suffix is from the config var LDVERSION sometimes, otherwise
# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows.
execute_process(
COMMAND
"${PYTHON_EXECUTABLE}" "-c" "from distutils import sysconfig as s;import sys;import struct;
print('.'.join(str(v) for v in sys.version_info));
print(sys.prefix);
print(s.get_python_inc(plat_specific=True));
print(s.get_python_lib(plat_specific=True));
print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO'));
print(hasattr(sys, 'gettotalrefcount')+0);
print(struct.calcsize('@P'));
print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION'));
print(s.get_config_var('LIBDIR') or '');
print(s.get_config_var('MULTIARCH') or '');
"
RESULT_VARIABLE _PYTHON_SUCCESS
OUTPUT_VARIABLE _PYTHON_VALUES
ERROR_VARIABLE _PYTHON_ERROR_VALUE)
if(NOT _PYTHON_SUCCESS MATCHES 0)
if(PythonLibsNew_FIND_REQUIRED)
message(FATAL_ERROR "Python config failure:\n${_PYTHON_ERROR_VALUE}")
endif()
set(PYTHONLIBS_FOUND FALSE)
set(PythonLibsNew_FOUND FALSE)
return()
endif()
# Convert the process output into a list
if(WIN32)
string(REGEX REPLACE "\\\\" "/" _PYTHON_VALUES ${_PYTHON_VALUES})
endif()
string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES})
string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES})
list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST)
list(GET _PYTHON_VALUES 1 PYTHON_PREFIX)
list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR)
list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES)
list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION)
list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG)
list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P)
list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX)
list(GET _PYTHON_VALUES 8 PYTHON_LIBDIR)
list(GET _PYTHON_VALUES 9 PYTHON_MULTIARCH)
# Make sure the Python has the same pointer-size as the chosen compiler
# Skip if CMAKE_SIZEOF_VOID_P is not defined
if(CMAKE_SIZEOF_VOID_P AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}"))
if(PythonLibsNew_FIND_REQUIRED)
math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8")
math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8")
message(FATAL_ERROR "Python config failure: Python is ${_PYTHON_BITS}-bit, "
"chosen compiler is ${_CMAKE_BITS}-bit")
endif()
set(PYTHONLIBS_FOUND FALSE)
set(PythonLibsNew_FOUND FALSE)
return()
endif()
# The built-in FindPython didn't always give the version numbers
string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST})
list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH)
set(PYTHON_VERSION "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}")
# Make sure all directory separators are '/'
string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX "${PYTHON_PREFIX}")
string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}")
string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES "${PYTHON_SITE_PACKAGES}")
if(CMAKE_HOST_WIN32)
set(PYTHON_LIBRARY "${PYTHON_PREFIX}/libs/python${PYTHON_LIBRARY_SUFFIX}.lib")
# when run in a venv, PYTHON_PREFIX points to it. But the libraries remain in the
# original python installation. They may be found relative to PYTHON_INCLUDE_DIR.
if(NOT EXISTS "${PYTHON_LIBRARY}")
get_filename_component(_PYTHON_ROOT ${PYTHON_INCLUDE_DIR} DIRECTORY)
set(PYTHON_LIBRARY "${_PYTHON_ROOT}/libs/python${PYTHON_LIBRARY_SUFFIX}.lib")
endif()
# if we are in MSYS & MINGW, and we didn't find windows python lib, look for system python lib
if(DEFINED ENV{MSYSTEM}
AND MINGW
AND NOT EXISTS "${PYTHON_LIBRARY}")
if(PYTHON_MULTIARCH)
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}")
else()
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}")
endif()
unset(PYTHON_LIBRARY)
find_library(
PYTHON_LIBRARY
NAMES "python${PYTHON_LIBRARY_SUFFIX}"
PATHS ${_PYTHON_LIBS_SEARCH}
NO_DEFAULT_PATH)
endif()
# raise an error if the python libs are still not found.
if(NOT EXISTS "${PYTHON_LIBRARY}")
message(FATAL_ERROR "Python libraries not found")
endif()
else()
if(PYTHON_MULTIARCH)
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}")
else()
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}")
endif()
#message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}")
# Probably this needs to be more involved. It would be nice if the config
# information the python interpreter itself gave us were more complete.
find_library(
PYTHON_LIBRARY
NAMES "python${PYTHON_LIBRARY_SUFFIX}"
PATHS ${_PYTHON_LIBS_SEARCH}
NO_DEFAULT_PATH)
# If all else fails, just set the name/version and let the linker figure out the path.
if(NOT PYTHON_LIBRARY)
set(PYTHON_LIBRARY python${PYTHON_LIBRARY_SUFFIX})
endif()
endif()
mark_as_advanced(PYTHON_LIBRARY PYTHON_INCLUDE_DIR)
# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the
# cache entries because they are meant to specify the location of a single
# library. We now set the variables listed by the documentation for this
# module.
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
if(NOT PYTHON_DEBUG_LIBRARY)
set(PYTHON_DEBUG_LIBRARY "")
endif()
set(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}")
find_package_message(PYTHON "Found PythonLibs: ${PYTHON_LIBRARY}"
"${PYTHON_EXECUTABLE}${PYTHON_VERSION_STRING}")
set(PYTHONLIBS_FOUND TRUE)
set(PythonLibsNew_FOUND TRUE)
if(NOT PYTHON_MODULE_PREFIX)
set(PYTHON_MODULE_PREFIX "")
endif()

View File

@ -0,0 +1,397 @@
#[======================================================[.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
pybind11::opt_size - avoid optimizations that increase code size
Adds the following functions::
pybind11_strip(target) - strip target after building on linux/macOS
pybind11_find_import(module) - See if a module is installed.
#]======================================================]
# 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()
# If not run in Python mode, we still would like this to at least
# include pybind11's include directory:
set(pybind11_INCLUDE_DIRS
"${pybind11_INCLUDE_DIR}"
CACHE INTERNAL "Include directory for pybind11 (Python not requested)")
# --------------------- 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) # That's also clang-cl
# /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)
# /MP enables multithreaded builds (relevant when there are many files) for MSVC
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # no Clang no Intel
if(CMAKE_VERSION VERSION_LESS 3.11)
set_property(
TARGET pybind11::windows_extras
APPEND
PROPERTY INTERFACE_COMPILE_OPTIONS $<$<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()
endif()
# ----------------------- Optimize binary size --------------------------
add_library(pybind11::opt_size IMPORTED INTERFACE ${optional_global})
if(MSVC)
set(PYBIND11_OPT_SIZE /Os)
else()
set(PYBIND11_OPT_SIZE -Os)
endif()
set_property(
TARGET pybind11::opt_size
APPEND
PROPERTY INTERFACE_COMPILE_OPTIONS $<$<CONFIG:Release>:${PYBIND11_OPT_SIZE}>
$<$<CONFIG:MinSizeRel>:${PYBIND11_OPT_SIZE}>
$<$<CONFIG:RelWithDebInfo>:${PYBIND11_OPT_SIZE}>)
# ----------------------- 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_CPP_STANDARD")
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()
# --------------------- pybind11_find_import -------------------------------
if(NOT _pybind11_nopython)
# Check to see if modules are importable. Use REQUIRED to force an error if
# one of the modules is not found. <package_name>_FOUND will be set if the
# package was found (underscores replace dashes if present). QUIET will hide
# the found message, and VERSION will require a minimum version. A successful
# find will cache the result.
function(pybind11_find_import PYPI_NAME)
# CMake variables need underscores (PyPI doesn't care)
string(REPLACE "-" "_" NORM_PYPI_NAME "${PYPI_NAME}")
# Return if found previously
if(${NORM_PYPI_NAME}_FOUND)
return()
endif()
set(options "REQUIRED;QUIET")
set(oneValueArgs "VERSION")
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "" ${ARGN})
if(ARG_REQUIRED)
set(status_level FATAL_ERROR)
else()
set(status_level WARNING)
endif()
execute_process(
COMMAND
${${_Python}_EXECUTABLE} -c
"from pkg_resources import get_distribution; print(get_distribution('${PYPI_NAME}').version)"
RESULT_VARIABLE RESULT_PRESENT
OUTPUT_VARIABLE PKG_VERSION
ERROR_QUIET)
string(STRIP "${PKG_VERSION}" PKG_VERSION)
# If a result is present, this failed
if(RESULT_PRESENT)
set(${NORM_PYPI_NAME}_FOUND
${NORM_PYPI_NAME}-NOTFOUND
CACHE INTERNAL "")
# Always warn or error
message(
${status_level}
"Missing: ${PYPI_NAME} ${ARG_VERSION}\nTry: ${${_Python}_EXECUTABLE} -m pip install ${PYPI_NAME}"
)
else()
if(ARG_VERSION AND PKG_VERSION VERSION_LESS ARG_VERSION)
message(
${status_level}
"Version incorrect: ${PYPI_NAME} ${PKG_VERSION} found, ${ARG_VERSION} required - try upgrading"
)
else()
set(${NORM_PYPI_NAME}_FOUND
YES
CACHE INTERNAL "")
set(${NORM_PYPI_NAME}_VERSION
${PKG_VERSION}
CACHE INTERNAL "")
endif()
if(NOT ARG_QUIET)
message(STATUS "Found ${PYPI_NAME} ${PKG_VERSION}")
endif()
endif()
if(NOT ARG_VERSION OR (NOT PKG_VERSION VERSION_LESS ARG_VERSION))
# We have successfully found a good version, cache to avoid calling again.
endif()
endfunction()
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)
# CONFIG takes multiple values in CMake 3.19+, until then we have to use OR
set(is_debug "$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>")
set(not_debug "$<NOT:${is_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/macOS
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

@ -0,0 +1,267 @@
# 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)
else()
set(_pybind11_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()
# If a user finds Python, they may forget to include the Interpreter component
# and the following two steps require it. It is highly recommended by CMake
# when finding development libraries anyway, so we will require it.
if(NOT DEFINED ${_Python}_EXECUTABLE)
message(
FATAL_ERROR
"${_Python} was found without the Interpreter component. Pybind11 requires this component.")
endif()
if(NOT DEFINED PYTHON_IS_DEBUG)
# Debug check - see https://stackoverflow.com/questions/646518/python-how-to-detect-debug-Interpreter
execute_process(
COMMAND "${${_Python}_EXECUTABLE}" "-c"
"import sys; sys.exit(hasattr(sys, 'gettotalrefcount'))"
RESULT_VARIABLE _PYTHON_IS_DEBUG)
set(PYTHON_IS_DEBUG
"${_PYTHON_IS_DEBUG}"
CACHE INTERNAL "Python debug status")
endif()
# Get the suffix - SO is deprecated, should use EXT_SUFFIX, but this is
# required for PyPy3 (as of 7.3.1)
if(NOT DEFINED PYTHON_MODULE_EXTENSION)
execute_process(
COMMAND
"${${_Python}_EXECUTABLE}" "-c"
"from distutils import sysconfig as s;print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO'))"
OUTPUT_VARIABLE _PYTHON_MODULE_EXTENSION
ERROR_VARIABLE _PYTHON_MODULE_EXTENSION_ERR
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(_PYTHON_MODULE_EXTENSION STREQUAL "")
message(
FATAL_ERROR "pybind11 could not query the module file extension, likely the 'distutils'"
"package is not installed. Full error message:\n${_PYTHON_MODULE_EXTENSION_ERR}")
endif()
# This needs to be available for the pybind11_extension function
set(PYTHON_MODULE_EXTENSION
"${_PYTHON_MODULE_EXTENSION}"
CACHE INTERNAL "")
endif()
# Python debug libraries expose slightly different objects before 3.8
# https://docs.python.org/3.6/c-api/intro.html#debugging-builds
# https://stackoverflow.com/questions/39161202/how-to-work-around-missing-pymodule-create2-in-amd64-win-python35-d-lib
if(PYTHON_IS_DEBUG)
set_property(
TARGET pybind11::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)
# Only add Python for build - must be added during the import for config
# since it has to be re-discovered.
#
# This needs to be a target to be included after the local pybind11
# directory, just in case there there is an installed pybind11 sitting
# next to Python's includes. It also ensures Python is a SYSTEM library.
add_library(pybind11::python_headers INTERFACE IMPORTED)
set_property(
TARGET pybind11::python_headers PROPERTY INTERFACE_INCLUDE_DIRECTORIES
"$<BUILD_INTERFACE:${${_Python}_INCLUDE_DIRS}>")
set_property(
TARGET pybind11::pybind11
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python_headers)
set(pybind11_INCLUDE_DIRS
"${pybind11_INCLUDE_DIR}" "${${_Python}_INCLUDE_DIRS}"
CACHE INTERNAL "Directories where pybind11 and possibly Python headers are located")
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()
# WITHOUT_SOABI and WITH_SOABI will disable the custom extension handling used by pybind11.
# WITH_SOABI is passed on to python_add_library.
function(pybind11_add_module target_name)
cmake_parse_arguments(PARSE_ARGV 1 ARG
"STATIC;SHARED;MODULE;THIN_LTO;OPT_SIZE;NO_EXTRAS;WITHOUT_SOABI" "" "")
if(ARG_STATIC)
set(lib_type STATIC)
elseif(ARG_SHARED)
set(lib_type SHARED)
else()
set(lib_type MODULE)
endif()
if("${_Python}" STREQUAL "Python")
python_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
elseif("${_Python}" STREQUAL "Python3")
python3_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
elseif("${_Python}" STREQUAL "Python2")
python2_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
else()
message(FATAL_ERROR "Cannot detect FindPython version: ${_Python}")
endif()
target_link_libraries(${target_name} PRIVATE pybind11::headers)
if(lib_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()
# -fvisibility=hidden is required to allow multiple modules compiled against
# different pybind versions to work properly, and for some features (e.g.
# py::module_local). We force it on everything inside the `pybind11`
# namespace; also turning it on for a pybind module compilation here avoids
# potential warnings or issues from having mixed hidden/non-hidden types.
if(NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
endif()
if(NOT DEFINED CMAKE_CUDA_VISIBILITY_PRESET)
set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden")
endif()
# If we don't pass a WITH_SOABI or WITHOUT_SOABI, use our own default handling of extensions
if(NOT ARG_WITHOUT_SOABI OR NOT "WITH_SOABI" IN_LIST ARG_UNPARSED_ARGUMENTS)
pybind11_extension(${target_name})
endif()
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/macOS
pybind11_strip(${target_name})
endif()
if(MSVC)
target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
endif()
if(ARG_OPT_SIZE)
target_link_libraries(${target_name} PRIVATE pybind11::opt_size)
endif()
endfunction()
function(pybind11_extension name)
# The extension is precomputed
set_target_properties(${name} PROPERTIES PREFIX "" SUFFIX "${PYTHON_MODULE_EXTENSION}")
endfunction()

View File

@ -0,0 +1,220 @@
# tools/pybind11Tools.cmake -- Build system for the pybind11 modules
#
# Copyright (c) 2020 Wenzel Jakob <wenzel.jakob@epfl.ch>
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
# Built-in in CMake 3.5+
include(CMakeParseArguments)
if(pybind11_FIND_QUIETLY)
set(_pybind11_quiet QUIET)
else()
set(_pybind11_quiet "")
endif()
# If this is the first run, PYTHON_VERSION can stand in for PYBIND11_PYTHON_VERSION
if(NOT DEFINED PYBIND11_PYTHON_VERSION AND DEFINED PYTHON_VERSION)
message(WARNING "Set PYBIND11_PYTHON_VERSION to search for a specific version, not "
"PYTHON_VERSION (which is an output). Assuming that is what you "
"meant to do and continuing anyway.")
set(PYBIND11_PYTHON_VERSION
"${PYTHON_VERSION}"
CACHE STRING "Python version to use for compiling modules")
unset(PYTHON_VERSION)
unset(PYTHON_VERSION CACHE)
elseif(DEFINED PYBIND11_PYTHON_VERSION)
# If this is set as a normal variable, promote it
set(PYBIND11_PYTHON_VERSION
"${PYBIND11_PYTHON_VERSION}"
CACHE STRING "Python version to use for compiling modules")
else()
# Make an empty cache variable.
set(PYBIND11_PYTHON_VERSION
""
CACHE STRING "Python version to use for compiling modules")
endif()
# A user can set versions manually too
set(Python_ADDITIONAL_VERSIONS
"3.10;3.9;3.8;3.7;3.6;3.5;3.4"
CACHE INTERNAL "")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED ${_pybind11_quiet})
list(REMOVE_AT CMAKE_MODULE_PATH -1)
# Cache variables so pybind11_add_module can be used in parent projects
set(PYTHON_INCLUDE_DIRS
${PYTHON_INCLUDE_DIRS}
CACHE INTERNAL "")
set(PYTHON_LIBRARIES
${PYTHON_LIBRARIES}
CACHE INTERNAL "")
set(PYTHON_MODULE_PREFIX
${PYTHON_MODULE_PREFIX}
CACHE INTERNAL "")
set(PYTHON_MODULE_EXTENSION
${PYTHON_MODULE_EXTENSION}
CACHE INTERNAL "")
set(PYTHON_VERSION_MAJOR
${PYTHON_VERSION_MAJOR}
CACHE INTERNAL "")
set(PYTHON_VERSION_MINOR
${PYTHON_VERSION_MINOR}
CACHE INTERNAL "")
set(PYTHON_VERSION
${PYTHON_VERSION}
CACHE INTERNAL "")
set(PYTHON_IS_DEBUG
"${PYTHON_IS_DEBUG}"
CACHE INTERNAL "")
if(PYBIND11_MASTER_PROJECT)
if(PYTHON_MODULE_EXTENSION MATCHES "pypy")
if(NOT DEFINED PYPY_VERSION)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c
[=[import sys; sys.stdout.write(".".join(map(str, sys.pypy_version_info[:3])))]=]
OUTPUT_VARIABLE pypy_version)
set(PYPY_VERSION
${pypy_version}
CACHE INTERNAL "")
endif()
message(STATUS "PYPY ${PYPY_VERSION} (Py ${PYTHON_VERSION})")
else()
message(STATUS "PYTHON ${PYTHON_VERSION}")
endif()
endif()
# Only add Python for build - must be added during the import for config since
# it has to be re-discovered.
#
# This needs to be an target to it is included after the local pybind11
# directory, just in case there are multiple versions of pybind11, we want the
# one we expect.
add_library(pybind11::python_headers INTERFACE IMPORTED)
set_property(TARGET pybind11::python_headers PROPERTY INTERFACE_INCLUDE_DIRECTORIES
"$<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>")
set_property(
TARGET pybind11::pybind11
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python_headers)
set(pybind11_INCLUDE_DIRS
"${pybind11_INCLUDE_DIR}" "${PYTHON_INCLUDE_DIRS}"
CACHE INTERNAL "Directories where pybind11 and possibly Python headers are located")
# 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 pybind11::pybind11
APPEND
PROPERTY INTERFACE_COMPILE_DEFINITIONS Py_DEBUG)
endif()
set_property(
TARGET pybind11::module
APPEND
PROPERTY
INTERFACE_LINK_LIBRARIES pybind11::python_link_helper
"$<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Cygwin>>:$<BUILD_INTERFACE:${PYTHON_LIBRARIES}>>")
if(PYTHON_VERSION VERSION_LESS 3)
set_property(
TARGET pybind11::pybind11
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python2_no_register)
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()
# Build a Python extension module:
# pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL]
# [NO_EXTRAS] [THIN_LTO] [OPT_SIZE] source1 [source2 ...])
#
function(pybind11_add_module target_name)
set(options "MODULE;SHARED;EXCLUDE_FROM_ALL;NO_EXTRAS;SYSTEM;THIN_LTO;OPT_SIZE")
cmake_parse_arguments(ARG "${options}" "" "" ${ARGN})
if(ARG_MODULE AND ARG_SHARED)
message(FATAL_ERROR "Can't be both MODULE and SHARED")
elseif(ARG_SHARED)
set(lib_type SHARED)
else()
set(lib_type MODULE)
endif()
if(ARG_EXCLUDE_FROM_ALL)
set(exclude_from_all EXCLUDE_FROM_ALL)
else()
set(exclude_from_all "")
endif()
add_library(${target_name} ${lib_type} ${exclude_from_all} ${ARG_UNPARSED_ARGUMENTS})
target_link_libraries(${target_name} PRIVATE pybind11::module)
if(ARG_SYSTEM)
message(
STATUS
"Warning: this does not have an effect - use NO_SYSTEM_FROM_IMPORTED if using imported targets"
)
endif()
pybind11_extension(${target_name})
# -fvisibility=hidden is required to allow multiple modules compiled against
# different pybind versions to work properly, and for some features (e.g.
# py::module_local). We force it on everything inside the `pybind11`
# namespace; also turning it on for a pybind module compilation here avoids
# potential warnings or issues from having mixed hidden/non-hidden types.
if(NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
endif()
if(NOT DEFINED CMAKE_CUDA_VISIBILITY_PRESET)
set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden")
endif()
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)
pybind11_strip(${target_name})
endif()
if(MSVC)
target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
endif()
if(ARG_OPT_SIZE)
target_link_libraries(${target_name} PRIVATE pybind11::opt_size)
endif()
endfunction()
# Provide general way to call common Python commands in "common" file.
set(_Python
PYTHON
CACHE INTERNAL "" FORCE)