如何在 link 使用 cmake 为同一项目中的测试可执行文件构建库时?
How to build a library while link to a testing executable in the same project using cmake?
我正在尝试构建一个项目,其中包含多个用户定义的库和一个测试可执行文件,以在 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/[=64中找到liblib1.so =] 并且构建 lib1 库没有错误,我猜 lib1 库已成功构建。
更奇怪的是,我得到“对...的未定义引用”只有那些在lib1.cpp[=64=中实现的函数]. lib1.h中实现的简单函数不会触发“undefined reference to...”错误。
有什么建议吗?谢谢!
---编辑---
我按照建议把add_subdirectory(lib1)放在了add_subdirectory(test)前面在根 CMakeLists.txt 中。但是还是一样的问题。
---编辑---
这是我的项目:https://www.dropbox.com/s/082oyglyjj46438/recognition.tar.gz?dl=0。
它与原始问题略有不同,因为它链接到外部库 PCL。但架构基本相同。
问题是您没有正确链接到创建的库,因为您在添加 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)
希望有用! ;)
好的...回答我自己的问题。
问题并非来自 CMakeLists.txt。实际上是因为 class 是模板化的。模板化的 class 无法编译成共享库或静态库。[参见参考文献]
以下是三种可能的解决方案
使用所有 class 定义编译主程序.cpps
将 class 定义移动到包含 class 声明的头文件中。
**实例化模板
如果模板类型有限。您可以在 class 定义 .cpps.
的末尾实例化模板
例如,假设您的 class 模板化如下:
template<T>
class myClass
{
//class definitions
}
,你知道模板化类型 T 只能是 float 或 整数。然后只需将以下内容添加到 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
我正在尝试构建一个项目,其中包含多个用户定义的库和一个测试可执行文件,以在 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/[=64中找到liblib1.so =] 并且构建 lib1 库没有错误,我猜 lib1 库已成功构建。
更奇怪的是,我得到“对...的未定义引用”只有那些在lib1.cpp[=64=中实现的函数]. lib1.h中实现的简单函数不会触发“undefined reference to...”错误。
有什么建议吗?谢谢!
---编辑---
我按照建议把add_subdirectory(lib1)放在了add_subdirectory(test)前面在根 CMakeLists.txt 中。但是还是一样的问题。
---编辑---
这是我的项目:https://www.dropbox.com/s/082oyglyjj46438/recognition.tar.gz?dl=0。
它与原始问题略有不同,因为它链接到外部库 PCL。但架构基本相同。
问题是您没有正确链接到创建的库,因为您在添加 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)
希望有用! ;)
好的...回答我自己的问题。
问题并非来自 CMakeLists.txt。实际上是因为 class 是模板化的。模板化的 class 无法编译成共享库或静态库。[参见参考文献]
以下是三种可能的解决方案
使用所有 class 定义编译主程序.cpps
将 class 定义移动到包含 class 声明的头文件中。
**实例化模板
如果模板类型有限。您可以在 class 定义 .cpps.
的末尾实例化模板例如,假设您的 class 模板化如下:
template<T>
class myClass
{
//class definitions
}
,你知道模板化类型 T 只能是 float 或 整数。然后只需将以下内容添加到 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