4

I've got a strange problem building an executable coded in C++ that uses a C++ library which itself relies on a C library. I compiled the C modules making up the C library using gcc and all other source modules using g++. Both, the C and C++ library are static libs.

When I include a header file from the C library in C++ source code, I alwas wrap it in extern "C":

extern "C"
{
  #include <c-library-header.h> 
}

The strange thing now is that get "undefined reference" errors when linking, but these change depending on the order I list the libraries:

  • If I list the C library first, all the symbols in that library referenced by C++ modules show as "undefined".
  • If I list the C++ library first, all the symbols in that library referenced by C++ modules show as "undefined".

I would have thought to order in which static libs appear on the g++ command-line would be totally irrelevant. Anybody any clues?

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
pete
  • 705
  • 6
  • 8

2 Answers2

7

The order is important.

If libxxx depends on libyyy, then libxxx should be specified first, i.e. -lxxx -lyyy

In the unfortunate case, when both depend on each other, then one library may be mentioned twice

-lxxx -lyyy -lxxx

See:

Community
  • 1
  • 1
Arun
  • 19,750
  • 10
  • 51
  • 60
  • +1 for a great answer. Blows me away though. For once Microsoft did a great job as its linker doesn't require me to worry about such silly details. – pete Apr 03 '14 at 03:26
2

Instead of listing the libraries multiple times (this may be cumbersome if there are many interdependent libraries) one can rely on GNU ld to do the right thing and search the library list back and forth until all the symbols are resolved. This is achieved using start_group/end_group command line switches:

g++ <...flags...> -Wl,--start-group -lxxx -lyyy -Wl,--end-group <...other flags...>

or by directly supplying the archives if they happen to be named in "non-conforming" way:

g++ <...flags...> -Wl,--start-group xxx.a yyy.a -Wl,--end-group <...other flags...>

The price to pay for such a neat feature is reduced linking speed, which, in many case, is not critical.

oakad
  • 6,945
  • 1
  • 22
  • 31
  • Just chipping in to say that the `-Wl,` bit is important, I first tried to use `--start-group` after finding it in the gcc man pages, but if you forget the `-Wl,` it just silently skips over it, no error message. Couldn't figure out why it wasn't working as documented. – M.M Apr 03 '14 at 04:33
  • Does anyone know why GNU ld doesn't default to multiple passes? – M.M Apr 03 '14 at 04:34
  • Because it's rather slow on big links and rarely needed on small ones. – oakad Apr 03 '14 at 04:39
  • You'd only need to do it if there were still unresolved symbols after the first pass though, so it would not slow down anything that would have worked without it. – M.M Apr 03 '14 at 04:44
  • Well, you're not the first to wonder about this exact issue: http://stackoverflow.com/questions/16838719/why-does-the-gnu-linker-not-default-to-grouped-libs :) – oakad Apr 03 '14 at 04:47
  • You are the first one to answer, apparently :) – M.M Apr 03 '14 at 04:49