Add missing cmake
This commit is contained in:
parent
bbcc840989
commit
24f6cc99fa
|
@ -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)
|
|
@ -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)
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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)
|
Loading…
Reference in New Issue