@@ -9,14 +9,29 @@ option (PYLIB_INCLUDE_SONAME "If ON, soname/soversion will be set for Python mod
99option (PYLIB_LIB_PREFIX "If ON, prefix the Python module with 'lib'" OFF )
1010set (PYMODULE_SUFFIX "" CACHE STRING "Suffix to add to Python module init namespace" )
1111set (OIIO_PYTHON_BINDINGS_BACKEND "pybind11" CACHE STRING
12- "Which Python binding backend to build: pybind11 or nanobind " )
12+ "Which Python binding backend(s) to build: pybind11, nanobind, or both " )
1313set_property (CACHE OIIO_PYTHON_BINDINGS_BACKEND PROPERTY STRINGS
14- pybind11 nanobind)
14+ pybind11 nanobind both )
1515
16+ # Normalize and validate the user-facing backend selector early so the rest
17+ # of the file can make simple boolean decisions.
1618string (TOLOWER "${OIIO_PYTHON_BINDINGS_BACKEND} " OIIO_PYTHON_BINDINGS_BACKEND)
17- if (NOT OIIO_PYTHON_BINDINGS_BACKEND MATCHES "^(pybind11|nanobind)$" )
19+ if (NOT OIIO_PYTHON_BINDINGS_BACKEND MATCHES "^(pybind11|nanobind|both )$" )
1820 message (FATAL_ERROR
19- "OIIO_PYTHON_BINDINGS_BACKEND must be pybind11 or nanobind" )
21+ "OIIO_PYTHON_BINDINGS_BACKEND must be one of: pybind11, nanobind, both" )
22+ endif ()
23+
24+ # Derive internal switches used by the top-level CMakeLists and the Python
25+ # helper macros below.
26+ set (OIIO_BUILD_PYTHON_PYBIND11 OFF )
27+ set (OIIO_BUILD_PYTHON_NANOBIND OFF )
28+ if (OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "pybind11"
29+ OR OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "both" )
30+ set (OIIO_BUILD_PYTHON_PYBIND11 ON )
31+ endif ()
32+ if (OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "nanobind"
33+ OR OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "both" )
34+ set (OIIO_BUILD_PYTHON_NANOBIND ON )
2035endif ()
2136
2237if (WIN32 )
@@ -65,7 +80,7 @@ macro (find_python)
6580 Python3_Development.Module_FOUND
6681 Python3_Interpreter_FOUND )
6782
68- if (OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "nanobind" )
83+ if (OIIO_BUILD_PYTHON_NANOBIND )
6984 # nanobind's CMake package expects the generic FindPython targets and
7085 # variables (Python::Module, Python_EXECUTABLE, etc.), not the
7186 # versioned Python3::* targets that the rest of OIIO uses today.
@@ -218,7 +233,7 @@ endmacro ()
218233
219234macro (setup_python_module_nanobind )
220235 cmake_parse_arguments (lib "" "TARGET;MODULE"
221- "SOURCES;LIBS;INCLUDES;SYSTEM_INCLUDE_DIRS"
236+ "SOURCES;LIBS;INCLUDES;SYSTEM_INCLUDE_DIRS;PACKAGE_FILES "
222237 ${ARGN} )
223238
224239 set (target_name ${lib_TARGET} )
@@ -249,20 +264,44 @@ macro (setup_python_module_nanobind)
249264 OUTPUT_NAME ${lib_MODULE}
250265 DEBUG_POSTFIX "" )
251266
252- if (SKBUILD)
253- set (PYTHON_SITE_DIR .)
254- endif ()
267+ if (OIIO_PYTHON_BINDINGS_BACKEND STREQUAL "both" )
268+ if (SKBUILD)
269+ set (_nanobind_install_dir .)
270+ else ()
271+ set (_nanobind_install_dir ${PYTHON_SITE_DIR} )
272+ endif ()
255273
256- set_target_properties (${target_name} PROPERTIES
257- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR } /lib/python/site-packages
258- ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR } /lib/python/site-packages
259- )
274+ # Keep nanobind modules isolated in the build tree so they don't alter
275+ # how the existing top-level OpenImageIO module is imported during tests.
276+ set_target_properties (${target_name} PROPERTIES
277+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR } /lib/python/nanobind/OpenImageIO
278+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR } /lib/python/nanobind/OpenImageIO
279+ )
260280
261- install (TARGETS ${target_name}
262- RUNTIME DESTINATION ${PYTHON_SITE_DIR } COMPONENT user
263- LIBRARY DESTINATION ${PYTHON_SITE_DIR } COMPONENT user)
281+ install (TARGETS ${target_name}
282+ RUNTIME DESTINATION ${_nanobind_install_dir } COMPONENT user
283+ LIBRARY DESTINATION ${_nanobind_install_dir } COMPONENT user)
264284
265- install (FILES __init__.py stubs/OpenImageIO/__init__.pyi stubs/OpenImageIO/py.typed
266- DESTINATION ${PYTHON_SITE_DIR} COMPONENT user)
285+ if (lib_PACKAGE_FILES)
286+ install (FILES ${lib_PACKAGE_FILES}
287+ DESTINATION ${_nanobind_install_dir} COMPONENT user)
288+ endif ()
289+ else ()
290+ if (SKBUILD)
291+ set (PYTHON_SITE_DIR .)
292+ endif ()
293+
294+ set_target_properties (${target_name} PROPERTIES
295+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR } /lib/python/site-packages
296+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR } /lib/python/site-packages
297+ )
298+
299+ install (TARGETS ${target_name}
300+ RUNTIME DESTINATION ${PYTHON_SITE_DIR} COMPONENT user
301+ LIBRARY DESTINATION ${PYTHON_SITE_DIR} COMPONENT user)
302+
303+ install (FILES __init__.py stubs/OpenImageIO/__init__.pyi stubs/OpenImageIO/py.typed
304+ DESTINATION ${PYTHON_SITE_DIR} COMPONENT user)
305+ endif ()
267306
268307endmacro ()
0 commit comments