|
- # ==============================================================================
- #
- # Copyright 2022 <Huawei Technologies Co., Ltd>
- #
- # Licensed under the Apache License, Version 2.0 (the "License"); you may not
- # use this file except in compliance with the License. You may obtain a copy of
- # the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- # License for the specific language governing permissions and limitations under
- # the License.
- # ==============================================================================
- #
- # Looking for pybind11 can be somewhat complicated now that there are two
- # possible packages: - pybind11 - pybind11-global
- #
- # Here we try our best to look for pybind11 in all possible locations and in a
- # meaningful way. In practice, this means that we look for a valid package in
- # the following order: 1. First we look in a virtualenv (if one is active) for
- # a) pybind11-global b) pybind11 >= 2.6.0 c) pybind11 < 2.6.0 && pybind11-cmake
- # 2. pybind11-gobal in user site (if not in a virtualenv) 3. pybind11-gobal in
- # global site package (also done if within a virtualenv) 4. pybind11 >= 2.6.0 in
- # user and global sites NB: if the version of pybind11 is more recent than
- # pybind11-global, we choose pybind11 5. pybind11 < 2.6.0 && pybind11-cmake in
- # user and global sites
- #
- # ==============================================================================
-
- # ~~~
- # Make sure that pybind11 finds the correct python version
- # - pybind11 < 2.6.0 uses find_package(PythonInterp ...)
- # - pybind11 >= 2.6.0 looks for the `python` command or PYTHON_EXECUTABLE
- # => specify PYTHON_EXECUTABLE manually to guarantee we find the same
- # interpreter and libraries as for other python packages
- # ~~~
- set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
- set(PYBIND11_PYTHON_VERSION ${Python_VERSION}) # maybe not strictly required
-
- macro(_pybind11_message)
- if(NOT pybind11_FIND_QUIETLY)
- message(${ARGN})
- endif()
- endmacro()
-
- _pybind11_message(CHECK_START "Looking for pybind11")
- list(APPEND CMAKE_MESSAGE_INDENT " ")
-
- # ==============================================================================
- # First detect whether we are in a virtualenv or not
-
- execute_process(
- COMMAND ${Python_EXECUTABLE} -c "import sys; print(int(sys.prefix != sys.base_prefix))"
- OUTPUT_VARIABLE _is_virtualenv
- ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- if(_is_virtualenv)
- # ~~~
- # Try to find in order within the virtualenv:
- # - pybind11-global
- # - pybind11 >= 2.6.0
- # - pybind11 < 2.6.0 with pybind11-cmake
- # - if all of that fails, revert to user and global sites (as far as is possible)
- # ~~~
-
- _pybind11_message(CHECK_START "Looking for pybind11-global in virtualenv")
-
- # Look for pybind11-global
- execute_process(
- COMMAND ${Python_EXECUTABLE} -c "import sys, os; print(os.path.join(sys.prefix, 'share', 'cmake', 'pybind11'))"
- OUTPUT_VARIABLE pybind11_DIR
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- if(NOT EXISTS pybind11_DIR)
- _pybind11_message(CHECK_FAIL "Not-found")
-
- # Could not find pybind11-global, try pybind11 >= 2.6.0
- _pybind11_message(CHECK_START "Looking for pybind11 >= 2.6.0 in virtualenv")
-
- __find_python_module(pybind11 VERSION 2.6.0)
- if(PYMOD_PYBIND11_FOUND)
- _pybind11_message(CHECK_PASS "Found")
- execute_process(
- COMMAND ${Python_EXECUTABLE} -m pybind11 --cmakedir
- OUTPUT_VARIABLE pybind11_DIR
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- else()
- _pybind11_message(CHECK_FAIL "Not-found")
- # Now try pybind11 < 2.6.0 && pybind11-cmake
- __find_python_module(pybind11-cmake)
- if(PYMOD_PYBIND11_CMAKE_FOUND)
- execute_process(
- COMMAND ${Python_EXECUTABLE} -c "import pybind11_cmake; print(pybind11_cmake.__path__[0])"
- OUTPUT_VARIABLE pybind11_DIR
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- endif()
- endif()
- else()
- _pybind11_message(CHECK_PASS "Found")
- endif()
-
- # Try to find some valid pybind11 config within the virtualenv
- find_package(pybind11 2.6.0 CONFIG QUIET NO_DEFAULT_PATH)
- endif()
-
- # ------------------------------------------------------------------------------
-
- if(NOT pybind11_FOUND)
- _pybind11_message(CHECK_START "Looking for pybind11-global in global and user sites")
-
- if(NOT _is_virtualenv)
- # Try pybind11-global in user site
- execute_process(
- COMMAND ${Python_EXECUTABLE} -m site --user-base
- RESULT_VARIABLE _status
- OUTPUT_VARIABLE _user_base
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- # NB: _status == 0 means user site enabled. Anything else and we really should not consider it
- if(_status EQUAL 0 AND EXISTS "${_user_base}/share/cmake/pybind11/")
- # cmake-lint: disable=C0103
- set(pybind11_DIR "${_user_base}/share/cmake/pybind11/")
- endif()
- endif()
-
- # Try to find pybind11-global either in user-site or global-site (even in the case of a virtualenv since we did not
- # find anything useful in it previously)
- find_package(pybind11 2.6.0 CONFIG QUIET)
-
- if(pybind11_FOUND)
- _pybind11_message(CHECK_PASS "Found")
- else()
- _pybind11_message(CHECK_PASS "Not-found")
- endif()
-
- if(NOT _is_virtualenv)
- _pybind11_message(CHECK_START "Looking for pybind11 Python module")
-
- # Try to find pybind11 either in user-site or global-site
- if(pybind11_FIND_QUIETLY)
- set(_args QUIET)
- endif()
- __find_python_module(pybind11 VERSION 2.6.0 ${_args})
- unset(_args)
-
- if(PYMOD_PYBIND11_FOUND)
- _pybind11_message(CHECK_PASS "Found")
- else()
- _pybind11_message(CHECK_PASS "Not-found")
- endif()
-
- if(PYMOD_PYBIND11_FOUND AND PYMOD_PYBIND11_VERSION VERSION_GREATER pybind11_VERSION)
- # We prefer pybind11 over pybind11 global if its version is more recent. This could typically be the case if a
- # user installs a more recent version of pybind11 in its user site.
- execute_process(
- COMMAND ${Python_EXECUTABLE} -m pybind11 --cmakedir
- OUTPUT_VARIABLE pybind11_DIR
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- endif()
-
- _pybind11_message(CHECK_START "Looking for pybind11 (final)")
-
- # Look for pybind11 again in case we have pybind11 more recent than pybind11-global
- find_package(pybind11 2.6.0 CONFIG QUIET NO_DEFAULT_PATH)
-
- # If we are not in a virtualenv, we should still try to look for pybind11 < 2.6.0 && pybind11-cmake
- if(NOT pybind11_FOUND)
- _pybind11_message(CHECK_PASS "Not-found")
-
- _pybind11_message(CHECK_START "Looking for pybind11-cmake")
- # If everything else fails, rely on the pybind11_cmake package
- __find_python_module(pybind11-cmake)
- if(PYMOD_PYBIND11_CMAKE_FOUND)
- _pybind11_message(CHECK_PASS "Done")
- execute_process(
- COMMAND ${Python_EXECUTABLE} -c "import pybind11_cmake; print(pybind11_cmake.__path__[0])"
- OUTPUT_VARIABLE pybind11_DIR
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- else()
- _pybind11_message(CHECK_FAIL "Failed")
- endif()
- else()
- _pybind11_message(CHECK_PASS "Found")
- endif()
- endif()
- endif()
-
- # ------------------------------------------------------------------------------
- # Now look for pybind11 using the CONFIG method one last time. This would typically only be useful in the case of
- # pybind11 < 2.6.0 located in either user or global sites.
-
- list(POP_BACK CMAKE_MESSAGE_INDENT)
- if(pybind11_DIR)
- _pybind11_message(CHECK_PASS "Done")
- else()
- _pybind11_message(CHECK_FAIL "Failed")
- endif()
- find_package(pybind11 2.6.0 CONFIG NO_DEFAULT_PATH)
-
- # ==============================================================================
-
- # With pybind11-cmake 1.0.0 we might need to fix the include path
- if(PYMOD_PYBIND11_CMAKE_FOUND)
- include(CheckCXXSourceCompiles)
- check_cxx_source_compiles("#include <pybind11/pybind11.h>
- int main() {return 0;}" pybind11_compiles)
-
- if(NOT pybind11_compiles)
- # This could happen with pybind11_cmake == 1.0.0 because there is a typo in the pybind11Config.cmake
- execute_process(
- COMMAND ${Python_EXECUTABLE} -c "import pybind11
- print(pybind11.get_include(False) + ';' + pybind11.get_include(True))"
- OUTPUT_VARIABLE _pybind11_inc_dir
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- get_directory_property(_inc_dirs INCLUDE_DIRECTORIES)
- list(FILTER _inc_dirs EXCLUDE REGEX .*pybind11_INCLUDE_DIR$)
- list(APPEND _inc_dirs ${_pybind11_inc_dir})
- set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${_inc_dirs}")
- endif()
- endif()
-
- # ==============================================================================
-
- if(pybind11_FOUND)
- if(NOT TARGET pybind11::headers)
- _pybind11_message(SEND_ERROR
- "Target pybind11::headers was not defined! Perhaps try updating pybind11 on your system?")
- endif()
- if(NOT TARGET pybind11::pybind11)
- _pybind11_message(SEND_ERROR
- "Target pybind11::pybind11 was not defined! Perhaps try updating pybind11 on your system?")
- endif()
- if(NOT TARGET pybind11::module)
- _pybind11_message(SEND_ERROR
- "Target pybind11::module was not defined! Perhaps try updating pybind11 on your system?")
- endif()
-
- # NB: workardound for NVHPC compiler that requires -isystem (e.g. for /usr/include)
- get_target_property(_include_dir pybind11::pybind11_headers INTERFACE_INCLUDE_DIRECTORIES)
-
- if(_include_dir)
- target_include_directories(pybind11::pybind11_headers SYSTEM INTERFACE ${_include_dir})
- endif()
- else()
- _pybind11_message(STATUS "pybind11 was not found on your system or it is an incompatible version")
- _pybind11_message(STATUS " -> will be fetching pybind11 from an external Git repository")
-
- set(PKG_NAME pybind11)
- set(PKG_ROOT ${DEP_DIR}/${PKG_NAME}-src)
-
- set(URL "https://gitee.com/mirrors/pybind11/repository/archive/v2.9.0.tar.gz")
-
- FetchContent_Declare(${PKG_NAME} URL ${URL})
- FetchContent_GetProperties(${PKG_NAME})
- if(NOT ${PKG_NAME}_POPULATED)
- FetchContent_Populate(${PKG_NAME})
- endif()
-
- include_directories(${PKG_ROOT}/include)
- add_subdirectory(${PKG_ROOT} pybind11-build)
- endif()
-
- # ------------------------------------------------------------------------------
-
- include(FindPackageHandleStandardArgs)
- find_package_handle_standard_args(
- pybind11
- REQUIRED_VARS pybind11_INCLUDE_DIR
- VERSION_VAR pybind11_VERSION)
-
- # ------------------------------------------------------------------------------
-
- # For debugging
- if(pybind11_FOUND)
- _pybind11_message(STATUS "Found pybind11 using the CONFIG method in ${pybind11_DIR}")
- _pybind11_message(STATUS "Found pybind11 and defined the pybind11::pybind11 imported target:")
- _pybind11_message(STATUS " - include: ${pybind11_INCLUDE_DIR}")
- _pybind11_message(STATUS " - version: ${pybind11_VERSION}")
- endif()
-
- # ==============================================================================
-
- mark_as_advanced(pybind11_DIR)
-
- # ==============================================================================
|