Skip to content

Commit 3733b32

Browse files
Add documentation about -Clinker-plugin-lto to rustc book.
1 parent 04f425d commit 3733b32

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

src/doc/rustc/src/SUMMARY.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
- [Targets](targets/index.md)
1414
- [Built-in Targets](targets/built-in.md)
1515
- [Custom Targets](targets/custom.md)
16-
- [Contributing to `rustc`](contributing.md)
16+
- [Linker-plugin based LTO](linker-plugin-lto.md)
17+
- [Contributing to `rustc`](contributing.md)
+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Linker-plugin-LTO
2+
3+
The `-C linker-plugin-lto` flag allows for deferring the LTO optimization
4+
to the actual linking step, which in turn allows for performing
5+
interprocedural optimizations across programming language boundaries if
6+
all the object files being linked were created by LLVM based toolchains.
7+
The prime example here would be linking Rust code together with
8+
Clang-compiled C/C++ code.
9+
10+
## Usage
11+
12+
There are two main cases how linker plugin based LTO can be used:
13+
14+
- compiling a Rust `staticlib` that is used as a C ABI dependency
15+
- compiling a Rust binary where `rustc` invokes the linker
16+
17+
In both cases the Rust code has to be compiled with `-C linker-plugin-lto` and
18+
the C/C++ code with `-flto` or `-flto=thin` so that object files are emitted
19+
as LLVM bitcode.
20+
21+
### Rust `staticlib` as dependency in C/C++ program
22+
23+
In this case the Rust compiler just has to make sure that the object files in
24+
the `staticlib` are in the right format. For linking, a linker with the
25+
LLVM plugin must be used (e.g. LLD).
26+
27+
Using `rustc` directly:
28+
29+
```bash
30+
# Compile the Rust staticlib
31+
rustc --crate-type=staticlib -Clinker-plugin-lto -Copt-level=2 ./lib.rs
32+
# Compile the C code with `-flto=thin`
33+
clang -c -O2 -flto=thin -o main.o ./main.c
34+
# Link everything, making sure that we use an appropriate linker
35+
clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o
36+
```
37+
38+
Using `cargo`:
39+
40+
```bash
41+
# Compile the Rust staticlib
42+
RUSTFLAGS="-Clinker-plugin-lto" cargo build --release
43+
# Compile the C code with `-flto=thin`
44+
clang -c -O2 -flto=thin -o main.o ./main.c
45+
# Link everything, making sure that we use an appropriate linker
46+
clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o
47+
```
48+
49+
### C/C++ code as a dependency in Rust
50+
51+
In this case the linker will be invoked by `rustc`. We again have to make sure
52+
that an appropriate linker is used.
53+
54+
Using `rustc` directly:
55+
56+
```bash
57+
# Compile C code with `-flto`
58+
clang ./clib.c -flto=thin -c -o ./clib.o -O2
59+
# Create a static library from the C code
60+
ar crus ./libxyz.a ./clib.o
61+
62+
# Invoke `rustc` with the additional arguments
63+
rustc -Clinker-plugin-lto -L. -Copt-level=2 -Clinker=clang -Clink-arg=-fuse-ld=lld ./main.rs
64+
```
65+
66+
Using `cargo` directly:
67+
68+
```bash
69+
# Compile C code with `-flto`
70+
clang ./clib.c -flto=thin -c -o ./clib.o -O2
71+
# Create a static library from the C code
72+
ar crus ./libxyz.a ./clib.o
73+
74+
# Set the linking arguments via RUSTFLAGS
75+
RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release
76+
```
77+
78+
### Explicitly specifying the linker plugin to be used by `rustc`
79+
80+
If one wants to use a linker other than LLD, the LLVM linker plugin has to be
81+
specified explicitly. Otherwise the linker cannot read the object files. The
82+
path to the plugin is passed as an argument to the `-Clinker-plugin-lto`
83+
option:
84+
85+
```bash
86+
rustc -Clinker-plugin-lto="/path/to/LLVMgold.so" -L. -Copt-level=2 ./main.rs
87+
```
88+
89+
90+
## Toolchain Compatibility
91+
92+
In order for this kind of LTO to work, the LLVM linker plugin must be able to
93+
handle the LLVM bitcode produced by both `rustc` and `clang`.
94+
95+
Best results are achieved by using a `rustc` and `clang` that are based on the
96+
exact same version of LLVM. One can use `rustc -vV` in order to view the LLVM
97+
used by a given `rustc` version. Note that the version number given
98+
here is only an approximation as Rust sometimes uses unstable revisions of
99+
LLVM. However, the approximation is usually reliable.
100+
101+
The following table shows known good combinations of toolchain versions.
102+
103+
| | Clang 7 | Clang 8 |
104+
|-----------|-----------|-----------|
105+
| Rust 1.34 |||
106+
| Rust 1.35 || ✓(?) |
107+
108+
Note that the compatibility policy for this feature might change in the future.

0 commit comments

Comments
 (0)