DYLD_LIBRARY_PATH/LD_LIBRARY_PATH 的替代方案
我正在开发可在 OSX 和 Linux 中使用的 python C++ 扩展。目前,我可以使用包装器脚本 wrapper.sh
运行我的代码:
#!/bin/bash
trunk=`dirname $0`
trunk=`cd $trunk; pwd`
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$trunk/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$trunk/lib/:$trunk/src/hdf5/lib/:$trunk/src/python/lib
$trunk/src/python/bin/python "$@"
它能够像这样设置我的运行: wrapper.sh app.py
我想要什么要做的就是消除对wrapper.sh的需要,因此我需要DYLD_LIBRARY_PATH和LD_LIBRARY_PATH的替代品。我无法将我的库放在像 /usr/local/lib
这样的标准位置,因为在我的机器上,我维护了我的库的几个独立实例。也就是说,我的库需要保存在相对于我的安装路径的某个位置。出于同样的原因,我无法将这些环境变量放入我的登录脚本中。目前,我需要调用我的一个 wrapper.sh
脚本来使用关联库。我的目标是能够仅运行 app.py
,如果它位于我的安装路径中,应该能够找到其关联的 python 和库。目的是简化用户的执行,并简化外部工具(如nosetests)的使用。
当我构建我的 python 版本时,一种替代方案似乎是使用 rpath:
./configure --enable-shared --prefix=$(CURDIR)/$(PYTHON_DIR) LDFLAGS="-Wl,-rpath,$(CURDIR)/lib/ -Wl,-rpath,$(CURDIR)/src/hdf5/lib -Wl,-rpath,$(CURDIR)/src/python/lib"
这个技巧似乎在 Linux 上工作得很好,尽管我的一个库最终需要直接复制到 trunk/src/python/lib/python2 中.6/lib-dynload 由于某种原因我不清楚。然而,这个技巧在 OSX 上不起作用;看来我需要在所有 dylibs 库上运行 install_name_tool
。
我想出的另一种选择是这样做:
ln -s wrapper.sh python
这样我的脚本都可以使用 #! ../python
,但我收到了 Unmatched ".
错误。如果我使用 #! ../wrapper.sh
也会出现同样的情况。我并不是真正的 bash 专家...
但是,这些看起来都不必要地复杂,而且这肯定是其他人已经解决的问题?谢谢您的建议!
I'm developing python C++ extensions for use in both OSX and linux. Currently, I can run my code with a wrapper script wrapper.sh
:
#!/bin/bash
trunk=`dirname $0`
trunk=`cd $trunk; pwd`
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$trunk/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$trunk/lib/:$trunk/src/hdf5/lib/:$trunk/src/python/lib
$trunk/src/python/bin/python "$@"
which is able to set up my run like this: wrapper.sh app.py
What I would like to do is to eliminate the need for wrapper.sh
, so I need alternatives for DYLD_LIBRARY_PATH and LD_LIBRARY_PATH. I can not put my libraries in some standard location like /usr/local/lib
because on my machine, I maintain several independent instances of my libraries. That is, my libraries need to be kept somewhere relative to my installation path. I can't put these environment variables in my login script for the same reason. Currently, I need to call one of my wrapper.sh
scripts to use the associated libraries. My goal is to be able to run merely app.py
, which if it lives in my installation path, should be able to find its associated python and libraries. The purpose is to simplify execution for users, and to simplify usage of external tools like nosetests.
One alternative seems to be using rpath when I build my version of python:
./configure --enable-shared --prefix=$(CURDIR)/$(PYTHON_DIR) LDFLAGS="-Wl,-rpath,$(CURDIR)/lib/ -Wl,-rpath,$(CURDIR)/src/hdf5/lib -Wl,-rpath,$(CURDIR)/src/python/lib"
This trick seems to work fine on linux, even though one of my libraries ended up needing to be copied directly into trunk/src/python/lib/python2.6/lib-dynload
for some reason unclear to me. However, this trick is not working on OSX; it looks like I need to run install_name_tool
on all my dylibs libraries.
The other alternative I came up with was to do something like this:
ln -s wrapper.sh python
so that my scripts could all use #! ../python
, but I'm getting Unmatched ".
errors. Same thing if I use #! ../wrapper.sh
. I'm not really an expert in bash...
However, these all seem so unnecessarily complicated, and surely this is something that other people have solved?? Thanks for any advice!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于 python 扩展,请考虑使用 PYTHONPATH:Python 解释器将在 PYTHONPATH 中搜索 .py/.pyc/.pyo/.so 模块以及包。请参阅 Python 2.x 文档 以及 Python 3.x 文档;特别是两个页面上名为“模块搜索路径”的部分。这还引用了似乎表明可以在运行时更新模块搜索路径的信息,如果为真,则意味着您可以将所有逻辑添加到程序中,并且它可以自行搜索其库(假设它会在 /usr/libexec/pkgname/... 某处或某处安装一个副本)。
不过,对于除最复杂的情况之外的所有情况,设置 PYTHONPATH 并使用 shell 脚本或本机编译的二进制包装器来启动核心程序是一种不错的方法,并且也可以在其他语言环境(包括 Mono 和 Java)中使用。
For python extensions, consider using PYTHONPATH: the Python interpreter will search the PYTHONPATH for .py/.pyc/.pyo/.so modules, as well as packages. See docs for Python 2.x as well as docs for Python 3.x; specifically the section named "The Module Search Path" on both pages. This also references information that seems to indicate that it is possible to update the module search path at runtime, which, if true, means that you could add all that logic to your program and it can hunt for its libraries on its own (say if it installs a copy in /usr/libexec/pkgname/... somewhere or something).
For all but the most complex of cases, though, setting PYTHONPATH and using a shell-script or native-compiled binary wrapper to start the core program is an okay approach, and one that is also used in other language environments including Mono and Java.
不确定这在您的情况下是否是可接受的(部分)解决方案,但在 linux 上让 ld 注意到库的另一种方法是将库的路径添加到
/etc/ld.so.conf
然后运行ldconfig
对于 Mac,我不记得详细信息,但我认为 Apple 提供了一些用于分发打包为 .app 的应用程序的资源,其中包括一些默认位置(相对于.app)用于库,或者他们所说的“框架”。需要从那里进行一些谷歌搜索 - 抱歉无法进一步提供帮助,但希望你能取得一些进展:-)
Not sure if this would be an acceptable (partial) solution in your circumstances, but another way to get libraries noticed by ld on linux is to add the path to the libraries to
/etc/ld.so.conf
and then runldconfig
For the Mac I don't remember the details, but I think Apple provide some resources for distributing apps packaged as a .app which includes some default locations (relative to the root of the .app) for libraries, or "frameworks" as they call them. Would require some googling from there - sorry can't help further on that but hope you get some progress :-)