【问题标题】:How to build a library while link to a testing executable in the same project using cmake?如何在使用 cmake 链接到同一项目中的测试可执行文件时构建库?
【发布时间】:2015-03-17 13:18:33
【问题描述】:

我正在尝试构建一个项目,其中包含几个用户定义的库和一个测试可执行文件,以在 Ubuntu 上使用 cmake 测试这些库。项目结构如下:

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

rootdir/test/test.cpp 已包含 rootdir/lib1/include/lib1.h

rootdir/lib1/src/lib1.cpp 已包含 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)

问题是我得到“undefined reference to...lib1中定义的函数。

因为我可以在 build/lib1/ 中找到 liblib1.so 并且构建 lib1 时没有错误> 库,我猜 lib1 库构建成功。

更奇怪的是,我得到“undefined reference to...”只有那些在 lib1.cpp 中实现的函数。 lib1.h 中实现的简单函数不会触发“undefined reference to...”错误。

有什么建议吗?谢谢!

---编辑---

我按照建议将 add_subdirectory(lib1) 放在根 CMakeLists.txt 中的 add_subdirectory(test) 前面。但是,同样的问题仍然存在。

---编辑---

这是我的项目:https://www.dropbox.com/s/082oyglyjj46438/recognition.tar.gz?dl=0

它与原始问题略有不同,因为它链接到外部库 PCL。但架构大体相同。

【问题讨论】:

  • 我没有将cmake_minimum_required(VERSION 2.6 FATAL_ERROR)project(test) 部分放在测试应用程序中。我把它作为根项目的一部分。
  • add_subdirectory(test)放在根CMakeLists.txt中add_subdirectory(lib1)之后,去掉cmake_minimum_required(VERSION 2.6 FATAL_ERROR)project(lib1)
  • 我听从你的建议:1) 删除 test/CMakeLists.txt 和 lib1/CMakeLists.txt 中的 cmake_minimum_required() 和 project()。 2) 将 add_subdirectory(test) 放在 add_subdirectory(lib1) 之后。但是,完全相同的问题仍然存在。

标签: cmake


【解决方案1】:

问题是您没有正确链接到创建的库,因为您在添加 lib1 之前添加了 test 子目录。不管怎样,试试这些 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)

我希望它有效! ;)

【讨论】:

  • 我尝试了您的解决方案以及 drescherjm 在原始帖子中的评论,但仍然遇到完全相同的问题。
  • 你试过我的代码了吗?和你的不一样
  • 是的,我只是复制并粘贴您的 CMakeLists.txt 并修改一些文件名和文件夹名。这是我的项目:dropbox.com/s/082oyglyjj46438/recognition.tar.gz?dl=0。它与原始问题略有不同,因为它链接到外部库 PCL。但架构大体相同。
【解决方案2】:

好的...回答我自己的问题。

问题并非来自 CMakeLists.txt。实际上是因为该类是模板化的。模板类不能编译成共享或静态库。[参见 Ref.]

这里有三种可能的解决方案

  1. 用所有类定义.cpps编译你的主程序

  2. 将类定义移动到包含类声明的头文件中。

  3. **实例化模板

如果模板类型有限。您可以在类定义 .cpps 的末尾实例化模板。

例如,假设您的类的模板如下:

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

,你知道模板化类型 T 只能是 floatint。然后只需将以下内容添加到 lib1.cpp:

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

参考。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    相关资源
    最近更新 更多