为什么不在这里传播DYLD_LIBRARY_PATH?

时间:2016-02-23 03:14:20

标签: macos bash shell environment-variables

我有一个简单的C ++程序,我试图运行它与我之前构建的Boost.Thread库的版本相关联。我似乎无法理解运行时库路径在OS X上的行为方式。

由于我的Boost库没有RPATH-relative install name,我使用DYLD_LIBRARY_PATH环境变量告诉动态链接器在运行时找到libboost_thread.dylib的位置。

如果我直接在我的(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.

但是,这个程序是我autoconf类似框架的一系列测试的一部分,我正在使用它。它使用sh -c在子shell中运行程序。如果我尝试这样做会发生什么:

[~/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

在这种情况下,好像环境变量没有传播到dyld。为什么会这样?我更熟悉Linux上LD_LIBRARY_PATH的行为,我认为它应该与上面的例子一起使用。为了使这项工作还有其他我需要做的事情吗?

1 个答案:

答案 0 :(得分:10)

据推测,您正在运行El Capitan(OS X 10.11)或更高版本。这是系统完整性保护的副作用。来自System Integrity Protection Guide: Runtime Protections文章:

  

当一个进程启动时,内核会检查是否为main   可执行文件在磁盘上受保护或使用特殊系统进行签名   权利。如果其中任何一个为真,则设置一个标志来表示它   保护免受修改。 ...

     

......任何动态链接器(dyld)   环境变量(例如DYLD_LIBRARY_PATH)在清除时被清除   启动受保护的流程。

所有系统提供的解释器(包括/bin/sh)都以这种方式受到保护。因此,当您调用sh时,将清除所有DYLD_ *环境变量。

您可以编写一个设置DYLD_LIBRARY_PATH的shell脚本,然后执行.sconf_temp/conftest_7。您可以使用shell解释器来执行 - 实际上,您必须 - 并且环境变量也没问题,因为在启动受保护的可执行文件时会发生清除。基本上,这种方法类似于您的问题中的工作示例,但是封装在shell脚本中。