For dynamic dependencies, you can leverage the existing --thinlto-emit-imports-files
option. In the following example at the end of this reply, if --thinlto-emit-imports-files
is specified, ld.lld will create import files lto/[abc].o.imports
.
lto/a.o.imports
lists files from which compiling a.o
will import.
lto/c.o.imports
will be empty: the build system does not need to know whether a lazy LLVM bitcode file is extracted or not.
You can post-process *.imports
to get Makefile fragments. It’s certainly less convenient than having lld output Makefile fragments itself, but I don’t see a good justification for a redundant output interface.
I don’t understand the (regular archive to thin archive conversion) part as well.
Archives are unsupported because it’s unclear where to emit the generated files for an archive member and clang -fthinlto-index=
doesn’t support taking an archive member as input. See https://discourse.llvm.org/t/running-distributed-thinlto-without-thin-archives/52261.
Distributed ThinLTO example
Let’s say we want to compile a.c
, b.c
, and c.c
with LTO and link them with two ELF relocatable files elf0.o
and elf1.o
.
We link LLVM bitcode files b.o
and c.o
as lazy files, which have archive semantics (surrounded by --start-lib
and --end-lib
).
echo 'int bb(); int main() { return bb(); }' > a.c
echo 'int elf0(); int bb() { return elf0(); }' > b.c
echo 'int cc() { return 0; }' > c.c
echo 'int elf0() { return 0; }' > elf0.c && clang -c elf0.c
echo '' > elf1.c && clang -c elf1.c
clang -c -O2 -flto=thin a.c b.c c.c
clang -flto=thin -fuse-ld=lld -Wl,--thinlto-index-only=a.rsp,--thinlto-emit-imports-files -Wl,--thinlto-prefix-replace=';lto/' elf0.o a.o -Wl,--start-lib b.o c.o -Wl,--end-lib elf1.o
clang -c -O2 -fthinlto-index=lto/a.o.thinlto.bc a.o -o lto/a.o
clang -c -O2 -fthinlto-index=lto/b.o.thinlto.bc b.o -o lto/b.o
clang -c -O2 -fthinlto-index=lto/c.o.thinlto.bc c.o -o lto/c.o
clang -fuse-ld=lld @a.rsp elf0.o elf1.o # a.rsp contains lto/a.o and lto/b.o