I have some newbie questions related to LTO in GCC as IMHO it's kinda hard to find answers to my questions across the internet. Please consider the real use case from the image below (not very professional but it should be meaningful enough for the sake of this thread).
There are four distinct libraries in the example. For the purpose of this example let's assume every single module is compiled with appropriate lto flag (the same applies for linkers).
inner.a- a static library which consists of two modulesouter1.a- a static library which consists of a one module along with theinner.alibrary embedded into itouter2.a- a static library which consists of two modules similar to theinner.ashared.so- a shared library which comprisesouter1.aandouter2.arespectively- some executable which is linked against
shared.so
Where may the LTO mechanism performs some optimisations and where not? From my understanding:
inner.ashould got optimised - it's a static library- the same for
outer1.a- the linker has full view of themodule3.oand theinner.alibrary which is to be embedded outer2.asimilarly as the above libraries
What about shared.so? It's a shared object but consists of the two static libs and still full view should be preserved in order to optimise during outer1.a and outer2.a linkage.
The executable marked as yellow box is linked dynamically against the shared.so so the LTO mechanism can really do nothing and the "lucky chain" is broken there?
Also I'd really appreciate any materials on this particular subject.

You appear to have an incorrect mental model of linking.
inner.ais just a container of.ofiles. At the time of static linking individual.os are copied from it (similar to taking a book off the shelf), and linked into an executable or a shared library. It is at that stage that LTO may happen.This is wrong again.
shared.so(possibly) contains code and data which came from (were copied from) the various.os, but it does not contain these objects, and it certainly doesn't contain any archive libraries.So let's talk about LTO. Suppose that
module1.ccontains this code:and
module5.chas this:When
module1.cis compiled, the compiler can not transform that code intobecause it has no idea what
foo()returns.But when the LTO pass runs at the time of linking
shared.so, that pass does know thatfoo()returns a constant value, and can therefore optimizebar()to also return a constant.Correct.
P.S. In addition, an archive library can't really contain another archive library as your picture shows. You can put
inner.ainto anouter.a, but if you do, the linker will simply ignoreinner.aand treatouter.aas if it only containedmodule3.o.