]> git.proxmox.com Git - rustc.git/blob - src/doc/rustc-dev-guide/src/building/suggested.md
New upstream version 1.74.1+dfsg1
[rustc.git] / src / doc / rustc-dev-guide / src / building / suggested.md
1 # Suggested Workflows
2
3 The full bootstrapping process takes quite a while. Here are some suggestions
4 to make your life easier.
5
6 <!-- toc -->
7
8 ## Installing a pre-push hook
9
10 CI will automatically fail your build if it doesn't pass `tidy`, our
11 internal tool for ensuring code quality. If you'd like, you can install a
12 [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
13 that will automatically run `./x test tidy` on each push, to ensure
14 your code is up to par. If the hook fails then run `./x test tidy --bless`
15 and commit the changes. If you decide later that the pre-push behavior is
16 undesirable, you can delete the `pre-push` file in `.git/hooks`.
17
18 A prebuilt git hook lives at [`src/etc/pre-push.sh`](https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh) which can be copied into your `.git/hooks` folder as `pre-push` (without the `.sh` extension!).
19
20 You can also install the hook as a step of running `./x setup`!
21
22 ## Configuring `rust-analyzer` for `rustc`
23
24 ### Visual Studio Code
25
26 `rust-analyzer` can help you check and format your code whenever you save
27 a file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt`
28 commands, but you can override these commands to use more adapted versions
29 of these tools when hacking on `rustc`. For example, `x setup vscode` will prompt
30 you to create a `.vscode/settings.json` file which will configure Visual Studio code.
31 This will ask `rust-analyzer` to use `./x check` to check the sources, and the
32 stage 0 rustfmt to format them.
33 The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`].
34
35 If you have enough free disk space and you would like to be able to run `x` commands while
36 rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the
37 `overrideCommand` to avoid x locking.
38
39 If running `./x check` on save is inconvenient, in VS Code you can use a [Build
40 Task] instead:
41
42 ```JSON
43 // .vscode/tasks.json
44 {
45 "version": "2.0.0",
46 "tasks": [
47 {
48 "label": "./x check",
49 "command": "./x check",
50 "type": "shell",
51 "problemMatcher": "$rustc",
52 "presentation": { "clear": true },
53 "group": { "kind": "build", "isDefault": true }
54 }
55 ]
56 }
57 ```
58
59 [Build Task]: https://code.visualstudio.com/docs/editor/tasks
60
61
62 ### Neovim
63
64 For Neovim users there are several options for configuring for rustc. The easiest way is by using
65 [neoconf.nvim](https://github.com/folke/neoconf.nvim/), which allows for project-local
66 configuration files with the native LSP. The steps for how to use it are below. Note that requires
67 Rust-Analyzer to already be configured with Neovim. Steps for this can be
68 [found here](https://rust-analyzer.github.io/manual.html#nvim-lsp).
69
70 1. First install the plugin. This can be done by following the steps in the README.
71 2. Run `x setup`, which will have a prompt for it to create a `.vscode/settings.json` file.
72 `neoconf` is able to read and update Rust-Analyzer settings automatically when the project is
73 opened when this file is detected.
74
75 If you're running `coc.nvim`,
76 you can use `:CocLocalConfig` to create a `.vim/coc-settings.json`,
77 and copy the settings from [`src/etc/rust_analyzer_settings.json`].
78
79 Another way is without a plugin, and creating your own logic in your configuration. To do this you
80 must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It
81 must be put in the `["rust-analyzer"]` key of the setup table, which is
82 [shown here](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#rust_analyzer)
83
84 If you would like to use the build task that is described above, you may either make your own
85 command in your config, or you can install a plugin such as
86 [overseer.nvim](https://github.com/stevearc/overseer.nvim) that can [read VSCode's `task.json`
87 files](https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks), and
88 follow the same instructions as above.
89
90 ## Check, check, and check again
91
92 When doing simple refactorings, it can be useful to run `./x check`
93 continuously. If you set up `rust-analyzer` as described above, this will
94 be done for you every time you save a file. Here you are just checking that
95 the compiler can **build**, but often that is all you need (e.g., when renaming a
96 method). You can then run `./x build` when you actually need to
97 run tests.
98
99 In fact, it is sometimes useful to put off tests even when you are not
100 100% sure the code will work. You can then keep building up
101 refactoring commits and only run the tests at some later time. You can
102 then use `git bisect` to track down **precisely** which commit caused
103 the problem. A nice side-effect of this style is that you are left
104 with a fairly fine-grained set of commits at the end, all of which
105 build and pass tests. This often helps reviewing.
106
107 ## `x suggest`
108
109 The `x suggest` subcommand suggests (and runs) a subset of the extensive
110 `rust-lang/rust` tests based on files you have changed. This is especially useful
111 for new contributors who have not mastered the arcane `x` flags yet and more
112 experienced contributors as a shorthand for reducing mental effort. In all cases
113 it is useful not to run the full tests (which can take on the order of tens of
114 minutes) and just run a subset which are relevant to your changes. For example,
115 running `tidy` and `linkchecker` is useful when editing Markdown files, whereas UI
116 tests are much less likely to be helpful. While `x suggest` is a useful tool, it
117 does not guarantee perfect coverage (just as PR CI isn't a substitute for bors).
118 See the [dedicated chapter](../tests/suggest-tests.md) for more information and
119 contribution instructions.
120
121 Please note that `x suggest` is in a beta state currently and the tests that it
122 will suggest are limited.
123
124 ## Configuring `rustup` to use nightly
125
126 Some parts of the bootstrap process uses pinned, nightly versions of tools like
127 rustfmt. To make things like `cargo fmt` work correctly in your repo, run
128
129 ```console
130 cd <path to rustc repo>
131 rustup override set nightly
132 ```
133
134 after [installing a nightly toolchain] with `rustup`. Don't forget to do this for all
135 directories you have [setup a worktree for]. You may need to use the pinned
136 nightly version from `src/stage0.json`, but often the normal `nightly` channel
137 will work.
138
139 **Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses,
140 and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler
141
142 **Note** This does _not_ allow you to build `rustc` with cargo directly. You
143 still have to use `x` to work on the compiler or standard library, this just
144 lets you use `cargo fmt`.
145
146 [installing a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust
147 [setup a worktree for]: ./suggested.md#working-on-multiple-branches-at-the-same-time
148 [the section on vscode]: suggested.md#configuring-rust-analyzer-for-rustc
149 [the section on rustup]: how-to-build-and-run.md?highlight=rustup#creating-a-rustup-toolchain
150
151 ## Faster builds with `--keep-stage`.
152
153 Sometimes just checking
154 whether the compiler builds is not enough. A common example is that
155 you need to add a `debug!` statement to inspect the value of some
156 state or better understand the problem. In that case, you don't really need
157 a full build. By bypassing bootstrap's cache invalidation, you can often get
158 these builds to complete very fast (e.g., around 30 seconds). The only
159 catch is this requires a bit of fudging and may produce compilers that
160 don't work (but that is easily detected and fixed).
161
162 The sequence of commands you want is as follows:
163
164 - Initial build: `./x build library`
165 - As [documented previously], this will build a functional
166 stage1 compiler as part of running all stage0 commands (which include
167 building a `std` compatible with the stage1 compiler) as well as the
168 first few steps of the "stage 1 actions" up to "stage1 (sysroot stage1)
169 builds std".
170 - Subsequent builds: `./x build library --keep-stage 1`
171 - Note that we added the `--keep-stage 1` flag here
172
173 [documented previously]: ./how-to-build-and-run.md#building-the-compiler
174
175 As mentioned, the effect of `--keep-stage 1` is that we just _assume_ that the
176 old standard library can be re-used. If you are editing the compiler, this
177 is almost always true: you haven't changed the standard library, after
178 all. But sometimes, it's not true: for example, if you are editing
179 the "metadata" part of the compiler, which controls how the compiler
180 encodes types and other states into the `rlib` files, or if you are
181 editing things that wind up in the metadata (such as the definition of
182 the MIR).
183
184 **The TL;DR is that you might get weird behavior from a compile when
185 using `--keep-stage 1`** -- for example, strange
186 [ICEs](../appendix/glossary.html#ice) or other panics. In that case, you
187 should simply remove the `--keep-stage 1` from the command and
188 rebuild. That ought to fix the problem.
189
190 You can also use `--keep-stage 1` when running tests. Something like this:
191
192 - Initial test run: `./x test tests/ui`
193 - Subsequent test run: `./x test tests/ui --keep-stage 1`
194
195 ## Using incremental compilation
196
197 You can further enable the `--incremental` flag to save additional
198 time in subsequent rebuilds:
199
200 ```bash
201 ./x test tests/ui --incremental --test-args issue-1234
202 ```
203
204 If you don't want to include the flag with every command, you can
205 enable it in the `config.toml`:
206
207 ```toml
208 [rust]
209 incremental = true
210 ```
211
212 Note that incremental compilation will use more disk space than usual.
213 If disk space is a concern for you, you might want to check the size
214 of the `build` directory from time to time.
215
216 ## Fine-tuning optimizations
217
218 Setting `optimize = false` makes the compiler too slow for tests. However, to
219 improve the test cycle, you can disable optimizations selectively only for the
220 crates you'll have to rebuild
221 ([source](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/incremental.20compilation.20question/near/202712165)).
222 For example, when working on `rustc_mir_build`, the `rustc_mir_build` and
223 `rustc_driver` crates take the most time to incrementally rebuild. You could
224 therefore set the following in the root `Cargo.toml`:
225
226 ```toml
227 [profile.release.package.rustc_mir_build]
228 opt-level = 0
229 [profile.release.package.rustc_driver]
230 opt-level = 0
231 ```
232
233 ## Working on multiple branches at the same time
234
235 Working on multiple branches in parallel can be a little annoying, since
236 building the compiler on one branch will cause the old build and the
237 incremental compilation cache to be overwritten. One solution would be
238 to have multiple clones of the repository, but that would mean storing the
239 Git metadata multiple times, and having to update each clone individually.
240
241 Fortunately, Git has a better solution called [worktrees]. This lets you
242 create multiple "working trees", which all share the same Git database.
243 Moreover, because all of the worktrees share the same object database,
244 if you update a branch (e.g. master) in any of them, you can use the new
245 commits from any of the worktrees. One caveat, though, is that submodules
246 do not get shared. They will still be cloned multiple times.
247
248 [worktrees]: https://git-scm.com/docs/git-worktree
249
250 Given you are inside the root directory for your Rust repository, you can
251 create a "linked working tree" in a new "rust2" directory by running
252 the following command:
253
254 ```bash
255 git worktree add ../rust2
256 ```
257
258 Creating a new worktree for a new branch based on `master` looks like:
259
260 ```bash
261 git worktree add -b my-feature ../rust2 master
262 ```
263
264 You can then use that rust2 folder as a separate workspace for modifying
265 and building `rustc`!
266
267 ## Using nix-shell
268
269 If you're using nix, you can use the following nix-shell to work on Rust:
270
271 ```nix
272 { pkgs ? import <nixpkgs> {} }:
273
274 # This file contains a development shell for working on rustc.
275 let
276 # Build configuration for rust-lang/rust. Based on `config.example.toml` (then called
277 # `config.toml.example`) from `1bd30ce2aac40c7698aa4a1b9520aa649ff2d1c5`
278 config = pkgs.writeText "rustc-config" ''
279 profile = "compiler" # you may want to choose a different profile, like `library` or `tools`
280 changelog-seen = 2
281
282 [build]
283 patch-binaries-for-nix = true
284 # The path to (or name of) the GDB executable to use. This is only used for
285 # executing the debuginfo test suite.
286 gdb = "${pkgs.gdb}/bin/gdb"
287 python = "${pkgs.python3Full}/bin/python"
288
289 [rust]
290 debug = true
291 incremental = true
292 deny-warnings = false
293
294 # Indicates whether some LLVM tools, like llvm-objdump, will be made available in the
295 # sysroot.
296 llvm-tools = true
297
298 # Print backtrace on internal compiler errors during bootstrap
299 backtrace-on-ice = true
300 '';
301
302 ripgrepConfig =
303 let
304 # Files that are ignored by ripgrep when searching.
305 ignoreFile = pkgs.writeText "rustc-rgignore" ''
306 configure
307 config.example.toml
308 x.py
309 LICENSE-MIT
310 LICENSE-APACHE
311 COPYRIGHT
312 **/*.txt
313 **/*.toml
314 **/*.yml
315 **/*.nix
316 *.md
317 src/ci
318 src/etc/
319 src/llvm-emscripten/
320 src/llvm-project/
321 src/rtstartup/
322 src/rustllvm/
323 src/stdsimd/
324 src/tools/rls/rls-analysis/test_data/
325 '';
326 in
327 pkgs.writeText "rustc-ripgreprc" "--ignore-file=${ignoreFile}";
328 in
329 pkgs.mkShell {
330 name = "rustc";
331 nativeBuildInputs = with pkgs; [
332 gcc9 binutils cmake ninja openssl pkgconfig python39 git curl cacert patchelf nix psutils
333 ];
334 RIPGREP_CONFIG_PATH = ripgrepConfig;
335 RUST_BOOTSTRAP_CONFIG = config;
336 }
337 ```
338
339 ## Shell Completions
340
341 If you use Bash, Fish or PowerShell, you can find automatically-generated shell completion scripts for `x.py` in [`src/etc/completions`](https://github.com/rust-lang/rust/tree/master/src/etc/completions).
342 Zsh support will also be included once issues with [`clap_complete`](https://crates.io/crates/clap_complete) have been resolved.
343
344 You can use `source ./src/etc/completions/x.py.<extension>`
345 to load completions for your shell of choice,
346 or `source .\src\etc\completions\x.py.ps1` for PowerShell.
347 Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion.
348
349 [`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json