Monday, May 16, 2011

LD_LIBRARY_PATH in Zsh

‹prev | My Chain | next›

Today I start tying up a few loose ends from my 64 bit eventmachine + edge (NPN-enabled) openssl romp. First up is some confusion over zsh. I have been using zsh (with oh-my-zsh) for several months now. For the most part I like it, though I still have not gotten to the point that I strongly prefer it to bash.

The behavior that I do not quite understand surrounds LD_LIBRARY_PATH. I eventually gave up on zsh while trying to build a local openssl and link other libraries against it. Either LD_LIBRARY_PATH does not do what I think it does (another place for the OS to find shared objects) or zsh is not honoring it in the way that bash does. Granted it was during some very frustrating times, so I could well be conflating other problems, but that is the point—I do not know for sure.

First up, I check out LD_LIBRARY_PATH in bash, which I know I can get to work. If I unset LD_LIBRARY_PATH, then the OS cannot find the libssl version 1.1 against which evenmachine is linked. If I set LD_LIBRARY_PATH, then the OS can find it:
1.9.2@spdy ~/repos/spdy (master)$ export -n LD_LIBRARY_PATH=
1.9.2@spdy ~/repos/spdy (master)$ ldd /home/cstrom/.rvm/gems/ruby-1.9.2-p180@spdy/gems/eventmachine-1.0.0.beta.3/lib/rubyeventmachine.so
...
libssl.so.1.1.0 => not found
libcrypto.so.1.1.0 => not found
...
1.9.2@spdy ~/repos/spdy (master)$ export LD_LIBRARY_PATH=/home/cstrom/local/lib
1.9.2@spdy ~/repos/spdy (master)$ ldd /home/cstrom/.rvm/gems/ruby-1.9.2-p180@spdy/gems/eventmachine-1.0.0.beta.3/lib/rubyeventmachine.so
...
libssl.so.1.1.0 => /home/cstrom/local/lib/libssl.so.1.1.0 (0x00007f8727123000)
libcrypto.so.1.1.0 => /home/cstrom/local/lib/libcrypto.so.1.1.0 (0x00007f8726d59000)
...
1.9.2@spdy ~/repos/spdy (master)$ env | grep LD_LIBRARY_PATH
LD_LIBRARY_PATH=/home/cstrom/local/lib
Everything works as I expect there, which I why I ended up using bash.

So let's try the same thing in zsh:
➜  ~  export LD_LIBRARY_PATH=
➜ ~ ldd /home/cstrom/.rvm/gems/ruby-1.9.2-p180@spdy/gems/eventmachine-1.0.0.beta.3/lib/rubyeventmachine.so
...
libssl.so.1.1.0 => not found
libcrypto.so.1.1.0 => not found
...
➜ ~ export LD_LIBRARY_PATH=/home/cstrom/local/lib
➜ ~ ldd /home/cstrom/.rvm/gems/ruby-1.9.2-p180@spdy/gems/eventmachine-1.0.0.beta.3/lib/rubyeventmachine.so
...
libssl.so.1.1.0 => /home/cstrom/local/lib/libssl.so.1.1.0 (0x00007f22c37cb000)
libcrypto.so.1.1.0 => /home/cstrom/local/lib/libcrypto.so.1.1.0 (0x00007f22c3401000)
...
➜ ~ env | grep LD_LIBRARY_PATH
LD_LIBRARY_PATH=/home/cstrom/local/lib
Hunh?! That is exactly the same behavior as bash.

If nothing else, this is yet more proof that only fools believe what frustration teaches them.

So I take a step back to try to understand why I thought there was a problem. In my .zshrc file, I have the following code that sets various paths for locally installed binaries:
# For locally installed binaries
LD_LIBRARY_PATH=$HOME/local/lib
PATH=$HOME/local/bin:$PATH
PKG_CONFIG_PATH=$HOME/local/lib/pkgconfig
CPATH=$HOME/local/include

