You've already forked uutils.github.io
mirror of
https://github.com/uutils/uutils.github.io.git
synced 2026-06-10 16:12:28 -07:00
deploy: f0e8d44e6e
This commit is contained in:
+28
-27
@@ -176,11 +176,11 @@
|
||||
<li>GNU Make (optional)</li>
|
||||
</ul>
|
||||
<h3 id="rust-version"><a class="header" href="#rust-version">Rust Version</a></h3>
|
||||
<p>uutils follows Rust's release channels and is tested against stable, beta and nightly.
|
||||
The current Minimum Supported Rust Version (MSRV) is <code>1.64.0</code>.</p>
|
||||
<p>uutils follows Rust's release channels and is tested against stable, beta and
|
||||
nightly. The current Minimum Supported Rust Version (MSRV) is <code>1.64.0</code>.</p>
|
||||
<h2 id="building"><a class="header" href="#building">Building</a></h2>
|
||||
<p>There are currently two methods to build the uutils binaries: either Cargo
|
||||
or GNU Make.</p>
|
||||
<p>There are currently two methods to build the uutils binaries: either Cargo or
|
||||
GNU Make.</p>
|
||||
<blockquote>
|
||||
<p>Building the full package, including all documentation, requires both Cargo
|
||||
and Gnu Make on a Unix platform.</p>
|
||||
@@ -190,15 +190,15 @@ and Gnu Make on a Unix platform.</p>
|
||||
cd coreutils
|
||||
</code></pre>
|
||||
<h3 id="cargo"><a class="header" href="#cargo">Cargo</a></h3>
|
||||
<p>Building uutils using Cargo is easy because the process is the same as for
|
||||
every other Rust program:</p>
|
||||
<p>Building uutils using Cargo is easy because the process is the same as for every
|
||||
other Rust program:</p>
|
||||
<pre><code class="language-shell">cargo build --release
|
||||
</code></pre>
|
||||
<p>This command builds the most portable common core set of uutils into a multicall
|
||||
(BusyBox-type) binary, named 'coreutils', on most Rust-supported platforms.</p>
|
||||
<p>Additional platform-specific uutils are often available. Building these
|
||||
expanded sets of uutils for a platform (on that platform) is as simple as
|
||||
specifying it as a feature:</p>
|
||||
<p>Additional platform-specific uutils are often available. Building these expanded
|
||||
sets of uutils for a platform (on that platform) is as simple as specifying it
|
||||
as a feature:</p>
|
||||
<pre><code class="language-shell">cargo build --release --features macos
|
||||
# or ...
|
||||
cargo build --release --features windows
|
||||
@@ -206,15 +206,15 @@ cargo build --release --features windows
|
||||
cargo build --release --features unix
|
||||
</code></pre>
|
||||
<p>If you don't want to build every utility available on your platform into the
|
||||
final binary, you can also specify which ones you want to build manually.
|
||||
For example:</p>
|
||||
final binary, you can also specify which ones you want to build manually. For
|
||||
example:</p>
|
||||
<pre><code class="language-shell">cargo build --features "base32 cat echo rm" --no-default-features
|
||||
</code></pre>
|
||||
<p>If you don't want to build the multicall binary and would prefer to build
|
||||
the utilities as individual binaries, that is also possible. Each utility
|
||||
is contained in its own package within the main repository, named
|
||||
"uu_UTILNAME". To build individual utilities, use cargo to build just the
|
||||
specific packages (using the <code>--package</code> [aka <code>-p</code>] option). For example:</p>
|
||||
<p>If you don't want to build the multicall binary and would prefer to build the
|
||||
utilities as individual binaries, that is also possible. Each utility is
|
||||
contained in its own package within the main repository, named "uu_UTILNAME". To
|
||||
build individual utilities, use cargo to build just the specific packages (using
|
||||
the <code>--package</code> [aka <code>-p</code>] option). For example:</p>
|
||||
<pre><code class="language-shell">cargo build -p uu_base32 -p uu_cat -p uu_echo -p uu_rm
|
||||
</code></pre>
|
||||
<h3 id="gnu-make"><a class="header" href="#gnu-make">GNU Make</a></h3>
|
||||
@@ -236,9 +236,11 @@ specific packages (using the <code>--package</code> [aka <code>-p</code>] option
|
||||
<p>Likewise, installing can simply be done using:</p>
|
||||
<pre><code class="language-shell">cargo install --path . --locked
|
||||
</code></pre>
|
||||
<p>This command will install uutils into Cargo's <em>bin</em> folder (<em>e.g.</em> <code>$HOME/.cargo/bin</code>).</p>
|
||||
<p>This does not install files necessary for shell completion or manpages.
|
||||
For manpages or shell completion to work, use <code>GNU Make</code> or see <code>Manually install shell completions</code>/<code>Manually install manpages</code>.</p>
|
||||
<p>This command will install uutils into Cargo's <em>bin</em> folder (<em>e.g.</em>
|
||||
<code>$HOME/.cargo/bin</code>).</p>
|
||||
<p>This does not install files necessary for shell completion or manpages. For
|
||||
manpages or shell completion to work, use <code>GNU Make</code> or see
|
||||
<code>Manually install shell completions</code>/<code>Manually install manpages</code>.</p>
|
||||
<h3 id="install-with-gnu-make"><a class="header" href="#install-with-gnu-make">Install with GNU Make</a></h3>
|
||||
<p>To install all available utilities:</p>
|
||||
<pre><code class="language-shell">make install
|
||||
@@ -266,26 +268,25 @@ make PREFIX=/my/path install
|
||||
for <code>bash</code>, <code>fish</code> and <code>zsh</code>. Completions for <code>elvish</code> and <code>powershell</code> can also
|
||||
be generated; See <code>Manually install shell completions</code>.</p>
|
||||
<h3 id="manually-install-shell-completions"><a class="header" href="#manually-install-shell-completions">Manually install shell completions</a></h3>
|
||||
<p>The <code>coreutils</code> binary can generate completions for the <code>bash</code>, <code>elvish</code>, <code>fish</code>, <code>powershell</code>
|
||||
and <code>zsh</code> shells. It prints the result to stdout.</p>
|
||||
<p>The <code>coreutils</code> binary can generate completions for the <code>bash</code>, <code>elvish</code>,
|
||||
<code>fish</code>, <code>powershell</code> and <code>zsh</code> shells. It prints the result to stdout.</p>
|
||||
<p>The syntax is:</p>
|
||||
<pre><code class="language-shell">cargo run completion <utility> <shell>
|
||||
</code></pre>
|
||||
<p>So, to install completions for <code>ls</code> on <code>bash</code> to <code>/usr/local/share/bash-completion/completions/ls</code>,
|
||||
run:</p>
|
||||
<p>So, to install completions for <code>ls</code> on <code>bash</code> to
|
||||
<code>/usr/local/share/bash-completion/completions/ls</code>, run:</p>
|
||||
<pre><code class="language-shell">cargo run completion ls bash > /usr/local/share/bash-completion/completions/ls
|
||||
</code></pre>
|
||||
<h3 id="manually-install-manpages"><a class="header" href="#manually-install-manpages">Manually install manpages</a></h3>
|
||||
<p>To generate manpages, the syntax is:</p>
|
||||
<pre><code class="language-bash">cargo run manpage <utility>
|
||||
</code></pre>
|
||||
<p>So, to install the manpage for <code>ls</code> to <code>/usr/local/share/man/man1/ls.1</code>
|
||||
run:</p>
|
||||
<p>So, to install the manpage for <code>ls</code> to <code>/usr/local/share/man/man1/ls.1</code> run:</p>
|
||||
<pre><code class="language-bash">cargo run manpage ls > /usr/local/share/man/man1/ls.1
|
||||
</code></pre>
|
||||
<h2 id="un-installation"><a class="header" href="#un-installation">Un-installation</a></h2>
|
||||
<p>Un-installation differs depending on how you have installed uutils. If you used
|
||||
Cargo to install, use Cargo to uninstall. If you used GNU Make to install, use
|
||||
<p>Un-installation differs depending on how you have installed uutils. If you used
|
||||
Cargo to install, use Cargo to uninstall. If you used GNU Make to install, use
|
||||
Make to uninstall.</p>
|
||||
<h3 id="uninstall-with-cargo"><a class="header" href="#uninstall-with-cargo">Uninstall with Cargo</a></h3>
|
||||
<p>To uninstall uutils:</p>
|
||||
|
||||
+166
-29
@@ -170,23 +170,13 @@
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
<!-- markdownlint-disable MD041 -->
|
||||
<!-- spell-checker:ignore reimplementing toybox -->
|
||||
<!-- spell-checker:ignore reimplementing toybox RUNTEST -->
|
||||
<h1 id="contributing-to-coreutils"><a class="header" href="#contributing-to-coreutils">Contributing to coreutils</a></h1>
|
||||
<p>Contributions are very welcome, and should target Rust's main branch until the
|
||||
standard libraries are stabilized. You may <em>claim</em> an item on the to-do list by
|
||||
following these steps:</p>
|
||||
<ol>
|
||||
<li>Open an issue named "Implement [the utility of your choice]", e.g. "Implement
|
||||
ls".</li>
|
||||
<li>State that you are working on this utility.</li>
|
||||
<li>Develop the utility.</li>
|
||||
<li>Add integration tests.</li>
|
||||
<li>Add the reference to your utility into Cargo.toml and Makefile.</li>
|
||||
<li>Remove utility from the to-do list in the README.</li>
|
||||
<li>Submit a pull request and close the issue.</li>
|
||||
</ol>
|
||||
<p>The steps above imply that, before starting to work on a utility, you should
|
||||
search the issues to make sure no one else is working on it.</p>
|
||||
<p>Contributions are very welcome via Pull Requests. If you don't know where to
|
||||
start, take a look at the
|
||||
<a href="https://github.com/uutils/coreutils/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22"><code>good-first-issues</code></a>.
|
||||
If you have any questions, feel free to ask them in the issues or on
|
||||
<a href="https://discord.gg/wQVJbvJ">Discord</a>.</p>
|
||||
<h2 id="best-practices"><a class="header" href="#best-practices">Best practices</a></h2>
|
||||
<ol>
|
||||
<li>Follow what GNU is doing in terms of options and behavior. It is recommended
|
||||
@@ -208,30 +198,166 @@ other binaries.</li>
|
||||
utilities, nor should it link to or reference GNU libraries.</li>
|
||||
</ol>
|
||||
<h2 id="platforms"><a class="header" href="#platforms">Platforms</a></h2>
|
||||
<p>We take pride in supporting many operating systems and architectures.</p>
|
||||
<p><strong>Tip:</strong>
|
||||
For Windows, Microsoft provides some images (VMWare, Hyper-V, VirtualBox and Parallels)
|
||||
for development:
|
||||
<p>We take pride in supporting many operating systems and architectures. Any code
|
||||
you contribute must at least compile without warnings for all platforms in the
|
||||
CI. However, you can use <code>#[cfg(...)]</code> attributes to create platform dependent features.</p>
|
||||
<p><strong>Tip:</strong> For Windows, Microsoft provides some images (VMWare, Hyper-V,
|
||||
VirtualBox and Parallels) for development:
|
||||
<a href="https://developer.microsoft.com/windows/downloads/virtual-machines/">https://developer.microsoft.com/windows/downloads/virtual-machines/</a></p>
|
||||
<h2 id="tools"><a class="header" href="#tools">Tools</a></h2>
|
||||
<p>We have an extensive CI that will check your code before it can be merged. This
|
||||
section explains how to run those checks locally to avoid waiting for the CI.</p>
|
||||
<h3 id="pre-commit-hooks"><a class="header" href="#pre-commit-hooks">pre-commit hooks</a></h3>
|
||||
<p>A configuration for <code>pre-commit</code> is provided in the repository. It allows
|
||||
automatically checking every git commit you make to ensure it compiles, and
|
||||
passes <code>clippy</code> and <code>rustfmt</code> without warnings.</p>
|
||||
<p>To use the provided hook:</p>
|
||||
<ol>
|
||||
<li><a href="https://pre-commit.com/#install">Install <code>pre-commit</code></a></li>
|
||||
<li>Run <code>pre-commit install</code> while in the repository directory</li>
|
||||
</ol>
|
||||
<p>Your git commits will then automatically be checked. If a check fails, an error
|
||||
message will explain why, and your commit will be canceled. You can then make
|
||||
the suggested changes, and run <code>git commit ...</code> again.</p>
|
||||
<h3 id="clippy"><a class="header" href="#clippy">clippy</a></h3>
|
||||
<pre><code class="language-shell">cargo clippy --all-targets --all-features
|
||||
</code></pre>
|
||||
<p>The <code>msrv</code> key in the clippy configuration file <code>clippy.toml</code> is used to disable
|
||||
lints pertaining to newer features by specifying the minimum supported Rust
|
||||
version (MSRV).</p>
|
||||
<h3 id="rustfmt"><a class="header" href="#rustfmt">rustfmt</a></h3>
|
||||
<pre><code class="language-shell">cargo fmt --all
|
||||
</code></pre>
|
||||
<h3 id="cargo-deny"><a class="header" href="#cargo-deny">cargo-deny</a></h3>
|
||||
<p>This project uses <a href="https://github.com/EmbarkStudios/cargo-deny/">cargo-deny</a> to
|
||||
detect duplicate dependencies, checks licenses, etc. To run it locally, first
|
||||
install it and then run with:</p>
|
||||
<pre><code>cargo deny --all-features check all
|
||||
</code></pre>
|
||||
<h3 id="markdown-linter"><a class="header" href="#markdown-linter">Markdown linter</a></h3>
|
||||
<p>We use <a href="https://github.com/DavidAnson/markdownlint">markdownlint</a> to lint the
|
||||
Markdown files in the repository.</p>
|
||||
<h3 id="spell-checker"><a class="header" href="#spell-checker">Spell checker</a></h3>
|
||||
<p>We use <code>cspell</code> as spell checker for all files in the project. If you are using
|
||||
VS Code, you can install the
|
||||
<a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker">code spell checker</a>
|
||||
extension to enable spell checking within your editor. Otherwise, you can
|
||||
install <a href="https://cspell.org/">cspell</a> separately.</p>
|
||||
<p>If you want to make the spell checker ignore a word, you can add</p>
|
||||
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>// spell-checker:ignore word_to_ignore
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<p>at the top of the file.</p>
|
||||
<h2 id="testing"><a class="header" href="#testing">Testing</a></h2>
|
||||
<p>Testing can be done using either Cargo or <code>make</code>.</p>
|
||||
<h3 id="testing-with-cargo"><a class="header" href="#testing-with-cargo">Testing with Cargo</a></h3>
|
||||
<p>Just like with building, we follow the standard procedure for testing using
|
||||
Cargo:</p>
|
||||
<pre><code class="language-shell">cargo test
|
||||
</code></pre>
|
||||
<p>By default, <code>cargo test</code> only runs the common programs. To run also platform
|
||||
specific tests, run:</p>
|
||||
<pre><code class="language-shell">cargo test --features unix
|
||||
</code></pre>
|
||||
<p>If you would prefer to test a select few utilities:</p>
|
||||
<pre><code class="language-shell">cargo test --features "chmod mv tail" --no-default-features
|
||||
</code></pre>
|
||||
<p>If you also want to test the core utilities:</p>
|
||||
<pre><code class="language-shell">cargo test -p uucore -p coreutils
|
||||
</code></pre>
|
||||
<p>To debug:</p>
|
||||
<pre><code class="language-shell">gdb --args target/debug/coreutils ls
|
||||
(gdb) b ls.rs:79
|
||||
(gdb) run
|
||||
</code></pre>
|
||||
<h3 id="testing-with-gnu-make"><a class="header" href="#testing-with-gnu-make">Testing with GNU Make</a></h3>
|
||||
<p>To simply test all available utilities:</p>
|
||||
<pre><code class="language-shell">make test
|
||||
</code></pre>
|
||||
<p>To test all but a few of the available utilities:</p>
|
||||
<pre><code class="language-shell">make SKIP_UTILS='UTILITY_1 UTILITY_2' test
|
||||
</code></pre>
|
||||
<p>To test only a few of the available utilities:</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' test
|
||||
</code></pre>
|
||||
<p>To include tests for unimplemented behavior:</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' SPEC=y test
|
||||
</code></pre>
|
||||
<h3 id="run-busybox-tests"><a class="header" href="#run-busybox-tests">Run Busybox Tests</a></h3>
|
||||
<p>This testing functionality is only available on *nix operating systems and
|
||||
requires <code>make</code>.</p>
|
||||
<p>To run busybox tests for all utilities for which busybox has tests</p>
|
||||
<pre><code class="language-shell">make busytest
|
||||
</code></pre>
|
||||
<p>To run busybox tests for a few of the available utilities</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' busytest
|
||||
</code></pre>
|
||||
<p>To pass an argument like "-v" to the busybox test runtime</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' RUNTEST_ARGS='-v' busytest
|
||||
</code></pre>
|
||||
<h3 id="comparing-with-gnu"><a class="header" href="#comparing-with-gnu">Comparing with GNU</a></h3>
|
||||
<p>To run uutils against the GNU test suite locally, run the following commands:</p>
|
||||
<pre><code class="language-shell">bash util/build-gnu.sh
|
||||
bash util/run-gnu-test.sh
|
||||
# To run a single test:
|
||||
bash util/run-gnu-test.sh tests/touch/not-owner.sh # for example
|
||||
# To run several tests:
|
||||
bash util/run-gnu-test.sh tests/touch/not-owner.sh tests/rm/no-give-up.sh # for example
|
||||
# If this is a perl (.pl) test, to run in debug:
|
||||
DEBUG=1 bash util/run-gnu-test.sh tests/misc/sm3sum.pl
|
||||
</code></pre>
|
||||
<p>Note that it relies on individual utilities (not the multicall binary).</p>
|
||||
<h3 id="improving-the-gnu-compatibility"><a class="header" href="#improving-the-gnu-compatibility">Improving the GNU compatibility</a></h3>
|
||||
<p>The Python script <code>./util/remaining-gnu-error.py</code> shows the list of failing
|
||||
tests in the CI.</p>
|
||||
<p>To improve the GNU compatibility, the following process is recommended:</p>
|
||||
<ol>
|
||||
<li>Identify a test (the smaller, the better) on a program that you understand or
|
||||
is easy to understand. You can use the <code>./util/remaining-gnu-error.py</code> script
|
||||
to help with this decision.</li>
|
||||
<li>Build both the GNU and Rust coreutils using: <code>bash util/build-gnu.sh</code></li>
|
||||
<li>Run the test with <code>bash util/run-gnu-test.sh <your test></code></li>
|
||||
<li>Start to modify <code><your test></code> to understand what is wrong. Examples:
|
||||
<ol>
|
||||
<li>Add <code>set -v</code> to have the bash verbose mode</li>
|
||||
<li>Add <code>echo $?</code> where needed</li>
|
||||
<li>When the variable <code>fail</code> is used in the test, <code>echo $fail</code> to see when the
|
||||
test started to fail</li>
|
||||
<li>Bump the content of the output (ex: <code>cat err</code>)</li>
|
||||
<li>...</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Or, if the test is simple, extract the relevant information to create a new
|
||||
test case running both GNU & Rust implementation</li>
|
||||
<li>Start to modify the Rust implementation to match the expected behavior</li>
|
||||
<li>Add a test to make sure that we don't regress (our test suite is super quick)</li>
|
||||
</ol>
|
||||
<h2 id="commit-messages"><a class="header" href="#commit-messages">Commit messages</a></h2>
|
||||
<p>To help the project maintainers review pull requests from contributors across
|
||||
numerous utilities, the team has settled on conventions for commit messages.</p>
|
||||
<p>From <a href="http://git-scm.com/book/ch5-2.html">http://git-scm.com/book/ch5-2.html</a>:</p>
|
||||
<pre><code>Short (50 chars or less) summary of changes
|
||||
<p>From <a href="https://git-scm.com/book/ch5-2.html">https://git-scm.com/book/ch5-2.html</a>:</p>
|
||||
<pre><code>Capitalized, short (50 chars or less) summary
|
||||
|
||||
More detailed explanatory text, if necessary. Wrap it to about 72
|
||||
characters or so. In some contexts, the first line is treated as the
|
||||
subject of an email and the rest of the text as the body. The blank
|
||||
line separating the summary from the body is critical (unless you omit
|
||||
the body entirely); tools like rebase can get confused if you run the
|
||||
the body entirely); tools like rebase will confuse you if you run the
|
||||
two together.
|
||||
|
||||
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
|
||||
or "Fixes bug." This convention matches up with commit messages generated
|
||||
by commands like git merge and git revert.
|
||||
|
||||
Further paragraphs come after blank lines.
|
||||
|
||||
- Bullet points are okay, too
|
||||
|
||||
- Typically a hyphen or asterisk is used for the bullet, preceded by a
|
||||
- Typically a hyphen or asterisk is used for the bullet, followed by a
|
||||
single space, with blank lines in between, but conventions vary here
|
||||
|
||||
- Use a hanging indent
|
||||
</code></pre>
|
||||
<p>Furthermore, here are a few examples for a summary line:</p>
|
||||
<ul>
|
||||
@@ -254,12 +380,23 @@ lines for non-utility modules include:</p>
|
||||
</code></pre>
|
||||
<pre><code>gitignore: add temporary files
|
||||
</code></pre>
|
||||
<h2 id="cargo-deny"><a class="header" href="#cargo-deny">cargo-deny</a></h2>
|
||||
<p>This project uses <a href="https://github.com/EmbarkStudios/cargo-deny/">cargo-deny</a> to
|
||||
detect duplicate dependencies, checks licenses, etc. To run it locally, first
|
||||
install it and then run with:</p>
|
||||
<pre><code>cargo deny --all-features check all
|
||||
<h2 id="code-coverage"><a class="header" href="#code-coverage">Code coverage</a></h2>
|
||||
<!-- spell-checker:ignore (flags) Ccodegen Coverflow Cpanic Zinstrument Zpanic -->
|
||||
<p>Code coverage report can be generated using <a href="https://github.com/mozilla/grcov">grcov</a>.</p>
|
||||
<h3 id="using-nightly-rust"><a class="header" href="#using-nightly-rust">Using Nightly Rust</a></h3>
|
||||
<p>To generate <a href="https://github.com/mozilla/grcov#example-how-to-generate-gcda-files-for-a-rust-project">gcov-based</a> coverage report</p>
|
||||
<pre><code class="language-shell">export CARGO_INCREMENTAL=0
|
||||
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||
export RUSTDOCFLAGS="-Cpanic=abort"
|
||||
cargo build <options...> # e.g., --features feat_os_unix
|
||||
cargo test <options...> # e.g., --features feat_os_unix test_pathchk
|
||||
grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-existing --ignore build.rs --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?\#\[derive\()" -o ./target/debug/coverage/
|
||||
# open target/debug/coverage/index.html in browser
|
||||
</code></pre>
|
||||
<p>if changes are not reflected in the report then run <code>cargo clean</code> and run the above commands.</p>
|
||||
<h3 id="using-stable-rust"><a class="header" href="#using-stable-rust">Using Stable Rust</a></h3>
|
||||
<p>If you are using stable version of Rust that doesn't enable code coverage instrumentation by default
|
||||
then add <code>-Z-Zinstrument-coverage</code> flag to <code>RUSTFLAGS</code> env variable specified above.</p>
|
||||
<h2 id="other-implementations"><a class="header" href="#other-implementations">Other implementations</a></h2>
|
||||
<p>The Coreutils have different implementations, with different levels of completions:</p>
|
||||
<ul>
|
||||
|
||||
+194
-56
@@ -405,11 +405,11 @@ unfinished or buggy.</p>
|
||||
<li>GNU Make (optional)</li>
|
||||
</ul>
|
||||
<h3 id="rust-version"><a class="header" href="#rust-version">Rust Version</a></h3>
|
||||
<p>uutils follows Rust's release channels and is tested against stable, beta and nightly.
|
||||
The current Minimum Supported Rust Version (MSRV) is <code>1.64.0</code>.</p>
|
||||
<p>uutils follows Rust's release channels and is tested against stable, beta and
|
||||
nightly. The current Minimum Supported Rust Version (MSRV) is <code>1.64.0</code>.</p>
|
||||
<h2 id="building"><a class="header" href="#building">Building</a></h2>
|
||||
<p>There are currently two methods to build the uutils binaries: either Cargo
|
||||
or GNU Make.</p>
|
||||
<p>There are currently two methods to build the uutils binaries: either Cargo or
|
||||
GNU Make.</p>
|
||||
<blockquote>
|
||||
<p>Building the full package, including all documentation, requires both Cargo
|
||||
and Gnu Make on a Unix platform.</p>
|
||||
@@ -419,15 +419,15 @@ and Gnu Make on a Unix platform.</p>
|
||||
cd coreutils
|
||||
</code></pre>
|
||||
<h3 id="cargo-1"><a class="header" href="#cargo-1">Cargo</a></h3>
|
||||
<p>Building uutils using Cargo is easy because the process is the same as for
|
||||
every other Rust program:</p>
|
||||
<p>Building uutils using Cargo is easy because the process is the same as for every
|
||||
other Rust program:</p>
|
||||
<pre><code class="language-shell">cargo build --release
|
||||
</code></pre>
|
||||
<p>This command builds the most portable common core set of uutils into a multicall
|
||||
(BusyBox-type) binary, named 'coreutils', on most Rust-supported platforms.</p>
|
||||
<p>Additional platform-specific uutils are often available. Building these
|
||||
expanded sets of uutils for a platform (on that platform) is as simple as
|
||||
specifying it as a feature:</p>
|
||||
<p>Additional platform-specific uutils are often available. Building these expanded
|
||||
sets of uutils for a platform (on that platform) is as simple as specifying it
|
||||
as a feature:</p>
|
||||
<pre><code class="language-shell">cargo build --release --features macos
|
||||
# or ...
|
||||
cargo build --release --features windows
|
||||
@@ -435,15 +435,15 @@ cargo build --release --features windows
|
||||
cargo build --release --features unix
|
||||
</code></pre>
|
||||
<p>If you don't want to build every utility available on your platform into the
|
||||
final binary, you can also specify which ones you want to build manually.
|
||||
For example:</p>
|
||||
final binary, you can also specify which ones you want to build manually. For
|
||||
example:</p>
|
||||
<pre><code class="language-shell">cargo build --features "base32 cat echo rm" --no-default-features
|
||||
</code></pre>
|
||||
<p>If you don't want to build the multicall binary and would prefer to build
|
||||
the utilities as individual binaries, that is also possible. Each utility
|
||||
is contained in its own package within the main repository, named
|
||||
"uu_UTILNAME". To build individual utilities, use cargo to build just the
|
||||
specific packages (using the <code>--package</code> [aka <code>-p</code>] option). For example:</p>
|
||||
<p>If you don't want to build the multicall binary and would prefer to build the
|
||||
utilities as individual binaries, that is also possible. Each utility is
|
||||
contained in its own package within the main repository, named "uu_UTILNAME". To
|
||||
build individual utilities, use cargo to build just the specific packages (using
|
||||
the <code>--package</code> [aka <code>-p</code>] option). For example:</p>
|
||||
<pre><code class="language-shell">cargo build -p uu_base32 -p uu_cat -p uu_echo -p uu_rm
|
||||
</code></pre>
|
||||
<h3 id="gnu-make"><a class="header" href="#gnu-make">GNU Make</a></h3>
|
||||
@@ -465,9 +465,11 @@ specific packages (using the <code>--package</code> [aka <code>-p</code>] option
|
||||
<p>Likewise, installing can simply be done using:</p>
|
||||
<pre><code class="language-shell">cargo install --path . --locked
|
||||
</code></pre>
|
||||
<p>This command will install uutils into Cargo's <em>bin</em> folder (<em>e.g.</em> <code>$HOME/.cargo/bin</code>).</p>
|
||||
<p>This does not install files necessary for shell completion or manpages.
|
||||
For manpages or shell completion to work, use <code>GNU Make</code> or see <code>Manually install shell completions</code>/<code>Manually install manpages</code>.</p>
|
||||
<p>This command will install uutils into Cargo's <em>bin</em> folder (<em>e.g.</em>
|
||||
<code>$HOME/.cargo/bin</code>).</p>
|
||||
<p>This does not install files necessary for shell completion or manpages. For
|
||||
manpages or shell completion to work, use <code>GNU Make</code> or see
|
||||
<code>Manually install shell completions</code>/<code>Manually install manpages</code>.</p>
|
||||
<h3 id="install-with-gnu-make"><a class="header" href="#install-with-gnu-make">Install with GNU Make</a></h3>
|
||||
<p>To install all available utilities:</p>
|
||||
<pre><code class="language-shell">make install
|
||||
@@ -495,26 +497,25 @@ make PREFIX=/my/path install
|
||||
for <code>bash</code>, <code>fish</code> and <code>zsh</code>. Completions for <code>elvish</code> and <code>powershell</code> can also
|
||||
be generated; See <code>Manually install shell completions</code>.</p>
|
||||
<h3 id="manually-install-shell-completions"><a class="header" href="#manually-install-shell-completions">Manually install shell completions</a></h3>
|
||||
<p>The <code>coreutils</code> binary can generate completions for the <code>bash</code>, <code>elvish</code>, <code>fish</code>, <code>powershell</code>
|
||||
and <code>zsh</code> shells. It prints the result to stdout.</p>
|
||||
<p>The <code>coreutils</code> binary can generate completions for the <code>bash</code>, <code>elvish</code>,
|
||||
<code>fish</code>, <code>powershell</code> and <code>zsh</code> shells. It prints the result to stdout.</p>
|
||||
<p>The syntax is:</p>
|
||||
<pre><code class="language-shell">cargo run completion <utility> <shell>
|
||||
</code></pre>
|
||||
<p>So, to install completions for <code>ls</code> on <code>bash</code> to <code>/usr/local/share/bash-completion/completions/ls</code>,
|
||||
run:</p>
|
||||
<p>So, to install completions for <code>ls</code> on <code>bash</code> to
|
||||
<code>/usr/local/share/bash-completion/completions/ls</code>, run:</p>
|
||||
<pre><code class="language-shell">cargo run completion ls bash > /usr/local/share/bash-completion/completions/ls
|
||||
</code></pre>
|
||||
<h3 id="manually-install-manpages"><a class="header" href="#manually-install-manpages">Manually install manpages</a></h3>
|
||||
<p>To generate manpages, the syntax is:</p>
|
||||
<pre><code class="language-bash">cargo run manpage <utility>
|
||||
</code></pre>
|
||||
<p>So, to install the manpage for <code>ls</code> to <code>/usr/local/share/man/man1/ls.1</code>
|
||||
run:</p>
|
||||
<p>So, to install the manpage for <code>ls</code> to <code>/usr/local/share/man/man1/ls.1</code> run:</p>
|
||||
<pre><code class="language-bash">cargo run manpage ls > /usr/local/share/man/man1/ls.1
|
||||
</code></pre>
|
||||
<h2 id="un-installation"><a class="header" href="#un-installation">Un-installation</a></h2>
|
||||
<p>Un-installation differs depending on how you have installed uutils. If you used
|
||||
Cargo to install, use Cargo to uninstall. If you used GNU Make to install, use
|
||||
<p>Un-installation differs depending on how you have installed uutils. If you used
|
||||
Cargo to install, use Cargo to uninstall. If you used GNU Make to install, use
|
||||
Make to uninstall.</p>
|
||||
<h3 id="uninstall-with-cargo"><a class="header" href="#uninstall-with-cargo">Uninstall with Cargo</a></h3>
|
||||
<p>To uninstall uutils:</p>
|
||||
@@ -535,23 +536,13 @@ Make to uninstall.</p>
|
||||
make PREFIX=/my/path uninstall
|
||||
</code></pre>
|
||||
<div style="break-before: page; page-break-before: always;"></div><!-- markdownlint-disable MD041 -->
|
||||
<!-- spell-checker:ignore reimplementing toybox -->
|
||||
<!-- spell-checker:ignore reimplementing toybox RUNTEST -->
|
||||
<h1 id="contributing-to-coreutils"><a class="header" href="#contributing-to-coreutils">Contributing to coreutils</a></h1>
|
||||
<p>Contributions are very welcome, and should target Rust's main branch until the
|
||||
standard libraries are stabilized. You may <em>claim</em> an item on the to-do list by
|
||||
following these steps:</p>
|
||||
<ol>
|
||||
<li>Open an issue named "Implement [the utility of your choice]", e.g. "Implement
|
||||
ls".</li>
|
||||
<li>State that you are working on this utility.</li>
|
||||
<li>Develop the utility.</li>
|
||||
<li>Add integration tests.</li>
|
||||
<li>Add the reference to your utility into Cargo.toml and Makefile.</li>
|
||||
<li>Remove utility from the to-do list in the README.</li>
|
||||
<li>Submit a pull request and close the issue.</li>
|
||||
</ol>
|
||||
<p>The steps above imply that, before starting to work on a utility, you should
|
||||
search the issues to make sure no one else is working on it.</p>
|
||||
<p>Contributions are very welcome via Pull Requests. If you don't know where to
|
||||
start, take a look at the
|
||||
<a href="https://github.com/uutils/coreutils/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22"><code>good-first-issues</code></a>.
|
||||
If you have any questions, feel free to ask them in the issues or on
|
||||
<a href="https://discord.gg/wQVJbvJ">Discord</a>.</p>
|
||||
<h2 id="best-practices"><a class="header" href="#best-practices">Best practices</a></h2>
|
||||
<ol>
|
||||
<li>Follow what GNU is doing in terms of options and behavior. It is recommended
|
||||
@@ -573,30 +564,166 @@ other binaries.</li>
|
||||
utilities, nor should it link to or reference GNU libraries.</li>
|
||||
</ol>
|
||||
<h2 id="platforms"><a class="header" href="#platforms">Platforms</a></h2>
|
||||
<p>We take pride in supporting many operating systems and architectures.</p>
|
||||
<p><strong>Tip:</strong>
|
||||
For Windows, Microsoft provides some images (VMWare, Hyper-V, VirtualBox and Parallels)
|
||||
for development:
|
||||
<p>We take pride in supporting many operating systems and architectures. Any code
|
||||
you contribute must at least compile without warnings for all platforms in the
|
||||
CI. However, you can use <code>#[cfg(...)]</code> attributes to create platform dependent features.</p>
|
||||
<p><strong>Tip:</strong> For Windows, Microsoft provides some images (VMWare, Hyper-V,
|
||||
VirtualBox and Parallels) for development:
|
||||
<a href="https://developer.microsoft.com/windows/downloads/virtual-machines/">https://developer.microsoft.com/windows/downloads/virtual-machines/</a></p>
|
||||
<h2 id="tools"><a class="header" href="#tools">Tools</a></h2>
|
||||
<p>We have an extensive CI that will check your code before it can be merged. This
|
||||
section explains how to run those checks locally to avoid waiting for the CI.</p>
|
||||
<h3 id="pre-commit-hooks"><a class="header" href="#pre-commit-hooks">pre-commit hooks</a></h3>
|
||||
<p>A configuration for <code>pre-commit</code> is provided in the repository. It allows
|
||||
automatically checking every git commit you make to ensure it compiles, and
|
||||
passes <code>clippy</code> and <code>rustfmt</code> without warnings.</p>
|
||||
<p>To use the provided hook:</p>
|
||||
<ol>
|
||||
<li><a href="https://pre-commit.com/#install">Install <code>pre-commit</code></a></li>
|
||||
<li>Run <code>pre-commit install</code> while in the repository directory</li>
|
||||
</ol>
|
||||
<p>Your git commits will then automatically be checked. If a check fails, an error
|
||||
message will explain why, and your commit will be canceled. You can then make
|
||||
the suggested changes, and run <code>git commit ...</code> again.</p>
|
||||
<h3 id="clippy"><a class="header" href="#clippy">clippy</a></h3>
|
||||
<pre><code class="language-shell">cargo clippy --all-targets --all-features
|
||||
</code></pre>
|
||||
<p>The <code>msrv</code> key in the clippy configuration file <code>clippy.toml</code> is used to disable
|
||||
lints pertaining to newer features by specifying the minimum supported Rust
|
||||
version (MSRV).</p>
|
||||
<h3 id="rustfmt"><a class="header" href="#rustfmt">rustfmt</a></h3>
|
||||
<pre><code class="language-shell">cargo fmt --all
|
||||
</code></pre>
|
||||
<h3 id="cargo-deny"><a class="header" href="#cargo-deny">cargo-deny</a></h3>
|
||||
<p>This project uses <a href="https://github.com/EmbarkStudios/cargo-deny/">cargo-deny</a> to
|
||||
detect duplicate dependencies, checks licenses, etc. To run it locally, first
|
||||
install it and then run with:</p>
|
||||
<pre><code>cargo deny --all-features check all
|
||||
</code></pre>
|
||||
<h3 id="markdown-linter"><a class="header" href="#markdown-linter">Markdown linter</a></h3>
|
||||
<p>We use <a href="https://github.com/DavidAnson/markdownlint">markdownlint</a> to lint the
|
||||
Markdown files in the repository.</p>
|
||||
<h3 id="spell-checker"><a class="header" href="#spell-checker">Spell checker</a></h3>
|
||||
<p>We use <code>cspell</code> as spell checker for all files in the project. If you are using
|
||||
VS Code, you can install the
|
||||
<a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker">code spell checker</a>
|
||||
extension to enable spell checking within your editor. Otherwise, you can
|
||||
install <a href="https://cspell.org/">cspell</a> separately.</p>
|
||||
<p>If you want to make the spell checker ignore a word, you can add</p>
|
||||
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>// spell-checker:ignore word_to_ignore
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<p>at the top of the file.</p>
|
||||
<h2 id="testing"><a class="header" href="#testing">Testing</a></h2>
|
||||
<p>Testing can be done using either Cargo or <code>make</code>.</p>
|
||||
<h3 id="testing-with-cargo"><a class="header" href="#testing-with-cargo">Testing with Cargo</a></h3>
|
||||
<p>Just like with building, we follow the standard procedure for testing using
|
||||
Cargo:</p>
|
||||
<pre><code class="language-shell">cargo test
|
||||
</code></pre>
|
||||
<p>By default, <code>cargo test</code> only runs the common programs. To run also platform
|
||||
specific tests, run:</p>
|
||||
<pre><code class="language-shell">cargo test --features unix
|
||||
</code></pre>
|
||||
<p>If you would prefer to test a select few utilities:</p>
|
||||
<pre><code class="language-shell">cargo test --features "chmod mv tail" --no-default-features
|
||||
</code></pre>
|
||||
<p>If you also want to test the core utilities:</p>
|
||||
<pre><code class="language-shell">cargo test -p uucore -p coreutils
|
||||
</code></pre>
|
||||
<p>To debug:</p>
|
||||
<pre><code class="language-shell">gdb --args target/debug/coreutils ls
|
||||
(gdb) b ls.rs:79
|
||||
(gdb) run
|
||||
</code></pre>
|
||||
<h3 id="testing-with-gnu-make"><a class="header" href="#testing-with-gnu-make">Testing with GNU Make</a></h3>
|
||||
<p>To simply test all available utilities:</p>
|
||||
<pre><code class="language-shell">make test
|
||||
</code></pre>
|
||||
<p>To test all but a few of the available utilities:</p>
|
||||
<pre><code class="language-shell">make SKIP_UTILS='UTILITY_1 UTILITY_2' test
|
||||
</code></pre>
|
||||
<p>To test only a few of the available utilities:</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' test
|
||||
</code></pre>
|
||||
<p>To include tests for unimplemented behavior:</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' SPEC=y test
|
||||
</code></pre>
|
||||
<h3 id="run-busybox-tests"><a class="header" href="#run-busybox-tests">Run Busybox Tests</a></h3>
|
||||
<p>This testing functionality is only available on *nix operating systems and
|
||||
requires <code>make</code>.</p>
|
||||
<p>To run busybox tests for all utilities for which busybox has tests</p>
|
||||
<pre><code class="language-shell">make busytest
|
||||
</code></pre>
|
||||
<p>To run busybox tests for a few of the available utilities</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' busytest
|
||||
</code></pre>
|
||||
<p>To pass an argument like "-v" to the busybox test runtime</p>
|
||||
<pre><code class="language-shell">make UTILS='UTILITY_1 UTILITY_2' RUNTEST_ARGS='-v' busytest
|
||||
</code></pre>
|
||||
<h3 id="comparing-with-gnu"><a class="header" href="#comparing-with-gnu">Comparing with GNU</a></h3>
|
||||
<p>To run uutils against the GNU test suite locally, run the following commands:</p>
|
||||
<pre><code class="language-shell">bash util/build-gnu.sh
|
||||
bash util/run-gnu-test.sh
|
||||
# To run a single test:
|
||||
bash util/run-gnu-test.sh tests/touch/not-owner.sh # for example
|
||||
# To run several tests:
|
||||
bash util/run-gnu-test.sh tests/touch/not-owner.sh tests/rm/no-give-up.sh # for example
|
||||
# If this is a perl (.pl) test, to run in debug:
|
||||
DEBUG=1 bash util/run-gnu-test.sh tests/misc/sm3sum.pl
|
||||
</code></pre>
|
||||
<p>Note that it relies on individual utilities (not the multicall binary).</p>
|
||||
<h3 id="improving-the-gnu-compatibility"><a class="header" href="#improving-the-gnu-compatibility">Improving the GNU compatibility</a></h3>
|
||||
<p>The Python script <code>./util/remaining-gnu-error.py</code> shows the list of failing
|
||||
tests in the CI.</p>
|
||||
<p>To improve the GNU compatibility, the following process is recommended:</p>
|
||||
<ol>
|
||||
<li>Identify a test (the smaller, the better) on a program that you understand or
|
||||
is easy to understand. You can use the <code>./util/remaining-gnu-error.py</code> script
|
||||
to help with this decision.</li>
|
||||
<li>Build both the GNU and Rust coreutils using: <code>bash util/build-gnu.sh</code></li>
|
||||
<li>Run the test with <code>bash util/run-gnu-test.sh <your test></code></li>
|
||||
<li>Start to modify <code><your test></code> to understand what is wrong. Examples:
|
||||
<ol>
|
||||
<li>Add <code>set -v</code> to have the bash verbose mode</li>
|
||||
<li>Add <code>echo $?</code> where needed</li>
|
||||
<li>When the variable <code>fail</code> is used in the test, <code>echo $fail</code> to see when the
|
||||
test started to fail</li>
|
||||
<li>Bump the content of the output (ex: <code>cat err</code>)</li>
|
||||
<li>...</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Or, if the test is simple, extract the relevant information to create a new
|
||||
test case running both GNU & Rust implementation</li>
|
||||
<li>Start to modify the Rust implementation to match the expected behavior</li>
|
||||
<li>Add a test to make sure that we don't regress (our test suite is super quick)</li>
|
||||
</ol>
|
||||
<h2 id="commit-messages"><a class="header" href="#commit-messages">Commit messages</a></h2>
|
||||
<p>To help the project maintainers review pull requests from contributors across
|
||||
numerous utilities, the team has settled on conventions for commit messages.</p>
|
||||
<p>From <a href="http://git-scm.com/book/ch5-2.html">http://git-scm.com/book/ch5-2.html</a>:</p>
|
||||
<pre><code>Short (50 chars or less) summary of changes
|
||||
<p>From <a href="https://git-scm.com/book/ch5-2.html">https://git-scm.com/book/ch5-2.html</a>:</p>
|
||||
<pre><code>Capitalized, short (50 chars or less) summary
|
||||
|
||||
More detailed explanatory text, if necessary. Wrap it to about 72
|
||||
characters or so. In some contexts, the first line is treated as the
|
||||
subject of an email and the rest of the text as the body. The blank
|
||||
line separating the summary from the body is critical (unless you omit
|
||||
the body entirely); tools like rebase can get confused if you run the
|
||||
the body entirely); tools like rebase will confuse you if you run the
|
||||
two together.
|
||||
|
||||
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
|
||||
or "Fixes bug." This convention matches up with commit messages generated
|
||||
by commands like git merge and git revert.
|
||||
|
||||
Further paragraphs come after blank lines.
|
||||
|
||||
- Bullet points are okay, too
|
||||
|
||||
- Typically a hyphen or asterisk is used for the bullet, preceded by a
|
||||
- Typically a hyphen or asterisk is used for the bullet, followed by a
|
||||
single space, with blank lines in between, but conventions vary here
|
||||
|
||||
- Use a hanging indent
|
||||
</code></pre>
|
||||
<p>Furthermore, here are a few examples for a summary line:</p>
|
||||
<ul>
|
||||
@@ -619,12 +746,23 @@ lines for non-utility modules include:</p>
|
||||
</code></pre>
|
||||
<pre><code>gitignore: add temporary files
|
||||
</code></pre>
|
||||
<h2 id="cargo-deny"><a class="header" href="#cargo-deny">cargo-deny</a></h2>
|
||||
<p>This project uses <a href="https://github.com/EmbarkStudios/cargo-deny/">cargo-deny</a> to
|
||||
detect duplicate dependencies, checks licenses, etc. To run it locally, first
|
||||
install it and then run with:</p>
|
||||
<pre><code>cargo deny --all-features check all
|
||||
<h2 id="code-coverage"><a class="header" href="#code-coverage">Code coverage</a></h2>
|
||||
<!-- spell-checker:ignore (flags) Ccodegen Coverflow Cpanic Zinstrument Zpanic -->
|
||||
<p>Code coverage report can be generated using <a href="https://github.com/mozilla/grcov">grcov</a>.</p>
|
||||
<h3 id="using-nightly-rust"><a class="header" href="#using-nightly-rust">Using Nightly Rust</a></h3>
|
||||
<p>To generate <a href="https://github.com/mozilla/grcov#example-how-to-generate-gcda-files-for-a-rust-project">gcov-based</a> coverage report</p>
|
||||
<pre><code class="language-shell">export CARGO_INCREMENTAL=0
|
||||
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||
export RUSTDOCFLAGS="-Cpanic=abort"
|
||||
cargo build <options...> # e.g., --features feat_os_unix
|
||||
cargo test <options...> # e.g., --features feat_os_unix test_pathchk
|
||||
grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-existing --ignore build.rs --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?\#\[derive\()" -o ./target/debug/coverage/
|
||||
# open target/debug/coverage/index.html in browser
|
||||
</code></pre>
|
||||
<p>if changes are not reflected in the report then run <code>cargo clean</code> and run the above commands.</p>
|
||||
<h3 id="using-stable-rust"><a class="header" href="#using-stable-rust">Using Stable Rust</a></h3>
|
||||
<p>If you are using stable version of Rust that doesn't enable code coverage instrumentation by default
|
||||
then add <code>-Z-Zinstrument-coverage</code> flag to <code>RUSTFLAGS</code> env variable specified above.</p>
|
||||
<h2 id="other-implementations"><a class="header" href="#other-implementations">Other implementations</a></h2>
|
||||
<p>The Coreutils have different implementations, with different levels of completions:</p>
|
||||
<ul>
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user