[Interest] Link failure with undefined references, on Ubuntu but not macOS
Thiago Macieira
thiago.macieira at intel.com
Thu Apr 30 05:43:41 CEST 2020
On Wednesday, 29 April 2020 18:57:24 PDT Ben Haller via Interest wrote:
> Aha! And I figured out that the order in which I declare the dependencies
> in my .pro file determines the order in which those dependencies appear in
> the link command. I fixed that, and now it builds.
>
> I guess this was not biting me before because I used to link these
> internal libraries dynamically instead; perhaps the link order is not
> important with dynamic linking?
Correct, searching for symbols in dynamic libraries is different because the
linker searches all of them. It doesn't need to solve from one to the other,
since that was resolved when each library was itself linked.
Hint: make sure you're using -Wl,--no-undefined. In your .pro file, for each
library and plugin:
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
> So when I recently changed to static
> linking for these internal libraries, the link order suddenly mattered, and
> my build broke. And I guess perhaps the linker on macOS doesn’t have this
> requirement, and so the build continued to work there?
I don't know how the Apple linker works.
The traditional linker works sequentially to avoid a very long link time.
After it's created the list of all outstanding undefined symbols from your
binary's .o files, it iterates over the library list. For each one, it checks
if the library solves some symbols and then each individual .o in the static
library to the build. After that, it promptly forgets about the library and
moves on to the next one. That's why libB.a can't depend on libA.a: the linker
won't search it again.
If it did, you could write:
-lA -lB -lA
Then the linker will search libA.a again for other .o that have symbols that
libB requires.
Note that this may add .o that need more symbols from libB.a that haven't been
added to the build yet. That means your linker line would need to be:
-lA -lB -lA -lB
This isn't infinite because there's a finite number of .o files in each
library. The GNU linker has a shorthand for this but I won't mention it here.
Read the docs if needed.
Conclusion: break the cycle. The library dependency graph should be one way
(directed acyclic graph). That's why I recommended that --no-undefined for
dynamic linking: it'll prevent you from making the cycles.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel System Software Products
More information about the Interest
mailing list