Require and LD_LIBRARY_PATH

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

···

--
Jim Freeze

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

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

jib:~ > ruby a.rb

···

On Fri, 20 Aug 2004 jim@freeze.org wrote:

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?

-------------------------------------------------------------------------------
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

===============================================================================