Quite often when updating abstractions there will be some documentation
that needs updating, but the build process is not very developer friendly
as it just gives out something like
"rust/doctests_kernel_generated.rs:12345:42" and it is a hassle to find
where the documentation actually is.
Add a script as rustc wrapper, which translates the error message by
appending a "(generated from original_file:original_line:col)" message to
the original source info emitted by rustc.
This is the result of an example diagnostics:
error: test
--> rust/doctests_kernel_generated.rs:4490:1 (generated from
rust/kernel/build_assert.rs:96:1)
|
4490 | compile_error!("test");
| ^^^^^^^^^^^^^^^^^^^^^^
Signed-off-by: Gary Guo <[email protected]>
---
Changes in v2:
- Fixed SPDX header.
- Detect tty with stderr instead of stdout.
- Match doctest anchors more loosely without hardcoding i32.
- Link to v1: https://patch.msgid.link/[email protected]
---
rust/Makefile | 6 ++++
scripts/rustdoc_test_map_source.py | 73 ++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/rust/Makefile b/rust/Makefile
index da1a7409d984..23f603d1356e 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -406,6 +406,12 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
$(objtree)/scripts/rustdoc_test_gen FORCE
+$(call if_changed,rustdoc_test_kernel)
+# When building rustdoc tests, instead of using the actual RUSTC_OR_CLIPPY,
use a wrapper to build
+# so we can convert line number in diagnostics.
+ACTUAL_RUSTC := $(RUSTC_OR_CLIPPY)
+%/doctests_kernel_generated.o: private RUSTC_OR_CLIPPY = \
+ PYTHONDONTWRITEBYTECODE=1 ACTUAL_RUSTC=$(ACTUAL_RUSTC) $(PYTHON3)
$(srctree)/scripts/rustdoc_test_map_source.py
+
# We cannot use `-Zpanic-abort-tests` because some tests are dynamic,
# so for the moment we skip `-Cpanic=abort`.
quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T $<
diff --git a/scripts/rustdoc_test_map_source.py
b/scripts/rustdoc_test_map_source.py
new file mode 100644
index 000000000000..673021bedf4c
--- /dev/null
+++ b/scripts/rustdoc_test_map_source.py
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0
+
+import sys
+import re
+import os
+import subprocess
+
+LOCATION_REGEX = re.compile(r"\.location: (.*):(\d+)")
+ANCHOR_REGEX = re.compile(r"static __DOCTEST_ANCHOR: .+ = .* \+ (\d+) \+
(\d+);")
+SOURCE_INFO_REGEX = re.compile(r"(rust/[\w/.-]+\.rs):(\d+):(\d+)")
+
+
+def transform(file, line):
+ with open(file, "r") as f:
+ lines = f.readlines()
+
+ line_idx = line - 1
+
+ # Find the last location and anchor before the erroring line
+ real_path = None
+ orig_line = None
+ anchor_line = None
+
+ for i in range(line_idx, -1, -1):
+ if real_path is None:
+ match = LOCATION_REGEX.search(lines[i])
+ if match:
+ real_path = match.group(1)
+ orig_line = int(match.group(2))
+
+ if anchor_line is None:
+ match = ANCHOR_REGEX.search(lines[i])
+ if match:
+ anchor_line = i + int(match.group(1)) + int(match.group(2))
+
+ if real_path is not None and anchor_line is not None:
+ break
+
+ new_line = orig_line + (line_idx - anchor_line)
+ return real_path, new_line
+
+
+def main():
+ actual_rustc = os.environ.get("ACTUAL_RUSTC")
+ args = sys.argv[1:]
+
+ # We redirected Rust output so it is not TTY anymore.
+ # Add `--color=always` back to preserve the color behaviour.
+ if sys.stderr.isatty() and not any(arg.startswith("--color") for arg in
args):
+ args.append("--color=always")
+
+ result = subprocess.run([actual_rustc] + args, stderr=subprocess.PIPE,
text=True)
+
+ def replacer(match):
+ orig = match.group(0)
+ file = match.group(1)
+ line = int(match.group(2))
+ col = int(match.group(3))
+
+ if file != "rust/doctests_kernel_generated.rs":
+ return orig
+
+ new_file, new_line = transform(file, line)
+ return f"{orig} (generated from {new_file}:{new_line}:{col})"
+
+ if result.stderr:
+ sys.stderr.write(SOURCE_INFO_REGEX.sub(replacer, result.stderr))
+
+ sys.exit(result.returncode)
+
+
+if __name__ == "__main__":
+ main()
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260903-rustdoc-sourcemap-160f904fe78f
Best regards,
--
Gary Guo <[email protected]>