Skip to content

Commit

Permalink
Documentation support
Browse files Browse the repository at this point in the history
Requires nightly 2021-02-20 due to added support for argument files,
see rust-lang/rust#82261.

Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
  • Loading branch information
ojeda committed Feb 22, 2021
1 parent d189aae commit 8584c78
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 5 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
arch: [x86_64, arm64]
toolchain: [gcc, clang, llvm]
config: [debug, release]
rustc: [2021-01-24]
rustc: [2021-02-20]
output: [src] # [src, build]
install: [rustup] # [rustup, standalone]
sysroot: [common] # [common, custom]
Expand All @@ -27,23 +27,23 @@ jobs:
- arch: x86_64
toolchain: gcc
config: debug
rustc: 2021-01-31
rustc: 2021-02-20
output: build
install: rustup
sysroot: custom

- arch: arm64
toolchain: clang
config: release
rustc: 2021-02-07
rustc: 2021-02-20
output: build
install: standalone
sysroot: common

- arch: x86_64
toolchain: llvm
config: debug
rustc: 2021-02-11
rustc: 2021-02-20
output: build
install: standalone
sysroot: custom
Expand Down Expand Up @@ -177,3 +177,6 @@ jobs:
# Report
- run: ls -l ${{ env.BUILD_DIR }}drivers/char/rust_example.o ${{ env.BUILD_DIR }}drivers/char/rust_example_3.ko ${{ env.BUILD_DIR }}rust/*.o ${{ env.BUILD_DIR }}vmlinux ${{ env.BUILD_DIR }}${{ env.IMAGE_PATH }}
- run: size ${{ env.BUILD_DIR }}drivers/char/rust_example.o ${{ env.BUILD_DIR }}drivers/char/rust_example_3.ko ${{ env.BUILD_DIR }}rust/*.o ${{ env.BUILD_DIR }}vmlinux

# Docs
- run: make ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_SYSROOT }} -j3 rustdoc
3 changes: 3 additions & 0 deletions Documentation/doc-guide/kernel-doc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ when it is embedded in source files.
reasons. The kernel source contains tens of thousands of kernel-doc
comments. Please stick to the style described here.

.. note:: kernel-doc does not cover Rust code: please see
:ref:`Documentation/rust/docs.rst <rust_docs>` instead.

The kernel-doc structure is extracted from the comments, and proper
`Sphinx C Domain`_ function and type descriptions with anchors are
generated from them. The descriptions are filtered for special kernel-doc
Expand Down
7 changes: 7 additions & 0 deletions Documentation/process/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ iptables 1.4.2 iptables -V
openssl & libcrypto 1.0.0 openssl version
bc 1.06.95 bc --version
Sphinx\ [#f1]_ 1.3 sphinx-build --version
rustdoc (optional) nightly rustdoc --version
====================== =============== ========================================

.. [#f1] Sphinx is needed only to build the Kernel documentation
Expand Down Expand Up @@ -332,6 +333,12 @@ Sphinx
Please see :ref:`sphinx_install` in :ref:`Documentation/doc-guide/sphinx.rst <sphinxdoc>`
for details about Sphinx requirements.

rustdoc
-------

``rustdoc`` is used to generate Rust documentation. Please see
:ref:`Documentation/rust/docs.rst <rust_docs>` for more information.

Getting updated software
========================

Expand Down
5 changes: 5 additions & 0 deletions Documentation/rust/coding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,8 @@ configuration:
#[cfg(CONFIG_X="m")] // `CONFIG_X` is enabled as a module (`m`)
#[cfg(not(CONFIG_X))] // `CONFIG_X` is disabled
Documentation
-------------

Please see :ref:`Documentation/rust/docs.rst <rust_docs>`.
109 changes: 109 additions & 0 deletions Documentation/rust/docs.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
.. _rust_docs:

Docs
====

Rust kernel code is not documented like C kernel code (i.e. via kernel-doc).
Instead, we use the usual system for documenting Rust code: the ``rustdoc``
tool, which uses Markdown (a *very* lightweight markup language).

This document describes how to make the most out of the kernel documentation
for Rust.


Reading the docs
----------------

An advantage of using Markdown is that it attempts to make text look almost as
you would have written it in plain text. This makes the documentation quite
pleasant to read even in its source form.

However, the generated HTML docs produced by ``rustdoc`` provide a *very* nice
experience, including integrated instant search, clickable items (types,
functions, constants, etc. -- including to all the standard Rust library ones
that we use in the kernel, e.g. ``core``), categorization, links to the source
code, etc.

Like for the rest of the kernel documentation, pregenerated HTML docs for
the libraries (crates) inside ``rust/`` that are used by the rest of the kernel
are available at `kernel.org`_.

// TODO: link when ready

.. _kernel.org: http://kernel.org/

Otherwise, you can generate them locally. This is quite fast (same order as
compiling the code itself) and you do not need any special tools or environment.
This has the added advantage that they will be tailored to your particular
kernel configuration. To generate them, simply use the ``rustdoc`` target with
the same invocation you use for compilation, e.g.::

make ARCH=... CROSS_COMPILE=... CC=... -j... rustdoc


Writing the docs
----------------

If you already know Markdown, learning how to write Rust documentation will be
a breeze. If not, understanding the basics is a matter of minutes reading other
code. There are also many guides available out there, a particularly nice one
is at `GitHub`_.

.. _GitHub: https://guides.github.com/features/mastering-markdown/#syntax

This is how a well-documented Rust function may look like (derived from the Rust
standard library)::

/// Returns the contained [`Some`] value, consuming the `self` value,
/// without checking that the value is not [`None`].
///
/// # Safety
///
/// Calling this method on [`None`] is *[undefined behavior]*.
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// # Examples
///
/// ```
/// let x = Some("air");
/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
/// ```
pub unsafe fn unwrap_unchecked(self) -> T {
match self {
Some(val) => val,

// SAFETY: the safety contract must be upheld by the caller.
None => unsafe { hint::unreachable_unchecked() },
}
}

This example showcases a few ``rustdoc`` features and some common conventions
(that we also follow in the kernel):

* The first paragraph must be a single sentence briefly describing what
the documented item does. Further explanations must go in extra paragraphs.

* ``unsafe`` functions must document the preconditions needed for a call to be
safe under a ``Safety`` section.

* While not shown here, if a function may panic, the conditions under which
that happens must be described under a ``Panics`` section.

* If providing examples of usage would help readers, they must be written in
a section called ``Examples``.

* Rust items (functions, types, constants...) will be automatically linked
(``rustdoc`` will find out the URL for you).

* Following the Rust standard library conventions, any ``unsafe`` block must be
preceded by a ``SAFETY`` comment describing why the code inside is sound.

While sometimes the reason might look trivial and therefore unneeded, writing
these comments is not just a good way of documenting what has been taken into
account, but also that there are no *extra* implicit constraints.

To learn more about how to write documentation for Rust and extra features,
please take a look at the ``rustdoc`` `book`_.

.. _book: https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
1 change: 1 addition & 0 deletions Documentation/rust/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ read the :ref:`Documentation/rust/quick-start.rst <rust_quick_start>` guide.

quick-start
coding
docs
arch-support

.. only:: subproject and html
Expand Down
18 changes: 17 additions & 1 deletion Documentation/rust/quick-start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ rustc
*****

A recent *nightly* Rust toolchain (with, at least, ``rustc``) is required,
e.g. ``nightly-2021-01-24``. Our goal is to use a stable toolchain as soon
e.g. ``nightly-2021-02-20``. Our goal is to use a stable toolchain as soon
as possible, but for the moment we depend on a handful of nightly features.

If you are using ``rustup``, run::
Expand Down Expand Up @@ -80,6 +80,22 @@ the component manually::
The standalone installers also come with ``rustfmt``.


rustdoc
*******

Optionally, if you install the ``rustdoc`` tool, then you will be able
to generate HTML documentation for Rust code, including for the libraries
(crates) inside ``rust/`` that are used by the rest of the kernel.

If you are using ``rustup``, its ``default`` profile already installs the tool,
so you should be good to go. If you are using another profile, you can install
the component manually::

rustup component add rustdoc

The standalone installers also come with ``rustdoc``.


Configuration
-------------

Expand Down
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,9 @@ help:
@echo 'Documentation targets:'
@$(MAKE) -f $(srctree)/Documentation/Makefile dochelp
@echo ''
@echo ' rustdoc - Generate Rust documentation'
@echo ' (requires kernel .config)'
@echo ''
@echo 'Architecture specific targets ($(SRCARCH)):'
@$(if $(archhelp),$(archhelp),\
echo ' No architecture specific help defined for $(SRCARCH)')
Expand Down Expand Up @@ -1722,6 +1725,16 @@ PHONY += $(DOC_TARGETS)
$(DOC_TARGETS):
$(Q)$(MAKE) $(build)=Documentation $@


# Rust documentation target
# ---------------------------------------------------------------------------

# Using the singular to avoid running afoul of `no-dot-config-targets`.
PHONY += rustdoc
rustdoc: prepare0
$(Q)$(MAKE) $(build)=rust $@


# Misc
# ---------------------------------------------------------------------------

Expand Down
1 change: 1 addition & 0 deletions rust/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

bindings_generated.rs
exports_*_generated.h
doc/
24 changes: 24 additions & 0 deletions rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ extra-$(CONFIG_RUST) += bindings_generated.rs libmodule.so
extra-$(CONFIG_RUST) += exports_core_generated.h exports_alloc_generated.h
extra-$(CONFIG_RUST) += exports_kernel_generated.h

RUSTDOC = rustdoc

rustdoc_flags = $(filter-out --emit=% --out-dir=%, $(rustc_flags))

quiet_cmd_rustdoc = RUSTDOC $<
cmd_rustdoc = \
RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
$(RUSTDOC) $(rustdoc_flags) $(rustdoc_target_flags) -L $(objtree)/rust/ \
--output $(objtree)/rust/doc --crate-name $(subst rustdoc-,,$@) \
-Wmissing-docs @$(objtree)/include/generated/rustc_cfg $<

rustdoc: rustdoc-module rustdoc-kernel

rustdoc-module: rustdoc_target_flags = --crate-type proc-macro \
--extern proc_macro
rustdoc-module: $(srctree)/rust/module.rs FORCE
$(call if_changed,rustdoc)

rustdoc-kernel: rustdoc_target_flags = --extern alloc \
--extern module=$(objtree)/rust/libmodule.so
rustdoc-kernel: $(srctree)/rust/kernel/lib.rs rustdoc-module \
$(objtree)/rust/libmodule.so $(objtree)/rust/bindings_generated.rs FORCE
$(call if_changed,rustdoc)

ifdef CONFIG_CC_IS_CLANG
bindgen_c_flags = $(c_flags)
else
Expand Down
3 changes: 3 additions & 0 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ compile_error!("Missing kernel configuration for conditional compilation");
use core::panic::PanicInfo;

mod allocator;

#[doc(hidden)]
pub mod bindings;

pub mod c_types;
pub mod chrdev;
mod error;
Expand Down

0 comments on commit 8584c78

Please sign in to comment.