jamesbowman / openexrpython

OpenEXR bindings for Python
Other
94 stars 35 forks source link

Failing at `pip install` on macOS Big Sur 11.4 - Proposed Fix #43

Open l-oneil opened 3 years ago

l-oneil commented 3 years ago

I had some issues with pip install openexr when trying to install this module on macOS latest version (at time of writing).

I've not had the time to dig into the nuts and bolts of this problem, it seems to stem from developmental changes to the OpenEXR library, forking off from Imath and making minor changes to their API.

I've written a patch which has gotten this library installing and tested to be working within the scope of what I need it for (reading and processing images stored as .exr), it can likely be tidied and better tested (so no PR), hopefully this helps any others who run into difficulties:

diff --git a/OpenEXR.cpp b/OpenEXR.cpp
index 99ff258..d73372c 100644
--- a/OpenEXR.cpp
+++ b/OpenEXR.cpp
@@ -62,6 +62,7 @@ typedef int Py_ssize_t;
 #include <ImfTimeCodeAttribute.h>
 #include <ImfVecAttribute.h>
 #include <ImfVersion.h>
+#include <ImfFrameBuffer.h>

 #include <OpenEXRConfig.h>

@@ -87,8 +88,8 @@ typedef int Py_ssize_t;
 #include <algorithm>
 #include <iostream>
 #include <iomanip>
-#include <iostream>
 #include <vector>
+#include <fstream>

 using namespace std;
 using namespace Imf;
@@ -121,8 +122,8 @@ class C_IStream: public IStream
     C_IStream (PyObject *fo):
         IStream(""), _fo(fo) {}
     virtual bool    read (char c[], int n);
-    virtual Int64   tellg ();
-    virtual void    seekg (Int64 pos);
+    virtual uint64_t   tellg ();
+    virtual void    seekg (uint64_t pos);
     virtual void    clear ();
     virtual const char*     fileName() const;
   private:
@@ -148,7 +149,7 @@ const char* C_IStream::fileName() const
 }

-Int64
+uint64_t
 C_IStream::tellg ()
 {
     PyObject *rv = PyObject_CallMethod(_fo, (char*)"tell", NULL);
@@ -157,14 +158,14 @@ C_IStream::tellg ()
       long long t = PyLong_AsLong(lrv);
       Py_DECREF(lrv);
       Py_DECREF(rv);
-      return (Int64)t;
+      return (uint64_t)t;
     } else {
       throw Iex::InputExc("tell failed");
     }
 }

 void
-C_IStream::seekg (Int64 pos)
+C_IStream::seekg (uint64_t pos)
 {
     PyObject *data = PyObject_CallMethod(_fo, (char*)"seek", (char*)"(L)", pos);
     if (data != NULL) {
@@ -186,8 +187,8 @@ class C_OStream: public OStream
   public:
     C_OStream (PyObject *fo): OStream(""), _fo(fo) {}
     virtual void    write (const char *c, int n);
-    virtual Int64   tellp ();
-    virtual void    seekp (Int64 pos);
+    virtual uint64_t   tellp ();
+    virtual void    seekp (uint64_t pos);
     virtual void    clear ();
     virtual const char*     fileName() const;
   private:
@@ -212,7 +213,7 @@ const char* C_OStream::fileName() const
 }

-Int64
+uint64_t
 C_OStream::tellp ()
 {
     PyObject *rv = PyObject_CallMethod(_fo, (char*)"tell", NULL);
@@ -221,14 +222,14 @@ C_OStream::tellp ()
       long long t = PyLong_AsLong(lrv);
       Py_DECREF(lrv);
       Py_DECREF(rv);
-      return (Int64)t;
+      return (uint64_t)t;
     } else {
       throw Iex::InputExc("tell failed");
     }
 }

 void
-C_OStream::seekp (Int64 pos)
+C_OStream::seekp (uint64_t pos)
 {
     PyObject *data = PyObject_CallMethod(_fo, (char*)"seek", (char*)"(L)", pos);
     if (data != NULL) {
diff --git a/setup.py b/setup.py
index 4d307ee..5aac585 100644
--- a/setup.py
+++ b/setup.py
@@ -32,9 +32,9 @@ setup(name='OpenEXR',
   ext_modules=[ 
     Extension('OpenEXR',
               ['OpenEXR.cpp'],
-              include_dirs=['/usr/include/OpenEXR', '/usr/local/include/OpenEXR', '/opt/local/include/OpenEXR'],
+              include_dirs=['/usr/include/OpenEXR', '/usr/local/include/OpenEXR', '/opt/local/include/OpenEXR', '/usr/local/include/Imath'],
               library_dirs=['/usr/local/lib', '/opt/local/lib'],
-              libraries=['Iex', 'Half', 'Imath', 'IlmImf', 'z'],
+              libraries=['Iex', 'Imath', 'OpenEXR', 'z'],
               extra_compile_args=compiler_args)
   ],
   py_modules=['Imath'],

The general installation flow should look something like:

$ git clone https://github.com/jamesbowman/openexrpython
$ cd openexrpython
$ mv <path/to/openexr_macos.patch> ./
$ git apply ./openexr_macos.patch
$ brew install openexr 
$ brew install imath
$ brew link openexr
$ brew link imath 
$ pip install ./

Hope this helps! Liam

fgolemo commented 2 years ago

If I do this, I get it to actually compile but when I try running it, I get the following error:

Python 3.8.12 (default, Oct 12 2021, 06:23:56) 
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import OpenEXR
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dlopen(/Users/florian/miniconda3/envs/py38/lib/python3.8/site-packages/OpenEXR.cpython-38-darwin.so, 2): Symbol not found: __ZTIN7Imf_3_114TypedAttributeIN9Imath_2_53BoxINS1_4Vec2IiEEEEEE
  Referenced from: /Users/florian/miniconda3/envs/py38/lib/python3.8/site-packages/OpenEXR.cpython-38-darwin.so
  Expected in: flat namespace
 in /Users/florian/miniconda3/envs/py38/lib/python3.8/site-packages/OpenEXR.cpython-38-darwin.so

Has anybody seen this before?

sonsongithub commented 2 years ago

I edited setup.py and OpenEXR.cpp, to support macOS 12.3 and other OSs, without patching. How about this?

https://github.com/sonsongithub/openexrpython/tree/macos