-
Notifications
You must be signed in to change notification settings - Fork 80
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
187 lines (156 loc) · 6.41 KB
/
CMakeLists.txt
File metadata and controls
187 lines (156 loc) · 6.41 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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# Refactor the cmake/setup.py build to use scikit-build
# https://github.com/wjakob/nanobind_example
# Rather than creating multiple modules and dealing with multiple __init__.py
# files, we can create a single module and use __init__.py to import the
# submodules, create one extension module with submodules
# https://stackoverflow.com/a/77020918/148668
cmake_minimum_required(VERSION 3.15...3.27)
project(pyigl)
# For std::filesystem::path (generic_string)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
# ≥17 for return value optimization
# <20 for embree
set(CMAKE_CXX_STANDARD 17)
find_package(Python 3.8
REQUIRED COMPONENTS Interpreter Development.Module
OPTIONAL_COMPONENTS Development.SABIModule)
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()
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
# Enable FetchContent to download dependencies at configure time
include(FetchContent)
# Download and set up nanobind
FetchContent_Declare(
nanobind
GIT_REPOSITORY https://github.com/wjakob/nanobind.git
GIT_TAG v2.7.0
)
FetchContent_MakeAvailable(nanobind)
# Download and set up libigl
option(LIBIGL_COPYLEFT_CORE "Build target igl_copyleft::core" ON)
option(LIBIGL_COPYLEFT_CGAL "Build target igl_copyleft::cgal" ON)
option(LIBIGL_EMBREE "Build target igl::embree" ON)
option(LIBIGL_COPYLEFT_TETGEN "Build target igl_copyleft::tetgen" ON)
option(LIBIGL_RESTRICTED_TRIANGLE "Build target igl_restricted::triangle" ON)
FetchContent_Declare(
libigl
GIT_REPOSITORY https://github.com/libigl/libigl.git
GIT_TAG 678e1fff76815e0c4c5d1f025ee2129181cc7d86
)
FetchContent_MakeAvailable(libigl)
# set PYIGL_OUTPUT_DIRECTORY to [this dir]/igl
set(PYIGL_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/igl")
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
# Color output
include(UseColors)
# Extra warnings
include(Warnings)
# Use C++11/14
include(CXXFeatures)
# Generate position independent code by default
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE INTERNAL "")
# don't need to worry about nested modules (opengl/** are the only ones and
# those probably aren't ever getting python bindings)
#
# prefix is either "", "copyleft", or "restricted"
function(pyigl_include prefix name)
string(TOUPPER "${prefix}" prefix_uc)
string(TOUPPER "${name}" name_uc)
if(prefix_uc)
string(PREPEND prefix_uc _)
endif()
string(TOLOWER "${prefix_uc}" prefix_lc)
# if(LIBIGL${prefix_uc}_${name_uc}) or name == "core"
if(LIBIGL${prefix_uc}_${name_uc} OR name STREQUAL "core")
if("${prefix}" STREQUAL "copyleft")
if("${name}" STREQUAL "core")
set(subpath "copyleft")
else()
set(subpath "copyleft/${name}")
endif()
elseif("${name}" STREQUAL "core")
set(subpath "")
else() # "" or "restricted"
set(subpath "${name}")
endif()
file(GLOB sources "${CMAKE_CURRENT_SOURCE_DIR}/src/${subpath}/*.cpp")
## Just compile a single file
#list(FILTER sources EXCLUDE REGEX ".*/module\\.cpp$")
#list(GET sources 0 sources)
#list(APPEND sources "${CMAKE_CURRENT_SOURCE_DIR}/src/${subpath}/module.cpp")
message(STATUS "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
message(STATUS "${prefix} ${name} sources: ${sources}")
set(BINDING_SOURCES ${sources})
list(FILTER BINDING_SOURCES EXCLUDE REGEX ".*/module\\.cpp$")
# keep just the first in the list and overwrite BINDING_SOURCES
# Generate the function calls based on filenames
set(BINDING_DECLARATIONS "")
foreach(source_file ${BINDING_SOURCES})
get_filename_component(filename ${source_file} NAME_WE)
set(BINDING_DECLARATIONS "${BINDING_DECLARATIONS}extern void bind_${filename}(nb::module_ &m);\n")
set(BINDING_INVOCATIONS "${BINDING_INVOCATIONS} bind_${filename}(m);\n")
endforeach()
# make a temporary folder in the build directory to store the generated files
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/include/${subpath}")
file(MAKE_DIRECTORY "${generated_dir}")
# write contents into BINDING_DECLARATIONS.h and BINDING_INVOCATIONS.h
file(WRITE "${generated_dir}/BINDING_DECLARATIONS.in" "${BINDING_DECLARATIONS}")
file(WRITE "${generated_dir}/BINDING_INVOCATIONS.in" "${BINDING_INVOCATIONS}")
set(target_name "pyigl${prefix_lc}_${name}")
nanobind_add_module(
${target_name}
STABLE_ABI
${sources})
# important for scikit-build
install(TARGETS ${target_name} LIBRARY DESTINATION "igl/${subpath}")
if("${name}" STREQUAL "core")
target_link_libraries(${target_name} PRIVATE igl::core)
else()
target_link_libraries(${target_name} PRIVATE igl::core igl${prefix_lc}::${name})
endif()
target_include_directories(${target_name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/include")
target_include_directories(${target_name} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
set(output_dir "${PYIGL_OUTPUT_DIRECTORY}/${subpath}")
file(MAKE_DIRECTORY ${output_dir})
file(WRITE "${output_dir}/__init__.py" "from .${target_name} import *\n")
install(FILES "${output_dir}/__init__.py" DESTINATION "igl/${subpath}")
set_target_properties(${target_name} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${output_dir}"
RUNTIME_OUTPUT_DIRECTORY "${output_dir}"
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${output_dir}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${output_dir}"
)
set(PYI_OUTPUT "${output_dir}/${target_name}.pyi")
nanobind_add_stub(
${target_name}_stub
MODULE ${target_name}
OUTPUT ${PYI_OUTPUT}
PYTHON_PATH $<TARGET_FILE_DIR:${target_name}>
DEPENDS ${target_name}
)
install(FILES "${PYI_OUTPUT}" DESTINATION "igl/${subpath}")
# just to add dependency?
if("${name}" STREQUAL "core")
else()
target_link_libraries(pyigl_core INTERFACE ${target_name})
endif()
endif()
endfunction()
pyigl_include("" "core")
if(LIBIGL_COPYLEFT_CORE)
pyigl_include("copyleft" "core")
endif()
if(LIBIGL_COPYLEFT_CGAL)
pyigl_include("copyleft" "cgal")
endif()
if(LIBIGL_EMBREE)
pyigl_include("" "embree")
endif()
if(LIBIGL_COPYLEFT_TETGEN)
pyigl_include("copyleft" "tetgen")
endif()
if(LIBIGL_RESTRICTED_TRIANGLE)
pyigl_include("restricted" "triangle")
endif()