| # The LLVM gold plugin | |
| ## Introduction | |
| Building with link time optimization requires cooperation from | |
| the system linker. LTO support on Linux systems is available via the | |
| [gold linker] which supports LTO via plugins. This is the same mechanism | |
| used by the [GCC LTO] project. | |
| The LLVM gold plugin implements the gold plugin interface on top of | |
| {ref}`libLTO`. The same plugin can also be used by other tools such as | |
| `ar` and `nm`. Note that ld.bfd from binutils version 2.21.51.0.2 | |
| and above also supports LTO via plugins. However, usage of the LLVM | |
| gold plugin with ld.bfd is not tested and therefore not officially | |
| supported or recommended. | |
| As of LLVM 15, the gold plugin will ignore bitcode from the `.llvmbc` | |
| section inside of ELF object files. However, LTO with bitcode files | |
| is still supported. | |
| (lto-how-to-build)= | |
| ## How to build it | |
| You need to have gold with plugin support and build the LLVMgold plugin. | |
| The gold linker is installed as ld.gold. To see whether gold is the default | |
| on your system, run `/usr/bin/ld -v`. It will report "GNU | |
| gold" or else "GNU ld" if not. If gold is already installed at | |
| `/usr/bin/ld.gold`, one option is to simply make that the default by | |
| backing up your existing `/usr/bin/ld` and creating a symbolic link | |
| with `ln -s /usr/bin/ld.gold /usr/bin/ld`. Alternatively, you can build | |
| with clang's `-fuse-ld=gold` or add `-fuse-ld=gold` to LDFLAGS, which will | |
| cause the clang driver to invoke `/usr/bin/ld.gold` directly. | |
| If you have gold installed, check for plugin support by running | |
| `/usr/bin/ld.gold -plugin`. If it complains "missing argument" then | |
| you have plugin support. If not, and you get an error such as "unknown option", | |
| then you will either need to build gold or install a version with plugin | |
| support. | |
| - Download, configure and build gold with plugin support: | |
| ```console | |
| $ git clone --depth 1 git://sourceware.org/git/binutils-gdb.git binutils | |
| $ mkdir build | |
| $ cd build | |
| $ ../binutils/configure --enable-gold --enable-plugins --disable-werror | |
| $ make all-gold | |
| ``` | |
| That should leave you with `build/gold/ld-new` which supports | |
| the `-plugin` option. Running `make` will additionally build | |
| `build/binutils/ar` and `nm-new` binaries supporting plugins. | |
| Once you're ready to switch to using gold, backup your existing | |
| `/usr/bin/ld` then replace it with `ld-new`. Alternatively, install | |
| in `/usr/bin/ld.gold` and use `-fuse-ld=gold` as described earlier. | |
| Optionally, add `--enable-gold=default` to the above configure invocation | |
| to automatically install the newly built gold as the default linker with | |
| `make install`. | |
| - Build the LLVMgold plugin. Run CMake with | |
| `-DLLVM_BINUTILS_INCDIR=/path/to/binutils/include`. The correct include | |
| path will contain the file `plugin-api.h`. | |
| ## Usage | |
| You should produce bitcode files from `clang` with the option | |
| `-flto`. This flag will also cause `clang` to look for the gold plugin in | |
| the `lib` directory under its prefix and pass the `-plugin` option to | |
| `ld`. It will not look for an alternate linker without `-fuse-ld=gold`, | |
| which is why you otherwise need gold to be the installed system linker in | |
| your path. | |
| `ar` and `nm` also accept the `-plugin` option and it's possible to | |
| install `LLVMgold.so` to `/usr/lib/bfd-plugins` for a seamless setup. | |
| If you built your own gold, be sure to install the `ar` and `nm-new` you | |
| built to `/usr/bin`. | |
| ### Example of link time optimization | |
| The following example shows a worked example of the gold plugin mixing LLVM | |
| bitcode and native code. | |
| ```c | |
| --- a.c --- | |
| #include <stdio.h> | |
| extern void foo1(void); | |
| extern void foo4(void); | |
| void foo2(void) { | |
| printf("Foo2\n"); | |
| } | |
| void foo3(void) { | |
| foo4(); | |
| } | |
| int main(void) { | |
| foo1(); | |
| } | |
| --- b.c --- | |
| #include <stdio.h> | |
| extern void foo2(void); | |
| void foo1(void) { | |
| foo2(); | |
| } | |
| void foo4(void) { | |
| printf("Foo4"); | |
| } | |
| ``` | |
| ```console | |
| --- command lines --- | |
| $ clang -flto a.c -c -o a.o # <-- a.o is LLVM bitcode file | |
| $ ar q a.a a.o # <-- a.a is an archive with LLVM bitcode | |
| $ clang b.c -c -o b.o # <-- b.o is native object file | |
| $ clang -flto a.a b.o -o main # <-- link with LLVMgold plugin | |
| ``` | |
| Gold informs the plugin that foo3 is never referenced outside the IR, | |
| leading LLVM to delete that function. However, unlike in the | |
| {ref}`libLTO example <libLTO-example>` gold does not currently eliminate foo4. | |
| ## Quickstart for using LTO with autotooled projects | |
| Once your system `ld`, `ar`, and `nm` all support LLVM bitcode, | |
| everything is in place for an easy-to-use LTO build of autotooled projects: | |
| - Follow the instructions | |
| {ref}`on how to build LLVMgold.so <lto-how-to-build>`. | |
| - Install the newly built binutils to `$PREFIX` | |
| - Copy `Release/lib/LLVMgold.so` to `$PREFIX/lib/bfd-plugins/` | |
| - Set environment variables (`$PREFIX` is where you installed clang and | |
| binutils): | |
| ```bash | |
| export CC="$PREFIX/bin/clang -flto" | |
| export CXX="$PREFIX/bin/clang++ -flto" | |
| export AR="$PREFIX/bin/ar" | |
| export NM="$PREFIX/bin/nm" | |
| export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a | |
| ``` | |
| - Or you can just set your path: | |
| ```bash | |
| export PATH="$PREFIX/bin:$PATH" | |
| export CC="clang -flto" | |
| export CXX="clang++ -flto" | |
| export RANLIB=/bin/true | |
| ``` | |
| - Configure and build the project as usual: | |
| ```console | |
| % ./configure && make && make check | |
| ``` | |
| The environment variable settings may work for non-autotooled projects too, | |
| but you may need to set the `LD` environment variable as well. | |
| ## Licensing | |
| Gold is licensed under the GPLv3. LLVMgold uses the interface file | |
| `plugin-api.h` from gold which means that the resulting `LLVMgold.so` | |
| binary is also GPLv3. This can still be used to link non-GPLv3 programs | |
| just as much as gold could without the plugin. | |
| [gcc lto]: http://gcc.gnu.org/wiki/LinkTimeOptimization | |
| [gold linker]: http://sourceware.org/binutils | |
| [gold plugin interface]: http://gcc.gnu.org/wiki/whopr/driver | |