I'm trying to refactor some classes from a large main file into separate header and cpp files and am getting undefined reference errors at link time.
I've got a project that looks like this:
├── 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
The project has a few classes, Interpolator
and InverseCDFProcess
, which I recently moved from the main executable file, test_icing.cpp
to their own .cpp
and .hpp
files, located within the lib
and include
directories, respectively.
Since the classes do depend on each other (InverseCDFProcess
needs Interpolator
, which in turn needs a function in XYParser.cpp
), I decided to build them as static libraries that then get linked into the main executable at compile time.
They're built like so:
add_library(xyparser STATIC XYParser.cpp)
add_library(interpolator STATIC Interpolator.cpp)
add_library(inversecdf STATIC InverseCDFProcess.cpp)
I then link these libraries into my executable in the normal way:
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})
This produces this link command:
/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
At this point the compilation stop with the error:
/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()'
It doesn't matter if the libraries are built STATIC
or SHARED
. The undefined reference error still happens.
My question is this: am I missing some extern
or similar in my class definitions or implementations? Why is this relatively straightforward refactoring resulting in undefined references? Is my link directory incorrect? Should it refer to build directories?
Any help is appreciated.