views:

1178

answers:

2

Hi,

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

+2  A: 

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.

rq
Hi rq,see the below answer. Thanks
vext01
+2  A: 

Hi Rq,

Thanks for your help.

You are correct to say that IMPORTED is probably not needed. Adding LINK_LIBRARIES(dbookpy dbook) indeed adds -ldbook to the gcc execution, so thats great.

However cmake appears to ignore LINK_DIRECTORIES, and so never finds -ldbook:

/usr/bin/gcc  -fPIC    -shared -o libdbookpy.so.0.1 "CMakeFiles/dbookpy.dir/dbookpy.o" -ldbook 
/usr/bin/ld: cannot find -ldbook

Here is the CMakeList as it stands:

PROJECT(dbookpy)
SET(CMAKE_VERBOSE_MAKEFILE ON)

OPTION(BUILD_SHARED_LIBS "turn OFF for .a libs" ON)
ADD_LIBRARY(dbookpy dbookpy)
SET_TARGET_PROPERTIES(dbookpy PROPERTIES LINKER_LANGUAGE C)


FIND_PACKAGE(PythonInterp)
FIND_PACKAGE(PythonLibs)

INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(/usr/local/include)
target_link_libraries(dbookpy dbook)
LINK_DIRECTORIES("/usr/local/lib")

SET_TARGET_PROPERTIES(dbookpy
PROPERTIES
        SOVERSION 0.1
        VERSION 0.1
)

INSTALL(TARGETS dbookpy
        LIBRARY DESTINATION lib
)

Any ideas?

vext01
the answer is to add LINK_DIRECTORIES before ADD_LIBRARY :)
vext01
It's worth noting that target_link_libraries expects the name of the project and the name of the lib, not the path to the lib (which an example I was using had suggested). In other words, the part that would show up next to -l, ie. db (for Berkeley DB) which is libdb and shows up as -ldb.
Asher