DBD::mysql on OS X Quirks: Architectures, MySQL Binaries and the Filesystem

Posted in: Technical Track

Yesterday evening, a friend of mine had some issues with installing DBD::mysql, and asked if I had encountered the same issue. The problem, as the output from make test showed, was that certain symbols was missing:

#     Tried to use 'DBD::mysql'.
#     Error:  Can't load '/Users/westerlund/src/perl/DBD-mysql-4.008/blib/arch/auto/DBD/mysql/mysql.bundle' for module DBD::mysql: dlopen(/Users/westerlund/src/perl/DBD-mysql-4.008/blib/arch/auto/DBD/mysql/mysql.bundle, 2): Symbol not found: _is_prefix

Fair enough, this is related to a 64-bit issue with MySQL—at least with my Perl version, which is now:

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
    osname=darwin, osvers=9.5.0, archname=darwin-thread-multi-64int-2level

If you try to link to a x86_64 version of MySQL, then you get the above mentioned error. So, I downloaded an x86 version of MySQL and tried again. The output from perl Makefile.PL:

  cflags        (mysql_config) = -I/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/include  -g -Os -arch i386 -fno-common   -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT  -DDONT_DECLARE_CXA_PURE_VIRTUAL
  embedded      (mysql_config) =
  libs          (mysql_config) = -L/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/lib -lmysqlclient -lz -lm     -lmygcc
  mysql_config  (Users choice) = /Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/bin/mysql_config

That looks all good and nice, the right paths, versions and everything. So I compiled it OK, but when running make test again:

#     Error:  Can't load '/Users/westerlund/src/perl/DBD-mysql-4.008/blib/arch/auto/DBD/mysql/mysql.bundle' for module DBD::mysql: dlopen(/Users/westerlund/src/perl/DBD-mysql-4.008/blib/arch/auto/DBD/mysql/mysql.bundle, 2): Library not loaded: /usr/local/mysql/lib/libmysqlclient.16.dylib
#   Referenced from: /Users/westerlund/src/perl/DBD-mysql-4.008/blib/arch/auto/DBD/mysql/mysql.bundle
#   Reason: image not found at /usr/local/lib/perl5/5.10.0/darwin-thread-multi-64int-2level/DynaLoader.pm line 207.

Okay, that is also a quite easy problem to solve. It couldn’t load /usr/local/mysql/lib/libmysqlclient.16.dylib because it wasn’t there. But wait a minute, I don’t even have /usr/local/mysql, so why would it try to load something from there? I was tired, so I just symlinked /usr/local/mysql to /Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86 and that solved it. The tests went fine and now DBD works like a charm. But I still couldn’t let go of the fact that it was looking somewhere I never told it to. So I checked the Makefile:

$ grep '/usr/local/' Makefile
LDDLFLAGS = -arch i386 -arch ppc -bundle -undefined dynamic_lookup -L/usr/local/lib
LDFLAGS = -arch i386 -arch ppc -L/usr/local/lib
INSTALLSITEBIN = /usr/local/bin
INSTALLVENDORBIN = /usr/local/bin
INSTALLSITEMAN1DIR = /usr/local/share/man/man1
INSTALLVENDORMAN1DIR = /usr/local/share/man/man1
INSTALLSITEMAN3DIR = /usr/local/share/man/man3
INSTALLVENDORMAN3DIR = /usr/local/share/man/man3
CCFLAGS = -arch i386 -arch ppc -g -pipe -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -Wdeclaration-after-statement -I/usr/local/include

That looks okay. Perhaps mysql_config gave it the idea of going there?

$ ./mysql_config
Usage: ./mysql_config [OPTIONS]
        --cflags         [-I/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/include  -g -Os -arch i386 -fno-common   -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT  -DDONT_DECLARE_CXA_PURE_VIRTUAL]
        --include        [-I/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/include]
        --libs           [-L/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/lib -lmysqlclient -lz -lm     -lmygcc]
        --libs_r         [-L/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/lib -lmysqlclient_r -lz -lm     -lmygcc]
        --plugindir      [/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/lib/plugin]
        --socket         [/tmp/mysql.sock]
        --port           [0]
        --version        [5.1.28-rc]
        --libmysqld-libs [-L/Users/westerlund/src/perl/mysql-5.1.28-rc-osx10.5-x86/lib -lmysqld -lz -lm       -lmygcc]

Nope, there is no reason whatsoever that it should look in /usr/local/mysql, so I am still not sure why it is. Looking through the files, I can find a couple possible reasons as to why this is happening:

  • mysql_config has pkglibdir='/usr/local/mysql/lib' set as default in the binary releases.
  • mysql itself is configured with --prefix=/usr/local/mysql for binary releases, which also shows in the actual library that we are trying to load:
    $ strings libmysqlclient.16.dylib | grep /usr/local/mysql

As for why it looks there, I don’t know. I do know, however, that if you follow the common practice of symlinking /usr/local/mysql to your local tarball installation of mysql, this symptom would not exist. But, what would still exist is the issue of DBD trying to load from /usr/local/mysql even though nothing tells it to do so. Maintenance is also easier when symlinking, as you don’t have to change paths when upgrading (just redo the symlink). Still, I fail to see why this would be required to install DBD::mysql.

Interested in working with Nicklas? Schedule a tech call.

1 Comment. Leave new

The same problem happens in different Linux distributions. The ‘missing’ library is “libmysqlclient.so.14”. Creating a symbolic link to “libmysqlclient.so.15” solves the problem

My $.02


Leave a Reply

Your email address will not be published. Required fields are marked *