I’ve been having a bit of a headache trying to install PythonMagick (the Python bindings for ImageMagick) on Mac OS X Snow Leopard, so having eventually had a modicum of success I thought I’d post my adventures here.

Problems Building From Source

But first, let me outline the problems I was having. Initially I tried building ImageMagick from source. That meant first downloading and installing Boost, which again I tried doing from source (1.46.1). When it became time to install the Boost::Python module, I tried following the instructions in the documentation:

$ cd libs/python/example/quickstart/
$ bjam toolset=darwin --verbose-test test

However, I’d find it would get so far and then just hang – I left it for about 24 hours with no progress. If I hit Ctrl-C and then tried again, it just sits there saying this:

...patience...
...patience...
...found 1603 targets...
...updating 8 targets...

Problems Using MacPorts

Since I couldn’t get very far that route, I decided to try the MacPorts approach, which makes installing these kinds of things very straightforward.

Again, first I had to try and install Boost, with the Python module enabled:

$ sudo port install boost +python26

So far, so good! That installed the package “boost @1.46.1_0+python26″. Next was to install ImageMagick:

$ sudo port install ImageMagick

Again, nice and smooth! That installed “ImageMagick @6.6.8-1_0+q16″. Now came the hard part: building PythonMagick. I used v0.9.3 since that seemed the latest version compatible with Python 2.x. The first step is to configure it. Reading around it became clear that I needed to specify the MacPorts include and library directories, like so:

$ ./configure --prefix=/opt/local CPPFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib

But no matter what I tried, I kept getting the message “checking whether the Boost::Python library is available… no”. Eventually I figured out that you can get more information by reading the config.log file. I was getting all sorts of error messages like this:

configure:14953: checking whether the Boost::Python library is available
configure:14983: g++ -c -g -O2 -I/opt/local/include conftest.cpp >&5
In file included from /opt/local/include/boost/python/detail/prefix.hpp:13,
from /opt/local/include/boost/python/module.hpp:8,
from conftest.cpp:23:
/opt/local/include/boost/python/detail/wrap_python.hpp:50:23: error: pyconfig.h: No such file or directory
/opt/local/include/boost/python/detail/wrap_python.hpp:75:24: error: patchlevel.h: No such file or directory
/opt/local/include/boost/python/detail/wrap_python.hpp:78:2: error: #error Python 2.2 or higher is required for this version of Boost.Python.
/opt/local/include/boost/python/detail/wrap_python.hpp:142:21: error: Python.h: No such file or directory

These pyconfig.h and Python.h files and so on are usually installed with the Python development package, but supposedly MacPorts just installs everything all together under /opt/local/include/python2.6, so I wondered what was going on. But somebody put me on to a good way to find out where MacPorts has put stuff:

$ port contents python26 | grep pyconfig.h

That revealed that the include files were being installed in /opt/local/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6. So let’s try the configure again with that new information:

$ ./configure --prefix=/opt/local CPPFLAGS="-I/opt/local/include -I/opt/local/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6" LDFLAGS=-L/opt/local/lib

Success! All seems to have worked this time – it picked up Boost::Python and no more errors showed up (I have secretly skipped a step where I installed the MacPorts python_select package to make sure that it was definitely using Python 2.6, but hopefully you can figure that one out on your own).

Building PythonMagick

But alas, not so easy. Next I had to actually compile the thing. And of course, it failed:

$ make
_Image.cpp: In function 'void Export_pyste_src_Image()':
_Image.cpp:89: error: address of overloaded function with no contextual type information
_Image.cpp:90: error: address of overloaded function with no contextual type information
_Image.cpp:97: error: address of overloaded function with no contextual type information
_Image.cpp:114: error: address of overloaded function with no contextual type information
... and many more such errors ...

It would seem that the ImageMagick API has changed a little, but thankfully the PythonMagick guys have patched that in the latest version. So I had to download PythonMagick 0.9.5 and copy the following files from it into the ‘pythonmagick_src’ directory of 0.9.3:

  • _Image.cpp
  • _DrawableDashArray.cpp
  • _DrawableMiterLimit.cpp
  • _DrawableViewbox.cpp
  • _Geometry.cpp

Installing PythonMagick

With that done, it then compiled quite nicely. So I run ‘sudo make install’, but then when I actually try and load it into Python, I get this error:

>>> import PythonMagick
Traceback (most recent call last):
File "", line 1, in 
File "PythonMagick/__init__.py", line 1, in 
import _PythonMagick
ImportError: No module named _PythonMagick

Hmm… So close! Yet so far away. Okay, well maybe I should just try adding the path where the module is installed to my Python path:

>>> import sys
>>> sys.path.append('/opt/local/lib/python2.6/site-packages')
>>> import PythonMagick
Fatal Python error: Interpreter not initialized (version mismatch?)
Abort trap

D’oh! Well, a quick look at the crash log revealed that it was now trying to use the version of the Boost libraries that I’d manually installed from source from ‘/usr/local/lib’ (rather than the MacPorts version in /opt/local/lib) so I deleted the unwanted versions and tried again. Then I got this error:

>>> import PythonMagick
Traceback (most recent call last):
File "", line 1, in 
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/PythonMagick/__init__.py", line 1, in 
import _PythonMagick
ImportError: dlopen(/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/PythonMagick/_PythonMagick.so, 2): Library not loaded: libboost_python.dylib
Referenced from: /opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/PythonMagick/_PythonMagick.so
Reason: image not found

Well that one’s obvious: I needed to add the MacPorts directory to my library path:

$ export LD_LIBRARY_PATH=/opt/local/lib
$ export DYLD_LIBRARY_PATH=/opt/local/lib

That gets me a little further:

>>> import PythonMagick
Traceback (most recent call last):
File "", line 1, in 
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/PythonMagick/__init__.py", line 1, in 
import _PythonMagick
ImportError: dlopen(/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/PythonMagick/_PythonMagick.so, 2): Symbol not found: __cg_jpeg_resync_to_restart
Referenced from: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO
Expected in: /opt/local/lib/libjpeg.8.dylib
in /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO

A bit of searching on Google eventually turned up this page that involves an egregious hack relying on case-insensitivity in Mac OS X:

sudo ln -sf
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib /opt/local/lib/libpng.dylib
sudo ln -sf
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib /opt/local/lib/libtiff.dylib
sudo ln -sf
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib /opt/local/lib/libjpeg.dylib

Still…. it seems to work, and I can now import PythonMagick into Python! Now I just need to test it.

Tagged with:
 

Comments are closed.