Skip to content

Commit

Permalink
Pybind11 starting point (#352)
Browse files Browse the repository at this point in the history
* Very very early WIP to start building out pybind11 versions of CMake

Bring over a bunch of the constants, but declare them as pybind11 enums.

I'm not sure yet how best to expose some of the stuff PyAlembic will
eventually need, and I needed to put PyImathVec.cpp in MODSOURCE as the
register symbols were not being found in LIBSOURCE.

Signed-off-by: Lucas Miller <[email protected]>

* Add an option to build the pybind11 bindings.
Make sure we dont try to use both at the same time.

Signed-off-by: Lucas Miller <[email protected]>

* Address most PR feedback.

Signed-off-by: Lucas Miller <[email protected]>

---------

Signed-off-by: Lucas Miller <[email protected]>
  • Loading branch information
lamiller0 authored Oct 12, 2023
1 parent 4d4e01c commit 8235c3a
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 19 deletions.
18 changes: 12 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ set(IMATH_VERSION_API "${Imath_VERSION_MAJOR}_${Imath_VERSION_MINOR}")
# version. Increment this number whenever, and only when, the ABI changes in
# non-backwards-compatible ways.
#
# The OpenEXR project policy is to append the library version
# "major.minor.patch" to the SONAME to form the real shared library name.
# The OpenEXR project policy is to append the library version
# "major.minor.patch" to the SONAME to form the real shared library name.
# For example, in "libImath.so.31.3.2.0", "libImath.so.31" is the SONAME
# and ".3.2.0" identifies the corresponding library release.

Expand Down Expand Up @@ -57,8 +57,14 @@ set(Imath_DIR "${CMAKE_CURRENT_BINARY_DIR}/config" CACHE PATH "" FORCE)
# be empty since we already defined the targets in add_subdirectory().
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/config/ImathTargets.cmake" "# Dummy file")

option(PYTHON "Set ON to compile PyImath bindings")
if (PYTHON)
option(PYTHON "Set ON to compile boost PyImath bindings")
option(PYBIND11 "Set ON to compile pybind11 PyImath bindings")

if (PYTHON AND PYBIND11)
message(FATAL_ERROR "Compiling both the boost and pybind11 python bindings at the same time is not currently supported")
endif()

if (PYTHON OR PYBIND11)
add_subdirectory(src/python)
endif()

Expand All @@ -71,7 +77,7 @@ endif()
# upload the results, cmake has builtin support for
# submitting to CDash, or any server who speaks the
# same protocol
#
#
# These settings will need to be set for your environment,
# and then a script such as the example in
#
Expand All @@ -82,7 +88,7 @@ endif()
# cmake -S cmake/SampleCTestScript.cmake
#
# [or whatever you name the file you edit]
#
#
#set(CTEST_PROJECT_NAME "Imath")
#set(CTEST_NIGHTLY_START_TIME "01:01:01 UTC")
#set(CTEST_DROP_METHOD "http") # there are others...
Expand Down
27 changes: 20 additions & 7 deletions src/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,20 @@ if(Boost_PYTHON${Python_VERSION_MAJOR}_FOUND OR Boost_${PYIMATH_PY_UPPER}_FOUND)
endif()
endif()

if (PYBIND11)
find_package(pybind11 REQUIRED)
endif()

if(Boost_PYTHON_FOUND AND NOT _pyimath_have_perver_boost)
# old boost case, I guess we just warn and assume it is python2 (likely)
message(WARNING "Ambiguous boost python module found, assuming python ${Python_VERSION_MAJOR}. If you have a new boost library, try cleaning the cmake cache and reconfigure with -DBoost_NO_BOOST_CMAKE=ON")
set(PYIMATH_BOOST_PY_COMPONENT python)
# set it to a bogus string but not empty so later we don't test against a namespace only target
# set(PYIMATH_BOOST_PY3_COMPONENT pythonIgnore)
elseif(NOT _pyimath_have_perver_boost)
elseif(NOT _pyimath_have_perver_boost AND NOT pybind11_FOUND)
message(WARNING "Unable to find boost::python library, disabling PyImath. If you believe this is wrong, check the cmake documentation and see if you need to set Boost_ROOT or Boost_NO_BOOST_CMAKE")
return()
else()
elseif(NOT pybind11_FOUND)
if(TARGET Boost::${PYIMATH_BOOST_PY_COMPONENT})
message(STATUS "Found Python ${Python_VERSION_MAJOR} boost: Boost::${PYIMATH_BOOST_PY_COMPONENT}")
elseif(Boost_PYTHON_FOUND OR Boost_${PYIMATH_PY_UPPER}_FOUND)
Expand Down Expand Up @@ -195,7 +199,14 @@ if(NOT BUILD_SHARED_LIBS)
message(WARNING "Forcing python bindings to be built with dynamic libraries")
endif()

add_subdirectory( PyImath )
if ( pybind11_FOUND )
message(STATUS "PyBind11 PyImath")
add_subdirectory( PyBindImath )
else()
message(STATUS "Boost PyImath")
add_subdirectory( PyImath )
endif()

if(TARGET Python2::ImathNumPy OR TARGET Python3::ImathNumPy)
add_subdirectory( PyImathNumpy )
endif()
Expand All @@ -206,9 +217,11 @@ endif()
include(CTest)
if(BUILD_TESTING)
enable_testing()
add_subdirectory( PyImathTest )
add_subdirectory( PyImathSpeedTest )
if(TARGET Python2::ImathNumPy OR TARGET Python3::ImathNumPy)
add_subdirectory( PyImathNumpyTest )
if (PYTHON)
add_subdirectory( PyImathTest )
add_subdirectory( PyImathSpeedTest )
if(TARGET Python2::ImathNumPy OR TARGET Python3::ImathNumPy)
add_subdirectory( PyImathNumpyTest )
endif()
endif()
endif()
17 changes: 17 additions & 0 deletions src/python/PyBindImath/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenEXR Project.

pyimath_define_module(imath
LIBNAME PyBindImath
PRIV_EXPORT PYIMATH_BUILD
CURDIR ${CMAKE_CURRENT_SOURCE_DIR}
LIBSOURCE
PyImathVec.cpp
MODSOURCE
imathmodule.cpp
PyImathVec.cpp
HEADERS
PyImathExport.h
DEPENDENCIES
Imath
)
24 changes: 24 additions & 0 deletions src/python/PyBindImath/PyImath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

// clang-format off

#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <pybind11/operators.h>
#include "PyImathExport.h"

#ifndef _PyBindImath_h_
#define _PyBindImath_h_

namespace PyImath {

PYIMATH_EXPORT void register_imath_vec(pybind11::module& m);

}

#endif
28 changes: 28 additions & 0 deletions src/python/PyBindImath/PyImathExport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

// clang-format off

#ifndef PYBINDIMATHEXPORT_H
#define PYBINDIMATHEXPORT_H

#if defined(IMATH_DLL)
#if defined(PLATFORM_VISIBILITY_AVAILABLE)
#define PYIMATH_EXPORT __attribute__((visibility("default")))
#define PYIMATH_EXPORT __attribute__((visibility("default")))
#elif defined(_MSC_VER)
#if defined(PYIMATH_BUILD)
#define PYIMATH_EXPORT __declspec(dllexport)
#else
#define PYIMATH_EXPORT __declspec(dllimport)
#endif
#else
#define PYIMATH_EXPORT
#endif
#else
#define PYIMATH_EXPORT
#endif

#endif // #ifndef PYBINDIMATHEXPORT_H
17 changes: 17 additions & 0 deletions src/python/PyBindImath/PyImathVec.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

#include "PyImath.h"
#include <ImathVec.h>

namespace PyImath {

void register_imath_vec(pybind11::module& m)
{
// TODO fill in
pybind11::class_<Imath::V3f>(m, "V3f");
}

}
72 changes: 72 additions & 0 deletions src/python/PyBindImath/imathmodule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

#include "PyImath.h"
#include <ImathEuler.h>

PYBIND11_MODULE(imath, m)
{
m.doc() = "Imath module";
m.attr("__version__") = IMATH_VERSION_STRING;

PyImath::register_imath_vec(m);
//
// Initialize constants
//
pybind11::enum_<IMATH_NAMESPACE::Eulerf::Order>(m, "Order")
.value("EULER_XYZ", IMATH_NAMESPACE::Eulerf::XYZ)
.value("EULER_XZY", IMATH_NAMESPACE::Eulerf::XZY)
.value("EULER_YZX", IMATH_NAMESPACE::Eulerf::YZX)
.value("EULER_YXZ", IMATH_NAMESPACE::Eulerf::YXZ)
.value("EULER_ZXY", IMATH_NAMESPACE::Eulerf::ZXY)
.value("EULER_ZYX", IMATH_NAMESPACE::Eulerf::ZYX)
.value("EULER_XZX", IMATH_NAMESPACE::Eulerf::XZX)
.value("EULER_XYX", IMATH_NAMESPACE::Eulerf::XYX)
.value("EULER_YXY", IMATH_NAMESPACE::Eulerf::YXY)
.value("EULER_YZY", IMATH_NAMESPACE::Eulerf::YZY)
.value("EULER_ZYZ", IMATH_NAMESPACE::Eulerf::ZYZ)
.value("EULER_ZXZ", IMATH_NAMESPACE::Eulerf::ZXZ)
.value("EULER_XYZr", IMATH_NAMESPACE::Eulerf::XYZr)
.value("EULER_XZYr", IMATH_NAMESPACE::Eulerf::XZYr)
.value("EULER_YZXr", IMATH_NAMESPACE::Eulerf::YZXr)
.value("EULER_YXZr", IMATH_NAMESPACE::Eulerf::YXZr)
.value("EULER_ZXYr", IMATH_NAMESPACE::Eulerf::ZXYr)
.value("EULER_ZYXr", IMATH_NAMESPACE::Eulerf::ZYXr)
.value("EULER_XZXr", IMATH_NAMESPACE::Eulerf::XZXr)
.value("EULER_XYXr", IMATH_NAMESPACE::Eulerf::XYXr)
.value("EULER_YXYr", IMATH_NAMESPACE::Eulerf::YXYr)
.value("EULER_YZYr", IMATH_NAMESPACE::Eulerf::YZYr)
.value("EULER_ZYZr", IMATH_NAMESPACE::Eulerf::ZYZr)
.value("EULER_ZXZr", IMATH_NAMESPACE::Eulerf::ZXZr)
.export_values();

pybind11::enum_<IMATH_NAMESPACE::Eulerf::Axis>(m, "Axis")
.value("EULER_X_AXIS", IMATH_NAMESPACE::Eulerf::X)
.value("EULER_Y_AXIS", IMATH_NAMESPACE::Eulerf::Y)
.value("EULER_Z_AXIS", IMATH_NAMESPACE::Eulerf::Z)
.export_values();

pybind11::enum_<IMATH_NAMESPACE::Eulerf::InputLayout>(m, "InputLayout")
.value("EULER_IJKLayout", IMATH_NAMESPACE::Eulerf::IJKLayout)
.value("EULER_XYZLayout", IMATH_NAMESPACE::Eulerf::XYZLayout)
.export_values();


m.attr("INT_MIN") = std::numeric_limits<int>::min();
m.attr("INT_MAX") = std::numeric_limits<int>::max();
m.attr("INT_LOWEST") = std::numeric_limits<int>::lowest();
m.attr("INT_EPS") = std::numeric_limits<int>::epsilon();

m.attr("FLT_MIN") = std::numeric_limits<float>::min();
m.attr("FLT_MAX") = std::numeric_limits<float>::max();
m.attr("FLT_LOWEST") = std::numeric_limits<float>::lowest();
m.attr("FLT_EPS") = std::numeric_limits<float>::epsilon();

m.attr("DBL_MIN") = std::numeric_limits<double>::min();
m.attr("DBL_MAX") = std::numeric_limits<double>::max();
m.attr("DBL_LOWEST") = std::numeric_limits<double>::lowest();
m.attr("DBL_EPS") = std::numeric_limits<double>::epsilon();

}
16 changes: 10 additions & 6 deletions src/python/config/ModuleDefine.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ function(PYIMATH_ADD_LIBRARY_PRIV libname)
if(Boost_INCLUDE_DIR)
target_include_directories(${libname} PUBLIC ${Boost_INCLUDE_DIR})
endif()
if (pybind11_INCLUDE_DIRS)
target_include_directories(${libname} PUBLIC ${pybind11_INCLUDE_DIRS})
endif()
target_link_libraries(${libname} PUBLIC ${PYIMATH_CURLIB_DEPENDENCIES})
if(PYIMATH_CURLIB_PRIVATE_DEPS)
target_link_libraries(${libname} PRIVATE ${PYIMATH_CURLIB_PRIVATE_DEPS})
Expand Down Expand Up @@ -100,8 +103,9 @@ function(PYIMATH_DEFINE_MODULE modname)
# NB: make this one last so we can cheat and add the python and boost
# libs as private deps at the end regardless of whether it was provided
list(APPEND libarglist PRIVATE_DEPS ${PYIMATH_CURMOD_PRIVATE_DEPS})

if(USE_PYTHON2)
if(TARGET Python2::Python AND TARGET Boost::${PYIMATH_BOOST_PY_COMPONENT})
if(TARGET Python2::Python)
set(libname "${PYIMATH_CURMOD_LIBNAME}${PYIMATH_LIB_PYTHONVER_ROOT}${Python2_VERSION_MAJOR}_${Python2_VERSION_MINOR}")
set(extraDeps ${PYIMATH_CURMOD_MODULE_DEPS})
list(TRANSFORM extraDeps APPEND ${PYIMATH_LIB_PYTHONVER_ROOT}${Python2_VERSION_MAJOR}_${Python2_VERSION_MINOR})
Expand All @@ -110,7 +114,7 @@ function(PYIMATH_DEFINE_MODULE modname)
${libarglist}
${extraDeps}
Python2::Python
Boost::${PYIMATH_BOOST_PY_COMPONENT}
$<TARGET_NAME_IF_EXISTS:Boost::${PYIMATH_BOOST_PY_COMPONENT}>
)

