588 lines
34 KiB
HTML
588 lines
34 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="light sidebar-visible" dir="ltr">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>Suggested workflows - Rust Compiler Development Guide</title>
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
<meta name="description" content="A guide to developing the Rust compiler (rustc)">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff">
|
|
|
|
<link rel="icon" href="../favicon.svg">
|
|
<link rel="shortcut icon" href="../favicon.png">
|
|
<link rel="stylesheet" href="../css/variables.css">
|
|
<link rel="stylesheet" href="../css/general.css">
|
|
<link rel="stylesheet" href="../css/chrome.css">
|
|
<link rel="stylesheet" href="../css/print.css" media="print">
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
|
<link rel="stylesheet" href="../fonts/fonts.css">
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
|
|
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
|
|
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
|
|
<!-- Provide site root and default themes to javascript -->
|
|
<script>
|
|
const path_to_root = "../";
|
|
const default_light_theme = "light";
|
|
const default_dark_theme = "navy";
|
|
</script>
|
|
<!-- Start loading toc.js asap -->
|
|
<script src="../toc.js"></script>
|
|
</head>
|
|
<body>
|
|
<div id="body-container">
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script>
|
|
try {
|
|
let theme = localStorage.getItem('mdbook-theme');
|
|
let sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script>
|
|
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
|
let theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
const html = document.documentElement;
|
|
html.classList.remove('light')
|
|
html.classList.add(theme);
|
|
html.classList.add("js");
|
|
</script>
|
|
|
|
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script>
|
|
let sidebar = null;
|
|
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
} else {
|
|
sidebar = 'hidden';
|
|
}
|
|
sidebar_toggle.checked = sidebar === 'visible';
|
|
html.classList.remove('sidebar-visible');
|
|
html.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<!-- populated by js -->
|
|
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
|
<noscript>
|
|
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
|
</noscript>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
|
<div class="sidebar-resize-indicator"></div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
<div id="menu-bar" class="menu-bar sticky">
|
|
<div class="left-buttons">
|
|
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</label>
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<h1 class="menu-title">Rust Compiler Development Guide</h1>
|
|
|
|
<div class="right-buttons">
|
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
</a>
|
|
<a href="https://github.com/rust-lang/rustc-dev-guide" title="Git repository" aria-label="Git repository">
|
|
<i id="git-repository-button" class="fa fa-github"></i>
|
|
</a>
|
|
<a href="https://github.com/rust-lang/rustc-dev-guide/edit/master/src/building/suggested.md" title="Suggest an edit" aria-label="Suggest an edit">
|
|
<i id="git-edit-button" class="fa fa-edit"></i>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script>
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<h1 id="suggested-workflows"><a class="header" href="#suggested-workflows">Suggested workflows</a></h1>
|
|
<p>The full bootstrapping process takes quite a while. Here are some suggestions to
|
|
make your life easier.</p>
|
|
<ul>
|
|
<li><a href="#installing-a-pre-push-hook">Installing a pre-push hook</a></li>
|
|
<li><a href="#config-extensions">Config extensions</a></li>
|
|
<li><a href="#configuring-rust-analyzer-for-rustc">Configuring <code>rust-analyzer</code> for <code>rustc</code></a>
|
|
<ul>
|
|
<li><a href="#checking-the-library-tree">Checking the "library" tree</a></li>
|
|
<li><a href="#project-local-rust-analyzer-setup">Project-local rust-analyzer setup</a></li>
|
|
<li><a href="#using-a-separate-build-directory-for-rust-analyzer">Using a separate build directory for rust-analyzer</a></li>
|
|
<li><a href="#visual-studio-code">Visual Studio Code</a></li>
|
|
<li><a href="#neovim">Neovim</a></li>
|
|
<li><a href="#emacs">Emacs</a></li>
|
|
<li><a href="#helix">Helix</a></li>
|
|
<li><a href="#zed">Zed</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#check-check-and-check-again">Check, check, and check again</a></li>
|
|
<li><a href="#x-suggest"><code>x suggest</code></a></li>
|
|
<li><a href="#configuring-rustup-to-use-nightly">Configuring <code>rustup</code> to use nightly</a></li>
|
|
<li><a href="#faster-builds-with-ci-rustc">Faster Builds with CI-rustc</a></li>
|
|
<li><a href="#using-incremental-compilation">Using incremental compilation</a></li>
|
|
<li><a href="#fine-tuning-optimizations">Fine-tuning optimizations</a></li>
|
|
<li><a href="#working-on-multiple-branches-at-the-same-time">Working on multiple branches at the same time</a></li>
|
|
<li><a href="#working-with-nix">Working with nix</a>
|
|
<ul>
|
|
<li><a href="#note">Note</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#shell-completions">Shell Completions</a></li>
|
|
</ul>
|
|
<h2 id="installing-a-pre-push-hook"><a class="header" href="#installing-a-pre-push-hook">Installing a pre-push hook</a></h2>
|
|
<p>CI will automatically fail your build if it doesn't pass <code>tidy</code>, our internal
|
|
tool for ensuring code quality. If you'd like, you can install a <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">Git
|
|
hook</a> that will
|
|
automatically run <code>./x test tidy</code> on each push, to ensure your code is up to
|
|
par. If the hook fails then run <code>./x test tidy --bless</code> and commit the changes.
|
|
If you decide later that the pre-push behavior is undesirable, you can delete
|
|
the <code>pre-push</code> file in <code>.git/hooks</code>.</p>
|
|
<p>A prebuilt git hook lives at <a href="https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh"><code>src/etc/pre-push.sh</code></a>. It can be copied into
|
|
your <code>.git/hooks</code> folder as <code>pre-push</code> (without the <code>.sh</code> extension!).</p>
|
|
<p>You can also install the hook as a step of running <code>./x setup</code>!</p>
|
|
<h2 id="config-extensions"><a class="header" href="#config-extensions">Config extensions</a></h2>
|
|
<p>When working on different tasks, you might need to switch between different bootstrap configurations.
|
|
Sometimes you may want to keep an old configuration for future use. But saving raw config values in
|
|
random files and manually copying and pasting them can quickly become messy, especially if you have a
|
|
long history of different configurations.</p>
|
|
<p>To simplify managing multiple configurations, you can create config extensions.</p>
|
|
<p>For example, you can create a simple config file named <code>cross.toml</code>:</p>
|
|
<pre><code class="language-toml">[build]
|
|
build = "x86_64-unknown-linux-gnu"
|
|
host = ["i686-unknown-linux-gnu"]
|
|
target = ["i686-unknown-linux-gnu"]
|
|
|
|
|
|
[llvm]
|
|
download-ci-llvm = false
|
|
|
|
[target.x86_64-unknown-linux-gnu]
|
|
llvm-config = "/path/to/llvm-19/bin/llvm-config"
|
|
</code></pre>
|
|
<p>Then, include this in your <code>bootstrap.toml</code>:</p>
|
|
<pre><code class="language-toml">include = ["cross.toml"]
|
|
</code></pre>
|
|
<p>You can also include extensions within extensions recursively.</p>
|
|
<p><strong>Note:</strong> In the <code>include</code> field, the overriding logic follows a right-to-left order. For example,
|
|
in <code>include = ["a.toml", "b.toml"]</code>, extension <code>b.toml</code> overrides <code>a.toml</code>. Also, parent extensions
|
|
always overrides the inner ones.</p>
|
|
<h2 id="configuring-rust-analyzer-for-rustc"><a class="header" href="#configuring-rust-analyzer-for-rustc">Configuring <code>rust-analyzer</code> for <code>rustc</code></a></h2>
|
|
<h3 id="checking-the-library-tree"><a class="header" href="#checking-the-library-tree">Checking the "library" tree</a></h3>
|
|
<p>Checking the "library" tree requires a stage1 compiler, which can be a heavy process on some computers.
|
|
For this reason, bootstrap has a flag called <code>--skip-std-check-if-no-download-rustc</code> that skips checking the
|
|
"library" tree if <code>rust.download-rustc</code> isn't available. If you want to avoid putting a heavy load on your computer
|
|
with <code>rust-analyzer</code>, you can add the <code>--skip-std-check-if-no-download-rustc</code> flag to your <code>./x check</code> command in
|
|
the <code>rust-analyzer</code> configuration.</p>
|
|
<h3 id="project-local-rust-analyzer-setup"><a class="header" href="#project-local-rust-analyzer-setup">Project-local rust-analyzer setup</a></h3>
|
|
<p><code>rust-analyzer</code> can help you check and format your code whenever you save a
|
|
file. By default, <code>rust-analyzer</code> runs the <code>cargo check</code> and <code>rustfmt</code> commands,
|
|
but you can override these commands to use more adapted versions of these tools
|
|
when hacking on <code>rustc</code>. With custom setup, <code>rust-analyzer</code> can use <code>./x check</code>
|
|
to check the sources, and the stage 0 rustfmt to format them.</p>
|
|
<p>The default <code>rust-analyzer.check.overrideCommand</code> 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 <code>x check compiler --json-output</code> to only check the compiler part.
|
|
You can run <code>x check --help --verbose</code> to see the available parts.</p>
|
|
<p>Running <code>./x setup editor</code> will prompt you to create a project-local LSP config
|
|
file for one of the supported editors. You can also create the config file as a
|
|
step of running <code>./x setup</code>.</p>
|
|
<h3 id="using-a-separate-build-directory-for-rust-analyzer"><a class="header" href="#using-a-separate-build-directory-for-rust-analyzer">Using a separate build directory for rust-analyzer</a></h3>
|
|
<p>By default, when rust-analyzer runs a check or format command, it will share
|
|
the same build directory as manual command-line builds. This can be inconvenient
|
|
for two reasons:</p>
|
|
<ul>
|
|
<li>Each build will lock the build directory and force the other to wait, so it
|
|
becomes impossible to run command-line builds while rust-analyzer is running
|
|
commands in the background.</li>
|
|
<li>There is an increased risk of one of the builds deleting previously-built
|
|
artifacts due to conflicting compiler flags or other settings, forcing
|
|
additional rebuilds in some cases.</li>
|
|
</ul>
|
|
<p>To avoid these problems:</p>
|
|
<ul>
|
|
<li>Add <code>--build-dir=build/rust-analyzer</code> to all of the custom <code>x</code> commands in
|
|
your editor's rust-analyzer configuration.
|
|
(Feel free to choose a different directory name if desired.)</li>
|
|
<li>Modify the <code>rust-analyzer.rustfmt.overrideCommand</code> setting so that it points
|
|
to the copy of <code>rustfmt</code> in that other build directory.</li>
|
|
<li>Modify the <code>rust-analyzer.procMacro.server</code> setting so that it points to the
|
|
copy of <code>rust-analyzer-proc-macro-srv</code> in that other build directory.</li>
|
|
</ul>
|
|
<p>Using separate build directories for command-line builds and rust-analyzer
|
|
requires extra disk space.</p>
|
|
<h3 id="visual-studio-code"><a class="header" href="#visual-studio-code">Visual Studio Code</a></h3>
|
|
<p>Selecting <code>vscode</code> in <code>./x setup editor</code> will prompt you to create a
|
|
<code>.vscode/settings.json</code> file which will configure Visual Studio code. The
|
|
recommended <code>rust-analyzer</code> settings live at
|
|
<a href="https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json"><code>src/etc/rust_analyzer_settings.json</code></a>.</p>
|
|
<p>If running <code>./x check</code> on save is inconvenient, in VS Code you can use a <a href="https://code.visualstudio.com/docs/editor/tasks">Build
|
|
Task</a> instead:</p>
|
|
<pre><code class="language-JSON">// .vscode/tasks.json
|
|
{
|
|
"version": "2.0.0",
|
|
"tasks": [
|
|
{
|
|
"label": "./x check",
|
|
"command": "./x check",
|
|
"type": "shell",
|
|
"problemMatcher": "$rustc",
|
|
"presentation": { "clear": true },
|
|
"group": { "kind": "build", "isDefault": true }
|
|
}
|
|
]
|
|
}
|
|
</code></pre>
|
|
<h3 id="neovim"><a class="header" href="#neovim">Neovim</a></h3>
|
|
<p>For Neovim users, there are a few options. The
|
|
easiest way is by using <a href="https://github.com/folke/neoconf.nvim/">neoconf.nvim</a>,
|
|
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 <a href="https://rust-analyzer.github.io/manual.html#nvim-lsp">found
|
|
here</a>.</p>
|
|
<ol>
|
|
<li>First install the plugin. This can be done by following the steps in the
|
|
README.</li>
|
|
<li>Run <code>./x setup editor</code>, and select <code>vscode</code> to create a
|
|
<code>.vscode/settings.json</code> file. <code>neoconf</code> is able to read and update
|
|
rust-analyzer settings automatically when the project is opened when this
|
|
file is detected.</li>
|
|
</ol>
|
|
<p>If you're using <code>coc.nvim</code>, you can run <code>./x setup editor</code> and select <code>vim</code> to
|
|
create a <code>.vim/coc-settings.json</code>. The settings can be edited with
|
|
<code>:CocLocalConfig</code>. The recommended settings live at
|
|
<a href="https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json"><code>src/etc/rust_analyzer_settings.json</code></a>.</p>
|
|
<p>Another way is without a plugin, and creating your own logic in your
|
|
configuration. The following code will work for any checkout of rust-lang/rust (newer than Febuary 2025):</p>
|
|
<pre><code class="language-lua">local function expand_config_variables(option)
|
|
local var_placeholders = {
|
|
['${workspaceFolder}'] = function(_)
|
|
return vim.lsp.buf.list_workspace_folders()[1]
|
|
end,
|
|
}
|
|
|
|
if type(option) == "table" then
|
|
local mt = getmetatable(option)
|
|
local result = {}
|
|
for k, v in pairs(option) do
|
|
result[expand_config_variables(k)] = expand_config_variables(v)
|
|
end
|
|
return setmetatable(result, mt)
|
|
end
|
|
if type(option) ~= "string" then
|
|
return option
|
|
end
|
|
local ret = option
|
|
for key, fn in pairs(var_placeholders) do
|
|
ret = ret:gsub(key, fn)
|
|
end
|
|
return ret
|
|
end
|
|
lspconfig.rust_analyzer.setup {
|
|
root_dir = function()
|
|
local default = lspconfig.rust_analyzer.config_def.default_config.root_dir()
|
|
-- the default root detection uses the cargo workspace root.
|
|
-- but for rust-lang/rust, the standard library is in its own workspace.
|
|
-- use the git root instead.
|
|
local compiler_config = vim.fs.joinpath(default, "../src/bootstrap/defaults/config.compiler.toml")
|
|
if vim.fs.basename(default) == "library" and vim.uv.fs_stat(compiler_config) then
|
|
return vim.fs.dirname(default)
|
|
end
|
|
return default
|
|
end,
|
|
on_init = function(client)
|
|
local path = client.workspace_folders[1].name
|
|
local config = vim.fs.joinpath(path, "src/etc/rust_analyzer_zed.json")
|
|
if vim.uv.fs_stat(config) then
|
|
-- load rust-lang/rust settings
|
|
local file = io.open(config)
|
|
local json = vim.json.decode(file:read("*a"))
|
|
client.config.settings["rust-analyzer"] = expand_config_variables(json.lsp["rust-analyzer"].initialization_options)
|
|
client.notify("workspace/didChangeConfiguration", { settings = client.config.settings })
|
|
end
|
|
return true
|
|
end
|
|
}
|
|
</code></pre>
|
|
<p>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
|
|
<a href="https://github.com/stevearc/overseer.nvim">overseer.nvim</a> that can <a href="https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks">read
|
|
VSCode's <code>task.json</code>
|
|
files</a>,
|
|
and follow the same instructions as above.</p>
|
|
<h3 id="emacs"><a class="header" href="#emacs">Emacs</a></h3>
|
|
<p>Emacs provides support for rust-analyzer with project-local configuration
|
|
through <a href="https://www.gnu.org/software/emacs/manual/html_node/eglot/">Eglot</a>.
|
|
Steps for setting up Eglot with rust-analyzer can be <a href="https://rust-analyzer.github.io/manual.html#eglot">found
|
|
here</a>.
|
|
Having set up Emacs & Eglot for Rust development in general, you can run
|
|
<code>./x setup editor</code> and select <code>emacs</code>, which will prompt you to create
|
|
<code>.dir-locals.el</code> with the recommended configuration for Eglot.
|
|
The recommended settings live at <a href="https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_eglot.el"><code>src/etc/rust_analyzer_eglot.el</code></a>.
|
|
For more information on project-specific Eglot configuration, consult <a href="https://www.gnu.org/software/emacs/manual/html_node/eglot/Project_002dspecific-configuration.html">the
|
|
manual</a>.</p>
|
|
<h3 id="helix"><a class="header" href="#helix">Helix</a></h3>
|
|
<p>Helix comes with built-in LSP and rust-analyzer support.
|
|
It can be configured through <code>languages.toml</code>, as described
|
|
<a href="https://docs.helix-editor.com/languages.html">here</a>.
|
|
You can run <code>./x setup editor</code> and select <code>helix</code>, which will prompt you to
|
|
create <code>languages.toml</code> with the recommended configuration for Helix. The
|
|
recommended settings live at <a href="https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_helix.toml"><code>src/etc/rust_analyzer_helix.toml</code></a>.</p>
|
|
<h3 id="zed"><a class="header" href="#zed">Zed</a></h3>
|
|
<p>Zed comes with built-in LSP and rust-analyzer support.
|
|
It can be configured through <code>.zed/settings.json</code>, as described
|
|
<a href="https://zed.dev/docs/configuring-languages">here</a>. Selecting <code>zed</code>
|
|
in <code>./x setup editor</code> will prompt you to create a <code>.zed/settings.json</code>
|
|
file which will configure Zed with the recommended configuration. The
|
|
recommended <code>rust-analyzer</code> settings live
|
|
at <a href="https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_zed.json"><code>src/etc/rust_analyzer_zed.json</code></a>.</p>
|
|
<h2 id="check-check-and-check-again"><a class="header" href="#check-check-and-check-again">Check, check, and check again</a></h2>
|
|
<p>When doing simple refactoring, it can be useful to run <code>./x check</code>
|
|
continuously. If you set up <code>rust-analyzer</code> as described above, this will be
|
|
done for you every time you save a file. Here you are just checking that the
|
|
compiler can <strong>build</strong>, but often that is all you need (e.g., when renaming a
|
|
method). You can then run <code>./x build</code> when you actually need to run tests.</p>
|
|
<p>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 <code>git bisect</code> to track down
|
|
<strong>precisely</strong> 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.</p>
|
|
<h2 id="x-suggest"><a class="header" href="#x-suggest"><code>x suggest</code></a></h2>
|
|
<p>The <code>x suggest</code> subcommand suggests (and runs) a subset of the extensive
|
|
<code>rust-lang/rust</code> tests based on files you have changed. This is especially
|
|
useful for new contributors who have not mastered the arcane <code>x</code> 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 <code>tidy</code> and <code>linkchecker</code> is useful when editing Markdown files,
|
|
whereas UI tests are much less likely to be helpful. While <code>x suggest</code> is a
|
|
useful tool, it does not guarantee perfect coverage (just as PR CI isn't a
|
|
substitute for bors). See the <a href="../tests/suggest-tests.html">dedicated chapter</a> for
|
|
more information and contribution instructions.</p>
|
|
<p>Please note that <code>x suggest</code> is in a beta state currently and the tests that it
|
|
will suggest are limited.</p>
|
|
<h2 id="configuring-rustup-to-use-nightly"><a class="header" href="#configuring-rustup-to-use-nightly">Configuring <code>rustup</code> to use nightly</a></h2>
|
|
<p>Some parts of the bootstrap process uses pinned, nightly versions of tools like
|
|
rustfmt. To make things like <code>cargo fmt</code> work correctly in your repo, run</p>
|
|
<pre><code class="language-console">cd <path to rustc repo>
|
|
rustup override set nightly
|
|
</code></pre>
|
|
<p>after <a href="https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust">installing a nightly toolchain</a> with <code>rustup</code>. Don't forget to do this
|
|
for all directories you have <a href="./suggested.html#working-on-multiple-branches-at-the-same-time">setup a worktree for</a>. You may need to use the
|
|
pinned nightly version from <code>src/stage0</code>, but often the normal <code>nightly</code> channel
|
|
will work.</p>
|
|
<p><strong>Note</strong> see <a href="suggested.html#configuring-rust-analyzer-for-rustc">the section on vscode</a> for how to configure it with this real
|
|
rustfmt <code>x</code> uses, and <a href="how-to-build-and-run.html">the section on rustup</a> for how to setup <code>rustup</code>
|
|
toolchain for your bootstrapped compiler</p>
|
|
<p><strong>Note</strong> This does <em>not</em> allow you to build <code>rustc</code> with cargo directly. You
|
|
still have to use <code>x</code> to work on the compiler or standard library, this just
|
|
lets you use <code>cargo fmt</code>.</p>
|
|
<h2 id="faster-builds-with-ci-rustc"><a class="header" href="#faster-builds-with-ci-rustc">Faster Builds with CI-rustc</a></h2>
|
|
<p>If you are not working on the compiler, you often don't need to build the compiler tree.
|
|
For example, you can skip building the compiler and only build the <code>library</code> tree or the
|
|
tools under <code>src/tools</code>. To achieve that, you have to enable this by setting the <code>download-rustc</code>
|
|
option in your configuration. This tells bootstrap to use the latest nightly compiler for <code>stage > 0</code>
|
|
steps, meaning it will have two precompiled compilers: stage0 compiler and <code>download-rustc</code> compiler
|
|
for <code>stage > 0</code> steps. This way, it will never need to build the in-tree compiler. As a result, your
|
|
build time will be significantly reduced by not building the in-tree compiler.</p>
|
|
<h2 id="using-incremental-compilation"><a class="header" href="#using-incremental-compilation">Using incremental compilation</a></h2>
|
|
<p>You can further enable the <code>--incremental</code> flag to save additional time in
|
|
subsequent rebuilds:</p>
|
|
<pre><code class="language-bash">./x test tests/ui --incremental --test-args issue-1234
|
|
</code></pre>
|
|
<p>If you don't want to include the flag with every command, you can enable it in
|
|
the <code>bootstrap.toml</code>:</p>
|
|
<pre><code class="language-toml">[rust]
|
|
incremental = true
|
|
</code></pre>
|
|
<p>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 <code>build</code>
|
|
directory from time to time.</p>
|
|
<h2 id="fine-tuning-optimizations"><a class="header" href="#fine-tuning-optimizations">Fine-tuning optimizations</a></h2>
|
|
<p>Setting <code>optimize = false</code> makes the compiler too slow for tests. However, to
|
|
improve the test cycle, you can disable optimizations selectively only for the
|
|
crates you'll have to rebuild
|
|
(<a href="https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/incremental.20compilation.20question/near/202712165">source</a>).
|
|
For example, when working on <code>rustc_mir_build</code>, the <code>rustc_mir_build</code> and
|
|
<code>rustc_driver</code> crates take the most time to incrementally rebuild. You could
|
|
therefore set the following in the root <code>Cargo.toml</code>:</p>
|
|
<pre><code class="language-toml">[profile.release.package.rustc_mir_build]
|
|
opt-level = 0
|
|
[profile.release.package.rustc_driver]
|
|
opt-level = 0
|
|
</code></pre>
|
|
<h2 id="working-on-multiple-branches-at-the-same-time"><a class="header" href="#working-on-multiple-branches-at-the-same-time">Working on multiple branches at the same time</a></h2>
|
|
<p>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.</p>
|
|
<p>Fortunately, Git has a better solution called <a href="https://git-scm.com/docs/git-worktree">worktrees</a>. 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.</p>
|
|
<p>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:</p>
|
|
<pre><code class="language-bash">git worktree add ../rust2
|
|
</code></pre>
|
|
<p>Creating a new worktree for a new branch based on <code>master</code> looks like:</p>
|
|
<pre><code class="language-bash">git worktree add -b my-feature ../rust2 master
|
|
</code></pre>
|
|
<p>You can then use that rust2 folder as a separate workspace for modifying and
|
|
building <code>rustc</code>!</p>
|
|
<h2 id="working-with-nix"><a class="header" href="#working-with-nix">Working with nix</a></h2>
|
|
<p>Several nix configurations are defined in <code>src/tools/nix-dev-shell</code>.</p>
|
|
<p>If you're using direnv, you can create a symbol link to <code>src/tools/nix-dev-shell/envrc-flake</code> or <code>src/tools/nix-dev-shell/envrc-shell</code></p>
|
|
<pre><code class="language-bash">ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc # Use flake
|
|
</code></pre>
|
|
<p>or</p>
|
|
<pre><code class="language-bash">ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell
|
|
</code></pre>
|
|
<h3 id="note"><a class="header" href="#note">Note</a></h3>
|
|
<p>Note that when using nix on a not-NixOS distribution, it may be necessary to set
|
|
<strong><code>patch-binaries-for-nix = true</code> in <code>bootstrap.toml</code></strong>. Bootstrap tries to detect
|
|
whether it's running in nix and enable patching automatically, but this
|
|
detection can have false negatives.</p>
|
|
<p>You can also use your nix shell to manage <code>bootstrap.toml</code>:</p>
|
|
<pre><code class="language-nix">let
|
|
config = pkgs.writeText "rustc-config" ''
|
|
# Your bootstrap.toml content goes here
|
|
''
|
|
pkgs.mkShell {
|
|
/* ... */
|
|
# This environment variable tells bootstrap where our bootstrap.toml is.
|
|
RUST_BOOTSTRAP_CONFIG = config;
|
|
}
|
|
</code></pre>
|
|
<h2 id="shell-completions"><a class="header" href="#shell-completions">Shell Completions</a></h2>
|
|
<p>If you use Bash, Zsh, Fish or PowerShell, you can find automatically-generated shell
|
|
completion scripts for <code>x.py</code> in
|
|
<a href="https://github.com/rust-lang/rust/tree/master/src/etc/completions"><code>src/etc/completions</code></a>.</p>
|
|
<p>You can use <code>source ./src/etc/completions/x.py.<extension></code> to load completions
|
|
for your shell of choice, or <code>& .\src\etc\completions\x.py.ps1</code> for PowerShell.
|
|
Adding this to your shell's startup script (e.g. <code>.bashrc</code>) will automatically
|
|
load this completion.</p>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
<a rel="prev" href="../building/prerequisites.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../building/build-install-distribution-artifacts.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
<a rel="prev" href="../building/prerequisites.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../building/build-install-distribution-artifacts.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
window.playground_copyable = true;
|
|
</script>
|
|
|
|
|
|
<script src="../elasticlunr.min.js"></script>
|
|
<script src="../mark.min.js"></script>
|
|
<script src="../searcher.js"></script>
|
|
|
|
<script src="../clipboard.min.js"></script>
|
|
<script src="../highlight.js"></script>
|
|
<script src="../book.js"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
<script src="../mermaid.min.js"></script>
|
|
<script src="../mermaid-init.js"></script>
|
|
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|