ait has asked for the wisdom of the Perl Monks concerning the following question:
Hello fellow a monk,
I am considering this as an RFC for a tutorial on Perl Mac OS X so if you think it's useful as a tutorial on PM, make your comment and I will expand it and draft into a general tutorial for Perl Mac OS X.
After some research I discovered that a lot of people have been having problems with Mac OS X and Perl modules that use XS bindings to C even here on PM dyld.
CPAN modules will rarely fail but modules from source or trying to cook your own on OS X may not be so easy. I've been banging my head trying to get an XS module to work for the past day and a half so after getting it working I though it was useful to share how...
The main thing to understand is that Mac OS X will ship with a relatively new version of Perl and some thing depend on this so you shouldn't be using this Perl for your development. This is similar to Solaris in that the base system depends on a very specific version of Perl.
You should then have 2 Perls in your Mac. A good option is MacPorts but there are others, including installing from source. I use MacPorts so
which perl
Will result in
/opt/local/bin/perl
Libraries and CPAN modules will install in /opt/local as well keeping it separate from the system Perl.
Thats why it's important to use the newer tendency in shebang lines:
#!/usr/bin/env perl
Instead of the retrogade:
#!/usr/bin/perl
In fact in Mac OS X this is very important because it is expected that system Perl is /usr/bin/perl !
OK, so now that we clearly have 2 Perls and our development Perl is NOT the system Perl we try to build or compile an XS module.
I won't go into the details of compiling a dynamic library for Darwin but let me point out for reference that there are some important differences from other Operating Systems. Most notably is the distinction between shared libraries and dynamically loadable modules ("a.k.a. bundles"). On ELF systems both are the same and en in .so, on OS X however, bundles end in .bundle or more confusingly in .so whilst dynamic libraries (the .so we are used to in ELF-based systems) en in .dylib.The other interesting feature of Perl in Mac OS X is that it supports both 32 and 64 bit code. The exact mechanisms are described here
OK, so now you know that your XS code will probably be using a dylib and the lib will probably be in /opt/local/lib. Again just for reference just in case you want to compile your C library on a Mac here is the difference from "soname" on ELF systems and you should build with something like this in your Makefile:
os := $(shell uname) libboxr : boxr.c # MacOSX ifeq ($(os),Darwin) gcc -fno-common -c boxr.c gcc -dynamiclib -install_name /opt/local/lib/libboxr.1.dylib \ -compatibility_version 1.0 -current_version 1.0.0 \ -o libboxr.1.0.0.dylib boxr.o #Linux else gcc -shared -fPIC -g -Wall -Wl,-soname,libboxr.so.1 \ -o libboxr.so.1.0.0 -lc boxr.c endif
Assuming you compiled and installed you .dylib correctly, you should now be able to run hsxs -x foo.h and it should locate foo.h from /opt/local/include
So far so good, but try to make test and you will get an undefined symbol, which is what many people have been getting. This is because the standard Makefile built from Makefile.PL will have PERL_DL_NONLAZY=1 which will force the dynloader to resolve all the DL symbols when Perl fires up, which is of course a good thing for developing and testing your XS code. In fact, the XS distro built by default will already have a couple of tests written for you! Anyway, this undefined symbol can occur for several reasons including:
- The dylib cannot be found
- The dylib cannot be loaded (64/32 bit problems)
- The symbols really don't exist on the dynamic lib
Not surprisingly the solution is actually quite simple. Edit the Makefile.PL and add -lfoo to the LIBS variable before you make the Makefile like so:
WriteMakefile( NAME => 'Boxr', VERSION_FROM => 'lib/Boxr.pm', [snip] LIBS => ['-lfoo -lbar'], [snip]
And that's it folks. Hopefully that should fix most of your XS pain on Mac OS X.
Cheers,
--
Alejandro Imass
|
---|