本文介绍了使用cmake构建Python共享对象绑定,这取决于外部库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个名为dbookpy.c的ac文件,它将提供一个Python绑定的一些C函数。



接下来我们决定使用cmake构建一个合适的.so看起来我们在绑定中链接外部库libdbook时出错了:



CMakeLists.txt如下:

  PROJECT(dbookpy)

FIND_PACKAGE(PythonInterp)
FIND_PACKAGE(PythonLibs)

INCLUDE_DIRECTORIES($ {PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(/ usr / local / include)
LINK_DIRECTORIES(/ usr / local / lib)
OPTION(BUILD_SHARED_LIBS ON)

ADD_LIBRARY(dbookpy dbookpy)
SET_TARGET_PROPERTIES(dbookpy PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES dbook)
SET_TARGET_PROPERTIES(dbookpy PROPERTIES LINKER_LANGUAGE C)
#SET_TARGET_PROPERTIES(dbookpy PROPERTIES LINK_INTERFACE_LIBRARIES dbook)
#SET_TARGET_PROPERTIES(dbookpy PROPERTIES ENABLE_EXPORTS ON)
#TARGET_LINK_LIBRARIES(dbookpy LINK_INTERFACE_LIBRARIES dbook)

SET_TARGET_PROPERTIES(dbookpy
PROPERTIES
SOVERSION 0.1
VERSION 0.1

然后我们建立:

  x31%mkdir build 
x31%cd build
x31%cmake ..
- 检查工作C编译器:/ usr / bin / gcc
- 检查工作C编译器:/ usr / bin / gcc - works
- 检查void *的大小
- 检查void *的大小 - done
- 检查工作CXX编译器:/ usr / bin / c ++
- 检查是否工作CXX编译器:/ usr / bin / c ++ - 工作
- 配置完成
- 生成done
- 构建文件已写入:/ home / edd / dbook2 / dbookpy / build
x31%make
扫描目标的依赖关系dbookpy
[100%] Building C对象CMakeFiles / dbookpy.dir / dbookpy.o
链接C共享库libdbookpy.so
[100%]内置目标dbookpy

到目前为止很好。测试Python:

  x31%python 
Python 2.5.4(r254:67916,Apr 24 2009,15: 28:40)
[gcc 3.3.5(propolice)] on openbsd4
更多信息,请输入帮助,版权,信用或许可证。
>>>> import libdbookpy
python:./ libdbookpy.so:undefined symbol'dbook_isbn_13_to_10'
python:./ libdbookpy.so:undefined symbol'dbook_isbn_10_to_13'
python:./ libdbookpy.so:undefined symbol 'dbook_sanitize'
python:./ libdbookpy.so:undefined symbol'dbook_check_isbn'
python:./ libdbookpy.so:undefined symbol'dbook_get_isbn_details'
回溯(最近一次调用)
在< module>中的文件< stdin>,第1行
ImportError:无法加载指定的对象

Hmmm。链接器错误。看起来它未连接libdbook:

  x31%ldd libdbookpy.so 
libdbookpy.so:
开始结束类型打开Ref GrpRef名称
05ae8000 25aec000 dlib 1 0 0 /home/edd/dbook2/dbookpy/build/libdbookpy.so.0.1

不是。对libdbook的正确链接如下所示:

  x31%ldd / usr / local / bin / dbook-test 
/ usr / local / bin / dbook-test:
开始结束类型打开Ref GrpRef名称
1c000000 3c004000 exe 1 0 0 / usr / local / bin / dbook-test
08567000 28571000 rlib 0 2 0 /usr/lib/libm.so.5.0
09ef7000 29efb000 rlib 0 1 0 /usr/local/lib/libdbook.so.0.1
053a0000 253d8000 rlib 0 1 0 / usr / lib / libc .so.50.1
0c2bc000 0c2bc000 rtld 0 1 0 /usr/libexec/ld.so


Edd

非常感谢。

解决方案

您需要将dbookpy与dbook链接:

  target_link_libraries(dbookpy dbook)

在行后添加 ADD_LIBRARY (dbookpy dbookpy)应该这样做。



我看到你使用IMPORTED - IMPORTED_LINK_INTERFACE_LIBRARIES 读取:

 列出当IMPORTED库目标
链接到另一个目标时包含其接口的库。库将包括在
目标的链接行上。与LINK_INTERFACE_LIBRARIES属性不同,此属性
适用于所有导入的目标类型,包括STATIC库。对于非导入目标,将忽略此
属性。

这意味着/ usr / local / lib中的dbook导入的库:

  add_library(dbook SHARED IMPORTED)

这真的是你想要的吗?我的意思是,导入的库是在CMake外部构建的,但是作为源代码树的一部分。 dbook库似乎已安装或至少预期安装。我不认为你需要进口这里 - 它似乎是一个常规的联系问题。但这可能只是一个副作用,创建一个最小的例子在这里张贴。



通过它的声音,为了获得链接的库和链接目录整理,我可能会使用 find_library(),它将看起来像合理的默认位置,如/ usr / local / lib,然后附加到链接库。

  find_library(DBOOK_LIBRARY dbook REQUIRED)
target_link_libraries(dbookpy $ {DBOOK_LIBRARY})

无论如何,似乎你现在已经排序。


We have a c file called dbookpy.c, which will provide a Python binding some C functions.

Next we decided to build a proper .so with cmake, but it seems we are doing something wrong with regards to linking the external library 'libdbook' in the binding:

The CMakeLists.txt is as follows:

PROJECT(dbookpy)

FIND_PACKAGE(PythonInterp)
FIND_PACKAGE(PythonLibs)

INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES("/usr/local/include")
LINK_DIRECTORIES(/usr/local/lib)
OPTION(BUILD_SHARED_LIBS "turn OFF for .a libs" ON)

ADD_LIBRARY(dbookpy dbookpy)
SET_TARGET_PROPERTIES(dbookpy PROPERTIES  IMPORTED_LINK_INTERFACE_LIBRARIES dbook)
SET_TARGET_PROPERTIES(dbookpy PROPERTIES LINKER_LANGUAGE C)
#SET_TARGET_PROPERTIES(dbookpy PROPERTIES LINK_INTERFACE_LIBRARIES dbook)
#SET_TARGET_PROPERTIES(dbookpy PROPERTIES ENABLE_EXPORTS ON)
#TARGET_LINK_LIBRARIES(dbookpy LINK_INTERFACE_LIBRARIES dbook)

SET_TARGET_PROPERTIES(dbookpy
PROPERTIES
    SOVERSION 0.1
    VERSION 0.1
)

Then we build:

x31% mkdir build
x31% cd build
x31% cmake ..
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Check size of void*
-- Check size of void* - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Configuring done
-- Generating done
-- Build files have been written to: /home/edd/dbook2/dbookpy/build
x31% make
Scanning dependencies of target dbookpy
[100%] Building C object CMakeFiles/dbookpy.dir/dbookpy.o
Linking C shared library libdbookpy.so
[100%] Built target dbookpy

So far so good. Test in Python:

x31% python
Python 2.5.4 (r254:67916, Apr 24 2009, 15:28:40)
[GCC 3.3.5 (propolice)] on openbsd4
Type "help", "copyright", "credits" or "license" for more information.
>>> import libdbookpy
python:./libdbookpy.so: undefined symbol 'dbook_isbn_13_to_10'
python:./libdbookpy.so: undefined symbol 'dbook_isbn_10_to_13'
python:./libdbookpy.so: undefined symbol 'dbook_sanitize'
python:./libdbookpy.so: undefined symbol 'dbook_check_isbn'
python:./libdbookpy.so: undefined symbol 'dbook_get_isbn_details'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: Cannot load specified object

Hmmm. Linker error. Looks like it is not linking libdbook:

x31% ldd libdbookpy.so
libdbookpy.so:
        Start    End      Type Open Ref GrpRef Name
    05ae8000 25aec000 dlib 1    0   0      /home/edd/dbook2/dbookpy/build/libdbookpy.so.0.1

No it is not. A proper linkage to libdbook looks like this:

x31% ldd /usr/local/bin/dbook-test
/usr/local/bin/dbook-test:
    Start    End      Type Open Ref GrpRef Name
    1c000000 3c004000 exe  1    0   0      /usr/local/bin/dbook-test
    08567000 28571000 rlib 0    2   0      /usr/lib/libm.so.5.0
    09ef7000 29efb000 rlib 0    1   0      /usr/local/lib/libdbook.so.0.1
    053a0000 253d8000 rlib 0    1   0      /usr/lib/libc.so.50.1
    0c2bc000 0c2bc000 rtld 0    1   0      /usr/libexec/ld.so

Does anyone have any ideas why this is not working?

Many thanks.

Edd

解决方案

You need to link dbookpy against dbook:

target_link_libraries(dbookpy dbook)

Adding that just after the line ADD_LIBRARY(dbookpy dbookpy) should do it.

I see you are using IMPORTED - the help for IMPORTED_LINK_INTERFACE_LIBRARIES reads:

 Lists libraries whose interface is included when an IMPORTED library target is
 linked to another target.  The libraries will be included on the link line for
 the target.  Unlike the LINK_INTERFACE_LIBRARIES property, this property
 applies to all imported target types, including STATIC libraries.  This
 property is ignored for non-imported targets.

So that means that "dbook", which is in /usr/local/lib, should be an imported library:

 add_library(dbook SHARED IMPORTED)

Is that really what you wanted? I mean, imported libraries are ones that are built outside CMake but are included as part of your source tree. The dbook library seems to be installed or at least expected to be installed. I don't think you need imports here - it seems to be a regular linkage problem. But this may just be a side effect of creating a minimal example to post here.

By the sounds of it, in order to get the linked libraries and link directories sorted out, I would probably use find_library(), which will look in sensible default places like /usr/local/lib, and then append that to the link libraries.

find_library(DBOOK_LIBRARY dbook REQUIRED)
target_link_libraries(dbookpy ${DBOOK_LIBRARY})

Anyway, seems like you have it sorted now.

这篇关于使用cmake构建Python共享对象绑定,这取决于外部库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-02 17:02
查看更多