From 7d5ca5f4182fa661babb91c8e4b2655bfef03e15 Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Tue, 13 Feb 2024 15:32:43 -0800 Subject: [PATCH] Build python wheels via scikit-build-core (#1629) * Build python wheels via scikit-build-core This converts the setuptools configuration for building python wheels to use scikit-build-core, which has better support for CMake. There is no more setup.py; the configuration is entirely in `pyproject.toml` and the compile/link is done exclusively via cmake. The build/publish policy is: * A PR that changes any of the python wheel source/configuration (src/wrappers/python/* or .github/workflows/python-wheels.yml) triggers a build as a check. * PRs that change other library source do *not* trigger a build of the python wheels. Note that the primary CI workflow does build and test the bindings, although only for a single python version on a single arch for Linux/macOS/Windows. The wheel building validates multiple python versions and architectures, but involves signifant computation/time. Currently, the python wheels are a thin wrapper about basic read/write functions that don't add significant additional functionality to the library. Any potential problem will almost certainly get caught by the primary CI. * A tag of the form `v3.[0-9]+.[0-9]+-rc*` (e.g. `v3.2.4-rc`) triggers a full build of the wheels followed by a publish to `test.pypi.org`. This validates release candidates. * Publishing a release triggers a full build of the wheels followed by a publish to `pypi.org`. Signed-off-by: Cary Phillips * Add custom README.md for pypi.org Signed-off-by: Cary Phillips * fix typo Signed-off-by: Cary Phillips * reference src/wrappers/python/README.md in pyproject.toml Signed-off-by: Cary Phillips * Add copyright notice Signed-off-by: Cary Phillips * Update pyproject.toml Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com> Signed-off-by: Cary Phillips * Update pyproject.toml Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com> Signed-off-by: Cary Phillips * Update src/wrappers/python/CMakeLists.txt Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com> Signed-off-by: Cary Phillips * Add uninstall target (#1624) * Add uninstall target Satisfy the OpenSSF Best Practices Badge requirement for an insta/uninstall process: https://www.bestpractices.dev/en/criteria/1#1.installation_common CMake does not support a standard "uninstall" target, but the community recommends implementing an "uninstal" target that remove files named in the `install_manifest.txt`: https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake However, our existing process of installing the symlink to the "bare" library, i.e. the symlink from libImath-3_2.so to libImath.so, fails to add the symlink to the manifest, so "make uninstall" misses the symlink. The existing mechanism use "install(CODE execute_process(cmake -E create_symlink))". This changes that to use a simpler "file(CREATE_LINK)" and "install(FILES)" to accomplish the same thing while also registering the symlink the the manifest. Also, this fixes an issue where `OpenEXRConfig.h` was passed to `install()` twice, producing two entries in `install_manifest.txt`. Signed-off-by: Cary Phillips * mention uninstall in install instructions Signed-off-by: Cary Phillips * poke Signed-off-by: Cary Phillips * COPY_ON_ERROR Signed-off-by: Cary Phillips * clarify the uninstall instructions Signed-off-by: Cary Phillips --------- Signed-off-by: Cary Phillips * Add cmake.targets and OPENEXR_INSTALL=OFF Signed-off-by: Cary Phillips * INSTALL_TOOLS=OFF Signed-off-by: Cary Phillips * propogate OPENEXR_INSTALL to Imath Signed-off-by: Cary Phillips * test1 Signed-off-by: Cary Phillips * OPENEXR_INSTALL_PKG_CONFIG Signed-off-by: Cary Phillips * Fix CVE 2023 5841 (#1627) * enable deep file checks for core Signed-off-by: Kimball Thurston * fix possible int overflow Signed-off-by: Kimball Thurston * fix validation of deep sample counts Addresses CVE-2023-5841, fixing sample count check to not only check against 0 but previous sample as well. Signed-off-by: Kimball Thurston * add clarifying comment Signed-off-by: Kimball Thurston --------- Signed-off-by: Kimball Thurston * Bazel support: Bump Imath to 3.1.10 (#1626) Signed-off-by: Vertexwahn * Document security expectations (#1623) * Document security expectations Signed-off-by: Cary Phillips * Menion Imath as a dependency Signed-off-by: Cary Phillips * Update SECURITY.md Co-authored-by: Nick Porcino Signed-off-by: Cary Phillips * change 'Threat Model' to 'Potential Vulnerabilties' Signed-off-by: Cary Phillips * Mention GitHub issue as fallback security contact Signed-off-by: Cary Phillips * github security advisory Signed-off-by: Cary Phillips * mention exrcheck Signed-off-by: Cary Phillips --------- Signed-off-by: Cary Phillips Co-authored-by: Nick Porcino * Add uninstall target (#1624) * Add uninstall target Satisfy the OpenSSF Best Practices Badge requirement for an insta/uninstall process: https://www.bestpractices.dev/en/criteria/1#1.installation_common CMake does not support a standard "uninstall" target, but the community recommends implementing an "uninstal" target that remove files named in the `install_manifest.txt`: https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake However, our existing process of installing the symlink to the "bare" library, i.e. the symlink from libImath-3_2.so to libImath.so, fails to add the symlink to the manifest, so "make uninstall" misses the symlink. The existing mechanism use "install(CODE execute_process(cmake -E create_symlink))". This changes that to use a simpler "file(CREATE_LINK)" and "install(FILES)" to accomplish the same thing while also registering the symlink the the manifest. Also, this fixes an issue where `OpenEXRConfig.h` was passed to `install()` twice, producing two entries in `install_manifest.txt`. Signed-off-by: Cary Phillips * mention uninstall in install instructions Signed-off-by: Cary Phillips * poke Signed-off-by: Cary Phillips * COPY_ON_ERROR Signed-off-by: Cary Phillips * clarify the uninstall instructions Signed-off-by: Cary Phillips --------- Signed-off-by: Cary Phillips * Remove snyk-scan-pr.yml (#1631) This workflow is causing errors on each PR: Snyk is missing auth token in order to run inside CI. You must include your API token as an environment value: `SNYK_TOKEN=12345678` Error: Process completed with exit code 2. As discussed on #1608, the preferred workflow will run weekly, not on PR. Signed-off-by: Cary Phillips * fix issue with unpacking sample counts (#1630) When unpacking sample counts as "individual" counts (no longer monotonic), it writes the total sample count to a value 1 past the individual sample counts, but this is not in the packed data, so do not expect to unpack that many values. The buffer just needs to be allocated one value larger to avoid write past end of buffer which is taken care of in the update_pack_unpack_ptrs function Signed-off-by: Kimball Thurston * adjust checks for core to better match c++ checks (#1632) The core checks were not setting the same image / tile size limits and not disabling reads at quite the same level. Note: the core check does not read the entire image into a contiguous slice, so does not replicate the maximum deep sample checks in the same way, this is a source of potential false-negative failures This should address OSS-Fuzz 66491 and 66489 (different forms of the same failure where a large sample size allocation was happening), and are only constrained memory (2.5Gb) issues. Signed-off-by: Kimball Thurston * Fix install of symlink (#1633) PR #1624 caused the .so symlink without the `OPENEXR_LIB_SUFFIX` (e.g. libOpenEXR.so which links to libOpenEXR-3_2.so) to get created in the wrong directory. This caused certain invocations of cmake to fail, even though the invocation in the CI succeeded. It's not at all clear why. This also changes the CI to invoke cmake in the way that previously failed (e.g. from the top-level directory with `-B` and `-S`), as an additional check. Signed-off-by: Cary Phillips * adds a shortcut to avoid reconstructing every call (#1634) When there is a loop trying to get scan / tile info that is ignoring return values, add a shortcut to avoid trying to reconstruct the chunk table every time. This will still respect the strict header flag, either returning an error immediately (strict), or (non-strict) enabling a multi-part file with only partially corrupt parts to work. Signed-off-by: Kimball Thurston * check and control reduceMemory and reduceTime in stream mode (#1635) exrcheck by default uses file mode, but the fuzzer and exrcheck -s use stream mode, need to respect the memory and time flags consistently on that path as well. Will address OSS-Fuzz 66612, although real fix underlying is in #1634 Signed-off-by: Kimball Thurston * Update .github/workflows/python-wheels-publish-test.yml Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com> Signed-off-by: Cary Phillips * Add sdist Signed-off-by: Cary Phillips * Update .github/workflows/python-wheels-publish-test.yml Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com> Signed-off-by: Cary Phillips * fix sdist; remove debugging Signed-off-by: Cary Phillips --------- Signed-off-by: Cary Phillips Signed-off-by: Kimball Thurston Signed-off-by: Vertexwahn Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com> Co-authored-by: Kimball Thurston Co-authored-by: Vertexwahn Co-authored-by: Nick Porcino --- .github/workflows/ci_workflow.yml | 2 + .../workflows/python-wheels-publish-test.yml | 102 +++++++++++++ .github/workflows/python-wheels-publish.yml | 96 ++++++++++++ .github/workflows/python-wheels.yml | 109 ++++++-------- .github/workflows/website_workflow.yml | 4 + CMakeLists.txt | 40 +++-- cmake/OpenEXRSetup.cmake | 32 +++- pyproject.toml | 60 ++++++++ src/bin/CMakeLists.txt | 33 ++-- src/examples/CMakeLists.txt | 2 + src/lib/CMakeLists.txt | 2 + src/test/CMakeLists.txt | 17 ++- src/wrappers/python/CMakeLists.txt | 35 ++++- src/wrappers/python/README.md | 142 ++++++++++++++++++ src/wrappers/python/libdeflate.patch | 12 -- src/wrappers/python/openexr_skbuild_plugin.py | 106 +++++++++++++ src/wrappers/python/setup.py | 83 ---------- src/wrappers/python/tests/test_minimal.py | 6 +- src/wrappers/python/tests/test_unittest.py | 4 +- 19 files changed, 679 insertions(+), 208 deletions(-) create mode 100644 .github/workflows/python-wheels-publish-test.yml create mode 100644 .github/workflows/python-wheels-publish.yml create mode 100644 pyproject.toml create mode 100644 src/wrappers/python/README.md delete mode 100644 src/wrappers/python/libdeflate.patch create mode 100644 src/wrappers/python/openexr_skbuild_plugin.py delete mode 100644 src/wrappers/python/setup.py diff --git a/.github/workflows/ci_workflow.yml b/.github/workflows/ci_workflow.yml index bc51851d7e..33670f472c 100644 --- a/.github/workflows/ci_workflow.yml +++ b/.github/workflows/ci_workflow.yml @@ -25,6 +25,7 @@ on: - 'website/src/**' - '!bazel/**' - '!src/wrappers/**' + - '!.github/workflows/python-**.yml' pull_request: branches-ignore: - RB-2.* @@ -38,6 +39,7 @@ on: - 'website/src/**' - '!bazel/**' - '!src/wrappers/**' + - '!.github/workflows/python-**.yml' permissions: contents: read diff --git a/.github/workflows/python-wheels-publish-test.yml b/.github/workflows/python-wheels-publish-test.yml new file mode 100644 index 0000000000..6b46aef164 --- /dev/null +++ b/.github/workflows/python-wheels-publish-test.yml @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) Contributors to the OpenEXR Project. + +name: Publish python distribution 📦 to TestPyPI + +on: + + # Publish python wheels to test.pypi when a release candidate is tagged, + # e.g. v3.4.5-rc, v3.4.5-rc6, etc. + + push: + tags: + - v3.[0-9]+.[0-9]+-rc* + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + name: Python Wheels - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + environment: + name: testpypi + url: https://test.pypi.org/p/openexr + + permissions: + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Create sdist + # Only create it once. + if: ${{ matrix.os == 'ubuntu-latest' }} + run: pipx run build --sdist . --outdir wheelhouse + + - name: Build wheel + uses: pypa/cibuildwheel@v2.16 + with: + output-dir: wheelhouse + env: + CIBW_ARCHS_LINUX: x86_64 + CIBW_ARCHS_MACOS: x86_64 arm64 universal2 + # Skip python 3.6 since scikit-build-core requires 3.7+ + # Skip 32-bit wheels builds on Windows + # Also skip the PyPy builds, since they fail the unit tests + CIBW_SKIP: cp36-* *-win32 *_i686 pp* + CIBW_TEST_SKIP: "*-macosx_universal2:arm64" + CIBW_ENVIRONMENT: OPENEXR_RELEASE_CANDIDATE_TAG="${{ github.ref_name }}" + + - name: Upload artifact + uses: actions/upload-artifact@v4.0.0 + with: + name: wheels-${{ matrix.os }} + path: | + ./wheelhouse/*.whl + ./wheelhouse/*.tar.gz + + publish-to-testpypi: + name: Publish Python 🐍 distribution 📦 to TestPyPI + needs: + - build + runs-on: ubuntu-latest + + environment: + name: testpypi + url: https://test.pypi.org/p/openexr + + permissions: + id-token: write + + steps: + - name: Download Linux artifacts + uses: actions/download-artifact@v4.0.0 + with: + name: wheels-ubuntu-latest + path: dist + - name: Download macOS artifacts + uses: actions/download-artifact@v4.0.0 + with: + name: wheels-macos-latest + path: dist + - name: Download Windows artifacts + uses: actions/download-artifact@v4.0.0 + with: + name: wheels-windows-latest + path: dist + - name: Publish distribution 📦 to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ \ No newline at end of file diff --git a/.github/workflows/python-wheels-publish.yml b/.github/workflows/python-wheels-publish.yml new file mode 100644 index 0000000000..2330847df3 --- /dev/null +++ b/.github/workflows/python-wheels-publish.yml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) Contributors to the OpenEXR Project. + +name: Publish python distribution 📦 to PyPI + +on: + # Publish wheels to pypi on release + release: + types: [published] + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + name: Python Wheels - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + environment: + name: pypi + url: https://pypi.org/p/openexr + + permissions: + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Create sdist + # Only create it once. + if: ${{ matrix.os == 'ubuntu-latest' }} + run: pipx run build --sdist . --outdir wheelhouse + + - name: Build wheel + uses: pypa/cibuildwheel@v2.16 + with: + output-dir: wheelhouse + env: + CIBW_BUILD: cp312-* + CIBW_ARCHS_LINUX: x86_64 + CIBW_ARCHS_MACOS: x86_64 arm64 universal2 + # Skip python 3.6 since scikit-build-core requires 3.7+ + # Skip 32-bit wheels builds on Windows + # Also skip the PyPy builds, since they fail the unit tests + CIBW_SKIP: cp36-* *-win32 *_i686 pp* + CIBW_TEST_SKIP: "*arm64" + + - name: Upload artifact + uses: actions/upload-artifact@v4.0.0 + with: + name: wheels-${{ matrix.os }} + path: | + ./wheelhouse/*.whl + ./wheelhouse/*.tar.gz + + publish-to-pypi: + name: Publish Python 🐍 distribution 📦 to PyPI + needs: + - build + runs-on: ubuntu-latest + + environment: + name: pypi + url: https://pypi.org/p/openexr + + permissions: + id-token: write + + steps: + - name: Download Linux artifacts + uses: actions/download-artifact@v4.0.0 + with: + name: wheels-ubuntu-latest + path: dist + - name: Download macOS artifacts + uses: actions/download-artifact@v4.0.0 + with: + name: wheels-macos-latest + path: dist + - name: Download Windows artifacts + uses: actions/download-artifact@v4.0.0 + with: + name: wheels-windows-latest + path: dist + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/python-wheels.yml b/.github/workflows/python-wheels.yml index cc926ef5c7..516af01390 100644 --- a/.github/workflows/python-wheels.yml +++ b/.github/workflows/python-wheels.yml @@ -1,91 +1,74 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) Contributors to the OpenEXR Project. -# -name: Python wheels +name: Python Wheels on: + + # Run on all changes (PR and push) to the python binding + # source/configuration files, except on the release branches, which + # have their own workflow, which also publish to pypi/test.pypi. + # Note that changes to the core libraries will *not* + # trigger building the wheels. However, the main ci workflow does + # build and test the bindings (for a single python version on a + # single arch) + push: branches-ignore: - - RB-2.* - tags-ignore: - - v1.* - - v2.* + - RB-* paths: - - '**' - - '!**.md' - - '!website/**' - - 'website/src/**' - - '!bazel/**' + - 'src/wrappers/python/**' + - 'pyproject.toml' + - '.github/workflows/python-wheels.yml' pull_request: branches-ignore: - - RB-2.* - tags-ignore: - - v1.* - - v2.* + - RB-* paths: - - '**' - - '!**.md' - - '!website/**' - - 'website/src/**' - - '!bazel/**' + - 'src/wrappers/python/**' + - 'pyproject.toml' + - '.github/workflows/python-wheels.yml' permissions: contents: read jobs: build_wheels: - name: Build Python wheels + name: Python Wheels - ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-22.04, windows-latest, macOS-latest] - env: - # On macOS we build both x86 and arm to support Intel and Apple Silicon. - CIBW_ARCHS_MACOS: x86_64 arm64 - # Skip 32-bit wheels builds on Windows. - # Also skip the PyPy builds, since they fail the unittests - CIBW_SKIP: "*-win32 *_i686 pp*" - # The CI platform is Intel based so we are doing cross compilation - # for arm64. It is not currently possible to test arm64 when cross - # compiling. - CIBW_TEST_SKIP: "*_arm64" - CIBW_BEFORE_BUILD: > - echo "Installing OpenEXR..." && - cd openexr.build && - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../openexr.install -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_PREFIX_PATH=../openexr.install -DCMAKE_INSTALL_LIBDIR=lib -DBUILD_TESTING=OFF -DOPENEXR_INSTALL_EXAMPLES=OFF -DOPENEXR_BUILD_TOOLS=OFF -DBUILD_SHARED_LIBS=OFF -DOPENEXR_FORCE_INTERNAL_DEFLATE=ON -DOPENEXR_FORCE_INTERNAL_IMATH=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON ../ && - cmake --build ./ --config Release --clean-first && - cmake --install ./ --config Release && - cd .. - CIBW_TEST_REQUIRES: pytest - CIBW_TEST_COMMAND: pytest {project}/src/wrappers/python/tests/ + os: [ubuntu-latest, macos-latest, windows-latest] steps: - - uses: actions/checkout@v3 - - # Used to host cibuildwheel - - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - name: Install cibuildwheel - run: python -m pip install cibuildwheel==2.16.2 + - name: Checkout + uses: actions/checkout@v4 - - name: Create setup.py - run: | - mv ${{github.workspace}}/src/wrappers/python/setup.py ${{github.workspace}}/setup.py - mv ${{github.workspace}}/src/wrappers/python/Imath.py ${{github.workspace}}/Imath.py - mv ${{github.workspace}}/src/wrappers/python/OpenEXR.cpp ${{github.workspace}}/OpenEXR.cpp + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' - - name: Create folders - run: | - mkdir -p ${{github.workspace}}/openexr.build - mkdir -p ${{github.workspace}}/openexr.install + - name: Create sdist + # Only create it once. + if: ${{ matrix.os == 'ubuntu-latest' }} + run: pipx run build --sdist . --outdir wheelhouse - - name: Build wheels - run: python -m cibuildwheel --output-dir wheelhouse + - name: Build wheel + uses: pypa/cibuildwheel@v2.16 + env: + CIBW_ARCHS_MACOS: x86_64 arm64 universal2 + # Skip python 3.6 since scikit-build-core requires 3.7+ + # Skip 32-bit wheels builds on Windows + # Also skip the PyPy builds, since they fail the unit tests + CIBW_SKIP: cp36-* *-win32 *_i686 pp* + CIBW_TEST_SKIP: "*-macosx*arm64" - - uses: actions/upload-artifact@v3 + - name: Upload artifact + uses: actions/upload-artifact@v4 with: - name: "Python wheels" - path: ./wheelhouse/*.whl + name: wheels-${{ matrix.os }} + path: | + ./wheelhouse/*.whl + ./wheelhouse/*.tar.gz + diff --git a/.github/workflows/website_workflow.yml b/.github/workflows/website_workflow.yml index afd69e38d3..28edd16a6f 100644 --- a/.github/workflows/website_workflow.yml +++ b/.github/workflows/website_workflow.yml @@ -14,6 +14,8 @@ on: branches:-ignore: - RB-2.* - RB-3.* + tags-ignore: + - v3.[0-9]+.[0-9]+-rc* paths: - 'website/**' @@ -21,6 +23,8 @@ on: branches:-ignore: - RB-2.* - RB-3.* + tags-ignore: + - v3.[0-9]+.[0-9]+-rc* paths: - 'website/**' diff --git a/CMakeLists.txt b/CMakeLists.txt index a365910645..cd28f765f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,8 +48,25 @@ set(OPENEXR_LIB_VERSION "${OPENEXR_LIB_SOVERSION}.${OPENEXR_VERSION}") # e.g. "3 option(OPENEXR_INSTALL "Install OpenEXR libraries" ON) option(OPENEXR_INSTALL_TOOLS "Install OpenEXR tools" ON) -if(OPENEXR_INSTALL_TOOLS AND NOT OPENEXR_INSTALL) - message(SEND_ERROR "OPENEXR_INSTALL_TOOLS requires OPENEXR_INSTALL") + +# uninstall target +if(NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif() + +# uninstall target +if(NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) endif() # uninstall target @@ -83,8 +100,13 @@ if(BUILD_TESTING AND NOT OPENEXR_IS_SUBPROJECT) endif() # Include these two modules without enable/disable options -add_subdirectory(src/lib) -add_subdirectory(src/bin) +if (OPENEXR_BUILD_LIBS) + add_subdirectory(src/lib) +endif() + +if(OPENEXR_BUILD_TOOLS AND OPENEXR_BUILD_LIBS) + add_subdirectory(src/bin) +endif() # Tell CMake where to find the OpenEXRConfig.cmake file. Makes it possible to call # find_package(OpenEXR) in downstream projects @@ -93,8 +115,7 @@ set(OpenEXR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake" CACHE PATH "" FORCE) # Can be empty since we already defined the targets in add_subdirectory file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cmake/OpenEXRTargets.cmake" "# Dummy file") -option(OPENEXR_INSTALL_EXAMPLES "Install OpenEXR examples" ON) -if(OPENEXR_INSTALL_EXAMPLES) +if(OPENEXR_BUILD_EXAMPLES AND OPENEXR_BUILD_LIBS) add_subdirectory( src/examples ) endif() @@ -122,7 +143,7 @@ endif() #set(CTEST_DROP_SITE_CDASH TRUE) include(CTest) -if(BUILD_TESTING AND NOT OPENEXR_IS_SUBPROJECT) +if(BUILD_TESTING AND OPENEXR_BUILD_LIBS AND NOT OPENEXR_IS_SUBPROJECT) add_subdirectory(src/test) endif() @@ -142,12 +163,11 @@ if (BUILD_WEBSITE AND NOT OPENEXR_IS_SUBPROJECT) add_subdirectory(website) endif() -if (NOT OPENEXR_IS_SUBPROJECT) +if (OPENEXR_BUILD_LIBS AND NOT OPENEXR_IS_SUBPROJECT) # Even if not building the website, still make sure the website example code compiles. add_subdirectory(website/src) endif() -option(OPENEXR_BUILD_PYTHON "Set ON to build python bindings") -if (OPENEXR_BUILD_PYTHON AND NOT OPENEXR_IS_SUBPROJECT) +if (OPENEXR_BUILD_PYTHON AND OPENEXR_BUILD_LIBS AND NOT OPENEXR_IS_SUBPROJECT) add_subdirectory(src/wrappers/python) endif() diff --git a/cmake/OpenEXRSetup.cmake b/cmake/OpenEXRSetup.cmake index 0a7dabcc6f..9f1a5ea5ee 100644 --- a/cmake/OpenEXRSetup.cmake +++ b/cmake/OpenEXRSetup.cmake @@ -51,8 +51,23 @@ option(OPENEXR_ENABLE_LARGE_STACK "Enables code to take advantage of large stack ######################## ## Build related options -# Whether to build & install the various command line utility programs +option(OPENEXR_INSTALL "Install OpenEXR libraries/binaries/bindings" ON) + +# Whether to build & install the main libraries +option(OPENEXR_BUILD_LIBS "Enables building of main libraries" ON) + +# Whether to build the various command line utility programs option(OPENEXR_BUILD_TOOLS "Enables building of utility programs" ON) +option(OPENEXR_INSTALL_TOOLS "Install OpenEXR tools" ON) + +option(OPENEXR_BUILD_EXAMPLES "Build OpenEXR examples" ON) +option(OPENEXR_INSTALL_EXAMPLES "Install OpenEXR examples" ON) + +option(OPENEXR_BUILD_PYTHON "Build python bindings" OFF) + +option(OPENEXR_TEST_LIBRARIES "Run library tests" ON) +option(OPENEXR_TEST_TOOLS "Run tool tests" ON) +option(OPENEXR_TEST_PYTHON "Run python binding tests" ON) # This is a variable here for use in controlling where include files are # installed. Care must be taken when changing this, as many things @@ -138,6 +153,10 @@ if(OPENEXR_USE_CLANG_TIDY) ) endif() +if (NOT OPENEXR_BUILD_LIBS) + return() +endif() + ############################### # Dependent libraries @@ -246,10 +265,8 @@ endif() option(OPENEXR_FORCE_INTERNAL_IMATH "Force using an internal imath" OFF) # Check to see if Imath is installed outside of the current build directory. -set(OPENEXR_IMATH_REPO "https://github.com/AcademySoftwareFoundation/Imath.git" CACHE STRING - "Repo for auto-build of Imath") -set(OPENEXR_IMATH_TAG "v3.1.9" CACHE STRING - "Tag for auto-build of Imath (branch, tag, or SHA)") +set(OPENEXR_IMATH_REPO "https://github.com/AcademySoftwareFoundation/Imath.git" CACHE STRING "Repo for auto-build of Imath") +set(OPENEXR_IMATH_TAG "v3.1.10" CACHE STRING "Tag for auto-build of Imath (branch, tag, or SHA)") if(NOT OPENEXR_FORCE_INTERNAL_IMATH) #TODO: ^^ Release should not clone from main, this is a place holder set(CMAKE_IGNORE_PATH "${CMAKE_CURRENT_BINARY_DIR}/_deps/imath-src/config;${CMAKE_CURRENT_BINARY_DIR}/_deps/imath-build/config") @@ -274,10 +291,13 @@ if(NOT TARGET Imath::Imath AND NOT Imath_FOUND) if(NOT Imath_POPULATED) FetchContent_Populate(Imath) + # Propagate OpenEXR's install setting to Imath + set(IMATH_INSTALL ${OPENEXR_INSTALL}) + # Propagate OpenEXR's setting for pkg-config generation to Imath: # If OpenEXR is generating it, the internal Imath should, too. set(IMATH_INSTALL_PKG_CONFIG ${OPENEXR_INSTALL_PKG_CONFIG}) - + # hrm, cmake makes Imath lowercase for the properties (to imath) add_subdirectory(${imath_SOURCE_DIR} ${imath_BINARY_DIR}) endif() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..fdc7b0370a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) Contributors to the OpenEXR Project. + +[build-system] +requires = ["scikit-build-core==0.8.0"] +build-backend = "scikit_build_core.build" + +[project] +name = "OpenEXR" +dynamic = ["version"] + +description="Python bindings for the OpenEXR image file format" +readme = "src/wrappers/python/README.md" +authors = [ + { name="Contributors to the OpenEXR project", email="info@openexr.com" }, +] +requires-python = ">=3.7" + +[project.urls] +"Homepage" = "https://openexr.com" +"Source" = "https://github.com/AcademySoftwareFoundation/OpenEXR" +"Bug Tracker" = "https://github.com/AcademySoftwareFoundation/OpenEXR/issues" + +[project.optional-dependencies] +test = ["pytest"] + +[tool.scikit-build] +wheel.expand-macos-universal-tags = true +sdist.exclude = [".github", "src/test", "src/examples", "website", "ASWF", "bazel", "share"] +cmake.targets = ["PyOpenEXR"] +# Enable experimental features if any are available +# In this case we need custom local plugin to get +# the project version from cmake. +experimental = true +metadata.version.provider = "openexr_skbuild_plugin" +metadata.version.provider-path = "./src/wrappers/python" + +[tool.scikit-build.cmake.define] +OPENEXR_INSTALL = 'OFF' +OPENEXR_BUILD_PYTHON = 'ON' +OPENEXR_BUILD_EXAMPLES = 'OFF' +OPENEXR_INSTALL_EXAMPLES = 'OFF' +OPENEXR_BUILD_TOOLS = 'OFF' +OPENEXR_INSTALL_TOOLS = 'OFF' +OPENEXR_INSTALL_PKG_CONFIG = 'OFF' +OPENEXR_FORCE_INTERNAL_DEFLATE = 'ON' +OPENEXR_FORCE_INTERNAL_IMATH = 'ON' +OPENEXR_TEST_LIBRARIES = 'OFF' +BUILD_SHARED_LIBS = 'OFF' +CMAKE_POSITION_INDEPENDENT_CODE = 'ON' + +[tool.cibuildwheel] +test-command = "ctest -R PyOpenEXR" +test-extras = ["test"] +test-skip = ["*universal2:arm64"] +build-verbosity = 1 + +manylinux-x86_64-image = "manylinux2014" +manylinux-i686-image = "manylinux2014" +manylinux-aarch64-image = "manylinux2014" diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt index 893fd58d11..99785681b1 100644 --- a/src/bin/CMakeLists.txt +++ b/src/bin/CMakeLists.txt @@ -1,19 +1,20 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) Contributors to the OpenEXR Project. -########################## -# Binaries / Utilities -########################## -if(OPENEXR_BUILD_TOOLS) - add_subdirectory( exr2aces ) - add_subdirectory( exrheader ) - add_subdirectory( exrinfo ) - add_subdirectory( exrmaketiled ) - add_subdirectory( exrstdattr ) - add_subdirectory( exrmakepreview ) - add_subdirectory( exrenvmap ) - add_subdirectory( exrmultiview ) - add_subdirectory( exrmultipart ) - add_subdirectory( exrcheck ) - add_subdirectory( exrmanifest ) -endif() +################## +# Binaries / Tools +################## + +message(STATUS "Building OpenEXR tools") + +add_subdirectory( exr2aces ) +add_subdirectory( exrheader ) +add_subdirectory( exrinfo ) +add_subdirectory( exrmaketiled ) +add_subdirectory( exrstdattr ) +add_subdirectory( exrmakepreview ) +add_subdirectory( exrenvmap ) +add_subdirectory( exrmultiview ) +add_subdirectory( exrmultipart ) +add_subdirectory( exrcheck ) +add_subdirectory( exrmanifest ) diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index ea34cb42c9..d6d092aee0 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -6,6 +6,8 @@ # standalone program linking against an already-installed OpenEXR # library. +message(STATUS "Building OpenEXR examples") + if("${CMAKE_PROJECT_NAME}" STREQUAL "") cmake_minimum_required(VERSION 3.12) project(OpenEXRExamples) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index a315e444c5..8b4b5f0fa8 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,6 +1,8 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) Contributors to the OpenEXR Project. +message(STATUS "Building OpenEXR libraries") + add_subdirectory( Iex ) add_subdirectory( IlmThread ) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 44d9185d8b..25f429daa2 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -4,10 +4,15 @@ # We require this to get object library link library support and # combined python 2 + 3 support -add_subdirectory(IexTest) -add_subdirectory(OpenEXRCoreTest) -add_subdirectory(OpenEXRTest) -add_subdirectory(OpenEXRUtilTest) -add_subdirectory(OpenEXRFuzzTest) -add_subdirectory(bin) +if (OPENEXR_TEST_LIBRARIES) + add_subdirectory(IexTest) + add_subdirectory(OpenEXRCoreTest) + add_subdirectory(OpenEXRTest) + add_subdirectory(OpenEXRUtilTest) + add_subdirectory(OpenEXRFuzzTest) +endif() + +if (OPENEXR_BUILD_TOOLS AND OPENEXR_TEST_TOOLS) + add_subdirectory(bin) +endif() diff --git a/src/wrappers/python/CMakeLists.txt b/src/wrappers/python/CMakeLists.txt index a136ad5531..471619b683 100644 --- a/src/wrappers/python/CMakeLists.txt +++ b/src/wrappers/python/CMakeLists.txt @@ -1,23 +1,42 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright Contributors to the OpenEXR Project. +message(STATUS "Building OpenEXR python bindings") + if(NOT "${CMAKE_PROJECT_NAME}" STREQUAL "OpenEXR") cmake_minimum_required(VERSION 3.12) project(PyOpenEXR) find_package(OpenEXR) endif() -add_library (PyOpenEXR SHARED OpenEXR.cpp) +find_package(Python COMPONENTS Interpreter Development.Module REQUIRED) + +python_add_library (PyOpenEXR MODULE OpenEXR.cpp) -set (Python_ADDITIONAL_VERSIONS 3) -find_package (PythonLibs REQUIRED) -find_package (PythonInterp REQUIRED) +target_link_libraries (PyOpenEXR PRIVATE "${Python_LIBRARIES}" OpenEXR::OpenEXR) -include_directories ("${PYTHON_INCLUDE_DIRS}") +# The python module should be called "OpenEXR.so", not "PyOpenEXR.so", +# but "OpenEXR" is taken as a library name by the main lib, so specify +# the name explicitly here. -set_target_properties (PyOpenEXR PROPERTIES PREFIX "") set_target_properties (PyOpenEXR PROPERTIES OUTPUT_NAME "OpenEXR") -set_target_properties (PyOpenEXR PROPERTIES SUFFIX ".so") -target_link_libraries (PyOpenEXR "${PYTHON_LIBRARIES}" OpenEXR::OpenEXR) +configure_file(Imath.py ${CMAKE_CURRENT_BINARY_DIR}/Imath.py COPYONLY) + +set(PYTHON_INSTALL_DIR "python/OpenEXR") +if(SKBUILD) + set(PYTHON_INSTALL_DIR ${SKBUILD_PLATLIB_DIR}) +endif() + +install(TARGETS PyOpenEXR DESTINATION ${PYTHON_INSTALL_DIR}) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Imath.py DESTINATION ${PYTHON_INSTALL_DIR}) +if(BUILD_TESTING AND OPENEXR_TEST_PYTHON) + + add_test(OpenEXR.PyOpenEXR pytest ${CMAKE_CURRENT_SOURCE_DIR}/tests) + + set_tests_properties(OpenEXR.PyOpenEXR PROPERTIES + ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ) + +endif() diff --git a/src/wrappers/python/README.md b/src/wrappers/python/README.md new file mode 100644 index 0000000000..d7c15c989a --- /dev/null +++ b/src/wrappers/python/README.md @@ -0,0 +1,142 @@ + + + +[![License](https://img.shields.io/github/license/AcademySoftwareFoundation/openexr)](https://github.com/AcademySoftwareFoundation/openexr/blob/main/LICENSE.md) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2799/badge)](https://bestpractices.coreinfrastructure.org/projects/2799) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/AcademySoftwareFoundation/openexr/badge)](https://securityscorecards.dev/viewer/?uri=github.com/AcademySoftwareFoundation/openexr) +[![Build Status](https://github.com/AcademySoftwareFoundation/openexr/workflows/CI/badge.svg)](https://github.com/AcademySoftwareFoundation/openexr/actions?query=workflow%3ACI) +[![Analysis Status](https://github.com/AcademySoftwareFoundation/openexr/workflows/Analysis/badge.svg)](https://github.com/AcademySoftwareFoundation/openexr/actions?query=workflow%3AAnalysis) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=AcademySoftwareFoundation_openexr&metric=alert_status)](https://sonarcloud.io/dashboard?id=AcademySoftwareFoundation_openexr) + +# OpenEXR + +OpenEXR provides the specification and reference implementation of the +EXR file format, the professional-grade image storage format of the +motion picture industry. + +The purpose of EXR format is to accurately and efficiently represent +high-dynamic-range scene-linear image data and associated metadata, +with strong support for multi-part, multi-channel use cases. + +OpenEXR is widely used in host application software where accuracy is +critical, such as photorealistic rendering, texture access, image +compositing, deep compositing, and DI. + +## OpenEXR Project Mission + +The goal of the OpenEXR project is to keep the EXR format reliable and +modern and to maintain its place as the preferred image format for +entertainment content creation. + +Major revisions are infrequent, and new features will be carefully +weighed against increased complexity. The principal priorities of the +project are: + +* Robustness, reliability, security +* Backwards compatibility, data longevity +* Performance - read/write/compression/decompression time +* Simplicity, ease of use, maintainability +* Wide adoption, multi-platform support - Linux, Windows, macOS, and others + +OpenEXR is intended solely for 2D data. It is not appropriate for +storage of volumetric data, cached or lit 3D scenes, or more complex +3D data such as light fields. + +The goals of the Imath project are simplicity, ease of use, +correctness and verifiability, and breadth of adoption. Imath is not +intended to be a comprehensive linear algebra or numerical analysis +package. + +## Python Module + +The OpenEXR python module provides rudimentary support for reading and +writing basic scanline image data. Many features of the file format +are not yet supported, including: + +- Writing of tiled images +- Multiresoltion images +- Deep image data +- Some attribute types +- Nonunity channel sampling frequencies +- No support for interleaved channel data + +## Project Governance + +OpenEXR is a project of the [Academy Software +Foundation](https://www.aswf.io). See the project's [governance +policies](https://github.com/AcademySoftwareFoundation/openexr/blob/main/GOVERNANCE.md), [contribution guidelines](https://github.com/AcademySoftwareFoundation/openexr/blob/main/CONTRIBUTING.md), and [code of conduct](https://github.com/AcademySoftwareFoundation/openexr/blob/main/CODE_OF_CONDUCT.md) +for more information. + +# Quick Start + +The "hello, world" image writer: + + import OpenEXR + + width = 10 + height = 10 + size = width * height + + h = OpenEXR.Header(width,height) + h['channels'] = {'R' : Imath.Channel(FLOAT), + 'G' : Imath.Channel(FLOAT), + 'B' : Imath.Channel(FLOAT), + 'A' : Imath.Channel(FLOAT)} + o = OpenEXR.OutputFile("hello.exr", h) + r = array('f', [n for n in range(size*0,size*1)]).tobytes() + g = array('f', [n for n in range(size*1,size*2)]).tobytes() + b = array('f', [n for n in range(size*2,size*3)]).tobytes() + a = array('f', [n for n in range(size*3,size*4)]).tobytes() + channels = {'R' : r, 'G' : g, 'B' : b, 'A' : a} + o.writePixels(channels) + o.close() + +# Community + +* **Ask a question:** + + - Email: openexr-dev@lists.aswf.io + + - Slack: [academysoftwarefdn#openexr](https://academysoftwarefdn.slack.com/archives/CMLRW4N73) + +* **Attend a meeting:** + + - Technical Steering Committee meetings are open to the + public, fortnightly on Thursdays, 1:30pm Pacific Time. + + - Calendar: https://lists.aswf.io/g/openexr-dev/calendar + + - Meeting notes: https://wiki.aswf.io/display/OEXR/TSC+Meetings + +* **Report a bug:** + + - Submit an Issue: https://github.com/AcademySoftwareFoundation/openexr/issues + +* **Report a security vulnerability:** + + - Email to security@openexr.com + +* **Contribute a Fix, Feature, or Improvement:** + + - Read the [Contribution Guidelines](https://github.com/AcademySoftwareFoundation/openexr/blob/main/CONTRIBUTING.md) and [Code of Conduct](https://github.com/AcademySoftwareFoundation/openexr/blob/main/CODE_OF_CONDUCT.md) + + - Sign the [Contributor License + Agreement](https://contributor.easycla.lfx.linuxfoundation.org/#/cla/project/2e8710cb-e379-4116-a9ba-964f83618cc5/user/564e571e-12d7-4857-abd4-898939accdd7) + + - Submit a Pull Request: https://github.com/AcademySoftwareFoundation/openexr/pulls + +# Resources + +- Website: http://www.openexr.com +- Technical documentation: https://openexr.readthedocs.io +- Porting help: [OpenEXR/Imath Version 2.x to 3.x Porting Guide](https://openexr.readthedocs.io/en/latest/PortingGuide.html) +- Reference images: https://github.com/AcademySoftwareFoundation/openexr-images +- Security policy: [SECURITY.md](https://github.com/AcademySoftwareFoundation/openexr/blob/main/SECURITY.md) +- Release notes: [CHANGES.md](https://github.com/AcademySoftwareFoundation/openexr/blob/main/CHANGES.md) +- Contributors: [CONTRIBUTORS.md](https://github.com/AcademySoftwareFoundation/openexr/blob/main/CONTRIBUTORS.md) + +# License + +OpenEXR is licensed under the [BSD-3-Clause license](https://github.com/AcademySoftwareFoundation/openexr/blob/main/LICENSE.md). + + diff --git a/src/wrappers/python/libdeflate.patch b/src/wrappers/python/libdeflate.patch deleted file mode 100644 index a1e2e5b0cc..0000000000 --- a/src/wrappers/python/libdeflate.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- CMakeLists.txt 2023-07-14 08:51:51.375958419 +0200 -+++ CMakeLists.txt 2023-07-14 08:47:47.854104430 +0200 -@@ -183,7 +183,8 @@ - endif() - set_target_properties(libdeflate_static PROPERTIES - OUTPUT_NAME ${STATIC_LIB_NAME} -- PUBLIC_HEADER libdeflate.h) -+ PUBLIC_HEADER libdeflate.h -+ POSITION_INDEPENDENT_CODE ON) - target_include_directories(libdeflate_static PUBLIC ${LIB_INCLUDE_DIRS}) - target_compile_definitions(libdeflate_static PRIVATE ${LIB_COMPILE_DEFINITIONS}) - target_compile_options(libdeflate_static PRIVATE ${LIB_COMPILE_OPTIONS}) diff --git a/src/wrappers/python/openexr_skbuild_plugin.py b/src/wrappers/python/openexr_skbuild_plugin.py new file mode 100644 index 0000000000..ea09221b46 --- /dev/null +++ b/src/wrappers/python/openexr_skbuild_plugin.py @@ -0,0 +1,106 @@ +# Copyright Contributors to the MaterialX Project +# SPDX-License-Identifier: Apache-2.0 +# copied from: https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/python/mtx_skbuild_plugin.py +# Modifications Copyright (c) Contributors to the OpenEXR Project. + +""" +This is a custom scikit-build-core plugin that will +fetch the OpenEXR version from the CMake project. +""" +import os +import tempfile +import subprocess +from pathlib import Path +from typing import FrozenSet, Dict, Optional, Union, List + +from scikit_build_core.file_api.query import stateless_query +from scikit_build_core.file_api.reply import load_reply_dir + + +def dynamic_metadata( + fields: FrozenSet[str], + settings: Optional[Dict[str, object]] = None, +) -> Dict[str, Union[str, Dict[str, Optional[str]]]]: + print("openexr_skbuild_plugin: Computing OpenEXR version from CMake...") + + if fields != "version": + msg = f"Only the 'version' field is supported: fields={fields}" + raise ValueError(msg) + + if settings: + msg = "No inline configuration is supported" + raise ValueError(msg) + + if "OPENEXR_RELEASE_CANDIDATE_TAG" in os.environ: + + # e.g. "v3.1.2-rc4" + # + # If OPENEXR_RELEASE_CANDIDATE_TAG is set, + # the build is for a publish to test.pypi.org. Multiple test + # publishes may happen in the course of preparing for a + # release, but published packages require unique + # names/versions, so use the release candidate tag as the + # version (minus the leading 'v'), + + rct = os.environ["OPENEXR_RELEASE_CANDIDATE_TAG"] + version = rct[1:] + + else: + + current_dir = os.path.dirname(__file__) + + with tempfile.TemporaryDirectory() as tmpdir: + # We will use CMake's file API to get the version + # instead of parsing the CMakeLists files. + + # First generate the query folder so that CMake can generate replies. + reply_dir = stateless_query(Path(tmpdir)) + + # Run cmake (configure). CMake will generate a reply automatically. + try: + subprocess.run( + [ + "cmake", + "-S", + current_dir + "../../../..", + "-B", + tmpdir, + "-DOPENEXR_BUILD_LIBS=OFF", + ], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True, + text=True, + ) + except subprocess.CalledProcessError as exc: + print(exc.stdout) + raise RuntimeError( + "Failed to configure project to get the version" + ) from exc + + # Get the generated replies. + index = load_reply_dir(reply_dir) + + # Get the version from the CMAKE_PROJECT_VERSION variable. + entries = [ + entry + for entry in index.reply.cache_v2.entries + if entry.name == "CMAKE_PROJECT_VERSION" + ] + + if not entries: + raise ValueError("Could not find OpenEXR version from CMake project") + + if len(entries) > 1: + raise ValueError("More than one entry for CMAKE_PROJECT_VERSION found...") + + version = entries[0].value + + print("openexr_skbuild_plugin: Computed version: {0}".format(version)) + + return version + +def get_requires_for_dynamic_metadata( + _settings: Optional[Dict[str, object]] = None, +) -> List[str]: + return ["cmake"] diff --git a/src/wrappers/python/setup.py b/src/wrappers/python/setup.py deleted file mode 100644 index 5cf4cda608..0000000000 --- a/src/wrappers/python/setup.py +++ /dev/null @@ -1,83 +0,0 @@ -from setuptools import setup, Extension -import os -import platform -import re - - -DESC = """Python bindings for the OpenEXR image file format. - -This is a script to autobuild the wheels using github actions. Please, do not -use it manually - -If you detect any problem, please feel free to report the issue on the GitHub -page: - -https://github.com/AcademySoftwareFoundation/openexr/issues -""" - -# Get the version and library suffix for both OpenEXR and Imath from -# the .pc pkg-config file. - -def pkg_config(var, pkg): - with open(f'./openexr.install/lib/pkgconfig/{pkg}.pc', 'r') as f: - return re.search(f'{var}([^ \n]+)', f.read()).group(1) - -imath_libsuffix = pkg_config("libsuffix=", "Imath") -openexr_libsuffix = pkg_config("libsuffix=", "OpenEXR") -openexr_version = pkg_config("Version: ", "OpenEXR") -openexr_version_major, openexr_version_minor, openexr_version_patch = openexr_version.split('.') - -libs=[] -libs_static=[f'OpenEXR{openexr_libsuffix}', - f'IlmThread{openexr_libsuffix}', - f'Iex{openexr_libsuffix}', - f'Imath{imath_libsuffix}', - f'OpenEXRCore{openexr_libsuffix}', - ] -definitions = [('PYOPENEXR_VERSION_MAJOR', f'{openexr_version_major}'), - ('PYOPENEXR_VERSION_MINOR', f'{openexr_version_minor}'), - ('PYOPENEXR_VERSION_PATCH', f'{openexr_version_patch}'),] -if platform.system() == "Windows": - definitions = [('PYOPENEXR_VERSION', f'\\"{openexr_version}\\"')] -extra_compile_args = [] -if platform.system() == 'Darwin': - extra_compile_args += ['-std=c++11', - '-Wc++11-extensions', - '-Wc++11-long-long'] - -libs_dir = "./openexr.install/lib/" -if not os.path.isdir(libs_dir): - libs_dir = "./openexr.install/lib64/" -if platform.system() == "Windows": - extra_link_args = [libs_dir + lib + ".lib" - for lib in libs_static] - extra_link_args = extra_link_args + [ - "ws2_32.lib", "dbghelp.lib", "psapi.lib", "kernel32.lib", "user32.lib", - "gdi32.lib", "winspool.lib", "shell32.lib", "ole32.lib", - "oleaut32.lib", "uuid.lib", "comdlg32.lib", "advapi32.lib"] -else: - extra_link_args = [libs_dir + "lib" + lib + ".a" - for lib in libs_static] - - -setup(name='OpenEXR', - author = 'Contributors to the OpenEXR Project', - author_email = 'info@openexr.com', - url = 'https://github.com/AcademySoftwareFoundation/openexr', - description = "Python bindings for the OpenEXR image file format", - long_description = DESC, - version=openexr_version, - ext_modules=[ - Extension('OpenEXR', - ['OpenEXR.cpp'], - language='c++', - define_macros=definitions, - include_dirs=['./openexr.install/include/OpenEXR', - './openexr.install/include/Imath',], - libraries=libs, - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args, - ) - ], - py_modules=['Imath'], -) diff --git a/src/wrappers/python/tests/test_minimal.py b/src/wrappers/python/tests/test_minimal.py index 564bab0b74..43560a8560 100644 --- a/src/wrappers/python/tests/test_minimal.py +++ b/src/wrappers/python/tests/test_minimal.py @@ -1,5 +1,9 @@ -import pytest +#!/usr/bin/env python3 + +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) Contributors to the OpenEXR Project. +import pytest def test_import(): import OpenEXR diff --git a/src/wrappers/python/tests/test_unittest.py b/src/wrappers/python/tests/test_unittest.py index 5061ac2b91..e08a44b0b9 100644 --- a/src/wrappers/python/tests/test_unittest.py +++ b/src/wrappers/python/tests/test_unittest.py @@ -11,10 +11,8 @@ import random from array import array -import Imath import OpenEXR - -test_dir = os.path.dirname(os.path.abspath(__file__)) +import Imath FLOAT = Imath.PixelType(Imath.PixelType.FLOAT) UINT = Imath.PixelType(Imath.PixelType.UINT)