building/suggested: Add instructions for Emacs & Helix (#2080)
Co-authored-by: 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>
This commit is contained in:
parent
de2f32e59c
commit
34a13c2e52
|
|
@ -1,46 +1,53 @@
|
|||
# Suggested Workflows
|
||||
|
||||
The full bootstrapping process takes quite a while. Here are some suggestions
|
||||
to make your life easier.
|
||||
The full bootstrapping process takes quite a while. Here are some suggestions to
|
||||
make your life easier.
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Installing a pre-push hook
|
||||
|
||||
CI will automatically fail your build if it doesn't pass `tidy`, our
|
||||
internal tool for ensuring code quality. If you'd like, you can install a
|
||||
[Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
|
||||
that will automatically run `./x test tidy` on each push, to ensure
|
||||
your code is up to par. If the hook fails then run `./x test tidy --bless`
|
||||
and commit the changes. If you decide later that the pre-push behavior is
|
||||
undesirable, you can delete the `pre-push` file in `.git/hooks`.
|
||||
CI will automatically fail your build if it doesn't pass `tidy`, our internal
|
||||
tool for ensuring code quality. If you'd like, you can install a [Git
|
||||
hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that will
|
||||
automatically run `./x test tidy` on each push, to ensure your code is up to
|
||||
par. If the hook fails then run `./x test tidy --bless` and commit the changes.
|
||||
If you decide later that the pre-push behavior is undesirable, you can delete
|
||||
the `pre-push` file in `.git/hooks`.
|
||||
|
||||
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!).
|
||||
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!).
|
||||
|
||||
You can also install the hook as a step of running `./x setup`!
|
||||
|
||||
## Configuring `rust-analyzer` for `rustc`
|
||||
|
||||
### Project-local rust-analyzer setup
|
||||
|
||||
`rust-analyzer` can help you check and format your code whenever you save a
|
||||
file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands,
|
||||
but you can override these commands to use more adapted versions of these tools
|
||||
when hacking on `rustc`. With custom setup, `rust-analyzer` can use `./x check`
|
||||
to check the sources, and the stage 0 rustfmt to format them.
|
||||
|
||||
The default `rust-analyzer.check.overrideCommand` command line will check all
|
||||
the crates and tools in the repository. If you are working on a specific part,
|
||||
you can override the command to only check the part you are working on to save
|
||||
checking time. For example, if you are working on the compiler, you can override
|
||||
the command to `x check compiler --json-output` to only check the compiler part.
|
||||
You can run `x check --help --verbose` to see the available parts.
|
||||
|
||||
If you have enough free disk space and you would like to be able to run `x`
|
||||
commands while rust-analyzer runs in the background, you can also add
|
||||
`--build-dir build-rust-analyzer` to the `overrideCommand` to avoid x locking.
|
||||
|
||||
### Visual Studio Code
|
||||
|
||||
`rust-analyzer` can help you check and format your code whenever you save
|
||||
a file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt`
|
||||
commands, but you can override these commands to use more adapted versions
|
||||
of these tools when hacking on `rustc`. For example, `x setup vscode` will prompt
|
||||
you to create a `.vscode/settings.json` file which will configure Visual Studio code.
|
||||
This will ask `rust-analyzer` to use `./x check` to check the sources, and the
|
||||
stage 0 rustfmt to format them.
|
||||
The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`].
|
||||
|
||||
The default `rust-analyzer.check.overrideCommand` command line will check all the crates and tools
|
||||
in the repository. If you are working on a specific part, you can override the command to only
|
||||
check the part you are working on to save checking time. For example, if you are working on
|
||||
the compiler, you can override the command to `x check compiler --json-output` to only
|
||||
check the compiler part. You can run `x check --help --verbose` to see the available parts.
|
||||
|
||||
If you have enough free disk space and you would like to be able to run `x` commands while
|
||||
rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the
|
||||
`overrideCommand` to avoid x locking.
|
||||
Running `./x setup vscode` will prompt you to create a `.vscode/settings.json`
|
||||
file which will configure Visual Studio code. The recommended `rust-analyzer`
|
||||
settings live at [`src/etc/rust_analyzer_settings.json`].
|
||||
|
||||
If running `./x check` on save is inconvenient, in VS Code you can use a [Build
|
||||
Task] instead:
|
||||
|
|
@ -67,62 +74,87 @@ Task] instead:
|
|||
|
||||
### Neovim
|
||||
|
||||
For Neovim users there are several options for configuring for rustc. The easiest way is by using
|
||||
[neoconf.nvim](https://github.com/folke/neoconf.nvim/), which allows for project-local
|
||||
configuration files with the native LSP. The steps for how to use it are below.
|
||||
Note that they require rust-analyzer to already be configured with Neovim.
|
||||
Steps for this can be [found here](https://rust-analyzer.github.io/manual.html#nvim-lsp).
|
||||
For Neovim users there are several options for configuring for rustc. The
|
||||
easiest way is by using [neoconf.nvim](https://github.com/folke/neoconf.nvim/),
|
||||
which allows for project-local configuration files with the native LSP. The
|
||||
steps for how to use it are below. Note that they require rust-analyzer to
|
||||
already be configured with Neovim. Steps for this can be [found
|
||||
here](https://rust-analyzer.github.io/manual.html#nvim-lsp).
|
||||
|
||||
1. First install the plugin. This can be done by following the steps in the README.
|
||||
2. Run `x setup`, which will have a prompt for it to create a `.vscode/settings.json` file.
|
||||
`neoconf` is able to read and update rust-analyzer settings automatically when the project is
|
||||
opened when this file is detected.
|
||||
1. First install the plugin. This can be done by following the steps in the
|
||||
README.
|
||||
2. Run `x setup`, which will have a prompt for it to create a
|
||||
`.vscode/settings.json` file. `neoconf` is able to read and update
|
||||
rust-analyzer settings automatically when the project is opened when this
|
||||
file is detected.
|
||||
|
||||
If you're running `coc.nvim`,
|
||||
you can use `:CocLocalConfig` to create a `.vim/coc-settings.json`,
|
||||
and copy the settings from [`src/etc/rust_analyzer_settings.json`].
|
||||
If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a
|
||||
`.vim/coc-settings.json`, and copy the settings from
|
||||
[`src/etc/rust_analyzer_settings.json`].
|
||||
|
||||
Another way is without a plugin, and creating your own logic in your configuration. To do this you
|
||||
must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It
|
||||
must be put in the `["rust-analyzer"]` key of the setup table, which is
|
||||
[shown here](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#rust_analyzer).
|
||||
Another way is without a plugin, and creating your own logic in your
|
||||
configuration. To do this you must translate the JSON to Lua yourself. The
|
||||
translation is 1:1 and fairly straight-forward. It must be put in the
|
||||
`["rust-analyzer"]` key of the setup table, which is [shown
|
||||
here](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#rust_analyzer).
|
||||
|
||||
If you would like to use the build task that is described above, you may either make your own
|
||||
command in your config, or you can install a plugin such as
|
||||
[overseer.nvim](https://github.com/stevearc/overseer.nvim) that can [read VSCode's `task.json`
|
||||
files](https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks), and
|
||||
follow the same instructions as above.
|
||||
If you would like to use the build task that is described above, you may either
|
||||
make your own command in your config, or you can install a plugin such as
|
||||
[overseer.nvim](https://github.com/stevearc/overseer.nvim) that can [read
|
||||
VSCode's `task.json`
|
||||
files](https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks),
|
||||
and follow the same instructions as above.
|
||||
|
||||
### Emacs
|
||||
|
||||
Emacs provides support for rust-analyzer with project-local configuration
|
||||
through [Eglot](https://www.gnu.org/software/emacs/manual/html_node/eglot/).
|
||||
Steps for setting up Eglot with rust-analyzer can be [found
|
||||
here](https://rust-analyzer.github.io/manual.html#eglot).
|
||||
Having set up Emacs & Eglot for Rust development in general, you can use the
|
||||
configuration for rustc provided in [`src/etc/rust_analyzer_eglot.el`].
|
||||
Simply copy the provided file to `.dir-locals.el` in the project root directory.
|
||||
For more information on project-specific Eglot configuration, consult [the
|
||||
manual](https://www.gnu.org/software/emacs/manual/html_node/eglot/Project_002dspecific-configuration.html).
|
||||
|
||||
### Helix
|
||||
|
||||
Helix comes with built-in LSP and rust-analyzer support.
|
||||
It can be configured through `languages.toml`, as described
|
||||
[here](https://docs.helix-editor.com/languages.html).
|
||||
You can use the configuration for rustc provided in
|
||||
[`src/etc/rust_analyzer_helix.toml`].
|
||||
Simply copy the provided file to `.helix/languages.toml` in the project root
|
||||
directory.
|
||||
|
||||
## Check, check, and check again
|
||||
|
||||
When doing simple refactorings, it can be useful to run `./x check`
|
||||
continuously. If you set up `rust-analyzer` as described above, this will
|
||||
be done for you every time you save a file. Here you are just checking that
|
||||
the compiler can **build**, but often that is all you need (e.g., when renaming a
|
||||
method). You can then run `./x build` when you actually need to
|
||||
run tests.
|
||||
continuously. If you set up `rust-analyzer` as described above, this will be
|
||||
done for you every time you save a file. Here you are just checking that the
|
||||
compiler can **build**, but often that is all you need (e.g., when renaming a
|
||||
method). You can then run `./x build` when you actually need to run tests.
|
||||
|
||||
In fact, it is sometimes useful to put off tests even when you are not
|
||||
100% sure the code will work. You can then keep building up
|
||||
refactoring commits and only run the tests at some later time. You can
|
||||
then use `git bisect` to track down **precisely** which commit caused
|
||||
the problem. A nice side-effect of this style is that you are left
|
||||
with a fairly fine-grained set of commits at the end, all of which
|
||||
build and pass tests. This often helps reviewing.
|
||||
In fact, it is sometimes useful to put off tests even when you are not 100% sure
|
||||
the code will work. You can then keep building up refactoring commits and only
|
||||
run the tests at some later time. You can then use `git bisect` to track down
|
||||
**precisely** which commit caused the problem. A nice side-effect of this style
|
||||
is that you are left with a fairly fine-grained set of commits at the end, all
|
||||
of which build and pass tests. This often helps reviewing.
|
||||
|
||||
## `x suggest`
|
||||
|
||||
The `x suggest` subcommand suggests (and runs) a subset of the extensive
|
||||
`rust-lang/rust` tests based on files you have changed. This is especially useful
|
||||
for new contributors who have not mastered the arcane `x` flags yet and more
|
||||
experienced contributors as a shorthand for reducing mental effort. In all cases
|
||||
it is useful not to run the full tests (which can take on the order of tens of
|
||||
minutes) and just run a subset which are relevant to your changes. For example,
|
||||
running `tidy` and `linkchecker` is useful when editing Markdown files, whereas UI
|
||||
tests are much less likely to be helpful. While `x suggest` is a useful tool, it
|
||||
does not guarantee perfect coverage (just as PR CI isn't a substitute for bors).
|
||||
See the [dedicated chapter](../tests/suggest-tests.md) for more information and
|
||||
contribution instructions.
|
||||
`rust-lang/rust` tests based on files you have changed. This is especially
|
||||
useful for new contributors who have not mastered the arcane `x` flags yet and
|
||||
more experienced contributors as a shorthand for reducing mental effort. In all
|
||||
cases it is useful not to run the full tests (which can take on the order of
|
||||
tens of minutes) and just run a subset which are relevant to your changes. For
|
||||
example, running `tidy` and `linkchecker` is useful when editing Markdown files,
|
||||
whereas UI tests are much less likely to be helpful. While `x suggest` is a
|
||||
useful tool, it does not guarantee perfect coverage (just as PR CI isn't a
|
||||
substitute for bors). See the [dedicated chapter](../tests/suggest-tests.md) for
|
||||
more information and contribution instructions.
|
||||
|
||||
Please note that `x suggest` is in a beta state currently and the tests that it
|
||||
will suggest are limited.
|
||||
|
|
@ -137,12 +169,14 @@ cd <path to rustc repo>
|
|||
rustup override set nightly
|
||||
```
|
||||
|
||||
after [installing a nightly toolchain] with `rustup`. Don't forget to do this for all
|
||||
directories you have [setup a worktree for]. You may need to use the pinned
|
||||
nightly version from `src/stage0`, but often the normal `nightly` channel will work.
|
||||
after [installing a nightly toolchain] with `rustup`. Don't forget to do this
|
||||
for all directories you have [setup a worktree for]. You may need to use the
|
||||
pinned nightly version from `src/stage0`, but often the normal `nightly` channel
|
||||
will work.
|
||||
|
||||
**Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses,
|
||||
and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler
|
||||
**Note** see [the section on vscode] for how to configure it with this real
|
||||
rustfmt `x` uses, and [the section on rustup] for how to setup `rustup`
|
||||
toolchain for your bootstrapped compiler
|
||||
|
||||
**Note** This does _not_ allow you to build `rustc` with cargo directly. You
|
||||
still have to use `x` to work on the compiler or standard library, this just
|
||||
|
|
@ -155,42 +189,38 @@ lets you use `cargo fmt`.
|
|||
|
||||
## Faster builds with `--keep-stage`.
|
||||
|
||||
Sometimes just checking
|
||||
whether the compiler builds is not enough. A common example is that
|
||||
you need to add a `debug!` statement to inspect the value of some
|
||||
state or better understand the problem. In that case, you don't really need
|
||||
Sometimes just checking whether the compiler builds is not enough. A common
|
||||
example is that you need to add a `debug!` statement to inspect the value of
|
||||
some state or better understand the problem. In that case, you don't really need
|
||||
a full build. By bypassing bootstrap's cache invalidation, you can often get
|
||||
these builds to complete very fast (e.g., around 30 seconds). The only
|
||||
catch is this requires a bit of fudging and may produce compilers that
|
||||
don't work (but that is easily detected and fixed).
|
||||
these builds to complete very fast (e.g., around 30 seconds). The only catch is
|
||||
this requires a bit of fudging and may produce compilers that don't work (but
|
||||
that is easily detected and fixed).
|
||||
|
||||
The sequence of commands you want is as follows:
|
||||
|
||||
- Initial build: `./x build library`
|
||||
- As [documented previously], this will build a functional
|
||||
stage1 compiler as part of running all stage0 commands (which include
|
||||
building a `std` compatible with the stage1 compiler) as well as the
|
||||
first few steps of the "stage 1 actions" up to "stage1 (sysroot stage1)
|
||||
builds std".
|
||||
- As [documented previously], this will build a functional stage1 compiler as
|
||||
part of running all stage0 commands (which include building a `std`
|
||||
compatible with the stage1 compiler) as well as the first few steps of the
|
||||
"stage 1 actions" up to "stage1 (sysroot stage1) builds std".
|
||||
- Subsequent builds: `./x build library --keep-stage 1`
|
||||
- Note that we added the `--keep-stage 1` flag here
|
||||
|
||||
[documented previously]: ./how-to-build-and-run.md#building-the-compiler
|
||||
|
||||
As mentioned, the effect of `--keep-stage 1` is that we just _assume_ that the
|
||||
old standard library can be re-used. If you are editing the compiler, this
|
||||
is almost always true: you haven't changed the standard library, after
|
||||
all. But sometimes, it's not true: for example, if you are editing
|
||||
the "metadata" part of the compiler, which controls how the compiler
|
||||
encodes types and other states into the `rlib` files, or if you are
|
||||
editing things that wind up in the metadata (such as the definition of
|
||||
the MIR).
|
||||
old standard library can be re-used. If you are editing the compiler, this is
|
||||
almost always true: you haven't changed the standard library, after all. But
|
||||
sometimes, it's not true: for example, if you are editing the "metadata" part of
|
||||
the compiler, which controls how the compiler encodes types and other states
|
||||
into the `rlib` files, or if you are editing things that wind up in the metadata
|
||||
(such as the definition of the MIR).
|
||||
|
||||
**The TL;DR is that you might get weird behavior from a compile when
|
||||
using `--keep-stage 1`** -- for example, strange
|
||||
[ICEs](../appendix/glossary.html#ice) or other panics. In that case, you
|
||||
should simply remove the `--keep-stage 1` from the command and
|
||||
rebuild. That ought to fix the problem.
|
||||
**The TL;DR is that you might get weird behavior from a compile when using
|
||||
`--keep-stage 1`** -- for example, strange [ICEs](../appendix/glossary.html#ice)
|
||||
or other panics. In that case, you should simply remove the `--keep-stage 1`
|
||||
from the command and rebuild. That ought to fix the problem.
|
||||
|
||||
You can also use `--keep-stage 1` when running tests. Something like this:
|
||||
|
||||
|
|
@ -199,24 +229,24 @@ You can also use `--keep-stage 1` when running tests. Something like this:
|
|||
|
||||
## Using incremental compilation
|
||||
|
||||
You can further enable the `--incremental` flag to save additional
|
||||
time in subsequent rebuilds:
|
||||
You can further enable the `--incremental` flag to save additional time in
|
||||
subsequent rebuilds:
|
||||
|
||||
```bash
|
||||
./x test tests/ui --incremental --test-args issue-1234
|
||||
```
|
||||
|
||||
If you don't want to include the flag with every command, you can
|
||||
enable it in the `config.toml`:
|
||||
If you don't want to include the flag with every command, you can enable it in
|
||||
the `config.toml`:
|
||||
|
||||
```toml
|
||||
[rust]
|
||||
incremental = true
|
||||
```
|
||||
|
||||
Note that incremental compilation will use more disk space than usual.
|
||||
If disk space is a concern for you, you might want to check the size
|
||||
of the `build` directory from time to time.
|
||||
Note that incremental compilation will use more disk space than usual. If disk
|
||||
space is a concern for you, you might want to check the size of the `build`
|
||||
directory from time to time.
|
||||
|
||||
## Fine-tuning optimizations
|
||||
|
||||
|
|
@ -238,23 +268,23 @@ opt-level = 0
|
|||
## Working on multiple branches at the same time
|
||||
|
||||
Working on multiple branches in parallel can be a little annoying, since
|
||||
building the compiler on one branch will cause the old build and the
|
||||
incremental compilation cache to be overwritten. One solution would be
|
||||
to have multiple clones of the repository, but that would mean storing the
|
||||
Git metadata multiple times, and having to update each clone individually.
|
||||
building the compiler on one branch will cause the old build and the incremental
|
||||
compilation cache to be overwritten. One solution would be to have multiple
|
||||
clones of the repository, but that would mean storing the Git metadata multiple
|
||||
times, and having to update each clone individually.
|
||||
|
||||
Fortunately, Git has a better solution called [worktrees]. This lets you
|
||||
create multiple "working trees", which all share the same Git database.
|
||||
Moreover, because all of the worktrees share the same object database,
|
||||
if you update a branch (e.g. master) in any of them, you can use the new
|
||||
commits from any of the worktrees. One caveat, though, is that submodules
|
||||
do not get shared. They will still be cloned multiple times.
|
||||
Fortunately, Git has a better solution called [worktrees]. This lets you create
|
||||
multiple "working trees", which all share the same Git database. Moreover,
|
||||
because all of the worktrees share the same object database, if you update a
|
||||
branch (e.g. master) in any of them, you can use the new commits from any of the
|
||||
worktrees. One caveat, though, is that submodules do not get shared. They will
|
||||
still be cloned multiple times.
|
||||
|
||||
[worktrees]: https://git-scm.com/docs/git-worktree
|
||||
|
||||
Given you are inside the root directory for your Rust repository, you can
|
||||
create a "linked working tree" in a new "rust2" directory by running
|
||||
the following command:
|
||||
Given you are inside the root directory for your Rust repository, you can create
|
||||
a "linked working tree" in a new "rust2" directory by running the following
|
||||
command:
|
||||
|
||||
```bash
|
||||
git worktree add ../rust2
|
||||
|
|
@ -266,8 +296,8 @@ Creating a new worktree for a new branch based on `master` looks like:
|
|||
git worktree add -b my-feature ../rust2 master
|
||||
```
|
||||
|
||||
You can then use that rust2 folder as a separate workspace for modifying
|
||||
and building `rustc`!
|
||||
You can then use that rust2 folder as a separate workspace for modifying and
|
||||
building `rustc`!
|
||||
|
||||
## Using nix-shell
|
||||
|
||||
|
|
@ -293,9 +323,9 @@ pkgs.mkShell {
|
|||
```
|
||||
|
||||
Note that when using nix on a not-NixOS distribution, it may be necessary to set
|
||||
**`patch-binaries-for-nix = true` in `config.toml`**.
|
||||
Bootstrap tries to detect whether it's running in nix and enable patching automatically,
|
||||
but this detection can have false negatives.
|
||||
**`patch-binaries-for-nix = true` in `config.toml`**. Bootstrap tries to detect
|
||||
whether it's running in nix and enable patching automatically, but this
|
||||
detection can have false negatives.
|
||||
|
||||
You can also use your nix shell to manage `config.toml`:
|
||||
|
||||
|
|
@ -313,12 +343,15 @@ pkgs.mkShell {
|
|||
|
||||
## Shell Completions
|
||||
|
||||
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).
|
||||
Zsh support will also be included once issues with [`clap_complete`](https://crates.io/crates/clap_complete) have been resolved.
|
||||
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).
|
||||
Zsh support will also be included once issues with
|
||||
[`clap_complete`](https://crates.io/crates/clap_complete) have been resolved.
|
||||
|
||||
You can use `source ./src/etc/completions/x.py.<extension>`
|
||||
to load completions for your shell of choice,
|
||||
or `& .\src\etc\completions\x.py.ps1` for PowerShell.
|
||||
Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion.
|
||||
You can use `source ./src/etc/completions/x.py.<extension>` to load completions
|
||||
for your shell of choice, or `& .\src\etc\completions\x.py.ps1` for PowerShell.
|
||||
Adding this to your shell's startup script (e.g. `.bashrc`) will automatically
|
||||
load this completion.
|
||||
|
||||
[`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json
|
||||
|
|
|
|||
Loading…
Reference in New Issue