1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
#------------------------------------------------------------------------------#
# Distributed under the OSI-approved Apache License, Version 2.0. See
# accompanying file Copyright.txt for details.
#------------------------------------------------------------------------------#
#
# PythonModule
# -----------
#
# Try to find the path to a python module
#
# This module defines the following variables:
#
# PythonModule_${module_NAME}_FOUND - System has the module in question
#
# and the following imported targets:
# Python::${module_NAME}
#
# This is intented to be called by specifying components for the module name
# and any additional header files and libraries that may be needed to interface
# with it.
#
# For example, say you want to search for mpi4py but you also need it's header
# files to use for interfacing with your own python bindings that use MPI.
# You would call:
#
# find_package(PythonModule REQUIRED COMPONENTS mpi4py mpi4py/mpi4py.h)
#
# If found, this will generate an interface target with the appropriate usage
# requirements.
#
function(__get_filename_label fname var)
get_filename_component(fname_dir "${fname}" DIRECTORY)
get_filename_component(fname_nam "${fname}" NAME_WE)
set(fname_label "${fname_dir}_${fname_nam}")
string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" fname_label "${fname_label}")
set(${var} ${fname_label} PARENT_SCOPE)
endfunction()
# Parse out the components
set(module_INCLUDES)
set(module_LIBRARIES)
foreach(comp IN LISTS PythonModule_FIND_COMPONENTS)
if(comp MATCHES "^[a-zA-Z0-9_]*$")
set(module_NAME ${comp})
elseif(comp MATCHES "\\.h$")
list(APPEND module_INCLUDES "${comp}")
elseif(comp MATCHES "\\${CMAKE_SHARED_LIBRARY_SUFFIX}")
list(APPEND module_LIBRARIES "${comp}")
else()
message(FATAL_ERROR "${comp}: Unknown python module component")
endif()
endforeach()
if(NOT module_NAME)
message(FATAL_ERROR "Unspecified Python module name")
endif()
if(NOT PythonModule_${module_NAME}_FOUND)
set(PythonModule_${module_NAME}_PATH "" CACHE PATH "Python module ${module_NAME}")
mark_as_advanced(PythonModule_${module_NAME}_PATH)
# Try to handle the cross compiling case
if(NOT PythonModule_${module_NAME}_PATH)
if(CMAKE_CROSS_COMPILING)
message(ERROR "find_python_module() invoked in cross-compiling mode, please set the following cache variables appropriately:")
message(" PythonModule_${module_NAME}_PATH (advanced)")
message("For details see ${CMAKE_BINARY_DIR}/TryRunResults.cmake")
file(APPEND "${CMAKE_BINARY_DIR}/TryRunResults.cmake" "
set( PythonModule_${module_NAME}_PATH
\"PLEASE_FILL_OUT\"
CACHE PATH \"Python module ${module_NAME}\" FORCE)
")
else()
if(NOT Python_Interpreter_FOUND)
include(CMakeFindDependencyMacro)
find_dependency(Python COMPONENTS Interpreter)
endif()
if(Python_Interpreter_FOUND)
execute_process(
COMMAND
${Python_EXECUTABLE}
-c "import ${module_NAME}; print(${module_NAME}.__path__[0])"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE error
)
if(result EQUAL 0)
string(STRIP "${output}" output)
set(PythonModule_${module_NAME}_PATH "${output}"
CACHE PATH "Python module ${module_NAME}" FORCE)
endif()
endif()
endif()
endif()
set(required_vars PythonModule_${module_NAME}_PATH)
set(include_vars)
set(library_vars)
if(PythonModule_${module_NAME}_PATH)
# Locate interface includes
foreach(inc IN LISTS module_INCLUDES)
__get_filename_label("${inc}" inc_label)
set(inc_var PythonModule_${module_NAME}_${inc_label}_INCLUDE_DIR)
list(APPEND include_vars ${inc_var})
find_path(${inc_var} ${inc}
HINTS ${PythonModule_${module_NAME}_PATH}/include
NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
)
endforeach()
# Locate interface libraries
foreach(lib IN LISTS module_LIBRARY)
__get_filename_label("${lib}" lib_label)
set(lib_var PythonModule_${module_NAME}_${lib_label}_LIBRARY)
list(APPEND library_vars ${lib_var})
find_file(${lib_var} ${lib}
HINTS ${PythonModule_${module_NAME}_PATH}
NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
)
endforeach()
list(APPEND required_vars ${include_vars} ${library_vars})
endif()
include(FindPackageHandleStandardArgs)
set(CMAKE_FIND_PACKAGE_NAME PythonModule_${module_NAME})
foreach(VAR IN ITEMS REQUIRED QUIETLY VERSION COMPONENTS)
if(DEFINED PythonModule_FIND_${VAR})
set(PythonModule_${module_NAME}_FIND_${VAR} "${PythonModule_FIND_${VAR}}")
else()
unset(PythonModule_${module_NAME}_FIND_${VAR})
endif()
endforeach()
find_package_handle_standard_args(PythonModule_${module_NAME}
FOUND_VAR PythonModule_${module_NAME}_FOUND
REQUIRED_VARS ${required_vars}
)
endif()
if(PythonModule_${module_NAME}_FOUND AND
NOT TARGET ${module_NAME})
add_library(${module_NAME} INTERFACE)
add_library(Python::${module_NAME} ALIAS ${module_NAME})
foreach(inc_var IN LISTS include_vars)
target_include_directories(${module_NAME} SYSTEM INTERFACE ${${inc_var}})
endforeach()
foreach(lib_var IN LISTS library_vars)
target_link_libraries(${module_NAME} INTERFACE ${${lib_var}})
endforeach()
endif()
|