blob: 6d55fc1bb1b87029f698b14c7ccd956cae1555d6 [file] [log] [blame]
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Working on Cargo - Cargo Contributor Guide</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<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" href="../highlight.css">
<link rel="stylesheet" href="../tomorrow-night.css">
<link rel="stylesheet" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root to javascript -->
<script>
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</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 {
var theme = localStorage.getItem('mdbook-theme');
var 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>
var 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>
var sidebar = null;
var 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="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">Cargo Contributor 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/cargo/tree/master/src/doc/contrib/src" 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/cargo/edit/master/src/doc/contrib/src/process/working-on-cargo.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="working-on-cargo"><a class="header" href="#working-on-cargo">Working on Cargo</a></h1>
<p>This chapter gives an overview of how to build Cargo, make a change, and
submit a Pull Request.</p>
<ol start="0">
<li><a href="#before-hacking-on-cargo">Before hacking on Cargo.</a></li>
<li><a href="#checkout-out-the-source">Check out the Cargo source.</a></li>
<li><a href="#building-cargo">Building Cargo.</a></li>
<li><a href="#making-a-change">Making a change.</a></li>
<li><a href="../tests/index.html">Writing and running tests.</a></li>
<li><a href="#submitting-a-pull-request">Submitting a Pull Request.</a></li>
<li><a href="#the-merging-process">The merging process.</a></li>
</ol>
<h2 id="before-hacking-on-cargo"><a class="header" href="#before-hacking-on-cargo">Before hacking on Cargo</a></h2>
<p>We encourage people to discuss their design before hacking on code. This gives
the Cargo team a chance to know your idea more. Sometimes after a discussion,
we even find a way to solve the problem without coding! Typically, you
<a href="https://github.com/rust-lang/cargo/issues">file an issue</a> or start a thread on the <a href="https://internals.rust-lang.org/c/tools-and-infrastructure/cargo">internals forum</a> before submitting a
pull request.</p>
<p>Please read <a href="index.html">the process</a> of how features and bugs are managed in Cargo.
<strong>Only issues that have been explicitly marked as <a href="https://github.com/rust-lang/cargo/issues?q=is%3Aissue+is%3Aopen+label%3AS-accepted">accepted</a> will be reviewed.</strong></p>
<h2 id="checkout-the-source"><a class="header" href="#checkout-the-source">Checkout the source</a></h2>
<p>We use the “fork and pull” model <a href="https://help.github.com/articles/about-collaborative-development-models/">described here</a>, where
contributors push changes to their personal fork and <a href="https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request">create pull requests</a> to
bring those changes into the source repository. Cargo uses <a href="https://git-scm.com/">git</a> and <a href="https://github.com/">GitHub</a>
for all development.</p>
<ol>
<li>Fork the <a href="https://github.com/rust-lang/cargo/"><code>rust-lang/cargo</code></a> repository on GitHub to your personal account
(see <a href="https://docs.github.com/en/github/getting-started-with-github/fork-a-repo">GitHub docs</a>).</li>
<li>Clone your fork to your local machine using <code>git clone</code> (see <a href="https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository">GitHub
docs</a>)</li>
<li>It is recommended to start a new branch for the change you want to make.
All Pull Requests are made against the master branch.</li>
</ol>
<h2 id="building-cargo"><a class="header" href="#building-cargo">Building Cargo</a></h2>
<p>Cargo is built by…running <code>cargo</code>! There are a few prerequisites that you
need to have installed:</p>
<ul>
<li><code>rustc</code> and <code>cargo</code> need to be installed. Cargo is expected to build and
test with the current stable, beta, and nightly releases. It is your choice
which to use. Nightly is recommended, since some nightly-specific tests are
disabled when using the stable release. But using stable is fine if you
aren’t working on those.</li>
<li>A C compiler (typically gcc, clang, or MSVC).</li>
<li><a href="https://git-scm.com/">git</a></li>
<li>Unix:
<ul>
<li>pkg-config</li>
<li>OpenSSL (<code>libssl-dev</code> on Ubuntu, <code>openssl-devel</code> on Fedora)</li>
</ul>
</li>
<li>macOS:
<ul>
<li>OpenSSL (<a href="https://brew.sh/">homebrew</a> is recommended to install the <code>openssl</code> package)</li>
</ul>
</li>
</ul>
<p>If you can successfully run <code>cargo build</code>, you should be good to go!</p>
<h2 id="running-cargo"><a class="header" href="#running-cargo">Running Cargo</a></h2>
<p>You can use <code>cargo run</code> to run cargo itself, or you can use the path directly
to the cargo binary, such as <code>target/debug/cargo</code>.</p>
<p>If you are using <a href="https://rust-lang.github.io/rustup/"><code>rustup</code></a>, beware that running the binary directly can cause
issues with rustup overrides. Usually, when <code>cargo</code> is executed as part of
rustup, the toolchain becomes sticky (via an environment variable), and all
calls to <code>rustc</code> will use the same toolchain. But when <code>cargo</code> is not run via
rustup, the toolchain may change based on the directory. Since Cargo changes
the directory for each compilation, this can cause different calls to <code>rustc</code>
to use different versions. There are a few workarounds:</p>
<ul>
<li>Don’t use rustup overrides.</li>
<li>Use <code>rustup run &lt;toolchain&gt; target/debug/cargo</code> to specify the toolchain(rustc) to use.
For example, <code>rustup run nightly target/debug/cargo</code>.</li>
<li>Set the <code>RUSTC</code> environment variable to a specific <code>rustc</code> executable (not
the rustup wrapper).</li>
<li>Create a <a href="https://rust-lang.github.io/rustup/concepts/toolchains.html#custom-toolchains">custom toolchain</a>. This is a bit of a hack, but you can create a
directory in the rustup <code>toolchains</code> directory, and create symlinks for all
the files and directories in there to your toolchain of choice (such as
nightly), except for the <code>cargo</code> binary, which you can symlink to your
<code>target/debug/cargo</code> binary in your project directory.</li>
</ul>
<p><em>Normally</em>, all development is done by running Cargo’s test suite, so running
it directly usually isn’t required. But it can be useful for testing Cargo on
more complex projects.</p>
<h2 id="making-a-change"><a class="header" href="#making-a-change">Making a change</a></h2>
<p>Some guidelines on working on a change:</p>
<ul>
<li>All code changes are expected to comply with the formatting suggested by
<code>rustfmt</code>. You can use <code>rustup component add rustfmt</code> to install <code>rustfmt</code>
and use <code>cargo fmt</code> to automatically format your code.</li>
<li>Include tests that cover all non-trivial code. See the <a href="../tests/index.html">Testing chapter</a> for
more about writing and running tests.</li>
<li>All code should be warning-free. This is checked during tests.</li>
</ul>
<h2 id="submitting-a-pull-request"><a class="header" href="#submitting-a-pull-request">Submitting a Pull Request</a></h2>
<p>After you have committed your work, and pushed it to GitHub, you can
open a Pull Request</p>
<ul>
<li>Push your commits to GitHub and create a pull request against Cargo’s
<code>master</code> branch.</li>
<li>Include a clear description of what the change is and why it is being made.</li>
<li>Use <a href="https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue">GitHub’s keywords</a> in the description to automatically link to an issue
if the PR resolves the issue. For example <code>Closes #1234</code> will link issue
#1234 to the PR. When the PR is merged, GitHub will automatically close the
issue.</li>
</ul>
<p><a href="https://github.com/rustbot"><code>@rustbot</code></a> will automatically assign a reviewer for the PR. It
may take at least a few days for someone to respond. If you don’t get a
response in over a week, feel free to ping the assigned reviewer.</p>
<p>When your PR is submitted, GitHub automatically runs all tests. The GitHub
interface will show a green checkmark if it passes, or a red X if it fails.
There are links to the logs on the PR page to diagnose any issues. The tests
typically finish in under 30 minutes.</p>
<p>The reviewer might point out changes deemed necessary. Large or tricky changes
may require several passes of review and changes.</p>
<blockquote>
<p><strong>tip:</strong> Prefer atomic commits where each commit is a single, complete, and coherent unit of work.
For example, if your feature work leads to renaming a module, make the rename its own commit.
However, adding an internal function that is unused is not complete or coherent.</p>
<p>As part of your atomic commits, prefer adding tests as their own commit <em>before</em> any functionality changes.
The tests should pass in each commit, demonstrating the behavior before your
change and how each commit affects behavior.
This makes it easier for reviewers and community members to understand the
precise details of the side effects of your change and gives you confidence
that your tests are verifying the right behavior.</p>
<p>Examples:</p>
<ul>
<li><a href="https://github.com/rust-lang/cargo/pull/13910">#13910: fix: remove symlink dir on Windows</a></li>
<li><a href="https://github.com/rust-lang/cargo/pull/14006">#14006: fix(add): Avoid escaping double-quotes by using string literals</a></li>
</ul>
</blockquote>
<h3 id="status-labeling"><a class="header" href="#status-labeling">Status labeling</a></h3>
<p>PRs will get marked with <a href="https://github.com/rust-lang/cargo/labels">labels</a> like <a href="https://github.com/rust-lang/cargo/labels/S-waiting-on-review"><code>S-waiting-on-review</code></a> or <a href="https://github.com/rust-lang/cargo/labels/S-waiting-on-author"><code>S-waiting-on-author</code></a> to indicate their status.
The <a href="https://github.com/rustbot"><code>@rustbot</code></a> bot can be used by anyone to adjust the labels.
If a PR gets marked as <code>S-waiting-on-author</code>, and you have pushed new changes that you would like to be reviewed, you can write a comment on the PR with the text <code>@rustbot ready</code>.
The bot will switch the labels on the PR.</p>
<p>More information about these commands can be found at the <a href="https://forge.rust-lang.org/triagebot/shortcuts.html">shortcuts documentation</a>.</p>
<h2 id="the-merging-process"><a class="header" href="#the-merging-process">The merging process</a></h2>
<p>After a reviewer has approved your PR,
they will add the PR to <a href="https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue">GitHub merge queue</a>.
The merge queue will create a temporary branch with your PR,
and run all required jobs.
If it fails, it will be removed from the queue.
The merge queue ensures that the master branch is always in a good state,
and that merges are processed one at a time.
The <a href="https://github.com/rust-lang/cargo/queue/master">merge queue dashboard</a> shows the current queued pull requests.</p>
<p>Assuming everything works, congratulations! It may take at least a week for
the changes to arrive on the nightly channel. See the <a href="release.html">release chapter</a> for
more information on how Cargo releases are made.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../process/index.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="../process/release.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="../process/index.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="../process/release.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 -->
</div>
</body>
</html>