This is an automated email from the ASF dual-hosted git repository.
spectrometerHBH pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-tirx.git
The following commit(s) were added to refs/heads/main by this push:
new 2c9ee2529 [DOCS][RUST] Add the Rust API reference to the documentation
site (#91)
2c9ee2529 is described below
commit 2c9ee25297ab04bc29daa566a8021fd1c9a51d98
Author: Linzhang Li <[email protected]>
AuthorDate: Wed Oct 28 11:56:25 2026 -0400
[DOCS][RUST] Add the Rust API reference to the documentation site (#91)
## Summary
The documentation site has a Python and a C++ API reference, but the
Rust crate in `rust/` had no
page: its `cargo doc` had to be built and browsed by hand. This adds a
*Rust API* entry next to the
other two, generated by `cargo doc` the way the C++ reference is
generated by Doxygen, and turns
it on in the GPU pipeline that publishes the docs.
`docs/conf.py` builds the reference when `BUILD_RUST_DOCS=1`, as
`BUILD_CPP_DOCS=1` builds the
C++ one. It runs `cargo doc --no-deps` on `tvm-tirx` and on `tvm-ffi`,
the crate it re-exports as
`tvm_tirx::tvm_ffi`, so the links between the two stay inside the site
instead of pointing at
docs.rs; it clears `rust/target/doc` first, so pages of removed items do
not linger, except under
`sphinx-autobuild`, where cargo's incremental documentation is kept.
After the Sphinx build the
pages are copied under `reference/rust/generated` of the HTML output.
Rustdoc runs with
`-D warnings` unless `RUSTDOCFLAGS` is set, so a broken intra-doc link
fails the build as a
broken Sphinx reference does. The crate's build script links
`libtvm_tirx_compiler` through
`tvm-tirx-config`, so the package must be installed, which `uv run`
already arranges.
The new `docs/reference/rust/index.rst` introduces the crate, maps its
modules onto the Python
namespaces, and lists the two generated crates. `docs/dev/doc_build.rst`
and `docs/README.md`
document the switch, the `--watch rust/src` autobuild invocation, and
the cleanup of
`rust/target/doc`.
`tests/scripts/task_python_docs.sh` installs cargo through
`task_install_rust.sh`, as the Rust CI
tasks do, and sets `BUILD_RUST_DOCS=1`, so the published docs carry the
Rust reference.
`rust/src/lib.rs` moves the `tirx_register_ops` export into a
`#[doc(hidden)]` module. The
symbol is exported by `#[no_mangle]` from wherever it is, and the
macro's expansion otherwise
showed up as an item at the crate root in the generated reference.
Signed-off-by: Yuchuan <[email protected]>
---
docs/README.md | 3 +++
docs/conf.py | 43 +++++++++++++++++++++++++++++++++++++
docs/dev/doc_build.rst | 27 +++++++++++++++++++++++
docs/index.rst | 1 +
docs/reference/rust/index.rst | 44 ++++++++++++++++++++++++++++++++++++++
rust/src/lib.rs | 8 +++++--
tests/scripts/task_install_rust.sh | 6 +++---
tests/scripts/task_python_docs.sh | 6 +++++-
8 files changed, 132 insertions(+), 6 deletions(-)
diff --git a/docs/README.md b/docs/README.md
index 228c0a0b2..6250895ed 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -26,6 +26,9 @@ uv run --no-sync python -m sphinx -b html -W docs
docs/_build/html
```
Set `BUILD_CPP_DOCS=1` to also generate the C++ API reference; this requires
Doxygen.
+Set `BUILD_RUST_DOCS=1` to also generate the Rust API reference with `cargo
doc`; this
+requires Rust 1.85 or newer and the installed TIRx package, whose
`tvm-tirx-config`
+the crate's build script runs.
Open `docs/_build/html/index.html` to browse the Developer Manual and API
reference.
See [Build This Doc Site](dev/doc_build.rst) for local serving and clean
rebuilds.
diff --git a/docs/conf.py b/docs/conf.py
index 00b86830d..25766b6c8 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -17,6 +17,8 @@
import os
import re
+import shutil
+import subprocess
import sys
import xml.etree.ElementTree as ET
from pathlib import Path
@@ -25,8 +27,12 @@ from types import ModuleType
os.environ["TVM_FFI_BUILD_DOCS"] = "1"
build_exhale = os.environ.get("BUILD_CPP_DOCS", "0") == "1"
+build_rust_docs = os.environ.get("BUILD_RUST_DOCS", "0") == "1"
+# Under sphinx-autobuild, keep cargo's incremental documentation instead of
rebuilding it.
+is_autobuild = any("sphinx-autobuild" in str(arg) for arg in sys.argv)
_DOCS_DIR = Path(__file__).resolve().parent
+_RUST_DIR = _DOCS_DIR.parent / "rust"
project = "tvm-tirx"
html_title = project
@@ -166,6 +172,41 @@ def _prepare_stub_files() -> None:
dst_path.write_text(src_path.read_text(encoding="utf-8"),
encoding="utf-8")
+def _build_rust_docs() -> None:
+ """Build the Rust API reference with ``cargo doc`` when
``BUILD_RUST_DOCS=1``.
+
+ The crate's build script links ``libtvm_tirx_compiler`` through
``tvm-tirx-config``,
+ so the TIRx package must be installed and its ``tvm-tirx-config`` on
``PATH``, as
+ ``uv run`` arranges. The pages are copied into the HTML output by
+ :func:`_copy_rust_docs_to_output`.
+ """
+ if not build_rust_docs:
+ return
+ target_doc = _RUST_DIR / "target" / "doc"
+ if not is_autobuild and target_doc.exists():
+ shutil.rmtree(target_doc) # drop the pages of items that no longer
exist
+ print("Building the Rust API reference with cargo doc...")
+ env = {**os.environ, "RUSTDOCFLAGS": os.environ.get("RUSTDOCFLAGS", "-D
warnings")}
+ # The crate and the tvm-ffi it re-exports, so the links between them stay
local.
+ command = ["cargo", "doc", "--no-deps", "-p", "tvm-tirx", "-p", "tvm-ffi"]
+ try:
+ subprocess.run(command, check=True, cwd=_RUST_DIR, env=env)
+ except FileNotFoundError:
+ raise RuntimeError("BUILD_RUST_DOCS=1 needs cargo on PATH") from None
+
+
+def _copy_rust_docs_to_output(app, exception):
+ """Copy the ``cargo doc`` pages under ``reference/rust/generated`` of the
HTML output."""
+ if exception is not None or not build_rust_docs:
+ return
+ src_dir = _RUST_DIR / "target" / "doc"
+ dst_dir = Path(app.outdir) / "reference" / "rust" / "generated"
+ if dst_dir.exists():
+ shutil.rmtree(dst_dir)
+ shutil.copytree(src_dir, dst_dir)
+ print(f"Copied the Rust API reference to {dst_dir}")
+
+
def _mark_exhale_root_orphan(app, docname, source):
"""Prepend :orphan: to exhale-generated root so it stays out of the
sidebar."""
if docname == "reference/cpp/generated/index":
@@ -197,5 +238,7 @@ def _link_nested_class_to_enclosing_class(app, docname,
source):
def setup(app):
_prepare_stub_files()
+ _build_rust_docs()
app.connect("source-read", _mark_exhale_root_orphan)
app.connect("source-read", _link_nested_class_to_enclosing_class)
+ app.connect("build-finished", _copy_rust_docs_to_output)
diff --git a/docs/dev/doc_build.rst b/docs/dev/doc_build.rst
index 400a226f4..1435667fd 100644
--- a/docs/dev/doc_build.rst
+++ b/docs/dev/doc_build.rst
@@ -79,6 +79,32 @@ Set ``BUILD_CPP_DOCS=1`` on the desired build command to
enable the extra step:
# One-off build
BUILD_CPP_DOCS=1 uv run --no-sync python -m sphinx -b html -W docs
docs/_build/html
+.. _build-rust-docs:
+
+Build with Rust Docs
+--------------------
+
+The Rust API reference is the ``cargo doc`` output of the ``rust/`` crate,
copied
+under ``reference/rust/generated`` of the HTML output. Use Rust 1.85 or newer
to avoid
+the `Rust 1.84 rustdoc crash
<https://github.com/rust-lang/rust/issues/134715>`_
+when documenting ``tvm-ffi``. The crate's build script runs
+``tvm-tirx-config`` to find ``libtvm_tirx_compiler``, so
+build the package first; ``uv run`` puts the helper on ``PATH``. Set
+``BUILD_RUST_DOCS=1`` to enable the extra step:
+
+.. code-block:: bash
+
+ # Interactive build with auto-rebuild on crate changes
+ BUILD_RUST_DOCS=1 uv run --no-sync sphinx-autobuild docs docs/_build/html \
+ --ignore docs/reference/python/generated --ignore
docs/reference/cpp/generated \
+ --watch rust/src
+
+ # One-off build
+ BUILD_RUST_DOCS=1 uv run --no-sync python -m sphinx -b html -W docs
docs/_build/html
+
+Rustdoc warnings, such as a broken intra-doc link, fail the build; set
+``RUSTDOCFLAGS`` to override the ``-D warnings`` default.
+
Cleanup
-------
@@ -89,3 +115,4 @@ Remove generated artifacts when they are no longer needed:
rm -rf docs/_build/
rm -rf docs/reference/python/generated
rm -rf docs/reference/cpp/generated
+ rm -rf rust/target/doc
diff --git a/docs/index.rst b/docs/index.rst
index 4c3776c5a..0e1db6aaa 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -65,6 +65,7 @@ Table of Contents
Python API <reference/python/index>
C++ API <reference/cpp/index>
+ Rust API <reference/rust/index>
.. toctree::
:maxdepth: 1
diff --git a/docs/reference/rust/index.rst b/docs/reference/rust/index.rst
new file mode 100644
index 000000000..bd88642ad
--- /dev/null
+++ b/docs/reference/rust/index.rst
@@ -0,0 +1,44 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+Rust API
+========
+
+The ``tvm-tirx`` crate in ``rust/`` binds the TIRx compiler objects over TVM
FFI.
+Its modules follow the Python package: ``tvm_tirx::ir`` is :doc:`tvm_tirx.ir
+<../python/ir>`, ``tvm_tirx::tirx`` is :doc:`tvm_tirx.tirx <../python/tirx>`,
and so
+on. Operators can also be defined from Rust with its ``register_ops!`` macro,
as
+:doc:`tvm_tirx.backend.rust <../python/backend.rust>` loads them.
+
+The reference is generated by ``cargo doc`` when the documentation is built
with
+``BUILD_RUST_DOCS=1`` (see :doc:`../../dev/doc_build`).
+
+Crates
+------
+
+.. list-table::
+ :header-rows: 1
+ :widths: 30 70
+
+ * - Crate
+ - Description
+ * - 📦 `tvm-tirx <generated/tvm_tirx/index.html>`_
+ - The IR, TIRx, symbolic analysis, target, backend, runtime, codegen and
script
+ bindings, the Rust IR constructors and operators, and ``register_ops!``.
+ * - 📦 `tvm-ffi <generated/tvm_ffi/index.html>`_
+ - The TVM FFI objects, functions and containers the bindings are built on,
+ re-exported as ``tvm_tirx::tvm_ffi``.
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index d82481dc5..a7d1aeaac 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -322,5 +322,9 @@ pub use tvm_ffi;
// The errors of the static init blocks of every library built on the crate,
which
// `import tvm_tirx` raises for `libtvm_tirx_rust`:
`__tvm_ffi_tirx_register_ir`, the TVM FFI
-// function `tirx_register_ir` of the library as `tvm_ffi.load_module` loads
it.
-tvm_ffi::tvm_ffi_dll_export_typed_func!(tirx_register_ir,
tvm_ffi::run_static_init_blocks);
+// function `tirx_register_ir` of the library as `tvm_ffi.load_module` loads
it. The module keeps
+// the symbol, which `#[no_mangle]` exports from wherever it is, out of the
crate's documentation.
+#[doc(hidden)]
+pub mod exports {
+ tvm_ffi::tvm_ffi_dll_export_typed_func!(tirx_register_ir,
tvm_ffi::run_static_init_blocks);
+}
diff --git a/tests/scripts/task_install_rust.sh
b/tests/scripts/task_install_rust.sh
index 80ee6f42f..8144069b8 100755
--- a/tests/scripts/task_install_rust.sh
+++ b/tests/scripts/task_install_rust.sh
@@ -18,12 +18,12 @@
set -euxo pipefail
-# Install the toolchain of the crate's rust-version, which the CI images do
not have, for the build
-# and the tests of rust/. Source it from the repository root.
+# Install the toolchain given as the first argument, defaulting to the crate's
rust-version
+# for the build and tests of rust/. Source it from the repository root.
export RUSTUP_HOME="$PWD/.local/rustup" CARGO_HOME="$PWD/.local/cargo"
curl --proto '=https' --tlsv1.2 --retry 3 -sSf https://sh.rustup.rs | sh -s --
-y -q \
--no-modify-path --profile minimal \
- --default-toolchain "$(sed -n 's/^rust-version = "\(.*\)"$/\1/p'
rust/Cargo.toml)"
+ --default-toolchain "${1:-$(sed -n 's/^rust-version = "\(.*\)"$/\1/p'
rust/Cargo.toml)}"
export PATH="$CARGO_HOME/bin:$PATH"
# rustc links with the cc first on PATH, which in the CI images is a wrapper
of sccache: link with
diff --git a/tests/scripts/task_python_docs.sh
b/tests/scripts/task_python_docs.sh
index 643293e15..d07518080 100755
--- a/tests/scripts/task_python_docs.sh
+++ b/tests/scripts/task_python_docs.sh
@@ -19,7 +19,11 @@
set -euxo pipefail
source ./tests/scripts/test_task_install_dist_wheels.sh --group docs
+# cargo for the Rust API reference; the crate's build script finds the
installed wheel's
+# libtvm_tirx_compiler through the tvm-tirx-config of the activated .venv.
+# Rust 1.84's rustdoc crashes on proc-macro doc links (rust-lang/rust#134715).
+source ./tests/scripts/task_install_rust.sh 1.85.1
rm -rf docs/_build docs/reference/python/generated
-BUILD_CPP_DOCS=1 uv run --no-sync python -m sphinx -E -a -b html -d
docs/_build/doctrees -W --keep-going docs docs/_build/html
+BUILD_CPP_DOCS=1 BUILD_RUST_DOCS=1 uv run --no-sync python -m sphinx -E -a -b
html -d docs/_build/doctrees -W --keep-going docs docs/_build/html
git rev-parse HEAD > docs/_build/html/commit_hash
tar -czf docs.tgz -C docs/_build/html .