我正在尝试将大型文件中的某些类重构为单独的头文件和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
该项目有几个类Interpolator
和InverseCDFProcess
,最近我从主可执行文件test_icing.cpp
移到了自己的.cpp
和{{1} }文件,分别位于.hpp
和lib
目录中。
由于这些类确实相互依赖(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
或类似内容吗?为什么这种相对直接的重构导致未定义的引用?我的链接目录不正确吗?它应该引用构建目录吗?
感谢您的帮助。
答案 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?