Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't DYLD_LIBRARY_PATH being propagated here?

I have a simple C++ program that I'm trying to run that is linked against a version of the Boost.Thread library that I built previously. I seem to be having trouble understanding the way that runtime library paths behave on OS X.

Since my Boost library doesn't have an RPATH-relative install name, I'm using the DYLD_LIBRARY_PATH environment variable to tell the dynamic linker where to find libboost_thread.dylib at runtime.

This works fine if I run the program directly in my (bash) shell:

[~/git/project]$ echo $DYLD_LIBRARY_PATH
/Users/jasonr/git/project/boost/lib
[~/git/project]$ .sconf_temp/conftest_7
[~/git/project]$ # Program runs successfully; this is what I expect.

However, this program is run as part of a series of tests by an autoconf-like framework that I'm using. It runs the program in a child shell using sh -c. Here's what happens if I try that:

[~/git/project]$ # Make sure the environment variable is exported to child shells.
[~/git/project]$ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH
[~/git/project]$ # Try to run it in a child shell.
[~/git/project]$ sh -c .sconf_temp/conftest_7
dyld: Library not loaded: libboost_thread.dylib
  Referenced from: /Users/jasonr/git/project/.sconf_temp/conftest_7
  Reason: image not found
Trace/BPT trap: 5

It's as if the environment variable isn't propagated to dyld in this case. Why would this occur? I'm more familiar with the behavior of LD_LIBRARY_PATH on Linux, which (I think) should work with the above example. Is there something else I need to do in order to make this work?

like image 254
Jason R Avatar asked Feb 23 '16 03:02

Jason R


People also ask

What is Dyld_library_path?

DYLD_LIBRARY_PATH This is a colon separated list of directories that contain libraries. The dynamic linker searches these directories before it searches the default locations for libraries. It allows you to test new versions of existing libraries.


1 Answers

Presumably, you are running El Capitan (OS X 10.11) or later. It's a side effect of System Integrity Protection. From the System Integrity Protection Guide: Runtime Protections article:

When a process is started, the kernel checks to see whether the main executable is protected on disk or is signed with an special system entitlement. If either is true, then a flag is set to denote that it is protected against modification. …

… Any dynamic linker (dyld) environment variables, such as DYLD_LIBRARY_PATH, are purged when launching protected processes.

All of the system-provided interpreters, including /bin/sh, are protected in this fashion. Therefore, when you invoke sh, all DYLD_* environment variables are purged.

You could write a shell script which sets DYLD_LIBRARY_PATH and then executes .sconf_temp/conftest_7. You can use the the shell interpreter to execute that — indeed, you must — and the environment variable will be fine, since the purging happens when a protected executable is started. Basically, this approach is analogous to the working example in your question, but encapsulated in a shell script.

like image 169
Ken Thomases Avatar answered Oct 13 '22 00:10

Ken Thomases