使用cmake构建依赖外部库的Python共享对象绑定
我们有一个叫做 dbookpy.c 的 C 文件,它会为一些 C 函数提供 Python 的接口。
接下来,我们决定用 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
)
然后我们开始构建:
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
到目前为止一切顺利。在 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
嗯,出现了链接错误。看起来没有链接到 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
没错,确实没有。正确链接到 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
有没有人知道为什么这不行呢?
非常感谢。
Edd
1 个回答
4
你需要把 dbookpy 和 dbook 连接起来:
target_link_libraries(dbookpy dbook)
在 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.
这意味着 "dbook" 这个库在 /usr/local/lib 目录下,应该是一个被引入的库:
add_library(dbook SHARED IMPORTED)
这真的是你想要的吗?我的意思是,被引入的库是那些在 CMake 之外构建的,但作为你源代码的一部分被包含进来。dbook 库似乎已经安装好了,或者至少是预期会安装的。我觉得你在这里不需要引入,它看起来更像是一个普通的链接问题。不过,这可能只是因为你在这里创建了一个最小的示例。
听起来,为了整理好链接的库和链接目录,我可能会使用 find_library()
,这个函数会在一些合理的默认位置查找,比如 /usr/local/lib,然后把找到的库加到链接库中。
find_library(DBOOK_LIBRARY dbook REQUIRED)
target_link_libraries(dbookpy ${DBOOK_LIBRARY})
总之,看来你现在已经解决了这个问题。