Building a Python shared object binding with cmake, which depends upon external libraries

2024/10/1 15:12:25

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
PROPERTIESSOVERSION 0.1VERSION 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 Name05ae8000 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 Name1c000000 3c004000 exe  1    0   0      /usr/local/bin/dbook-test08567000 28571000 rlib 0    2   0      /usr/lib/libm.so.5.009ef7000 29efb000 rlib 0    1   0      /usr/local/lib/libdbook.so.0.1053a0000 253d8000 rlib 0    1   0      /usr/lib/libc.so.50.10c2bc000 0c2bc000 rtld 0    1   0      /usr/libexec/ld.so

Does anyone have any ideas why this is not working?

Many thanks.

Edd

Answer

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 islinked to another target.  The libraries will be included on the link line forthe target.  Unlike the LINK_INTERFACE_LIBRARIES property, this propertyapplies to all imported target types, including STATIC libraries.  Thisproperty 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.

https://en.xdnf.cn/q/70959.html

Related Q&A

What linux distro is better suited for Python web development?

Which linux distro is better suited for Python web development?Background:I currently develop on Windows and its fine, but I am looking to move my core Python development to Linux. Im sure most any di…

Relation between 2D KDE bandwidth in sklearn vs bandwidth in scipy

Im attempting to compare the performance of sklearn.neighbors.KernelDensity versus scipy.stats.gaussian_kde for a two dimensional array.From this article I see that the bandwidths (bw) are treated diff…

How to style (rich text) in QListWidgetItem and QCombobox items? (PyQt/PySide)

I have found similar questions being asked, but without answers or where the answer is an alternative solution.I need to create a breadcrumb trail in both QComboBoxes and QListWidgets (in PySide), and …

Reconnecting to device with pySerial

I am currently having a problem with the pySerial module in Python. My problem relates to connecting and disconnecting to a device. I can successfully connect to my device and communicate with it for a…

How to check if a sentence is a question with spacy?

I am using spacy library to build a chat bot. How do I check if a document is a question with a certain confidence? I know how to do relevance, but not sure how to filter statements from questions.I a…

Python: Lifetime of module-global variables

I have a shared resource with high initialisation cost and thus I want to access it across the system (its used for some instrumentation basically, so has to be light weight). So I created a module man…

Power spectrum with Cython

I am trying to optimize my code with Cython. It is doing a a power spectrum, not using FFT, because this is what we were told to do in class. Ive tried to write to code in Cython, but do not see any di…

Detect abbreviations in the text in python

I want to find abbreviations in the text and remove it. What I am currently doing is identifying consecutive capital letters and remove them.But I see that it does not remove abbreviations such as MOOC…

filtering of tweets received from statuses/filter (streaming API)

I have N different keywords that i am tracking (for sake of simplicity, let N=3). So in GET statuses/filter, I will give 3 keywords in the "track" argument.Now the tweets that i will be recei…

UndefinedError: current_user is undefined

I have a app with flask which works before But Now I use Blueprint in it and try to run it but got the error so i wonder that is the problem Blueprint that g.user Not working? and how can I fix it Thn…