If you need to build ZooKeeper Python bindings in 32-bit mode on 64-bit Mac OS X, it can be hard to do since ZooKeeper building scripts ignore the usual “-arch” flags for the compiler. But there is a simple workaround for this. And here it is.
Why?
If you have Mac OS X and you need Oracle InstantClient for your work as I do, you are in trouble: the 64-bit InstantClient crashes with “segfault” error code 11 on 64-bit Mac OS X. The only solution is to use 32-bit InstantClient, which does work.
But this workaround entails to every single bit of software, that uses InstantClient, should be 32-bit too. For example, if you code Python as I do, you need cx_Oracle to be 32-bit to work with 32-bit InstantClient (64-bit cx_Oracle binary part cannot work with 32-bit InstantClient libraries, obviously). And if you have 32-bit cx_Oracle, you ought to have 32-bit Python to load that 32-bit cx_Oracle. And if you have 32-bit Python, you ought to make all other binary libraries to be 32-bit. Thank you, Oracle, for this fun!
And if you use ZooKeeper together with InstantClient as I do, you have to build 32-bit ZooKeeper binaries and libraries. Well, lets work up to it from the beginning.
The Problem
Usually, you build ZooKeeper and zkpython bindings this straightforward way, and you can easily check that the library is 64-bit with “file” command and that Python is 64-bit with “sys.maxint” constant:
$ tar xf zookeeper-3.3.4.tar.gz $ cd zookeeper-3.3.4/ $ cd src/c $ ./configure $ make $ sudo make install $ file /usr/local/lib/libzookeeper_mt.2.dylib /usr/local/lib/libzookeeper_mt.2.dylib: Mach-O 64-bit dynamically linked shared library x86_64
$ cd ../../src/contrib/zkpython $ python src/python/setup.py install $ python >>> sys.maxint 9223372036854775807 >>> import zookeeper >>>
But if you have 32-bit Python, the last step will look like this:
$ python >>> import sys >>> sys.maxint 2147483647 >>> import zookeeper Traceback (most recent call last): File "", line 1, in ImportError: dlopen(/Users/nolar/env/32bit/lib/python2.7/site-packages/zookeeper.so, 2): Symbol not found: _ZOO_ASSOCIATING_STATE Referenced from: /Users/nolar/env/32bit/lib/python2.7/site-packages/zookeeper.so Expected in: flat namespace in /Users/nolar/env/32bit/lib/python2.7/site-packages/zookeeper.so >>>
This error happens because:
- 32-bit Python loads 32-bit part of the 32&64-bit zookeeper.so file;
- 32-bit part of zookeeper.so file tries to load 32-bit libzookeeper_mt.2.dylib;
- libzookeeper_mt.2.dylib happens to be 64-bit only and has no 32-bit part;
- zookeeper.so cannot find what it tries to find in the dylib and fails.
The Solution
Fortunately, there is a very simple solution. You just need 32-bit ZooKeeper libraries and binaries. Easy, yeah? :-)
Unfortunately, for some unknown reason, ZooKeeper ignores the usual ways of making 32-bit binaries: CFLAGS, LDFLAGS, ARCH_FLAGSL, etc. And you will be getting 64-bit ZooKeeper under 64-bit Mac OS X all the times.
Fortunately (again), this problem can be solved with a tiny one-line ten-char hack, which has taken 3 days of my time to figure it out. Just go edit your Makefile to add “-arch i386” flag into a definition of CC there. And that’s it! It will make 32-bit binaries and libraries.
Step by step
But for those of you who wants a step by step instruction, here it is. Take Makefile.patch file, and apply it after the “configure” stage, but before the “make” stage (or, for other versions of ZooKeeper, you can do that fix manually):
$ tar xf zookeeper-3.3.4.tar.gz $ cd zookeeper-3.3.4/ $ cd src/c $ ./configure $ patch < Makefile.patch $ make $ sudo make install $ file /usr/local/lib/libzookeeper_mt.2.dylib /usr/local/lib/libzookeeper_mt.2.dylib: Mach-O dynamically linked shared library i386
$ cd ../../src/contrib/zkpython $ python src/python/setup.py install $ python >>> sys.maxint 2147483647 >>> import zookeeper >>>
Ta-da! ZooKeeper libraries are now 32-bit, so the 32-bit part of zookeeper.so can load them with no errors. And you are happy having 32-bit ZooKeeper, 32-bit Python, and (damn you, Oracle) 32-bit InstantClient on your 64-bit Mac OS X.