0

I am trying to build a project that contains several user-defined libraries and a testing executables to test the libraries using cmake on Ubuntu. The structure of the project is as follow:

rootdir
|-- lib1
|   |-- include/lib1.h
|   |-- src/lib1.cpp
|   |-- CMakeLists.txt
|-- test
|   |-- test_lib1.cpp
|   |-- CMakeLists.txt
|---CMakeLists.txt

the rootdir/test/test.cpp has included the rootdir/lib1/include/lib1.h

the rootdir/lib1/src/lib1.cpp has included the rootdir/lib1/include/lib1.h

rootdir/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)

project(mylib)

add_subdirectory(lib1)
add_subdirectory(test)

rootdir/lib1/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)

project(lib1)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

add_library(lib1 SHARED src/lib1.cpp)

rootdir/test/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)

project(test)

include_directories(${CMAKE_SOURCE_DIR}/lib1/include)
link_directories(${CMAKE_BINARY_DIR}/lib1)

add_executable(test_lib1 test_lib1.cpp)
target_link_libraries (test_lib1 lib1)

The question is that I get "undefined reference to..." the functions defined in lib1.

Since I can find the liblib1.so in build/lib1/ and get no error building the lib1 library, I guess that the lib1 library is built successfully.

One more strange thing is that I get "undefined reference to..." only those functions implemented in lib1.cpp. The simple functions implemented in lib1.h will not trigger the "undefined reference to..." error.

Any suggestions? Thanks!

---EDIT---

I followed the suggestion and put add_subdirectory(lib1) in front of add_subdirectory(test) in the root CMakeLists.txt. However, the same problem is still there.

---EDIT---

This is my project : https://www.dropbox.com/s/082oyglyjj46438/recognition.tar.gz?dl=0.

It is slightly different from the original problem since it links to an external library PCL. But the architecture is mostly the same.

AlbertK
  • 231
  • 5
  • 13
  • I do not put the `cmake_minimum_required(VERSION 2.6 FATAL_ERROR)` or the `project(test)` part in the testing application. I make it part of the root project. – drescherjm Jan 20 '15 at 00:54
  • Put `add_subdirectory(test)` after `add_subdirectory(lib1)` in the root CMakeLists.txt and get rid of `cmake_minimum_required(VERSION 2.6 FATAL_ERROR)` and `project(lib1)` – drescherjm Jan 20 '15 at 00:58
  • I follow your suggest: 1) remove cmake_minimum_required() and project() in test/CMakeLists.txt and lib1/CMakeLists.txt. 2)put add_subdirectory(test) after add_subdirectory(lib1). However, the exact same problem remains. – AlbertK Jan 20 '15 at 03:41

2 Answers2

1

The problem is that you're not linking correctly with the created library because you're adding the test subdirectory before adding the lib1 one. Anyway, try with these CMakeLists.txt

rootdir/CMakeLists.txt

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(mylib)

SET(MYLIB_LIB_OUT_PATH ${mylib_SOURCE_DIR}/lib)
SET(MYLIB_BIN_OUT_PATH ${mylib_SOURCE_DIR}/test/bin)

add_subdirectory(lib1)
add_subdirectory(test)

rootdir/lib1/CMakeLists.txt

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(lib1)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
set(LIBRARY_OUTPUT_PATH ${MYLIB_LIB_OUT_PATH})

add_library(mylib SHARED src/lib1.cpp)

rootdir/test/CMakeLists.txt

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(test)

include_directories(${CMAKE_SOURCE_DIR}/lib1/include)
link_directories(${MYLIB_LIB_OUT_PATH})

set(EXECUTABLE_OUTPUT_PATH ${MYLIB_BIN_OUT_PATH})

add_executable(test_lib1 test_lib1.cpp)
target_link_libraries(test_lib1 mylib)

I hope it works! ;)

fenix688
  • 2,435
  • 2
  • 17
  • 23
  • I tried your solution as well as drescherjm's comment in the original post but still got the exact same problem. – AlbertK Jan 20 '15 at 12:38
  • Have you tried my code? It's different from yours one – fenix688 Jan 20 '15 at 14:25
  • Yes, I just copy and paste your CMakeLists.txt and modify some of the file names and folder names. This is my project : https://www.dropbox.com/s/082oyglyjj46438/recognition.tar.gz?dl=0. It is slightly different from the original problem since it links to an external library PCL. But the architecture is mostly the same. – AlbertK Jan 21 '15 at 03:47
0

OK...answer my own question.

The problem did not come from the CMakeLists.txt. Actually it is because the class is templated. A templated class just can't compile into a shared or static library.[see Ref.]

Here are three possible solutions

  1. Compile your main program with all the class definition .cpps

  2. Move the class definition into the header file, which contains the class declaration.

  3. **Instantiate the template

If the templated types are limited. You can instantiate the template in the end of the class definition .cpps.

For example, suppose that your class is templated as follow:

template<T>
class myClass
{
    //class definitions
}

, and you know that the templated type T can only be float or int. Then just add the following to the lib1.cpp:

template class myclass<int>;
template class myclass<float>;

Ref.

C++ Shared Library with Templates: Undefined symbols error

Compile header-only template library into a shared library?

https://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html#Template-Instantiation

Community
  • 1
  • 1
AlbertK
  • 231
  • 5
  • 13