Installing python-ldap in Mac OS X Lion
The Problem
Normally, you could install python-ldap like this:
sudo pip install python-ldap
That will appear to work fine, but then when you try to use the ldap module, you get this:
% python -c 'import ldap' Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Library/Python/2.7/site-packages/ldap/__init__.py", line 22, in <module> from _ldap import * ImportError: dlopen(/Library/Python/2.7/site-packages/_ldap.so, 2): Symbol not found: _ldap_create_assertion_control_value Referenced from: /Library/Python/2.7/site-packages/_ldap.so Expected in: flat namespace in /Library/Python/2.7/site-packages/_ldap.so
In a nutshell, /usr/include/ldap.h is a lie. It's the header for OpenLDAP 2.4.23, which is what comes bundled with Lion. All the binaries like ldapsearch, slapd, etc. are also at this version, but one thing was overlooked: the libraries.
% otool -L /usr/lib/libldap_r.dylib /usr/lib/libldap_r.dylib: /System/Library/Frameworks/LDAP.framework/Versions/A/LDAP (compatibility version 1.0.0, current version 2.2.0) /usr/lib/libsasl2.2.dylib (compatibility version 3.0.0, current version 3.15.0) /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8) /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8) /usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 46.0.0) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 633.0.0) /System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 55010.0.0) /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 395.6.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.0.0)
That's OpenLDAP 2.2.0, which is God knows how old. WTF, Apple?
The Work-around
One way around this is to use the older 2.3.13 version of python-ldap, but who wants that, right?
Install the OpenLDAP Libraries
What I did was set up Homebrew to install only the libraries and headers from OpenLDAP 2.4.23, then build python-ldap against them. If you don't use Homebrew for some reason, I'm sure you can figure out how to do things by hand after looking at the example.
Here's the formula for Homebrew. Save it to /usr/local/Library/Formula/openldap-libs.rb.
require 'formula' class OpenldapLibs < Formula url 'ftp://ftp.OpenLDAP.org/pub/OpenLDAP/openldap-stable/openldap-stable-20100719.tgz' homepage 'http://www.openldap.org/' md5 '90150b8c0d0192e10b30157e68844ddf' version '2.4.23' def install system "./configure", "--disable-debug", "--prefix=#{prefix}", "--disable-slapd", "--disable-slurpd" # empty Makefiles to prevent unnecessary installation attempts makefile = "all:\ninstall:\n" unwanted_paths = ['clients', 'servers', 'tests', 'doc'] unwanted_paths.each do |upath| File.open(Dir.getwd + '/' + upath + '/Makefile', 'w') {|f| f.write(makefile)} end system "make install" File.rename("#{prefix}/etc/openldap/ldap.conf", "#{prefix}/etc/openldap/ldap.conf.backup") File.symlink('/etc/openldap/ldap.conf', "#{prefix}/etc/openldap/ldap.conf") end end
Then install it:
% brew install openldap-libs ==> Downloading ftp://ftp.OpenLDAP.org/pub/OpenLDAP/openldap-stable/openldap-stable-20100719 ==> ./configure --disable-debug --prefix=/usr/local/Cellar/openldap-libs/2.4.23 --disable-sl ==> make install /usr/local/Cellar/openldap-libs/2.4.23: 19 files, 1.5M, built in 49 seconds
Things to be aware of:
- This does some hacky things to prevent installation of duplicate client tools and man pages. The ones you have bundled with the OS are fine. We just need the libraries.
- This symlinks
/usr/local/etc/openldap/ldap.confto/etc/openldap/ldap.conf. That way, you don't have to duplicate the settings that you've likely already put there. If you happened to have something in/usr/local/etc/openldap/ldap.confalready, it'll get backed up asldap.conf.backup. (I originally tried to just have the libraries point to the existing system's config files, but it attempts to install them, which is unnecessary and requires root privileges which Homebrew typically shouldn't have.)
Install python-ldap
You need to modify the default setup.cfg, so installing python-ldap is a manual process. Download the latest tarball from http://pypi.python.org/pypi/python-ldap/. Extract it and modify the _ldap section of setup.cfg to match what's shown below.
[_ldap] library_dirs = /usr/local/lib include_dirs = /usr/include/sasl extra_compile_args = -g -arch x86_64 extra_objects = libs = ldap_r lber sasl2 ssl crypto
Now build and install:
% python setup.py build extra_compile_args: -g -arch x86_64 extra_objects: include_dirs: /usr/include/sasl library_dirs: /usr/local/lib libs: ldap_r lber sasl2 ssl crypto running build running build_py …blah blah blah… % sudo python setup.py install …blah blah blah…
You should have a working module at this point.
% python -c 'import ldap; print ldap.__version__' 2.4.3
And for what it's worth, I'm assuming something similar should work for Snow Leopard.
blog comments powered by Disqus