Skip to content

Commit

Permalink
Reoganize pybind11 cmake configuration (#434)
Browse files Browse the repository at this point in the history
This reconfigures the new pybind11 implementation so it can be built
in parallel with the existing Boost.Python bindings, and arranges so
that the Boost.Python bindings can be deprecated and removed once with
new bindings are functional.

It's now possible to build the pybind11-based bindings without
requiring Boost.Python to be installed.

The CMake option ``PYTHON`` specifies whether to build the
Boost.Python-based bindings, same as always. The Boost.Python binding
source code is under src/python.

The new CMake optin ``PYBIND11`` specifies whether to build the
pybind11-based bindings. The pybind11 binding source code is under
src/pybind11. The bindings build into a module called "pybindimath"
and a library called "libPyBindImath.so". These are temporary names
until these bindings become official, at which time they'll be renamed
to "imath".

The new pybind11-based CMake configuration is simplfied, with all the
setup inline in src/pybind11/PyBindImath/CMakeLists.txt. It does not
rely on any of the sort of CMake functions or setups that the
Boost.Python bindings pull from src/python/config. That code is overly
complicated, and overly general since it's only used for two libraries
(PyImathand PyImathNumpy).

Signed-off-by: Cary Phillips <[email protected]>
  • Loading branch information
cary-ilm authored Sep 20, 2024
1 parent a2ef565 commit 6d97ae2
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 67 deletions.
53 changes: 46 additions & 7 deletions .github/workflows/ci_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
image: aswf/ci-openexr:${{ matrix.vfx-cy }}
strategy:
matrix:
build: [1, 2, 3, 4, 5, 6, 7, 8, 9]
build: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
include:
# -------------------------------------------------------------------
# GCC, VFX CY2024
Expand Down Expand Up @@ -188,6 +188,35 @@ jobs:
python-desc: python3.7.9
vfx-cy: 2021

# -------------------------------------------------------------------
# pybind11 and python together
# -------------------------------------------------------------------
- build: 10
build-type: Release
build-shared: 'ON'
cxx-standard: 17
cxx-compiler: g++
cc-compiler: gcc
compiler-desc: gcc11.2.1
python: 'ON'
pybind11: 'ON'
python-desc: python3.11
vfx-cy: 2024

# -------------------------------------------------------------------
# pybind11 w/o python
# -------------------------------------------------------------------
- build: 11
build-type: Release
build-shared: 'ON'
cxx-standard: 17
cxx-compiler: g++
cc-compiler: gcc
compiler-desc: gcc11.2.1
python: 'OFF'
pybind11: 'ON'
python-desc: python3.11
vfx-cy: 2024
env:
CXX: ${{ matrix.cxx-compiler }}
CC: ${{ matrix.cc-compiler }}
Expand All @@ -211,6 +240,7 @@ jobs:
-DCMAKE_VERBOSE_MAKEFILE:BOOL='OFF' \
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} \
-DPYTHON=${{ matrix.python }} \
-DPYBIND11=${{ matrix.pybind11 }} \
-DUSE_PYTHON2=${{ matrix.use-python2 }}
working-directory: _build
- name: Build
Expand All @@ -221,12 +251,6 @@ jobs:
working-directory: _build
- name: Examples
run: |
# Confirm the python module loads. Set PYTHONPATH to the
# _install directory of the module (better to find it
# procedurally than hard code a path).
export PYTHONPATH=`find ../_install -name imath.so | xargs dirname`
python -c "import imath;print(imath.__version__)"
# Make sure we can build the tests when configured as a
# standalone application linking against the just-installed
# Imath library.
Expand All @@ -252,6 +276,21 @@ jobs:
--config ${{ matrix.build-type }}
ctest
working-directory: _examples
- name: Test Python
run: |
# Confirm the python module loads. Set PYTHONPATH to the
# _install directory of the module (better to find it
# procedurally than hard code a path).
if [[ "${{ matrix.python }}" == "ON" ]]; then
export PYTHONPATH=`find ../_install -name imath.so | xargs dirname`
python -c "import imath;print(imath.__version__)"
fi
if [[ "${{ matrix.pybind11 }}" == "ON" ]]; then
export PYTHONPATH=`find ../_install -name 'pybindimath.*.so' | xargs dirname`
python -c "import pybindimath;print(pybindimath.__version__)"
fi
shell: bash
working-directory: _build
- name: Test
run: |
ctest -T Test ${{ matrix.exclude-tests }} \
Expand Down
11 changes: 5 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,13 @@ set(Imath_DIR "${CMAKE_CURRENT_BINARY_DIR}/config" CACHE PATH "" FORCE)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/config/ImathTargets.cmake" "# Dummy file")

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")
if (PYTHON)
add_subdirectory(src/python)
endif()

