first pass for debugger_visualizer docs

This commit is contained in:
Gibby Free 2023-02-27 13:24:43 -08:00 committed by Eric Huss
parent 1f8dc727e9
commit 2749bce830
2 changed files with 149 additions and 0 deletions

View File

@ -224,6 +224,7 @@ The following is an index of all built-in attributes.
- [`allow`], [`warn`], [`deny`], [`forbid`] — Alters the default lint level.
- [`deprecated`] — Generates deprecation notices.
- [`must_use`] — Generates a lint for unused values.
- [`debugger_visualizer`] — Embeds a file that specifies debugger output for a type
- ABI, linking, symbols, and FFI
- [`link`] — Specifies a native library to link with an `extern` block.
- [`link_name`] — Specifies the name of the symbol for functions or statics
@ -291,6 +292,7 @@ The following is an index of all built-in attributes.
[`cold`]: attributes/codegen.md#the-cold-attribute
[`crate_name`]: crates-and-source-files.md#the-crate_name-attribute
[`crate_type`]: linkage.md
[`debugger_visualizer`]: attributes/diagnostics.md#the-debugger_visualizer-attribute
[`deny`]: attributes/diagnostics.md#lint-check-attributes
[`deprecated`]: attributes/diagnostics.md#the-deprecated-attribute
[`derive`]: attributes/derive.md

View File

@ -301,7 +301,154 @@ When used on a function in a trait implementation, the attribute does nothing.
> let _ = five();
> ```
## The `debugger_visualizer` attribute
The `debugger_visualizer` attribute can be used to embed a debugger visualizer file into the PDB/ELF generated by `rustc`.
This enables an improved debugger experience for types outside of Rust's standard library.
### Using `debugger_visualizer` with Natvis
Natvis is an XML-based framework, and a `.natvis` file declares how a type's fields should be displayed in the debugger view.
A Natvis file is embedded using the `natvis-file` meta item.
Microsoft's [Natvis documentation] can be referenced to help developers write their own `.natvis` files.
<div class="warning">
Currently, this attribute only supports embedding Natvis files on `-windows-msvc` targets.
`-windows-gnu` targets are not currently supported.
</div>
Consider a crate with this directory structure:
```text
/Cargo.toml
/Foo.natvis (Note: the Natvis file does not have to match the name of the crate.)
+-- src
+-- main.rs
```
Where `main.rs` contains:
```rust
#![debugger_visualizer(natvis_file = "../Foo.natvis")]
struct FancyRect {
pub x: f32,
pub y: f32,
pub dx: f32,
pub dy: f32,
}
fn main() {
let mut fancy_rect = FancyRect::new(10.0, 10.0, 5.0, 5.0);
}
```
and `Foo.natvis` contains:
```xml
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="foo::FancyRect">
<DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
<Expand>
<Synthetic Name="LowerLeft">
<DisplayString>({x}, {y})</DisplayString>
</Synthetic>
<Synthetic Name="UpperLeft">
<DisplayString>({x}, {y + dy})</DisplayString>
</Synthetic>
<Synthetic Name="UpperRight">
<DisplayString>({x + dx}, {y + dy})</DisplayString>
</Synthetic>
<Synthetic Name="LowerRight">
<DisplayString>({x + dx}, {y})</DisplayString>
</Synthetic>
</Expand>
</Type>
</AutoVisualizer>
```
When viewed under WinDbg, the `fancy_rect` variable would be shown as follows:
```text
> Variables:
> fancy_rect: (10, 10) + (5, 5)
> LowerLeft: (10, 10)
> UpperLeft: (10, 15)
> UpperRight: (15, 15)
> LowerRight: (15, 10)
```
### Using `debugger_visualizer` with GDB
Developers using GDB are able to embed *pretty printers* onto types.
In GDB, a pretty printer is a structured Python script that describes how a type's fields should be displayed in the debugger view.
These scripts are embedded using the `gdb_script_file` meta item.
GDB's [pretty print documentation] can be referenced by developers to help them write their own `.py` scripts.
Consider a crate with this directory structure:
```text
/Cargo.toml
/bar.py (Note: the file does not have to match the name of the crate.)
+-- src
+-- main.rs
```
Where `main.rs` contains:
```rust
#![debugger_visualizer(gdb_script_file = "../bar.py")]
mod person {
pub struct Person {
pub name: String,
pub age: i32,
}
}
use person::Person;
fn main() {
let person = Person::new(String::from("Bob"), 10);
}
```
and `bar.py` contains:
```python
import gdb
class PersonPrinter:
"Print a Person"
def __init__(self, val):
self.val = val
self.name = val["name"]
self.age = int(val["age"])
def to_string(self):
return "{} is {} years old.".format(self.name, self.age)
def lookup(val):
lookup_tag = val.type.tag
if lookup_tag is None:
return None
if "main::Person" == lookup_tag:
return PersonPrinter(val)
return None
gdb.current_objfile().pretty_printers.append(lookup)
```
When the crate's debug executable is passed into GDB, `print person` should display:
```
"Bob" is 10 years old.
```
[Clippy]: https://github.com/rust-lang/rust-clippy
[Natvis documentation]: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects
[pretty print documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html
[_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax
[_MetaListPaths_]: ../attributes.md#meta-item-attribute-syntax
[_MetaNameValueStr_]: ../attributes.md#meta-item-attribute-syntax