I found a solution to my problem, thanks to suggestions from you wise monks.
macOS uses the environment variables 'DYLD_LIBRARY_PATH' and 'DYLD_FALLBACK_LIBRARY_PATH' for the location of dynamic libraries or 'dylibs'. From the Terminal app, I was able to load the Rmath dylib successfully by entering
export DYLD_LIBRARY_PATH=/thepathbefore running my Perl scripts.
Then I tried setting this variable in my Perl script, but this didn't work. Apparently, the variable must be set in the process that runs Perl. My software runs within TextMate, which uses Ruby to execute programs. So, I added a single line of Ruby code prior to executing Perl,
ENV['DYLD_LIBRARY_PATH'] = "#{ENV["TM_BUNDLE_SUPPORT"]}/lib/perl5"
This did the trick. Now I'm back to productive work. Thanks again to all.
| [reply] [d/l] [select] |
It's great that you solved it but allow me to say that in my opinion it is not a robust solution if you will ever try to distribute this to other users or even if you install it on other systems, OSX or not. It only works if you called your module via that specific Ruby program. So that excludes the stand-alone use of your module. And provided that the installer of your module has placed the library in 'lib/perl5'. And because DYLD_LIBRARY_PATH is OSX specific. And because adding (in your case it is "setting" as you discard any previous content) DYLD_LIBRARY_PATH can interfere with other things including being able to call the perl interpreter itself. If you do it via terminal, it will affect all future commands on that same terminal only, if you do it via your shell init (.bashrc e.g.) will affect all commands you run under bash and if you do it in the Ruby script, it may affect all system commands run from within (I think?). For this the bash idiom DYLD_LIBRARY_PATH=/thepath command can be useful as it sets that env var for just running "command".
I think the cleanest would be to do it via the XSLoader/DynaLoader by solving the problem at its root. But if it works as is, hey good job!
bw, bliako
| [reply] [d/l] |
Bliako, you are correct, my solution was not robust. It failed completely on newer versions of macOS with SIP (system integrity protection). It seems that moving the dylib to a non-standard location is a security risk known as "dylib hijacking." Apple has added checks to prevent this.
https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x
I was able to find a proper solution by linking the the Rmath library into the XS bundle. When compiling the Rmath dylib, an archive file is also produced – libRmath.a. This file is a compilation of the object (.o) code that went into the dylib. I changed a couple of lines in my Makefile.PL, removing the '-lRmath' from the 'LIBS' entry, and adding a new 'MYEXTLIB' line,
use 5.018002;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
NAME => 'ICC::Support::Rmath',
VERSION_FROM => 'lib/ICC/Support/Rmath.pm', # finds $VERSION
PREREQ_PM => {}, # e.g., Module::Name => 1.1
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'lib/ICC/Support/Rmath.pm', # retrieve abstra
+ct from module
AUTHOR => 'William Birkett <wbirkett@doplganger.com>')
+: ()),
LIBS => [], # e.g., '-lm'
DEFINE => '', # e.g., '-DHAVE_SOMETHING'
INC => '-I.', # e.g., '-I. -I/usr/include/other'
MYEXTLIB => '/usr/local/lib/libRmath.a',
# Un-comment this if you add C files to link with later:
# OBJECT => '$(O_FILES)', # link all the C files too
);
This change compiles the library code into the XS bundle, so the dylib is no longer required in my distribution. Everything works fine now. I sure wish there was better documentation for making XS modules.
Thanks, again, for your help.
| [reply] [d/l] |