Python2_add_library(${modname}_python2 MODULE ${PYIMATH_CURMOD_MODSOURCE})
Expand All @@ -120,7 +124,7 @@ function(PYIMATH_DEFINE_MODULE modname)
${extraDeps}
${PYIMATH_CURMOD_DEPENDENCIES}
${PYIMATH_CURMOD_PRIVATE_DEPS}
Boost::${PYIMATH_BOOST_PY_COMPONENT}
$<TARGET_NAME_IF_EXISTS:Boost::${PYIMATH_BOOST_PY_COMPONENT}>
)
set_target_properties(${modname}_python2 PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python${Python2_VERSION_MAJOR}_${Python2_VERSION_MINOR}/"
Expand All @@ -130,7 +134,7 @@ function(PYIMATH_DEFINE_MODULE modname)
install(TARGETS ${modname}_python2 DESTINATION ${PyImath_Python2_SITEARCH_REL})
endif()
else()
if(TARGET Python3::Python AND TARGET Boost::${PYIMATH_BOOST_PY_COMPONENT})
if(TARGET Python3::Python)
set(libname "${PYIMATH_CURMOD_LIBNAME}${PYIMATH_LIB_PYTHONVER_ROOT}${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR}")
set(extraDeps ${PYIMATH_CURMOD_MODULE_DEPS})
list(TRANSFORM extraDeps APPEND ${PYIMATH_LIB_PYTHONVER_ROOT}${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR})
Expand All @@ -139,15 +143,15 @@ function(PYIMATH_DEFINE_MODULE modname)
${libarglist}
${extraDeps}
Python3::Python
Boost::${PYIMATH_BOOST_PY_COMPONENT}
$<TARGET_NAME_IF_EXISTS:Boost::${PYIMATH_BOOST_PY_COMPONENT}>
)
Python3_add_library(${modname}_python3 MODULE ${PYIMATH_CURMOD_MODSOURCE})
target_link_libraries(${modname}_python3
PRIVATE
${libname} ${extraDeps}
${PYIMATH_CURMOD_DEPENDENCIES}
${PYIMATH_CURMOD_PRIVATE_DEPS}
Boost::${PYIMATH_BOOST_PY_COMPONENT}
$<TARGET_NAME_IF_EXISTS:Boost::${PYIMATH_BOOST_PY_COMPONENT}>
)
set_target_properties(${modname}_python3 PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR}/"
Expand Down

0 comments on commit 8235c3a

Please sign in to comment.