Связывание stati c библиотек в CMake Project - неопределенная ссылка - PullRequest
1 голос
/ 11 апреля 2020

Я пытаюсь преобразовать некоторые классы из большого основного файла в отдельный заголовок и 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 и .hpp, расположены в каталогах lib и include соответственно.

Поскольку классы зависят друг от друга (InverseCDFProcess требуется Interpolator, что, в свою очередь, требует функции в XYParser.cpp), я решил собрать их как stati c библиотеки, которые затем будут связаны с основным исполняемым файлом во время компиляции.

Они построены так:

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. По-прежнему возникает неопределенная ошибка ссылки.

У меня такой вопрос: я пропускаю некоторые extern или похожие в моих определениях классов или реализациях? Почему этот относительно простой рефакторинг приводит к неопределенным ссылкам? Мой каталог ссылок неверен? Должно ли это ссылаться на каталоги сборки?

Любая помощь приветствуется.

1 Ответ

1 голос
/ 12 апреля 2020

Собираюсь go вперед и ответим на этот вопрос для будущих людей:

Решение встроено в сообщения об ошибках:

/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 et c, и он должен работать как положено!

Причина, по которой шаблоны нуждаются в реализации, видна здесь: Почему шаблоны могут быть реализованы только в заголовочном файле?

...