使用cmake构建Python共享对象绑定,这取决于外部库

Edd*_*ett 6 c python unix linker cmake

我们有一个名为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 "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
)
Run Code Online (Sandbox Code Playgroud)

然后我们建立:

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
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.用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
Run Code Online (Sandbox Code Playgroud)

嗯.链接器错误.看起来它没有链接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
Run Code Online (Sandbox Code Playgroud)

不它不是.与libdbook的正确链接如下所示:

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
Run Code Online (Sandbox Code Playgroud)

有没有人有任何想法为什么这不起作用?

非常感谢.

埃德

ric*_*chq 4

您需要将 dbookpy 链接到 dbook:

target_link_libraries(dbookpy dbook)
Run Code Online (Sandbox Code Playgroud)

在该行后面添加ADD_LIBRARY(dbookpy dbookpy)它就可以了。

我看到您正在使用 IMPORTED - 阅读帮助IMPORTED_LINK_INTERFACE_LIBRARIES

 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.
Run Code Online (Sandbox Code Playgroud)

因此,这意味着 /usr/local/lib 中的“dbook”应该是导入的库:

 add_library(dbook SHARED IMPORTED)
Run Code Online (Sandbox Code Playgroud)

这真的是你想要的吗?我的意思是,导入的库是在 CMake 外部构建的库,但作为源代码树的一部分包含在内。dbook 库似乎已安装或至少预计已安装。我认为你不需要在这里导入 - 这似乎是一个常规的链接问题。但这可能只是创建一个最小示例发布到此处的副作用。

听起来,为了整理出链接库和链接目录,我可能会使用find_library(),它将在 /usr/local/lib 等合理的默认位置中查找,然后将其附加到链接库中。

find_library(DBOOK_LIBRARY dbook REQUIRED)
target_link_libraries(dbookpy ${DBOOK_LIBRARY})    
Run Code Online (Sandbox Code Playgroud)

不管怎样,看来你现在已经解决了。