]> git.lizzy.rs Git - rust.git/blob - src/doc/rustc/src/linker-plugin-lto.md
Special sync of 'e89801553ddbaccdeb2eac4db08900edb51ac7ff'
[rust.git] / src / doc / rustc / src / linker-plugin-lto.md
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 <!-- NOTE: to update the below table, you can use this shell script:
93
94 ```sh
95 rustup toolchain install --profile minimal nightly
96 MINOR_VERSION=$(rustc +nightly --version | cut -d . -f 2)
97 LOWER_BOUND=44
98
99 llvm_version() {
100     toolchain="$1"
101     printf "Rust $toolchain    |    Clang "
102     rustc +"$toolchain" -Vv | grep LLVM | cut -d ':' -f 2 | tr -d ' '
103 }
104
105 for version in `seq $LOWER_BOUND $((MINOR_VERSION - 2))`; do
106     toolchain=1.$version.0
107     rustup toolchain install --no-self-update --profile  minimal $toolchain >/dev/null 2>&1
108     llvm_version $toolchain
109 done
110 ```
111
112 -->
113
114 In order for this kind of LTO to work, the LLVM linker plugin must be able to
115 handle the LLVM bitcode produced by both `rustc` and `clang`.
116
117 Best results are achieved by using a `rustc` and `clang` that are based on the
118 exact same version of LLVM. One can use `rustc -vV` in order to view the LLVM
119 used by a given `rustc` version. Note that the version number given
120 here is only an approximation as Rust sometimes uses unstable revisions of
121 LLVM. However, the approximation is usually reliable.
122
123 The following table shows known good combinations of toolchain versions.
124
125 | Rust Version | Clang Version |
126 |--------------|---------------|
127 | Rust 1.34    |    Clang 8    |
128 | Rust 1.35    |    Clang 8    |
129 | Rust 1.36    |    Clang 8    |
130 | Rust 1.37    |    Clang 8    |
131 | Rust 1.38    |    Clang 9    |
132 | Rust 1.39    |    Clang 9    |
133 | Rust 1.40    |    Clang 9    |
134 | Rust 1.41    |    Clang 9    |
135 | Rust 1.42    |    Clang 9    |
136 | Rust 1.43    |    Clang 9    |
137 | Rust 1.44    |    Clang 9    |
138 | Rust 1.45    |    Clang 10   |
139 | Rust 1.46    |    Clang 10   |
140
141 Note that the compatibility policy for this feature might change in the future.