]> git.proxmox.com Git - rustc.git/blame - src/doc/rustc/src/linker-plugin-lto.md
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / rustc / src / linker-plugin-lto.md
CommitLineData
923072b8 1# Linker-plugin-based LTO
9fa01778
XL
2
3The `-C linker-plugin-lto` flag allows for deferring the LTO optimization
4to the actual linking step, which in turn allows for performing
5interprocedural optimizations across programming language boundaries if
6all the object files being linked were created by LLVM based toolchains.
7The prime example here would be linking Rust code together with
8Clang-compiled C/C++ code.
9
10## Usage
11
12There 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
17In both cases the Rust code has to be compiled with `-C linker-plugin-lto` and
18the C/C++ code with `-flto` or `-flto=thin` so that object files are emitted
19as LLVM bitcode.
20
21### Rust `staticlib` as dependency in C/C++ program
22
23In this case the Rust compiler just has to make sure that the object files in
24the `staticlib` are in the right format. For linking, a linker with the
25LLVM plugin must be used (e.g. LLD).
26
27Using `rustc` directly:
28
29```bash
30# Compile the Rust staticlib
31rustc --crate-type=staticlib -Clinker-plugin-lto -Copt-level=2 ./lib.rs
32# Compile the C code with `-flto=thin`
33clang -c -O2 -flto=thin -o main.o ./main.c
34# Link everything, making sure that we use an appropriate linker
35clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o
36```
37
38Using `cargo`:
39
40```bash
41# Compile the Rust staticlib
42RUSTFLAGS="-Clinker-plugin-lto" cargo build --release
43# Compile the C code with `-flto=thin`
44clang -c -O2 -flto=thin -o main.o ./main.c
45# Link everything, making sure that we use an appropriate linker
46clang -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
51In this case the linker will be invoked by `rustc`. We again have to make sure
52that an appropriate linker is used.
53
54Using `rustc` directly:
55
56```bash
57# Compile C code with `-flto`
58clang ./clib.c -flto=thin -c -o ./clib.o -O2
59# Create a static library from the C code
60ar crus ./libxyz.a ./clib.o
61
62# Invoke `rustc` with the additional arguments
63rustc -Clinker-plugin-lto -L. -Copt-level=2 -Clinker=clang -Clink-arg=-fuse-ld=lld ./main.rs
64```
65
66Using `cargo` directly:
67
68```bash
69# Compile C code with `-flto`
70clang ./clib.c -flto=thin -c -o ./clib.o -O2
71# Create a static library from the C code
72ar crus ./libxyz.a ./clib.o
73
74# Set the linking arguments via RUSTFLAGS
75RUSTFLAGS="-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
80If one wants to use a linker other than LLD, the LLVM linker plugin has to be
81specified explicitly. Otherwise the linker cannot read the object files. The
82path to the plugin is passed as an argument to the `-Clinker-plugin-lto`
83option:
84
85```bash
86rustc -Clinker-plugin-lto="/path/to/LLVMgold.so" -L. -Copt-level=2 ./main.rs
87```
88
5099ac24
FG
89### Usage with clang-cl and x86_64-pc-windows-msvc
90
91Cross language LTO can be used with the x86_64-pc-windows-msvc target, but this requires using the
92clang-cl compiler instead of the MSVC cl.exe included with Visual Studio Build Tools, and linking
93with lld-link. Both clang-cl and lld-link can be downloaded from [LLVM's download page](https://releases.llvm.org/download.html).
94Note that most crates in the ecosystem are likely to assume you are using cl.exe if using this target
95and that some things, like for example vcpkg, [don't work very well with clang-cl](https://github.com/microsoft/vcpkg/issues/2087).
96
97You will want to make sure your rust major LLVM version matches your installed LLVM tooling version,
98otherwise it is likely you will get linker errors:
99
100```bat
101rustc -V --verbose
102clang-cl --version
103```
104
105If you are compiling any proc-macros, you will get this error:
106
107```bash
108error: Linker plugin based LTO is not supported together with `-C prefer-dynamic` when
109targeting Windows-like targets
110```
111
112This is fixed if you explicitly set the target, for example
113`cargo build --target x86_64-pc-windows-msvc`
114Without an explicit --target the flags will be passed to all compiler invocations (including build
115scripts and proc macros), see [cargo docs on rustflags](https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags)
116
117If you have dependencies using the `cc` crate, you will need to set these
118environment variables:
119```bat
120set CC=clang-cl
121set CXX=clang-cl
122set CFLAGS=/clang:-flto=thin /clang:-fuse-ld=lld-link
123set CXXFLAGS=/clang:-flto=thin /clang:-fuse-ld=lld-link
124REM Needed because msvc's lib.exe crashes on LLVM LTO .obj files
125set AR=llvm-lib
126```
127
128If you are specifying lld-link as your linker by setting `linker = "lld-link.exe"` in your cargo config,
129you may run into issues with some crates that compile code with separate cargo invocations. You should be
130able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS
9fa01778
XL
131
132## Toolchain Compatibility
133
1b1a35ee
XL
134<!-- NOTE: to update the below table, you can use this shell script:
135
136```sh
137rustup toolchain install --profile minimal nightly
138MINOR_VERSION=$(rustc +nightly --version | cut -d . -f 2)
04454e1e 139LOWER_BOUND=61
1b1a35ee
XL
140
141llvm_version() {
142 toolchain="$1"
143 printf "Rust $toolchain | Clang "
144 rustc +"$toolchain" -Vv | grep LLVM | cut -d ':' -f 2 | tr -d ' '
145}
146
147for version in `seq $LOWER_BOUND $((MINOR_VERSION - 2))`; do
148 toolchain=1.$version.0
149 rustup toolchain install --no-self-update --profile minimal $toolchain >/dev/null 2>&1
150 llvm_version $toolchain
151done
152```
153
154-->
155
9fa01778
XL
156In order for this kind of LTO to work, the LLVM linker plugin must be able to
157handle the LLVM bitcode produced by both `rustc` and `clang`.
158
159Best results are achieved by using a `rustc` and `clang` that are based on the
160exact same version of LLVM. One can use `rustc -vV` in order to view the LLVM
161used by a given `rustc` version. Note that the version number given
162here is only an approximation as Rust sometimes uses unstable revisions of
163LLVM. However, the approximation is usually reliable.
164
165The following table shows known good combinations of toolchain versions.
166
1b1a35ee
XL
167| Rust Version | Clang Version |
168|--------------|---------------|
169| Rust 1.34 | Clang 8 |
170| Rust 1.35 | Clang 8 |
171| Rust 1.36 | Clang 8 |
172| Rust 1.37 | Clang 8 |
173| Rust 1.38 | Clang 9 |
174| Rust 1.39 | Clang 9 |
175| Rust 1.40 | Clang 9 |
176| Rust 1.41 | Clang 9 |
177| Rust 1.42 | Clang 9 |
178| Rust 1.43 | Clang 9 |
179| Rust 1.44 | Clang 9 |
180| Rust 1.45 | Clang 10 |
181| Rust 1.46 | Clang 10 |
04454e1e
FG
182| Rust 1.47 | Clang 11 |
183| Rust 1.48 | Clang 11 |
184| Rust 1.49 | Clang 11 |
185| Rust 1.50 | Clang 11 |
186| Rust 1.51 | Clang 11 |
187| Rust 1.52 | Clang 12 |
188| Rust 1.53 | Clang 12 |
189| Rust 1.54 | Clang 12 |
190| Rust 1.55 | Clang 12 |
191| Rust 1.56 | Clang 13 |
192| Rust 1.57 | Clang 13 |
193| Rust 1.58 | Clang 13 |
194| Rust 1.59 | Clang 13 |
195| Rust 1.60 | Clang 14 |
9fa01778
XL
196
197Note that the compatibility policy for this feature might change in the future.