c++cmakelinker-errorsceres-solver

Undefined symbols for architecture x86_64 - how to find missing files


I am trying to use the ceres-solver package. After installing it using home-brew, I added created my CMakeLists.txt file as follows:

cmake_minimum_required(VERSION 3.8)
project(myproject)

set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES main.cpp)
add_executable(untitled ${SOURCE_FILES})

# add extra include directories
include_directories(/usr/local/include)
include_directories(/usr/local/include/eigen3)

# add extra lib directories
link_directories(/usr/local/lib)

When I try to use the Ceres package, however, I get a linking error. As a very simple test case, I am using the following code:

#include "ceres.h"

int main(int argc, char** argv) {
    ceres::Problem problem;
    return 0;
}

which raises the following error:

Undefined symbols for architecture x86_64:
  "ceres::Problem::Problem()", referenced from:
      _main in main.cpp.o
  "ceres::Problem::~Problem()", referenced from:
      _main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

From looking around on stackoverflow, I now know that I am likely missing something from CMakeLists.txt, but no matter what I try including I can't seem to get rid of the error. Any suggestions on how to solve this?

I am currently working in CLion for Mac on OS 10.12.6.

Post solution edit

As recommended by PureVision, I changed my CMakeLists.txt to the following and all is well

cmake_minimum_required(VERSION 3.8)
project(myproject)

set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES main.cpp)

# add extra include directories
include_directories(/usr/local/include)
include_directories(/usr/local/include/eigen3)

# add extra lib directories
link_directories(/usr/local/lib)

link_libraries(glog)
link_libraries(ceres)

add_executable(myproject ${SOURCE_FILES})

Solution

  • Move your link_directories and include_directories calls before your add_executable call.

    Link_directories and include_directories only apply to targets created after those functions are called. See link_directories.

    Next, the reason why you are getting the linker error is probably due to the fact that you have not linked the library that you're trying to use into your target "untitled". The function you're looking for is target_link_libraries.

    An example is:

    target_link_libraries(untitled general NameOfLibrary)
    

    There are a lot more options you can apply to target_link_libraries but you can find more information inside of the link. One thing I will note, is that I don't have a path to the library inside of the target_link_libraries call, but that's assuming the library that you're looking for is specified in the link_directories() call. This function will accept paths as well however.

    Hopefully this is what you're looking for.