Description
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!