Неопределенные символы для архитектуры x86_64, общая библиотека Util, сборка с помощью cmake,

0

У меня есть простая, но смущающая проблема. Я искал вокруг и сети, и я не нашел ничего, что помогает. Я знаю, что эта проблема распространена, и подобные вопросы были заданы при переполнении стека, но они не помогли мне решить эту проблему;

Я создаю приложение, которое использует ITK и VTK в C++. Он построен с использованием cmake с unix make, я использую OS X 10.8.4 и компилирую с использованием g++ - 4.2. У меня есть структура, которая выглядит так:

    src
├── VascSeg //contains ITK filters that I have written
├── lib //contains header/source for some utility functions that I commonly use
└── test //contains tests for VascSeg Library

Вот ошибка, которую я получаю:

Undefined symbols for architecture x86_64:
  "void MyUt::print_vector<float>(std::vector<float, std::allocator<float> >&, char const*)", referenced from:
      _main in VascularLevelSetTest.cxx.o

  "void MyUt::DeepCopy<itk::Image<float, 2u> >(itk::Image<float, 2u> const*, itk::Image<float, 2u>::Pointer)", referenced from:          itk::CommandLevelSetObserver<...>in VascularLevelSetTest.cxx.o
      itk::CommandLevelSetObserver<...>:
:SaveWriteImage(...)in VascularLevelSetTest.cxx.o
ld: symbol(s) not found for architecture x86_64

Как правило, это ошибка с неправильным включением или неправильной ссылкой. Тем не менее, есть ряд других функций, которые я использую в этих файлах, и они отлично работают... Я также недавно изменил структуру файлов, чтобы использовать заголовок (.h) с исходной структурой (.cxx). Ранее я помещал объявление и реализацию в один файл.h. Файл слишком длинный и дезорганизованный, поэтому я реорганизован в структуру заголовка/источника.

Соответствующие линии:

using namespace MyUt;
...
std::vector<std::vector<float> > paramList_p1
std::vector<float> params1 = paramList_p1[config];
...

print_vector <float> (params1,"\t");

MyUtils.h:

namespace MyUt{
...
template<class T>
void print_vector(std::vector<T> &vec,const char* end = "\t");
...
}

MyUtils.cxx:

namespace MyUt{
...
template<class T>
void print_vector(std::vector<T> &vec,const char* end = "\t")
{...}
...
}

Библиотека /CMakeLists.txt:

add_library(MyUtils SHARED MyUtils.cxx 
            vtkUtils.cxx)
SET_TARGET_PROPERTIES(MyUtils PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(MyUtils ${ITK_LIBRARIES} ${VTK_LIBRARIES})

тест /CMakeLists.txt:

add_executable(VST VascularLevelSetTest.cxx)
TARGET_LINK_LIBRARIES(VST MyUtils)
TARGET_LINK_LIBRARIES(VST ${ITK_LIBRARIES})

Прошу прощения, если это повторный вопрос, но все, что я нашел, мне не помогли.

РЕДАКТИРОВАТЬ:

Я оставил строки для ошибки DeepCopy, но я решил, что проблемы, вероятно, связаны. Поэтому я оставил его, чтобы сохранить мой пост более кратким.

Теги:
makefile
linker
cmake

1 ответ

1
Лучший ответ

Ваша проблема заключается в следующем: функция шаблона (print_vector здесь) должна быть либо явно созданной, либо ее определение (тело) должно быть доступно в каждой единицы перевода, в которой оно используется.

Как правило, это означает, что вы никогда не можете поместить определение функции шаблона в файл .cxx (как вы это делали здесь) и ожидаете, что он будет работать.

Он может работать с одной версией компилятора, только для разрыва со следующей версией, или он может вообще не работать.

TL; DR Переместите тело print_vector из MyUtils.cxx в MyUtils.h.

  • 0
    Понимаю. Спасибо за ваш ответ! Теперь я помню это из моего класса старшекурсников ... Я видел шаблонные классы, помещенные в отдельный файл и включенные в конец файла .h. Есть ли хорошие рекомендации для этого?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню