How to deal with recursive dependencies between st

2019-03-09 22:15发布

问题:

I'm porting an existing system from Windows to Linux. The build is structured with multiple static libraries. I ran into a linking error where a symbol (defined in libA) could not be found in an object from libB. The linker line looked like

g++ test_obj.o -lA -lB -o test

The problem of course being that by the time the linker finds it needs the symbol from libA, it has already passed it by, and does not rescan, so it simply errors out even though the symbol is there for the taking.

My initial idea was of course to simply swap the link (to -lB -lA) so that libA is scanned afterwards, and any symbols missing from libB that are in libA are picked up. But then I find there is actually a recursive dependency between libA and libB! I'm assuming the Visual C++ linker handles this in some way (does it rescan by default?).

Ways of dealing with this I've considered:

  • Use shared objects. Unfortunately this is undesirable from the perspective of requiring PIC compliation (this is performance sensitive code and losing %ebx to hold the GOT would really hurt), and shared objects aren't needed.

  • Build one mega ar of all of the objects, avoiding the problem.

  • Restructure the code to avoid the recursive dependency (which is obviously the Right Thing to do, but I'm trying to do this port with minimal changes).

Do you have other ideas to deal with this? Is there some way I can convince the binutils linker to perform rescans of libraries it has already looked at when it is missing a symbol?

回答1:

Just do this:

g++ test_obj.o -lA -lB -lA       -o test

When the linker reads the first libA on the command line, it'll discard the object/symbols in it that noone has depended on yet, e.g. all the symbols libB needs but not test_obj.o. So you just make it read libA again, and it'll pick up the those symbols as well.



回答2:

While @nos provides a simple solution, it doesn't scale when there are multiple libraries involved and the mutual dependencies are more complex. To sort out the problems ld provides --start-group archives --end-group.

In your particular case:

g++ test_obj.o --start-group -lA -lB --end-group -o test