Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ By using [`cargo expand`](https://github.com/dtolnay/cargo-expand) or `cargo
doc` you can also explore the generated code. If there's a bug in `wit-bindgen`
and the generated bindings do not compile or if there's an error in the
generated code (which is probably also a bug in `wit-bindgen`), you can use
`WIT_BINDGEN_DEBUG=1` as an environment variable to help debug this.
`WIT_BINDGEN_DEBUG=/some/dir` as an environment variable to help debug this.

This project can then be built with:

Expand Down
5 changes: 0 additions & 5 deletions crates/guest-rust/macro/build.rs

This file was deleted.

69 changes: 55 additions & 14 deletions crates/guest-rust/macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use proc_macro2::{Span, TokenStream};
use quote::ToTokens;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
Expand Down Expand Up @@ -68,7 +68,7 @@ struct Config {
resolve: Resolve,
world: WorldId,
files: Vec<PathBuf>,
debug: bool,
debug: Option<syn::LitStr>,
}

/// The source of the wit package definition
Expand All @@ -88,7 +88,7 @@ impl Parse for Config {
let mut features = Vec::new();
let mut sync_configured = false;
let mut method_chaining_configured = false;
let mut debug = false;
let mut debug = None;

if input.peek(token::Brace) {
let content;
Expand Down Expand Up @@ -188,8 +188,8 @@ impl Parse for Config {
Opt::DisableCustomSectionLinkHelpers(disable) => {
opts.disable_custom_section_link_helpers = disable.value();
}
Opt::Debug(enable) => {
debug = enable.value();
Opt::Debug(dir) => {
debug = Some(dir);
}
Opt::Sync(val, span) => {
if sync_configured {
Expand Down Expand Up @@ -294,7 +294,41 @@ fn parse_source(
}

impl Config {
fn debug_output_dir(&self) -> Result<Option<PathBuf>> {
let dir = match (&self.debug, std::env::var_os("WIT_BINDGEN_DEBUG")) {
(Some(dir), _) => {
let value = dir.value();
if value.is_empty() {
return Err(Error::new(dir.span(), "`debug` directory cannot be empty"));
}
PathBuf::from(value)
}
(None, Some(env)) => {
// Historically `WIT_BINDGEN_DEBUG=1` was the documented way to
// turn this on, so reject that (and `0`, which previously
// still enabled debug output) rather than silently writing
// to a directory named `1` or `0`.
if env.is_empty() || env == "1" || env == "0" {
return Err(Error::new(
Span::call_site(),
format!(
"`WIT_BINDGEN_DEBUG={}` is no longer supported; set it to \
a directory to write generated code to instead, for example \
`WIT_BINDGEN_DEBUG=/tmp/wit-bindgen-debug`",
env.display(),
),
));
}
PathBuf::from(env)
}
(None, None) => return Ok(None),
};
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
Ok(Some(root.join(dir)))
}

fn expand(mut self) -> Result<TokenStream> {
let debug_output_dir = self.debug_output_dir()?;
let mut files = Default::default();
let mut generator = self.opts.build();
generator
Expand All @@ -303,23 +337,30 @@ impl Config {
let (_, src) = files.iter().next().unwrap();
let mut src = std::str::from_utf8(src).unwrap().to_string();

// If a magical `WIT_BINDGEN_DEBUG` environment variable is set then
// place a formatted version of the expanded code into a file. This file
// will then show up in rustc error messages for any codegen issues and can
// be inspected manually.
if std::env::var("WIT_BINDGEN_DEBUG").is_ok() || self.debug {
// If debugging is set then place a formatted version of the expanded
// code into a file in that directory. This file will then show up in
// rustc error messages for any codegen issues and can be inspected
// manually.
if let Some(root) = debug_output_dir {
static INVOCATION: AtomicUsize = AtomicUsize::new(0);
let root = Path::new(env!("DEBUG_OUTPUT_DIR"));
let world_name = &self.resolve.worlds[self.world].name;
let n = INVOCATION.fetch_add(1, Relaxed);
let path = root.join(format!("{world_name}{n}.rs"));
let krate = std::env::var("CARGO_CRATE_NAME").unwrap_or_default();
let path = root.join(format!("{krate}-{world_name}-{n}.rs"));

// optimistically format the code but don't require success
let contents = match fmt(&src) {
Ok(formatted) => formatted,
Err(_) => src.clone(),
};
std::fs::write(&path, contents.as_bytes()).unwrap();
std::fs::create_dir_all(&root)
.and_then(|()| std::fs::write(&path, contents.as_bytes()))
.map_err(|e| {
Error::new(
Span::call_site(),
format!("failed to write debug output to `{}`: {e}", path.display()),
)
})?;

src = format!("include!({path:?});");
}
Expand Down Expand Up @@ -456,7 +497,7 @@ enum Opt {
Features(Vec<syn::LitStr>),
DisableCustomSectionLinkHelpers(syn::LitBool),
Sync(AsyncFilterSet, Span),
Debug(syn::LitBool),
Debug(syn::LitStr),
ChainableMethods(ChainableMethodFilterSet, Span),
MergeStructurallyEqualTypes(syn::LitBool),
}
Expand Down
25 changes: 14 additions & 11 deletions crates/guest-rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,17 +618,18 @@ extern crate std;
/// inevitably bugs and issues that arise. These can range from bad error
/// messages to misconfigured invocations to bugs in the macro itself. To assist
/// with debugging these situations the macro recognizes an environment
/// variable:
/// variable naming a directory:
///
/// ```shell
/// export WIT_BINDGEN_DEBUG=1
/// export WIT_BINDGEN_DEBUG=/tmp/wit-bindgen-debug
/// ```
///
/// When set the macro will emit the result of expansion to a file and then
/// `include!` that file. Any error messages generated by `rustc` should then
/// point to the generated file and allow you to open it up, read it, and
/// inspect it. This can often provide better context to the error than rustc
/// provides by default with macros.
/// When set the macro will emit the result of expansion to a file in that
/// directory and then `include!` that file. Relative paths are resolved
/// against the `CARGO_MANIFEST_DIR` of the crate invoking the macro. Any error
/// messages generated by `rustc` should then point to the generated file and
/// allow you to open it up, read it, and inspect it. This can often provide
/// better context to the error than rustc provides by default with macros.
///
/// It is not recommended to set this environment variable by default as it will
/// cause excessive rebuilds of Cargo projects. It's recommended to only use it
Expand Down Expand Up @@ -855,10 +856,12 @@ extern crate std;
/// // emit more useful diagnostics for errors in the generated code. This
/// // is primarily useful for `wit-bindgen` developers.
/// //
/// // This does the same thing as setting `WIT_BINDGEN_DEBUG=1`, except
/// // that it can be used on a more fine-grained basis (i.e. it only affects
/// // the specific `generate!` call where it is used.
/// debug: true,
/// // This does the same thing as setting `WIT_BINDGEN_DEBUG=<dir>`,
/// // except that it can be used on a more fine-grained basis (i.e. it only
/// // affects the specific `generate!` call where it is used). The path is
/// // relative to `CARGO_MANIFEST_DIR`, and this option takes precedence
/// // over `WIT_BINDGEN_DEBUG`.
/// debug: "target/wit-bindgen-debug",
///
/// // Generate sync bindings for functions that are `async` in WIT.
/// //
Expand Down
Loading