intra vs inter module LTO

It is quite common for larger project to split the source tree into
multiple libraries, which are built statically and linked together at
the end. This practise also has advantages building tests, because only
the library for the classes under test has to be linked.

When it comes to LTO, I understand that it works when multiple .o files
are linked together, doing its magic hopefully optimizing the resulting
binary, be it a library or an executable. This is great for optimizing
the different parts of a larger project individually. I don't know if
there is an official term for that, but I'd call it intra-module LTO,
where module basically means a binary target, be it the only one or
just an intermediate.

I'd like to know if LTO also works in the second step, when multiple .a
libraries and potentially other .o files are linked together to the
final binary. So can LTO also work successfully between modules (being
inter-module).

And if it is possible, do I have to pay attention to some compiler
flags, linker options, etc., or does it work out-of-the-bos with -flto?

Kind regards

Hi,

It is quite common for larger project to split the source tree into
multiple libraries, which are built statically and linked together at
the end. This practise also has advantages building tests, because only
the library for the classes under test has to be linked.

When it comes to LTO, I understand that it works when multiple .o files
are linked together, doing its magic hopefully optimizing the resulting
binary, be it a library or an executable. This is great for optimizing
the different parts of a larger project individually. I don’t know if
there is an official term for that, but I’d call it intra-module LTO,

A “Module” is a single .o in LLVM (usually). So LTO is always about cross-module optimizations.

The closer to use to describe the scope of optimization is probably a DSO (Dynamic Shared Object): i.e. a shared library (.so) or the final binary.

where module basically means a binary target, be it the only one or
just an intermediate.

I’d like to know if LTO also works in the second step, when multiple .a
libraries and potentially other .o files are linked together to the
final binary. So can LTO also work successfully between modules (being
inter-module).

.a are really just an archive containing multiple .o, after the linker decide to pull some .o files out of a .a archive (there are some rule around this), there is no difference with .o directly passed on the command line as far as I know.

And if it is possible, do I have to pay attention to some compiler
flags, linker options, etc., or does it work out-of-the-bos with -flto?

So LTO work just as fine with .a, with one caveat: the tool used to create the .a has to be compatible with LLVM bitcode (i.e. use llvm-ar instead of ar to create the archive) otherwise the .a creation may fail or the link step may fail.

Best,