jmerkow
jmerkow

Reputation: 1860

Undefined symbols for architecture x86_64, shared Util Library, build with cmake,

I have a simple yet perplexing problem. I have searched around stack overflow and the web and I haven't found anything that helps. I am aware that this problem is common and similar questions have been asked on stack overflow, but they haven't helped me solve this issue;

I am building an application that uses ITK and VTK in C++. It is built using cmake with unix make, I am using OS X 10.8.4 and compiling using g++-4.2. I have a structure that looks like this:

    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

Here is the error I am getting:

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

Generally, this is an error with an improper include or improper link. However, there are a number of other functions that I am using in these files and they work fine... I also recently change the structure of the files to use a header(.h) with source (.cxx) structure. Previously, I put the declaration and the implementation in a single .h file. The file got too long and disorganized so I refactored to header/source structure.

Relevant Lines:

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")
{...}
...
}

lib/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})

test/CMakeLists.txt:

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

I am sorry if this is a repeat question but all the ones I found didn't help me.

EDIT:

I left out the lines for the DeepCopy error, but I figured that the problems are likely related. So I left it out to keep my post more concise.

Upvotes: 0

Views: 1356

Answers (1)

Employed Russian
Employed Russian

Reputation: 213456

Your problem is this: a template function (print_vector here) must be either explicitly instantiated, or its definition (body) must be available in every translation unit in which it is used.

Generally this means that you can never put a template function definition into a .cxx file (as you've done here) and expect it to work.

It may work with one version of the compiler, only to break with the next version, or it may not work at all.

TL;DR Move the body of print_vector from MyUtils.cxx to MyUtils.h.

Upvotes: 1

Related Questions