5

Here is the setup of this rather trivial application that I can't get to link properly. Basically a single source file main.cpp, a directory with a static library libbreakpad_client.a, and the headers for the library in breakpad.

$ ls .
main.cpp libs breakpad
$ ls libs
libbreakpad_client.a

Here is the source for main.cpp, taken verbatim from the Google Breakpad documentation.

#include "client/linux/handler/exception_handler.h"

void crash()
{
  volatile int* a = (int*)(NULL);
  *a = 1;
}

static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded)
{
  printf("Dump path: %s\n", descriptor.path());
  return succeeded;
}

int main()
{
    google_breakpad::MinidumpDescriptor descriptor("/tmp");
    google_breakpad::ExceptionHandler eh(descriptor, 0, dumpCallback, 0, true, -1);
    crash();
    return 0;
}

But when I try to compile it, the linker complains that it can't find the ExceptionHandler constructor and destructor.

$ g++ -Ibreakpad/src -lbreakpad_client -Llibs -o main main.cpp
/tmp/ccDDGnQk.o: In function `main':
main.cpp:(.text+0xed): undefined reference to `google_breakpad::ExceptionHandler::ExceptionHandler(google_breakpad::MinidumpDescriptor const&, bool (*)(void*), bool (*)(google_breakpad::MinidumpDescriptor const&, void*, bool), void*, bool, int)'
main.cpp:(.text+0x106): undefined reference to `google_breakpad::ExceptionHandler::~ExceptionHandler()'
collect2: error: ld returned 1 exit status

But if we look at the symbols present in libbreakpad_client.a, we see that the functions exist exactly as expected

$ nm -an libs/libbreakpad_client.a | c++filt | grep "ExceptionHandler("
000000000000076c T google_breakpad::ExceptionHandler::ExceptionHandler(google_breakpad::MinidumpDescriptor const&, bool (*)(void*), bool (*)(google_breakpad::MinidumpDescriptor const&, void*, bool), void*, bool, int)
000000000000076c T google_breakpad::ExceptionHandler::ExceptionHandler(google_breakpad::MinidumpDescriptor const&, bool (*)(void*), bool (*)(google_breakpad::MinidumpDescriptor const&, void*, bool), void*, bool, int)
0000000000000972 T google_breakpad::ExceptionHandler::~ExceptionHandler()
0000000000000972 T google_breakpad::ExceptionHandler::~ExceptionHandler()

So why does the linker complain that these are an undefined reference?

Community
  • 1
  • 1
Cory Klein
  • 51,188
  • 43
  • 183
  • 243

2 Answers2

8

The order of flags to the compiler matters. You need to put the -l flag after your source file names:

$ g++ -Ibreakpad/src -Llibs -o main main.cpp -lbreakpad_client

From the GCC documentation:

It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
4

The order of the link line matters! Libraries are only searched once when they show up on in the argument list. If there are no unresolved symbols at this point, nothing else will happen with them. Change you command to

g++ -Ibreakpad/src  -Llibs -o main main.cpp -lbreakpad_client
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380