8

I am attempting to use CMake to link a library(BNO055 Driver). Since the BNO055 Driver doesn't use CMake and it hasn't been changed for about a year I decided to just download the source files and put them in my project.

I then use CMake to create a library and link it.

The issue is that the link does not seem to be working. When I compile the project I get a undefined reference to <function> error, where <function> is a function defined by the BNO055 driver.

Am I creating or linking the library incorrectly?
Do I need to do something else to define these functions?

For the sake of not pasting in 200 lines of code, here is a simplified main.cpp that produces the same error as the real main.cpp. If you would like to see the real main.cpp follow the link bellow to the Github repo

#include "bno055.h"
#include "mraa.hpp"

struct bno055_t bno055;
mraa::I2c *i2c(0);

int main() {
    bno055_init(&bno055);
    i2c->address(0x29);
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.4)
project(imc-server)

# CMake
# -- Config
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")

# Global
# -- Include
include(ExternalProject)

# BNO055
# -- Include
include_directories(${CMAKE_SOURCE_DIR}/bno055)

set(SOURCE_FILES ${SOURCE_FILES}
        ${CMAKE_SOURCE_DIR}/bno055/bno055.h
        ${CMAKE_SOURCE_DIR}/bno055/bno055.c)

# MRAA
# -- Build
externalProject_add(mraa
        GIT_REPOSITORY https://github.com/intel-iot-devkit/mraa.git
        GIT_TAG        v0.7.5
)

# Compile
# -- Source
set(SOURCE_FILES ${SOURCE_FILES}
        main.cpp)

# -- Create
add_executable(imc-server ${SOURCE_FILES})
add_dependencies(imc-server mraa)

Relevant Part of Build Log

[ 90%] Linking CXX executable imc-server
CMakeFiles/imc-server.dir/test.cpp.o: In function `main':
/home/noah/Documents/Inertial-Motion-Capture/imc-server/test.cpp:8: undefined reference to `bno055_init(bno055_t*)'
CMakeFiles/imc-server.dir/test.cpp.o: In function `mraa::I2c::address(unsigned char)':
/usr/local/include/mraa/i2c.hpp:99: undefined reference to `mraa_i2c_address'
collect2: error: ld returned 1 exit status
make[2]: *** [imc-server] Error 1
make[1]: *** [CMakeFiles/imc-server.dir/all] Error 2
make: *** [all] Error 2

Project Github(39a6196)
Build Log

7
  • You use ${CMAKE_SOURCE_DIR}/bno055/bno055.c file for build bno055 library, so you shouldn't use that file for build imc-server executable. Also, it is better to use library target name for link that executable: target_link_libraries(imc-server bno055). As for external project mraa, you additionally need explicit target dependencies for correctly link with it: add_dependencies(imc-server mraa). Commented Sep 9, 2015 at 22:18
  • @Tsyvarev Ok, I just added the BNO055 files to the executable(So no lib or linking for bno055). However I am still getting undefined function errors. I also uncommented all the mraa code and I am getting undefined function errors for those functions as well. Is there something I am fundamentally missing here? Commit with changes => 39a6196 Commented Sep 9, 2015 at 22:29
  • Which source is being compiled, when you get error? Precise error message(at least, for one function) would be helpful. Commented Sep 10, 2015 at 9:03
  • @Tsyvarev Indeed, Here is the end part of the CMake build log. Pastebin Commented Sep 10, 2015 at 19:34
  • As build log shows, function (mraa_i2c_address) is defined in the mraa library, not in the bno055 one. You need both link with that library (target_link_libraries(imc-server libmraa.so) and add dependency with mraa target (add_dependencies(imc-server mraa)). Commented Sep 10, 2015 at 22:07

2 Answers 2

15

The problem was that the BNO055 library was written in C, and my program was written in C++.

I learned that to use a function defined in a C program, in a C++ program, you have to wrap the include of the C library in an extern "C" {} block like so:

extern "C" {
    #include "bno055.h"
}
#include "mraa.hpp"

struct bno055_t bno055;
mraa::I2c *i2c(0);

int main() {
    bno055_init(&bno055);
    i2c->address(0x29);
}
Sign up to request clarification or add additional context in comments.

Comments

0

Remove the header from your SOURCE_FILES.

set(SOURCE_FILES ${SOURCE_FILES}
        # ${CMAKE_SOURCE_DIR}/bno055/bno055.h
        ${CMAKE_SOURCE_DIR}/bno055/bno055.c)

CMake should find the required header by itself. Additional includes are found by include_directories

2 Comments

The issue was that I had to wrap the bno055 include in a extern "C" {}"
maybe you could post your own answer, it would be more visible

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.