if (PYTHON OR PYBIND11)
add_subdirectory(src/python)
option(PYBIND11 "Set ON to compile pybind11 PyImath bindings")
if (PYBIND11)
add_subdirectory(src/pybind11)
endif()

option(BUILD_WEBSITE "Set ON to build the readthedocs website source")
Expand Down
17 changes: 17 additions & 0 deletions src/pybind11/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.

set(PYBINDIMATH_OVERRIDE_PYTHON_INSTALL_DIR "" CACHE STRING "Override the install location for imath.so and imathnumpy.so modules")

########################
## Build related options

# Suffix to append to root name, this helps with version management
# but can be turned off if you don't care, or otherwise customized
#
set(PYBINDIMATH_LIB_SUFFIX "-${IMATH_VERSION_API}" CACHE STRING "String added to the end of all the libraries")
# This provides a root for the unique name of the library based on
# the version of python being compiled for
set(PYBINDIMATH_LIB_PYTHONVER_ROOT "_Python" CACHE STRING "String added as a root to the identifier of the python version in the libraries")

add_subdirectory(PyBindImath)
106 changes: 106 additions & 0 deletions src/pybind11/PyBindImath/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenEXR Project.

find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
find_package(pybind11 REQUIRED)

#
# Source/headers
#

set(PYBINDIMATH_SOURCES
PyBindImathBox.cpp
PyBindImathVec.cpp
)

set(PYBINDIMATH_HEADERS
PyBindImathExport.h
PyBindImath.h
)

#
# shared library, e.g. libPyBindImath_Python3_11-3_2.so.30.3.2.0
#

set(PYBINDIMATH_LIBRARY PyBindImath)

add_library(${PYBINDIMATH_LIBRARY} SHARED ${PYBINDIMATH_SOURCES})

target_link_libraries(${PYBINDIMATH_LIBRARY} PRIVATE Imath::Imath pybind11::module)

# Set include directories
target_include_directories(${PYBINDIMATH_LIBRARY} PRIVATE ${Python3_INCLUDE_DIRS} ${Imath_INCLUDE_DIRS})

if(NOT "${PYBINDIMATH_LIB_PYTHONVER_ROOT}" STREQUAL "")
set(pythonver_root "${PYBINDIMATH_LIB_PYTHONVER_ROOT}${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR}")
message("pythonver_root ${PYBINDIMATH_LIB_PYTHONVER_ROOT}${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR}")
endif()

if(BUILD_SHARED_LIBS)
# This creates the so-versioned library symlinks
set_target_properties(${PYBINDIMATH_LIBRARY} PROPERTIES
SOVERSION ${IMATH_LIB_SOVERSION}
VERSION ${IMATH_LIB_VERSION}
OUTPUT_NAME "${PYBINDIMATH_CURLIB_OUTROOT}${PYBINDIMATH_LIBRARY}${pythonver_root}${PYBINDIMATH_LIB_SUFFIX}"
)
endif()

#
# python module, e.g. pybindimath.cpython-311-x86_64-linux-gnu.so
#

set(PYBINDIMATH_MODULE pybindimath)

pybind11_add_module(pybindimath MODULE pybindimathmodule.cpp $<TARGET_OBJECTS:${PYBINDIMATH_LIBRARY}>)

target_link_libraries(${PYBINDIMATH_MODULE} PRIVATE Imath::Imath pybind11::module)

