diff options
| author | Michael Woerister <michaelwoerister@posteo> | 2019-02-12 15:07:04 +0100 |
|---|---|---|
| committer | Michael Woerister <michaelwoerister@posteo> | 2019-02-12 15:42:04 +0100 |
| commit | 3733b3267dba89b442757c5ff5a791de5e36531b (patch) | |
| tree | 92cfeeb0bb40629709150af5cc3e01609c94fc0c | |
| parent | 04f425d2c31ea0ef022793a3fdcb8af84d471b86 (diff) | |
| download | rust-3733b3267dba89b442757c5ff5a791de5e36531b.tar.gz rust-3733b3267dba89b442757c5ff5a791de5e36531b.zip | |
Add documentation about -Clinker-plugin-lto to rustc book.
| -rw-r--r-- | src/doc/rustc/src/SUMMARY.md | 3 | ||||
| -rw-r--r-- | src/doc/rustc/src/linker-plugin-lto.md | 108 |
2 files changed, 110 insertions, 1 deletions
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index e4c0939fd46..34708d1847f 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -13,4 +13,5 @@ - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) - [Custom Targets](targets/custom.md) -- [Contributing to `rustc`](contributing.md) \ No newline at end of file +- [Linker-plugin based LTO](linker-plugin-lto.md) +- [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md new file mode 100644 index 00000000000..73a2efcb33a --- /dev/null +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -0,0 +1,108 @@ +# Linker-plugin-LTO + +The `-C linker-plugin-lto` flag allows for deferring the LTO optimization +to the actual linking step, which in turn allows for performing +interprocedural optimizations across programming language boundaries if +all the object files being linked were created by LLVM based toolchains. +The prime example here would be linking Rust code together with +Clang-compiled C/C++ code. + +## Usage + +There are two main cases how linker plugin based LTO can be used: + + - compiling a Rust `staticlib` that is used as a C ABI dependency + - compiling a Rust binary where `rustc` invokes the linker + +In both cases the Rust code has to be compiled with `-C linker-plugin-lto` and +the C/C++ code with `-flto` or `-flto=thin` so that object files are emitted +as LLVM bitcode. + +### Rust `staticlib` as dependency in C/C++ program + +In this case the Rust compiler just has to make sure that the object files in +the `staticlib` are in the right format. For linking, a linker with the +LLVM plugin must be used (e.g. LLD). + +Using `rustc` directly: + +```bash +# Compile the Rust staticlib +rustc --crate-type=staticlib -Clinker-plugin-lto -Copt-level=2 ./lib.rs +# Compile the C code with `-flto=thin` +clang -c -O2 -flto=thin -o main.o ./main.c +# Link everything, making sure that we use an appropriate linker +clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o +``` + +Using `cargo`: + +```bash +# Compile the Rust staticlib +RUSTFLAGS="-Clinker-plugin-lto" cargo build --release +# Compile the C code with `-flto=thin` +clang -c -O2 -flto=thin -o main.o ./main.c +# Link everything, making sure that we use an appropriate linker +clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o +``` + +### C/C++ code as a dependency in Rust + +In this case the linker will be invoked by `rustc`. We again have to make sure +that an appropriate linker is used. + +Using `rustc` directly: + +```bash +# Compile C code with `-flto` +clang ./clib.c -flto=thin -c -o ./clib.o -O2 +# Create a static library from the C code +ar crus ./libxyz.a ./clib.o + +# Invoke `rustc` with the additional arguments +rustc -Clinker-plugin-lto -L. -Copt-level=2 -Clinker=clang -Clink-arg=-fuse-ld=lld ./main.rs +``` + +Using `cargo` directly: + +```bash +# Compile C code with `-flto` +clang ./clib.c -flto=thin -c -o ./clib.o -O2 +# Create a static library from the C code +ar crus ./libxyz.a ./clib.o + +# Set the linking arguments via RUSTFLAGS +RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release +``` + +### Explicitly specifying the linker plugin to be used by `rustc` + +If one wants to use a linker other than LLD, the LLVM linker plugin has to be +specified explicitly. Otherwise the linker cannot read the object files. The +path to the plugin is passed as an argument to the `-Clinker-plugin-lto` +option: + +```bash +rustc -Clinker-plugin-lto="/path/to/LLVMgold.so" -L. -Copt-level=2 ./main.rs +``` + + +## Toolchain Compatibility + +In order for this kind of LTO to work, the LLVM linker plugin must be able to +handle the LLVM bitcode produced by both `rustc` and `clang`. + +Best results are achieved by using a `rustc` and `clang` that are based on the +exact same version of LLVM. One can use `rustc -vV` in order to view the LLVM +used by a given `rustc` version. Note that the version number given +here is only an approximation as Rust sometimes uses unstable revisions of +LLVM. However, the approximation is usually reliable. + +The following table shows known good combinations of toolchain versions. + +| | Clang 7 | Clang 8 | +|-----------|-----------|-----------| +| Rust 1.34 | ✗ | ✓ | +| Rust 1.35 | ✗ | ✓(?) | + +Note that the compatibility policy for this feature might change in the future. |
