rust/CONTRIBUTING.md

278 lines
11 KiB
Markdown
Raw Normal View History

2019-09-14 06:40:37 -05:00
# Contribution Guide
If you want to hack on Miri yourself, great! Here are some resources you might
2019-09-14 06:40:37 -05:00
find useful.
## Getting started
2020-04-08 04:39:35 -05:00
Check out the issues on this GitHub repository for some ideas. In particular,
look for the green `E-*` labels which mark issues that should be rather
well-suited for onboarding. For more ideas or help with hacking on Miri, you can
contact us (`oli-obk` and `RalfJ`) on the [Rust Zulip].
2019-09-14 06:40:37 -05:00
[Rust Zulip]: https://rust-lang.zulipchat.com
2020-04-08 04:39:35 -05:00
## Preparing the build environment
2019-11-30 03:06:12 -06:00
2020-04-08 05:30:45 -05:00
Miri heavily relies on internal and unstable rustc interfaces to execute MIR,
which means it is important that you install a version of rustc that Miri
actually works with.
2019-11-30 03:06:12 -06:00
The `rust-version` file contains the commit hash of rustc that Miri is currently
tested against. Other versions will likely not work. After installing
[`rustup-toolchain-install-master`], you can run the following command to
install that exact version of rustc as a toolchain:
```
2019-12-01 03:20:16 -06:00
./rustup-toolchain
2019-11-30 03:06:12 -06:00
```
2020-04-08 05:30:45 -05:00
This will set up a rustup toolchain called `miri` and set it as an override for
the current directory.
2019-11-30 03:06:12 -06:00
You can also create a `.auto-everything` file (contents don't matter, can be empty), which
will cause any `./miri` command to automatically call `rustup-toolchain`, `clippy` and `rustfmt`
for you. If you don't want all of these to happen, you can add individual `.auto-toolchain`,
`.auto-clippy` and `.auto-fmt` files respectively.
2019-11-30 03:06:12 -06:00
[`rustup-toolchain-install-master`]: https://github.com/kennytm/rustup-toolchain-install-master
2020-04-08 04:39:35 -05:00
## Building and testing Miri
Invoking Miri requires getting a bunch of flags right and setting up a custom
2020-04-08 05:30:45 -05:00
sysroot with xargo. The `miri` script takes care of that for you. With the
2020-04-08 04:39:35 -05:00
build environment prepared, compiling Miri is just one command away:
2020-04-06 02:33:36 -05:00
```
./miri build
```
Run `./miri` without arguments to see the other commands our build tool
supports.
2020-04-08 04:39:35 -05:00
### Testing the Miri driver
2019-09-14 06:40:37 -05:00
2020-04-08 08:56:59 -05:00
The Miri driver compiled from `src/bin/miri.rs` is the "heart" of Miri: it is
2020-04-08 04:39:35 -05:00
basically a version of `rustc` that, instead of compiling your code, runs it.
It accepts all the same flags as `rustc` (though the ones only affecting code
generation and linking obviously will have no effect) [and more][miri-flags].
2019-09-14 06:40:37 -05:00
2020-04-08 04:39:35 -05:00
[miri-flags]: README.md#miri--z-flags-and-environment-variables
2019-09-14 06:40:37 -05:00
2020-04-08 04:39:35 -05:00
For example, you can (cross-)run the driver on a particular file by doing
2019-09-14 06:40:37 -05:00
```sh
./miri run tests/pass/format.rs
./miri run tests/pass/hello.rs --target i686-unknown-linux-gnu
2019-09-14 06:40:37 -05:00
```
2020-04-06 02:37:15 -05:00
and you can (cross-)run the entire test suite using:
2019-09-14 06:40:37 -05:00
```
./miri test
2020-03-22 02:55:53 -05:00
MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test
2019-09-14 06:40:37 -05:00
```
If your target doesn't support libstd, you can run miri with
```
MIRI_NO_STD=1 MIRI_TEST_TARGET=thumbv7em-none-eabihf ./miri test tests/fail/alloc/no_global_allocator.rs
MIRI_NO_STD=1 ./miri run tests/pass/no_std.rs --target thumbv7em-none-eabihf
```
to avoid attempting (and failing) to build libstd. Note that almost no tests will pass
this way, but you can run individual tests.
2019-09-14 06:40:37 -05:00
`./miri test FILTER` only runs those tests that contain `FILTER` in their
filename (including the base directory, e.g. `./miri test fail` will run all
compile-fail tests).
You can get a trace of which MIR statements are being executed by setting the
`MIRI_LOG` environment variable. For example:
```sh
MIRI_LOG=info ./miri run tests/pass/vec.rs
2019-09-14 06:40:37 -05:00
```
Setting `MIRI_LOG` like this will configure logging for Miri itself as well as
2020-04-08 05:30:45 -05:00
the `rustc_middle::mir::interpret` and `rustc_mir::interpret` modules in rustc. You
2019-09-14 06:40:37 -05:00
can also do more targeted configuration, e.g. the following helps debug the
stacked borrows implementation:
```sh
MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows ./miri run tests/pass/vec.rs
2019-09-14 06:40:37 -05:00
```
In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
evaluation error was originally raised.
#### UI testing
We use ui-testing in Miri, meaning we generate `.stderr` and `.stdout` files for the output
produced by Miri. You can use `./miri bless` to automatically (re)generate these files when
you add new tests or change how Miri presents certain output.
Note that when you also use `MIRIFLAGS` to change optimizations and similar, the ui output
will change in unexpected ways. In order to still be able
to run the other checks while ignoring the ui output, use `MIRI_SKIP_UI_CHECKS=1 ./miri test`.
For more info on how to configure ui tests see [the documentation on the ui test crate][ui_test]
[ui_test]: ui_test/README.md
2020-04-08 04:39:35 -05:00
### Testing `cargo miri`
2019-09-14 06:40:37 -05:00
Working with the driver directly gives you full control, but you also lose all
2020-04-08 05:30:45 -05:00
the convenience provided by cargo. Once your test case depends on a crate, it
is probably easier to test it with the cargo wrapper. You can install your
2019-09-14 06:40:37 -05:00
development version of Miri using
```
./miri install
```
and then you can use it as if it was installed by `rustup`. Make sure you use
the same toolchain when calling `cargo miri` that you used when installing Miri!
Usually this means you have to write `cargo +miri miri ...` to select the `miri`
toolchain that was installed by `./rustup-toolchain`.
2019-09-14 06:40:37 -05:00
There's a test for the cargo wrapper in the `test-cargo-miri` directory; run
2020-03-22 02:55:53 -05:00
`./run-test.py` in there to execute it. Like `./miri test`, this respects the
`MIRI_TEST_TARGET` environment variable to execute the test for another target.
2019-09-14 06:40:37 -05:00
### Using a modified standard library
Miri re-builds the standard library into a custom sysroot, so it is fairly easy
to test Miri against a modified standard library -- you do not even have to
build Miri yourself, the Miri shipped by `rustup` will work. All you have to do
is set the `MIRI_LIB_SRC` environment variable to the `library` folder of a
`rust-lang/rust` repository checkout. Note that changing files in that directory
does not automatically trigger a re-build of the standard library; you have to
2022-06-11 19:45:33 -05:00
clear the Miri build cache manually (on Linux, `rm -rf ~/.cache/miri`;
2022-06-12 14:10:13 -05:00
and on Windows, `rmdir /S "%LOCALAPPDATA%\rust-lang\miri\cache"`).
2022-07-04 14:15:23 -05:00
### Benchmarking
Miri comes with a few benchmarks; you can run `./miri bench` to run them with the locally built
Miri. Note: this will run `./miri install` as a side-effect. Also requires `hyperfine` to be
installed (`cargo install hyperfine`).
## Configuring `rust-analyzer`
To configure `rust-analyzer` and VS Code for working on Miri, save the following
to `.vscode/settings.json` in your local Miri clone:
```json
{
2022-07-04 11:51:20 -05:00
"rust-analyzer.rustc.source": "discover",
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
"./cargo-miri/Cargo.toml"
],
"rust-analyzer.checkOnSave.overrideCommand": [
2022-07-21 06:45:22 -05:00
"env",
"MIRI_AUTO_OPS=no",
"./miri",
2022-08-19 07:01:38 -05:00
"cargo",
"clippy", // make this `check` when working with a locally built rustc
"--message-format=json"
],
2022-08-17 06:44:12 -05:00
// Contrary to what the name suggests, this also affects proc macros.
"rust-analyzer.cargo.buildScripts.overrideCommand": [
2022-07-21 06:45:22 -05:00
"env",
"MIRI_AUTO_OPS=no",
2022-07-04 11:51:20 -05:00
"./miri",
2022-08-19 07:01:38 -05:00
"cargo",
2022-07-04 11:51:20 -05:00
"check",
"--message-format=json",
],
}
```
> #### Note
>
> If you are [building Miri with a locally built rustc][], set
> `rust-analyzer.rustcSource` to the relative path from your Miri clone to the
> root `Cargo.toml` of the locally built rustc. For example, the path might look
> like `../rust/Cargo.toml`.
See the rustc-dev-guide's docs on ["Configuring `rust-analyzer` for `rustc`"][rdg-r-a]
for more information about configuring VS Code and `rust-analyzer`.
[rdg-r-a]: https://rustc-dev-guide.rust-lang.org/building/suggested.html#configuring-rust-analyzer-for-rustc
2020-04-08 05:30:45 -05:00
## Advanced topic: other build environments
2020-04-08 04:39:35 -05:00
2020-04-08 05:30:45 -05:00
We described above the simplest way to get a working build environment for Miri,
which is to use the version of rustc indicated by `rustc-version`. But
sometimes, that is not enough.
### Updating `rustc-version`
The `rustc-version` file is regularly updated to keep Miri close to the latest
version of rustc. Usually, new contributors do not have to worry about this. But
sometimes a newer rustc is needed for a patch, and sometimes Miri needs fixing
for changes in rustc. In both cases, `rustc-version` needs updating.
2020-04-08 04:39:35 -05:00
To update the `rustc-version` file and install the latest rustc, you can run:
```
./rustup-toolchain HEAD
```
2020-04-08 05:30:45 -05:00
Now edit Miri until `./miri test` passes, and submit a PR. Generally, it is
preferred to separate updating `rustc-version` and doing what it takes to get
Miri working again, from implementing new features that rely on the updated
rustc. This avoids blocking all Miri development on landing a big PR.
2020-04-08 04:39:35 -05:00
2020-04-08 05:30:45 -05:00
### Building Miri with a locally built rustc
2019-09-14 06:40:37 -05:00
[building Miri with a locally built rustc]: #building-miri-with-a-locally-built-rustc
2019-09-14 06:40:37 -05:00
A big part of the Miri driver lives in rustc, so working on Miri will sometimes
2020-04-08 05:30:45 -05:00
require using a locally built rustc. The bug you want to fix may actually be on
2019-09-14 06:40:37 -05:00
the rustc side, or you just need to get more detailed trace of the execution
than what is possible with release builds -- in both cases, you should develop
Miri against a rustc you compiled yourself, with debug assertions (and hence
2019-09-14 06:40:37 -05:00
tracing) enabled.
The setup for a local rustc works as follows:
```sh
# Clone the rust-lang/rust repo.
git clone https://github.com/rust-lang/rust rustc
2019-09-14 06:40:37 -05:00
cd rustc
# Create a config.toml with defaults for working on Miri.
./x.py setup compiler
# Now edit `config.toml` and under `[rust]` set `debug-assertions = true`.
# Build a stage 2 rustc, and build the rustc libraries with that rustc.
# This step can take 30 minutes or more.
./x.py build --stage 2 compiler/rustc
2019-09-14 06:40:37 -05:00
# If you change something, you can get a faster rebuild by doing
./x.py build --keep-stage 0 --stage 2 compiler/rustc
2019-09-14 06:40:37 -05:00
# You may have to change the architecture in the next command
rustup toolchain link stage2 build/x86_64-unknown-linux-gnu/stage2
2019-09-14 06:40:37 -05:00
# Now cd to your Miri directory, then configure rustup
rustup override set stage2
2019-09-14 06:40:37 -05:00
```
Note: When you are working with a locally built rustc or any other toolchain that
is not the same as the one in `rust-version`, you should not have `.auto-everything` or
`.auto-toolchain` as that will keep resetting your toolchain.
```
rm -f .auto-everything .auto-toolchain
```
2022-05-10 14:38:32 -05:00
Important: You need to delete the Miri cache when you change the stdlib; otherwise the
2022-06-11 19:45:33 -05:00
old, chached version will be used. On Linux, the cache is located at `~/.cache/miri`,
2022-06-12 14:10:13 -05:00
and on Windows, it is located at `%LOCALAPPDATA%\rust-lang\miri\cache`; the exact
2022-05-10 14:38:32 -05:00
location is printed after the library build: "A libstd for Miri is now available in ...".
Note: `./x.py --stage 2 compiler/rustc` currently errors with `thread 'main'
panicked at 'fs::read(stamp) failed with No such file or directory (os error 2)`,
you can simply ignore that error; Miri will build anyway.
For more information about building and configuring a local compiler,
see <https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html>.
With this, you should now have a working development setup! See
2020-04-08 04:39:35 -05:00
[above](#building-and-testing-miri) for how to proceed working on Miri.