if(SKBUILD)
set(PYTHON_INSTALL_DIR ${SKBUILD_PLATLIB_DIR})
else()
set(PYTHON_INSTALL_DIR "lib/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages")
endif()

if (IMATH_INSTALL)

# module

install(TARGETS ${PYBINDIMATH_MODULE} DESTINATION ${PYTHON_INSTALL_DIR} COMPONENT python)

# shared library

install(TARGETS ${PYBINDIMATH_LIBRARY}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

if(BUILD_SHARED_LIBS AND (NOT "${IMATH_LIB_SUFFIX}" STREQUAL "") AND IMATH_INSTALL_SYM_LINK)

# create symlinks for the shared object so versions

string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
set(verlibname ${CMAKE_SHARED_LIBRARY_PREFIX}${PYBINDIMATH_LIBRARY}${pythonver_root}${IMATH_LIB_SUFFIX}${CMAKE_${uppercase_CMAKE_BUILD_TYPE}_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
set(baselibname ${CMAKE_SHARED_LIBRARY_PREFIX}${PYBINDIMATH_LIBRARY}${pythonver_root}${CMAKE_${uppercase_CMAKE_BUILD_TYPE}_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
file(CREATE_LINK ${verlibname} ${CMAKE_CURRENT_BINARY_DIR}/${baselibname} SYMBOLIC)
if(WIN32)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${baselibname} DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
install(CODE "message(STATUS \"Creating symlink ${CMAKE_INSTALL_FULL_BINDIR}/${baselibname} -> ${verlibname}\")")
else()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${baselibname} DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
install(CODE "message(STATUS \"Creating symlink ${CMAKE_INSTALL_FULL_LIBDIR}/${baselibname} -> ${verlibname}\")")
endif()
endif()

# pkgconfig

set(pcinfile PyBindImath.pc.in)
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "\${prefix}")
set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
string(REPLACE ".in" "" pcout ${pcinfile})
configure_file(${pcinfile} ${CMAKE_CURRENT_BINARY_DIR}/${pcout} @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${pcout} DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

endif()
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <pybind11/operators.h>
#include "PyImathExport.h"
#include "PyBindImathExport.h"

#ifndef _PyBindImath_h_
#define _PyBindImath_h_

namespace PyImath {
namespace PyBindImath {

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

}

Expand Down
17 changes: 17 additions & 0 deletions src/pybind11/PyBindImath/PyBindImath.pc.in
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.
##

prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
pythonver=@pythonver_root@

Name: PyBindImath
Description: pybind11-based python bindings for the Imath libraries
Version: @IMATH_VERSION@
Libs: -L${libdir} -lImath${libsuffix} -lPyBindImath${pythonver$}${libsuffix}

Cflags: -I${includedir} -I${includedir}/Imath
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
// Copyright Contributors to the OpenEXR Project.
//

#include "PyImath.h"
#include "PyBindImath.h"
#include <ImathBox.h>

namespace PyImath {
namespace PyBindImath {

template <class T, class V>
void register_box(pybind11::class_<T>& c)
Expand Down Expand Up @@ -57,4 +57,4 @@ void register_imath_box(pybind11::module& m)

}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@

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

#endif // #ifndef PYBINDIMATHEXPORT_H
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
// Copyright Contributors to the OpenEXR Project.
//

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

namespace PyImath {
namespace PyBindImath {

template <class T>
void register_vec(pybind11::class_<T>& c)
Expand Down Expand Up @@ -124,4 +124,4 @@ void register_imath_vec(pybind11::module& m)
register_vec4<Imath::V4f, float>(m, "V4f");
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
// Copyright Contributors to the OpenEXR Project.
//

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

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

PyImath::register_imath_vec(m);
PyImath::register_imath_box(m);
PyBindImath::register_imath_vec(m);
PyBindImath::register_imath_box(m);

//
// Initialize constants
Expand Down Expand Up @@ -71,4 +71,4 @@ PYBIND11_MODULE(imath, m)
m.attr("DBL_LOWEST") = std::numeric_limits<double>::lowest();
m.attr("DBL_EPS") = std::numeric_limits<double>::epsilon();

}
}
Loading

0 comments on commit 6d97ae2

Please sign in to comment.