# For node.js. For details see:
# http://blog.nodejs.org/2011/04/04/development-environment/
for i in $HOME/local/*; do
[ -d $i/bin ] && PATH="${i}/bin:${PATH}"
[ -d $i/sbin ] && PATH="${i}/sbin:${PATH}"
[ -d $i/include ] && CPATH="${i}/include:${CPATH}"
[ -d $i/lib ] && LD_LIBRARY_PATH="${i}/lib:${LD_LIBRARY_PATH}"
[ -d $i/lib/pkgconfig ] && PKG_CONFIG_PATH="${i}/lib/pkgconfig:${PKG_CONFIG_PATH}"
[ -d $i/share/man ] && MANPATH="${i}/share/man:${MANPATH}"
done
To the best of my knowledge, I have always done something similar when using bash and have been similarly using this since I switched to zsh. Then again, have I really needed to link against locally installed software with zsh? Have I needed to do it since I upgraded to Ubuntu 11.04?

To the best of my knowledge does not count for much, so I extract the PATHs code into a file named .profile_paths. I then include that file in both my .bashrc and .zshrc files:
source $HOME/.profile_paths
To try them out, I start two interactive sessions using the dash-el option to both zsh and bash, then check to see if my environment holds the necessary information to tell the OS where to find the local shared objects.

In zsh:
➜  ~  zsh -l
➜ ~ env | grep LD_
➜ ~ ldd /home/cstrom/.rvm/gems/ruby-1.9.2-p180@spdy/gems/eventmachine-1.0.0.beta.3/lib/rubyeventmachine.so
...
libssl.so.1.1.0 => not found
libcrypto.so.1.1.0 => not found
...
In bash:
➜  ~  bash -l
1.9.2 ~ $ env | grep LD_
LD_LIBRARY_PATH=/home/cstrom/local/node-v0.5.0-pre/lib:/home/cstrom/local/node-v0.4.7/lib:/home/cstrom/local/node-v0.4.5/lib:/home/cstrom/local/lib
1.9.2 ~ $ ldd /home/cstrom/.rvm/gems/ruby-1.9.2-p0@spdy/gems/eventmachine-1.0.0.beta.3/lib/rubyeventmachine.so
...
libssl.so.0.9.8 => /lib/libssl.so.0.9.8 (0x00007f60e26a4000)
libcrypto.so.0.9.8 => /lib/libcrypto.so.0.9.8 (0x00007f60e2315000)
...
Interesting. So setting LD_LIBRARY_PATH in the .zshrc file does not work whereas setting it in .bashrc does. Presumably, it will work if I explicitly export it into the global namespace—that is something that I have never had to do in the past (because it works as-is in bash).

But, before I verify that, I may as well verify that none of the variables are being set:
➜  ~  env | grep CPATH
CPATH=/home/cstrom/local/node-v0.5.0-pre/include:/home/cstrom/local/node-v0.4.7/include:/home/cstrom/local/node-v0.4.5/include:/home/cstrom/local/include
Hunh? CPATH is set but LD_LIBRARY_PATH is not? In fact, all of the variables from .profile_paths are in my zsh environment—except for LD_LIBRARY_PATH.

And yes, if I export LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=$HOME/local/lib
...then zsh sees LD_LIBRARY_PATH:
➜  ~  env | grep LD_
➜ ~ zsh -l
➜ ~ env | grep LD_
LD_LIBRARY_PATH=/home/cstrom/local/node-v0.5.0-pre/lib:/home/cstrom/local/node-v0.4.7/lib:/home/cstrom/local/node-v0.4.5/lib:/home/cstrom/local/lib
➜ ~ ldd /home/cstrom/.rvm/gems/ruby-1.9.2-p180@spdy/gems/eventmachine-1.0.0.beta.3/lib/rubyeventmachine.so
...
libssl.so.1.1.0 => /home/cstrom/local/lib/libssl.so.1.1.0 (0x00007fccb8bb0000)
libcrypto.so.1.1.0 => /home/cstrom/local/lib/libcrypto.so.1.1.0 (0x00007fccb87e7000)
...
As best my google-fu can tell, this behavior is undocumented. It is certainly annoying.


Day #22

No comments:

Post a Comment