--thinlto-index= is designed to replace --thinlto-index-only= for distributed
ThinLTO. Example:
Index files and backend compile files are in the same directory:
echo 'int g() { return 0; }' > a.c echo 'int f(); int main() { return f(); }' > b.c echo 'int g(); int f() { return g(); }' > c.c echo '' > d.c mkdir -p thin obj clang -c -flto=thin -O2 b.c -o thin/b.o -fthin-link-bitcode=thin/b.min.o clang -c -flto=thin -O2 c.c -o thin/c.o -fthin-link-bitcode=thin/c.min.o clang -c -flto=thin -O2 d.c -o thin/d.o -fthin-link-bitcode=thin/d.min.o clang -c -O2 a.c -o thin/a.o clang -flto=thin -fuse-ld=lld -Wl,--thinlto-index=obj/exe.map,--thinlto-emit-imports-files,--thinlto-prefix-replace='thin;obj',--thinlto-object-suffix-replace='.min.o;.o' \ a.o thin/b.min.o -Wl,--start-lib thin/c.min.o thin/d.min.o -Wl,--end-lib clang -c -O2 -fthinlto-index=obj/b.o.thinlto.bc thin/b.o -o obj/b.o clang -c -O2 -fthinlto-index=obj/c.o.thinlto.bc thin/c.o -o obj/c.o clang -c -O2 -fthinlto-index=obj/d.o.thinlto.bc thin/d.o -o obj/d.o clang -fuse-ld=lld -Wl,--remap-inputs-file=obj/exe.map a.o thin/b.min.o -Wl,--start-lib thin/c.min.o thin/d.min.o -Wl,--end-lib -o obj/exe
Index files and backend compile files are in different directories:
echo 'int g() { return 0; }' > a.c echo 'int f(); int main() { return f(); }' > b.c echo 'int g(); int f() { return g(); }' > c.c echo '' > d.c mkdir -p thin index obj clang -c -flto=thin -O2 b.c -o thin/b.o -fthin-link-bitcode=thin/b.min.o clang -c -flto=thin -O2 c.c -o thin/c.o -fthin-link-bitcode=thin/c.min.o clang -c -flto=thin -O2 d.c -o thin/d.o -fthin-link-bitcode=thin/d.min.o clang -c -O2 a.c -o a.o clang -flto=thin -fuse-ld=lld -Wl,--thinlto-index=obj/exe.map,--thinlto-emit-imports-files,--thinlto-prefix-replace='thin;index;obj',--thinlto-object-suffix-replace='.min.o;.o' \ a.o thin/b.min.o -Wl,--start-lib thin/c.min.o thin/d.min.o -Wl,--end-lib clang -c -O2 -fthinlto-index=index/b.o.thinlto.bc thin/b.o -o obj/b.o clang -c -O2 -fthinlto-index=index/c.o.thinlto.bc thin/c.o -o obj/c.o clang -c -O2 -fthinlto-index=index/d.o.thinlto.bc thin/c.o -o obj/d.o clang -fuse-ld=lld -Wl,--remap-inputs-file=obj/exe.map a.o thin/b.min.o -Wl,--start-lib thin/c.min.o thin/d.min.o -Wl,--end-lib -o obj/exe
The ThinLTO indexing and the final link have very similar command lines.
Actually we just need to replace -Wl,--thinlto-index= with -Wl,--remap-inputs-file=.
obj/exe.map redirects input minimized bitcode files to backend compilation outputs.
Here is an example of the old way (--thinlto-index-only=).
clang -flto=thin -fuse-ld=lld -Wl,--thinlto-index-only=obj/exe.params,--thinlto-prefix-replace='thin;obj',--thinlto-object-suffix-replace='.min.o;.o' \ a.o thin/b.min.o -Wl,--start-lib thin/c.min.o thin/d.min.o -Wl,--end-lib ... clang -fuse-ld=lld @obj/exe.params a.o -o obj/exe
--thinlto-index-only= specifies a response file containing all the backend
compilation produced native object files. The final link command line drops all
bitcode files (the build system recognize these files) and inserts @obj/exe.params
at the beginning. This reordering may cause different symbol resolution results
for ThinLTO indexing and the final link, which may lead to
- a different --start-lib native object file is picked
- spurious "undefined symbol": say, the different native object file may call a function defined in a bitcode file. The backend compilation for the bitcode file may not export the definition since it doesn't know it is referenced by this native object file.
Rejected alternative: let the response file include native object files.
This has complication:
- lld has to serialize all input files (shared objects, archives, linker scripts, etc) as well as --whole-archive/--as-needed states
- the build system has to recognize input files (including linker script) and remove them
- -nostdlib is required
Link: https://discourse.llvm.org/t/distributed-thinlto-final-linking-order/63804