forked from shap/shap
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
142 lines (111 loc) · 4.22 KB
/
Copy pathCMakeLists.txt
File metadata and controls
142 lines (111 loc) · 4.22 KB
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
# Followed https://nanobind.readthedocs.io/en/latest/building.html
cmake_minimum_required(VERSION 3.15...3.27)
project(shap_extensions LANGUAGES CXX)
if (NOT SKBUILD)
message(FATAL_ERROR "\
This CMakeLists.txt is meant to be used with scikit-build.
Please use 'python -m pip install .', not 'cmake'.")
endif()
# Find the Python interpreter and development components.
if (CMAKE_VERSION VERSION_LESS 3.18)
set(DEV_MODULE Development)
else()
set(DEV_MODULE Development.Module)
endif()
find_package(Python 3.12
COMPONENTS Interpreter ${DEV_MODULE} REQUIRED
OPTIONAL_COMPONENTS Development.SABIModule)
# Perform an optimized release build unless otherwise specified
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# ==============================================================================
# Build the nanobind extension module (cutils)
# ==============================================================================
# Detect the installed nanobind package and import it into CMake
find_package(nanobind CONFIG REQUIRED)
# Create the cutils module using nanobind
nanobind_add_module(
_cutils
# This extension is free-threaded
FREE_THREADED
# Target the stable ABI of Python 3.12+, reducing the number of binary wheels
STABLE_ABI
# Build libnanobind as a static library and link it into the module
NB_STATIC
# Sources for the cutils module
shap/cutils/cutils.cpp
)
nanobind_add_stub(
_cutils_stub
MODULE _cutils
OUTPUT _cutils.pyi
PYTHON_PATH $<TARGET_FILE_DIR:_cutils>
MARKER_FILE py.typed
DEPENDS _cutils
)
# Keep generated typing artifacts visible to language servers during local/editable
# development. VS Code/Pylance resolves this workspace package from source.
add_custom_command(
TARGET _cutils_stub POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/_cutils.pyi
${CMAKE_CURRENT_SOURCE_DIR}/shap/_cutils.pyi
)
# Install the module to shap
install(TARGETS _cutils LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME})
# ==============================================================================
# Build the Tree Logic extension module (cext)
# ==============================================================================
# Check if the SABI version is being requested
if(NOT "${SKBUILD_SABI_VERSION}" STREQUAL "")
set(USE_SABI USE_SABI ${SKBUILD_SABI_VERSION})
endif()
python_add_library(
_cext MODULE
# Target the stable ABI of Python 3.12+, reducing the number of binary wheels
${USE_SABI} WITH_SOABI
# Sources for the cext module
shap/cext/_cext.cc
)
# Get the include directory for NumPy and add it to the include path
execute_process(
COMMAND "${PYTHON_EXECUTABLE}"
-c "import numpy; print(numpy.get_include())"
OUTPUT_VARIABLE NUMPY_INCLUDE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
target_include_directories(_cext PUBLIC ${NUMPY_INCLUDE_DIR})
# Install directive for scikit-build-core
install(TARGETS _cext LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME})
# ==============================================================================
# Optional: Build the GPU Tree SHAP extension module (cext_gpu)
# Enabled via: SHAP_ENABLE_CUDA=1 pip install .
# ==============================================================================
if(DEFINED ENV{SHAP_ENABLE_CUDA})
enable_language(CUDA)
find_package(CUDAToolkit REQUIRED)
python_add_library(
_cext_gpu MODULE
${USE_SABI} WITH_SOABI
# The .cu file is compiled by nvcc, the .cc file by the host compiler
shap/cext/_cext_gpu.cu
shap/cext/_cext_gpu.cc
)
target_include_directories(_cext_gpu PUBLIC ${NUMPY_INCLUDE_DIR})
target_link_libraries(_cext_gpu PRIVATE CUDA::cudart)
set_target_properties(_cext_gpu PROPERTIES
CUDA_ARCHITECTURES "60;70;75;80"
CUDA_STANDARD 14
CUDA_EXTENSIONS ON
)
# nvcc flags matching the previous setup.py build
target_compile_options(_cext_gpu PRIVATE
$<$<COMPILE_LANGUAGE:CUDA>:
--expt-extended-lambda
--expt-relaxed-constexpr
>
)
install(TARGETS _cext_gpu LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME})
endif()