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 .

Reply via email to