2

I already read and searched a lot (e.g. 1 2 3, several docs for CMake, similar projects, etc. to find a solution but I have not been able to solve my problem. I am relatively new to Cmake and Linux (Ubuntu 14.04).

I want to use libsbp (https://github.com/swift-nav/libsbp) to write a program in C++ to communicate with a GPS module. I cloned the repository and installed the C-Library. So now in /usr/local/lib there are two files: libsbp.so and libsbp-static.a and the headers are in /usr/local/include/libsbp

In my own project I include the headers with #include "libsbp/sbp.h" which also works.

Now the Problem: if I want to use a method from libsbp e.g. sbp_state_init(&s); I get undefined reference to "sbp_state_init(sbp_state_t*)"

The relevant part of my Cmake for my own project:

link_directories(/usr/local/lib)

add_executable(main ${QT_SOURCES} ${QT_HEADER_HPP})
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)

As I said before, I tried some things:

  • find_library(SBP_LIB sbp /usr/local/lib) -> same error
  • same goes for using libsbp in target_link_libraries or searching for it
  • link_directory(/usr/local/lib)
  • trying different paths, even moveing libsbp.so into the project directory and "finding" it with ${CMAKE_CURRENT_SOURCE_DIR}

Maybe you can help me!

edit:

this is the CMakeList.txt from the libsbp/c/src directory

if (NOT DEFINED BUILD_SHARED_LIBS)
  set(BUILD_SHARED_LIBS ON)
endif (NOT DEFINED BUILD_SHARED_LIBS)

file(GLOB libsbp_HEADERS "${PROJECT_SOURCE_DIR}/include/libsbp/*.h")

include_directories("${PROJECT_SOURCE_DIR}/CBLAS/include")
include_directories("${PROJECT_SOURCE_DIR}/clapack-3.2.1-CMAKE/INCLUDE")
include_directories("${PROJECT_SOURCE_DIR}/lapacke/include")
include_directories("${PROJECT_SOURCE_DIR}/include/libsbp")

set(libsbp_SRCS
  edc.c
  sbp.c
)

add_library(sbp-static STATIC ${libsbp_SRCS})
install(TARGETS sbp-static DESTINATION lib${LIB_SUFFIX})

if(BUILD_SHARED_LIBS)
  add_library(sbp SHARED ${libsbp_SRCS})
  install(TARGETS sbp DESTINATION lib${LIB_SUFFIX})
else(BUILD_SHARED_LIBS)
  message(STATUS "Not building shared libraries")
endif(BUILD_SHARED_LIBS)

install(FILES ${libsbp_HEADERS} DESTINATION include/libsbp)

this is the CMakeList.txt from /libsbp/c/

cmake_minimum_required(VERSION 2.8.9)
project(libsbp)

# Setup flags for Code Coverage build mode
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} --coverage" CACHE STRING
    "Flags used by the C++ compiler for building with code coverage."
    FORCE )
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG} --coverage" CACHE STRING
    "Flags used by the C compiler for building with code coverage."
    FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
    "${CMAKE_EXE_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
    "Flags used for linking binaries with code coverage."
    FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
    "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
    "Flags used by the shared libraries linker during builds with code coverage."
    FORCE )
mark_as_advanced(
    CMAKE_CXX_FLAGS_COVERAGE
    CMAKE_C_FLAGS_COVERAGE
    CMAKE_EXE_LINKER_FLAGS_COVERAGE
    CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
# Update the documentation string of CMAKE_BUILD_TYPE for GUIs
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
  "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
   FORCE )

# Set project version using Git tag and hash.
execute_process(
  COMMAND git describe --dirty --tags --always
  WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
  RESULT_VARIABLE GIT_VERSION_FOUND
  ERROR_QUIET
  OUTPUT_VARIABLE GIT_VERSION
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_VERSION_FOUND)
  set(VERSION "unknown")
else (GIT_VERSION_FOUND)
  set(VERSION ${GIT_VERSION})
endif (GIT_VERSION_FOUND)

# Set project version explicitly for release tarballs.
#set(VERSION foo)

message(STATUS "libsbp version: ${VERSION}")

cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

# Some compiler options used globally
set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=gnu99 ${CMAKE_C_FLAGS}")

add_subdirectory(src)
add_subdirectory(docs)
add_subdirectory(test)
Community
  • 1
  • 1
SSA
  • 23
  • 1
  • 4
  • did you add_executable? http://www.cmake.org/cmake/help/v3.0/command/target_link_libraries.html – user3125280 Apr 17 '15 at 13:36
  • Can you try `make VERBOSE=1` and check that sbp is really passed to the linker? If it is, try `nm -C .../libsbp.so` and check if the function is provided by the library. – Finn Apr 18 '15 at 07:08
  • @Finn the output of `make VERBOSE=1` contained among others **/usr/local/lib/libsbp-static.a** the **.so** file doesn't appear there. `nm -C /usr/local/lib/libsbp.so` and **.../libsbp-static.a** contains the method I want to call. – SSA Apr 18 '15 at 12:00

2 Answers2

4

It seems that your program uses C++ and the library is written in C.

Symbols in C and C++ are encoded differently (mangled). When including C headers from C++ you need to tell the compiler. This can be done by declaring the symbols extern "C".

extern "C" {
#include <libsbp/sbp.h>
}

Some libraries already include this in their headers, but not sbp.

Finn
  • 1,018
  • 6
  • 6
  • awesome! Thank you! That solved my problem. so now I can use it like a C++ lib? or are there other important differences? – SSA Apr 19 '15 at 07:40
  • Generally you should be able to use it without problems. Differences can appear in new/delete vs. malloc/free and some corner cases. – Finn Apr 19 '15 at 08:03
0

You have (at least) two possibilities:

  1. Installing the library (this is what you did)
  2. Integrating the library in your CMake project

When installing the library, the target_link_libraries command needs to be modified slightly:

find_library(SBP_LIB sbp /usr/local/lib)
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} ${SBP_LIB})

When you integrate the library in your CMake project, you can directly use the following command without using find_library. This works, because the library is known to CMake since it is built within the current project.

target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)
m.s.
  • 16,063
  • 7
  • 53
  • 88
  • I tried both methods and I guess both worked (no error that the lib couldn't be found) but I still get the undefined reference error – SSA Apr 18 '15 at 12:05