MSVC: support LTCG native libraries in rlibs

400f4a2
Opened by Alex Crichton at 2022-01-13 16:53:18

MSVC supports the option to compile native libraries with link-time code generation enabled via the /GL switch to the compiler. This cause the compiler to change the format of the *.obj file emitted to no longer be a COFF object file. When MSVC's lib.exe tool is used to assemble these object files into a .lib, it will correctly detect that these are LTCG-enabled files, adding an appropriate symbol table to the archive being generated. This means that when the linker comes along to link the library, the internal symbol table of the archive points at the LTCG files, allowing the linker to find where symbols are and also produce object files on-the-fly.

With rustc, however, the symbol tables for LTCG files can be lost. Whenever a native library is included statically into an rlib, the objects are extracted by the compiler and then re-inserted into an rlib. This operation loses the entries in the symbol table of the rlib (LLVM doesn't understand the format of the file being inserted), causing the linker to later on ignore all LTCG enabled files.

Long story short, if a LTCG enabled C library is linked statically into an rlib, the linker will not resolve any of the symbols in the C library. This means that all native code linked statically to rlibs cannot have LTCG enabled, and this is occasionally somewhat difficult to retrofit on existing build systems.

Fixing this will involve improving the merging process of two archives, probably just blindly carrying over the symbol table from one archive to another (at least on MSVC). I'm not sure what the best route to do this is, but our options are:

  • Add support to llvm-ar.exe to do this.
  • Split apart llvm-ar.cpp into a library-like interface, and then rewrite the "driver" in rustc itself
  • Port llvm-ar.exe to Rust, and do everything in Rust

The latter two options have the great benefit of lifting the compiler's dependence on an ar tool, which would be nice!

  1. Now I'm wondering if a library built by cl.exe has PDB data, will llvm-ar.exe properly carry forward that debug info?

    Peter Atashian at 2015-07-07 21:27:09

  2. As a workaround, instead of using kind=static, consider using the recently implemented kind=static-nobundle. This way the library is passed directly to the linker (instead of being mangled by rustc) bypassing this issue entirely.

    Peter Atashian at 2017-03-18 15:50:07

  3. Triage: not aware of any changes here.

    Steve Klabnik at 2018-12-20 19:12:22