初始情况:
我有一个C / C ++库,并为不同的目标语言提供绑定。其中一种语言是Python。我决定使用Swig,因为它为很多语言提供了很好的支持,并且它与CMake的集成非常简单。
为了提高Python绑定及其安装的可用性,我想提供一个setup.py。我们的想法是从setup.py文件中运行CMake,因为CMake包含了如何正确创建绑定的所有逻辑。
我目前得到的内容:
我能够在setup.py中运行CMake并构建Python绑定的目标。
通过设计Swig,CMake文件需要区分Python 2和Python 3.在运行CMake时,它会检测Python安装的位置并配置环境。如果用户同时安装了Python 2和Python 3(及其开发包),CMake总是使用Python 3。
根据:https://cmake.org/cmake/help/v3.0/module/FindPythonLibs.html,可以通过设置PYTHON_LIBRARY和PYTHON_INCLUDE_DIR来指定实际使用的Python版本。例如,我必须运行:
cmake -DPYTHON_INCLUDE_DIR=/usr/include/python2.7 -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so
有什么问题:
如果用户执行:
python setup.py build
可执行文件的Python版本' python'可能是2但是CMake使用版本3构建绑定(见上文)。
根据Find python header path from within python?,我可以使用以下方式获取头文件的位置:
from distutils.sysconfig import get_python_inc
get_python_inc()
不幸的是,我不知道如何获取Python库的路径。由Distribution independent libpython path提供的解决方案对我不起作用,因为它总是返回' / usr / lib'而不是' /usr/lib/x86_64-linux-gnu/libpython2.7.so'
问题:
如何从Python中获取Python库的位置(完整路径)。
答案 0 :(得分:1)
问题:
如何从Python中获取Python库的位置(完整路径)。
答案:
在Python的Makefile中寻找INSTALL_SHARED: https://github.com/python/cpython/blob/3.5/Makefile.pre.in
我们可以找到:
$(INSTALL_SHARED) libpython$(VERSION)$(SO) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \
我们可以看到所提问息信息中没有单一变量。你需要从另外两个构建它:
from distutils.sysconfig import get_config_var
libpython = "%s/%s" % (get_config_var("LIBDIR"), get_config_var("INSTSONAME"))
在python 2.7中进行测试:
Python 2.7.13 (default, Nov 20 2017, 02:33:01)
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from distutils.sysconfig import get_config_var
>>> "%s/%s" % (get_config_var("LIBDIR"), get_config_var("INSTSONAME"))
'/usr/lib64/libpython2.7.so.1.0'
在python 3.3中测试:
Python 3.3.0 (default, Nov 11 2013, 09:56:47)
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from distutils.sysconfig import get_config_var
>>> "%s/%s" % (get_config_var("LIBDIR"), get_config_var("INSTSONAME"))
'/usr/lib64/libpython3.3m.so.1.0'
所以,它只适用于Linux中的CPython(> = 2.3),你可以在python Makefile中看到,并且无法保证它将在未来工作,无论如何,这在过去的14中没有改变年,自2003年5月11日。
您可以使用Windows的BINDIR和DLLLIBRARY变量,正如您在Makefile中看到的那样:
$(INSTALL_SHARED) libpython$(VERSION)$(SO) $(DESTDIR)$(BINDIR); \
但是,我无法在Windows中进行测试。
答案 1 :(得分:0)
我通过解决方法自行解决了这个问题。也许它可以帮助其他人面对相同或至少类似的问题。
首先,我介绍了环境变量PYTHON_INCLUDE_DIR和PYTHON_LIBRARY,它们与用于配置python路径的CMake的参数名称相同:-DPYTHON_INCLUDE_DIR和-DPYTHON_LIBRARY。此外,我将以下代码添加到我的CMake文件
if(DEFINED ENV{PYTHON_LIBRARY} AND DEFINED ENV{PYTHON_INCLUDE_DIR})
message(STATUS "Using environment variables PYTHON_LIBRARY and PYTHON_INCLUDE_DIR")
set(PYTHON_LIBRARY $ENV{PYTHON_LIBRARY})
set(PYTHON_INCLUDE_DIR $ENV{PYTHON_INCLUDE_DIR})
endif()
它只是将环境变量包装到CMake参数中。现在,用户可以在运行CMake之前定义这些变量而不是参数。
PYTHON_INCLUDE_DIR=/usr/include/python2.7 PYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so cmake
由于我的setup.py只是调用CMake而CMake现在能够获取环境变量并将它们分别包装到参数中,因此用户也可以在运行setup.py之前配置变量(或者pip,等)。
PYTHON_INCLUDE_DIR=/usr/include/python2.7 PYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so pip install tinyspline
说实话,用户仍然需要配置一些路径,但最终他/她能够这样做。
答案 2 :(得分:0)
我对Python并不了解很多,因此也无法找到一个很好的答案来弄清楚Python库的完整路径和名称。因此,我尝试通过使用以下方法进行测试来提出解决方案:
我使用CMake的find_package(Python3)
作为参考,这些是在每个平台上找到的库:
/usr/lib64/libpython3.6m.so
/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.so
C:/Python38/libs/python38.lib
从那以后,我试图找出是否存在配置变量的任何组合(如distutils.sysconfig.get_config_vars()
所报告的那样),这些组合可以为我提供CMake找到的路径和库名。在我看来,不幸的是,没有一种方法可以在所有这些平台上移植以获取完整的库路径。
我能得到的是这些组合似乎可以在每个平台上使用:
LIBDIR
+ LDLIBRARY
LIBPL
+ LDLIBRARY
BINDIR
+硬编码libs\python3.lib