require and LD_LIBRARY_PATH

J

jim

Here is a little something interesting that I just stumbled
across:

I have a a library installed in a non-standard location and
hence need to have LD_LIBRARY_PATH set so ld.so knows where
to look when loading the shared library.

Without LD_LIBRARY_PATH NOT set I get the following:

% ruby -e "require 'ITKDb'"
% ./ITKDb.so: libstdc++.so.5: cannot open shared object file: No such file or
directory - ./ITKDb.so (LoadError)
from -e:1
%

But, if I set it I get:

% setenv LD_LIBRARY_PATH /disk2/jfn/usr/local/lib
% ruby -e "require 'ITKDb'"
%

So, I thought, that if I set LD_LIBRARY_PATH before I did a require,
but inside the script, that I could still load the library.
Well, it turns out that this doesn't work.

% unsetenv LD_LIBRARY_PATH
% ruby -e 'ENV["LD_LIBRARY_PATH"] = "/disk2/jfn/usr/local/lib"; require "ITKDb"'
% ./ITKDb.so: libstdc++.so.5: cannot open shared object file: No such file
or directory - ./ITKDb.so (LoadError)
from -e:1

So, I assume that

ENV['LD_LIBRARY_PATH'] = "/disk2/jfn/user/local/lib"

is only setting a shell variable and not exporting it to the
environment.

Is this correct? If so, how do I export this variable?

Thanks
 
A

Ara.T.Howard

So, I assume that

ENV['LD_LIBRARY_PATH'] = "/disk2/jfn/user/local/lib"

is only setting a shell variable and not exporting it to the
environment.

Is this correct? If so, how do I export this variable?

i don't remember this - but it looks as if you are correct:


jib:~ > ruby a.rb
-------------------------------------------------------------------------------
LD_LIBRARY_PATH
-------------------------------------------------------------------------------
#<LoadError: libbarfoo.so: cannot open shared object file: No such file or directory - ./foobar.so>
-------------------------------------------------------------------------------
LD_RUN_PATH
-------------------------------------------------------------------------------
ruby rocks



jid:~ > cat a.rb
require 'tmpdir'
require 'rbconfig'
require 'fileutils'

$VERBOSE=nil

def run cmd
system "#{ cmd } >/dev/null 2>&1"
status = $?.exitstatus
raise "cmd <#{ cmd }> failed with <#{ status }>" unless status == 0
status
end

#
# setup
#
ruby = File.join(*Config::CONFIG.values_at('bindir','RUBY_INSTALL_NAME'))
Dir.chdir Dir.tmpdir
tmp = File.join(Dir.tmpdir, 'tmp')
FileUtils.mkdir_p tmp
at_exit{ FileUtils.rm_rf tmp }
barfoo_c = File.join tmp, 'barfoo.c'
barfoo_so = File.join tmp, 'libbarfoo.so'
foobar_c = 'foobar.c'
foobar_so = 'foobar.so'
extconf_rb = 'extconf.rb'
#
# make barfoo.c
#
src = <<-txt
#include <stdlib.h>
#include <stdio.h>
void barfoo(){ printf("ruby rocks\\n"); }
txt
open(barfoo_c,'w'){|f| f.write src }
at_exit{ FileUtils.rm_f barfoo_c }
#
# make barfoo.so
#
run "gcc -o #{ barfoo_so } -shared #{ barfoo_c }"
at_exit{ FileUtils.rm_f barfoo_so }
#
# make foobar.c
#
src = <<-txt
#include "ruby.h"
void Init_foobar(){ barfoo(); }
txt
open(foobar_c,'w'){|f| f.write src}
at_exit{ FileUtils.rm_f foobar_c }
#
# make extconf.rb
#
src = <<-txt
require 'mkmf'
dir_config 'barfoo'
find_library 'barfoo', 'barfoo', '#{ tmp }'
create_makefile 'foobar'
txt
open(extconf_rb,'w'){|f| f.write src}
at_exit{ FileUtils.rm_f extconf_rb }
run "#{ ruby } #{ extconf_rb } --with-barfoo-lib=#{ tmp }"
at_exit{ FileUtils.rm_f 'Makefile' }
#
# make foobar.so
#
run "make"
at_exit{ FileUtils.rm_f foobar_so }
#
# try foobar.so with LD_LIBRARY_PATH
#
fork do
begin
puts('-' * 79)
puts 'LD_LIBRARY_PATH'
puts('-' * 79)
ENV['LD_LIBRARY_PATH'] = tmp
require 'foobar'
rescue LoadError => le
p le
ensure
exit!
end
end
Process.wait
#
# try foobar.so after rebuilding with LD_RUN_PATH
#
fork do
begin
puts('-' * 79)
puts 'LD_RUN_PATH'
puts('-' * 79)
run "rm foobar.so && LD_RUN_PATH=#{ tmp } make"
require 'foobar'
rescue LoadError => le
p le
ensure
exit!
end
end
Process.wait



-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 
L

Lennon Day-Reynolds

Jim,

"Exporting" the LD_LIBRARY_PATH environment variable should only make
a difference in terms of its visibility to child processes spawned
after the export. Since the dynamic loader isn't running in a child
process, it won't affect its behavior.

More likely, the problem is that the loader only reads that variable
once when it is first initialized, and then uses the cached value
throughout the lifespan of the process. You may need to wrap your Ruby
program in a shell script which sets the environment variable
properly, and then execs your script.

Lennon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top