Subject: | Building of test libraries for G:O:I fails on OS X |
tl;dr - Need to change the file extension of the G:O:I test libraries when compiling G:O:I on OS X
This has been bothering me for a few years now, but I finally got the tuits to go after the problem.
On OS X, the test libraries are being built as "libregress.bundle"/"libgimarshallingtests.bundle", using $Config{dlext} to set the file extension of the test library files. Unfortunately, a "bundle" on OS X (and NeXT, and possibly Solaris) is a different form of a library file from a "dynamically loaded shared library" (dylib) file, so the linker can't find the files when it goes to link them.
The difference between .bundle and .dylib libraries on OS X is that .dylib libraries can be loaded with dlopen() (but won't be unloaded until the program exits), and .bundle files are loaded by first calling NSCreateObjectFileImageFromFile() (from <mach-o/dyld.h>), then loading library files from the bundle. Note that bundles can be unloaded while the program is running, unlike .dylib libraries. Bundle objects are similar to JAR files in Java, the libraries on OS X know enough to go inside a bundle file and pull out resources, such as icons/image files, as well as load any shared libraries inside the bundle into the program on request.
If the test libraries are compiled as a dylib (gcc is passed the "-shared" argument), but the compiled library file is incorrectly given a .bundle extension (via the contents of $Config{dlext} in Makefile.PL) , then the linker won't find these test libraries when it comes time to link them, and all of the tests in the test suite that use it will be skipped (basically, the entire test suite).
FWIW, you can change "-shared" to "-bundle" to create proper bundle files, but you still need to load the resulting bundle files via NSCreateObjectFileImageFromFile() in order to make use of them.
On OS X, all Perl XS files by default are compiled as .bundles, and there's the correct magick in DynLoader to load the library from inside the .bundle file. You can see this in the Perl source, in the file ext/DynaLoader/dl_dyld.xs +111
Here's the output of the 'file' command on OS X for the test libraries in $src/build. Note that by default, the two *.bundle files below were created, one at a time (see below), and the *.dylib files are just the *.bundle files copied to the new name.
$ file *.bundle *.dylib
libgimarshallingtests.bundle: Mach-O 64-bit dynamically linked shared library x86_64
libregress.bundle: Mach-O 64-bit dynamically linked shared library x86_64
libgimarshallingtests.dylib: Mach-O 64-bit dynamically linked shared library x86_64
libregress.dylib: Mach-O 64-bit dynamically linked shared library x86_64
If the *.dylib files are present in the $src/build directory when 'perl Makefile.PL' is run, then the testing libraries will be built, and tests will pass on OS X. You can create the two shared libraries needed by running 'perl Makefile.PL` twice, building each testing library then renaming the library with a *.dylib extension after it has been built as a *.bundle file.
The proposed change tells Makefile.PL and t/inc/setup.pl to use $Config{so} (dylib) when $^O =~ /Darwin/, so the testing dylib files get created with the correct filename extensions, and can then be found by the linker.