在CMake项目中链接静态库-未定义参考

时间:2020-04-11 19:45:30

标签: c++ class c++11 cmake

我正在尝试将大型文件中的某些类重构为单独的头文件和cpp文件,并且在链接时遇到未定义的引用错误。

我有一个看起来像这样的项目:

├── CMakeLists.txt
├── data
│   └── ICING BE SI Data.csv
├── gcc
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── lib
│   ├── Makefile
│   ├── src
│   └── tmp
├── include
│   ├── Interpolator.hpp
│   ├── InverseCDFProcess.hpp
│   └── XYParser.hpp
├── lib
│   ├── CMakeLists.txt
│   ├── Interpolator.cpp
│   ├── InverseCDFProcess.cpp
│   └── XYParser.cpp
└── test
    └── test_icing.cpp

该项目有几个类InterpolatorInverseCDFProcess,最近我从主可执行文件test_icing.cpp移到了自己的.cpp和{{1} }文件,分别位于.hpplib目录中。

由于这些类确实相互依赖(include需要InverseCDFProcess,这又需要Interpolator中的一个函数),所以我决定将它们构建为静态库,然后进行链接在编译时进入主可执行文件。

它们的构建方式如下:

XYParser.cpp

然后我以正常方式将这些库链接到我的可执行文件中:

add_library(xyparser STATIC XYParser.cpp)
add_library(interpolator STATIC Interpolator.cpp)
add_library(inversecdf STATIC InverseCDFProcess.cpp)

这将产生以下链接命令:

include_directories(include) link_directories(lib) link_directories(include) # Do I need this? add_executable(test_icing test/test_icing.cpp) # ... some code adding an external library which works fine target_link_libraries(test_icing inversecdf interpolator xyparser ${external_library_name})

这时编译停止并显示错误:

/usr/bin/c++      CMakeFiles/test_icing.dir/test/test_icing.cpp.o  -o test_icing  -L/mnt/c/Users/foo/projects/chase-icing/lib  -L/mnt/c/Users/foo/projects/chase-icing/include  -L/mnt/c/Users/foo/projects/chas
e-icing/gcc/src/imtc-build/lib -Wl,-rpath,/mnt/c/Users/foo/projects/chase-icing/lib:/mnt/c/Users/foo/projects/chase-icing/include:/mnt/c/Users/foo/projects/chase-icing/gcc/src/imtc-build/lib lib/libinversecdf
.a lib/libinterpolator.a lib/libxyparser.a -limt

构建库/mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xcca): undefined reference to `Interpolator<double>::Interpolator(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > co nst&)' /mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xd4c): undefined reference to `Interpolator<double>::set_bounds(std::pair<double, double> const&)' /mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xd99): undefined reference to `InverseCDFProcess<double>::InverseCDFProcess(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator< char> > const&)' /mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xdd9): undefined reference to `InverseCDFProcess<double>::generate()' STATIC无关紧要。未定义的参考错误仍然会发生。

我的问题是:我在类定义或实现中缺少一些SHARED或类似内容吗?为什么这种相对直接的重构导致未定义的引用?我的链接目录不正确吗?它应该引用构建目录吗?

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

将继续为未来的人们回答这个问题:

解决方案嵌入在错误消息中:

/mnt/c/Users/foo/projects/chase-icing/test/test_icing.cpp:(.text+0xdd9): undefined reference to `InverseCDFProcess<double>::generate()'

此错误表明类已模板化。问题是我将这些模板的实现放在.cpp文件中,如下所示:

├── include
│   ├── Interpolator.hpp
│   ├── InverseCDFProcess.hpp
│   └── XYParser.hpp
├── lib
│   ├── CMakeLists.txt
│   ├── Interpolator.cpp
│   ├── InverseCDFProcess.cpp
│   └── XYParser.cpp

模板需要在头文件中包含完整的实现。因此,好消息是,我不需要这些库。只是#include "Interpolator.hpp等,它应该可以正常工作!

需要模板的原因请参见:Why can templates only be implemented in the header file?