Edit: I have updated my question with changes I’ve made, upon answers.
I’m trying to link to a little library that I’ve wrote to learn ho this is done with C++ with no luck. G++ is complaining with undefined reference.
The root directory of library I want to link is in directory ~/code/gklib/cxx/. The structure of this directory is as follows:
~/code/gklib/cxx/
|
|`-> gk.{hh,cc}
|`-> libgk.o
|
`-> lib/
|
`-> libgk.a
I have compiled gk.cc with -c flag, then transformed the resulting object file to a .a file with ar rvsc lib/libgk.a libgk.o.
The client to this library is at folder ~/code/cpp. In this directory I compiled some_stuff.cc to an object file again, then I tried to link to it with this command:
$ cxx some_stuff.o -L../gklib/cxx/lib -lgk -o some_stuff
I get this error:
some_stuff.o: In function `main':
some_stuff.cc:(.text+0x49): undefined reference to `void GK::algorithms::insertionSort<int, 5ul>(int*)'
collect2: error: ld returned 1 exit status
These are contents of these files:
~/code/cpp/some_stuff.cc
#include <cstdlib>
#include <iostream>
#include <gk.hh>
using namespace std;
int main(int argc, char **argv) {
int i = -1;
int arr[5] = { 3, 4, 2, 1, 5 };
const size_t len = sizeof(arr)/sizeof(int);
GK::algorithms::insertionSort<int, len>(arr);
while(++i < 5)
cout << arr[i] << " ";
cout << endl;
exit(EXIT_SUCCESS);
}
~/code/gklib/cxx/gk.cc
#include "gk.hh"
template<class T, size_t len>
void GK::algorithms::insertionSort(T arr[len]){
// insertion sort
}
~/code/gklib/cxx/gk.hh
#pragma once
#include <cstdlib>
#define NAMESPACE(ns) namespace ns {
#define END_NAMESPACE(ns) }
NAMESPACE(GK)
NAMESPACE(algorithms)
template<class T, size_t len>
extern void insertionSort(T arr[len]);
END_NAMESPACE(algorithms)
END_NAMESPACE(GK)
I’ve tried many variations on my commands with no result. Internet is full of tutorials and forums with instructions those did not work for me. This code ran perfectly when all the stuff was in one file. How can I resolve this problem? Thanks in advance.
I see several problems: in order:
If this is your exact command line, the
-Loption doesn’tpoint to the structure you’ve shown above (where there is no
cxxin the path).I don’t know why you’re using
-B. This tells the compilerwhere to look for its libraries, etc. Normally, this is only
necessary when you want to test parts of the compiler you’ve
modified.
I don’t see where you’ve specified to link against the
library. Since the library doesn’t respect the usual naming
conventions (
libname.a), you’ll have tospecify it directly (in the same way you’d specify an object
file), and the
-Loption isn’t used. Alternatively, you nameit
libgk.a, or something like that, and add a-lgkto thecommand line, after your object files.
Finally, the error messages refer to an instantiation of
a template. This typically occurs because the implementation of
the template is in a source file, not in the header. The
standard requires that the implementation be visible when it
triggers the instantiation of a template. The way g++ (and
almost every other compiler) works is that if the implementation
isn’t visible, they suppose that the template will be
instantiated in another translation unit, and output external
references to it. But if the implementation is in a source,
there will be no instantiation, and you’ll get a linker error.
(You’ll also not find the assembler for the instantiation
anywhere, either, because the template hasn’t been
instantiated.) You should include the source code at the bottom
of your header, and not compile it separately.