Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
519 views
in Technique[技术] by (71.8m points)

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...