简体   繁体   中英

Linking with a library from external directory

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 think it's more something like:

cxx some_stuff.o -L$HOME/gklib/cxx/lib -B../gklib/cxx/lib -lgklib -o some_stuff

-lgklib , not -Igklib ( -I option specify an include folder)

but you'll have to rename your gklib.a by libgklib.a

Maybe you can even remove -B../gklib/cxx/lib , just try it out :)

I see several problems: in order:

  • If this is your exact command line, the -L option doesn't point to the structure you've shown above (where there is no cxx in the path).

  • I don't know why you're using -B . This tells the compiler where 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 ( lib name .a ), you'll have to specify it directly (in the same way you'd specify an object file), and the -L option isn't used. Alternatively, you name it libgk.a , or something like that, and add a -lgk to the command 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.

I have solved this problem, with the help of this and this questions. The problem lies in the fact that void insertionSort(T *) is a template function, and template functions can only be implemented in header files. The reason for this is, the compiler needs to reach the definition of the to create a new function for each call to it with a different type as the argument to template. I have moved the definition of this function to gk.h , which resulted in a successfull compilation and linkage.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM