Skip to content

Add support for specifying Natvis flags for Cargo to pass through to rustc #10192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2f686cf
Add support for specifying Natvis files in Cargo.toml and passing the…
ridwanabdillahi Nov 18, 2021
e672a95
Add fingerprinting support to ensure any changes to the set of Natvis…
ridwanabdillahi Dec 1, 2021
d12270e
Merge branch 'master' of https://github.com/ridwanabdillahi/cargo int…
ridwanabdillahi Dec 1, 2021
9099f1c
Fix broken unit tests.
ridwanabdillahi Dec 1, 2021
8a59eac
Fix fingerprinting failures by using a BTreeSet instead of a Vector.
ridwanabdillahi Dec 2, 2021
9299538
Update test name.
ridwanabdillahi Dec 2, 2021
65f8188
Minor cleanups.
ridwanabdillahi Dec 3, 2021
43bda3d
Minor refactors and formatting cleanups.
ridwanabdillahi Dec 8, 2021
9b76e5e
Update new toml section name.
ridwanabdillahi Dec 10, 2021
bc8aba7
Merge branch 'master' of https://github.com/ridwanabdillahi/cargo int…
ridwanabdillahi Dec 10, 2021
5827832
Merge branch 'master' of https://github.com/ridwanabdillahi/cargo int…
ridwanabdillahi Jan 5, 2022
e160ff2
Only add natvis for the primary unit of each package.
ridwanabdillahi Jan 7, 2022
d079926
Merge branch 'master' of https://github.com/ridwanabdillahi/cargo int…
ridwanabdillahi Jan 7, 2022
4693d67
Update the natvis flag specified to the rustc command when multiple n…
ridwanabdillahi Jan 20, 2022
061c11c
Merge branch 'master' of https://github.com/ridwanabdillahi/cargo int…
ridwanabdillahi Jan 20, 2022
efb14ac
Add support for Cargo to automatically finding `.natvis` in subdirect…
ridwanabdillahi Jan 28, 2022
2b5cd4a
Fix broken tests after latest changes to the compiler.
ridwanabdillahi Jan 28, 2022
2f26dae
Merge branch 'master' of https://github.com/ridwanabdillahi/cargo int…
ridwanabdillahi Jan 28, 2022
24d07bc
Update documentation regarding finding Natvis files in Cargo automati…
ridwanabdillahi Jan 31, 2022
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
3 changes: 3 additions & 0 deletions src/cargo/core/compiler/fingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,9 @@ fn calculate_normal(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Finger
if let Some(allow_features) = &cx.bcx.config.cli_unstable().allow_features {
allow_features.hash(&mut config);
}
if let Some(natvis) = &unit.pkg.manifest().natvis() {
natvis.hash(&mut config);
}
let compile_kind = unit.kind.fingerprint_hash();
Ok(Fingerprint {
rustc: util::hash_u64(&cx.bcx.rustc().verbose_version),
Expand Down
71 changes: 58 additions & 13 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ fn prepare_rustc(
.compilation
.rustc_process(unit, is_primary, is_workspace)?;

let mut unstable_opts = false;
if is_primary {
base.env("CARGO_PRIMARY_PACKAGE", "1");
}
Expand All @@ -611,7 +612,15 @@ fn prepare_rustc(
base.inherit_jobserver(&cx.jobserver);
}
build_base_args(cx, &mut base, unit, crate_types)?;
build_deps_args(&mut base, cx, unit)?;
build_natvis(&mut base, cx, unit, &mut unstable_opts)?;
build_deps_args(&mut base, cx, unit, &mut unstable_opts)?;

// This will only be set if we're already using a feature
// requiring nightly rust
if unstable_opts {
base.arg("-Z").arg("unstable-options");
}

Ok(base)
}

Expand Down Expand Up @@ -656,10 +665,11 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
Ok(output_dir.join(format!("{}.examples", unit.buildkey())))
};

let mut unstable_opts = false;
if unit.mode.is_doc_scrape() {
debug_assert!(cx.bcx.scrape_units.contains(unit));

rustdoc.arg("-Zunstable-options");
unstable_opts = true;

rustdoc
.arg("--scrape-examples-output-path")
Expand All @@ -680,7 +690,7 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
// We only pass scraped examples to packages in the workspace
// since examples are only coming from reverse-dependencies of workspace packages

rustdoc.arg("-Zunstable-options");
unstable_opts = true;

for scrape_unit in &cx.bcx.scrape_units {
rustdoc
Expand All @@ -689,7 +699,14 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
}
}

build_deps_args(&mut rustdoc, cx, unit)?;
build_deps_args(&mut rustdoc, cx, unit, &mut unstable_opts)?;

// This will only be set if we're already using a feature
// requiring nightly rust
if unstable_opts {
rustdoc.arg("-Z").arg("unstable-options");
}

rustdoc::add_root_urls(cx, unit, &mut rustdoc)?;

rustdoc.args(bcx.rustdocflags_args(unit));
Expand Down Expand Up @@ -1074,10 +1091,46 @@ fn lto_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
result
}

fn build_natvis(
cmd: &mut ProcessBuilder,
cx: &mut Context<'_, '_>,
unit: &Unit,
unstable_opts: &mut bool,
) -> CargoResult<()> {
if let Some(natvis) = &unit.pkg.manifest().natvis() {
// Only add natvis for the primary unit of each package.
// This will ensure units that depend on the primary
// unit, i.e. bins, integration tests or examples, will not
// have a duplicate set of natvis files.
let mut add_natvis = true;
let deps = cx.unit_deps(unit);
for dep in deps {
if cx.is_primary_package(&dep.unit) {
add_natvis = false;
break;
}
}

if add_natvis {
*unstable_opts = true;
for file in natvis {
cmd.arg("-C").arg(&{
let mut arg = OsString::from("natvis=");
arg.push(file);
arg
});
}
}
}

Ok(())
}

fn build_deps_args(
cmd: &mut ProcessBuilder,
cx: &mut Context<'_, '_>,
unit: &Unit,
unstable_opts: &mut bool,
) -> CargoResult<()> {
let bcx = cx.bcx;
cmd.arg("-L").arg(&{
Expand Down Expand Up @@ -1121,24 +1174,16 @@ fn build_deps_args(
}
}

let mut unstable_opts = false;

for dep in deps {
if dep.unit.mode.is_run_custom_build() {
cmd.env("OUT_DIR", &cx.files().build_script_out_dir(&dep.unit));
}
}

for arg in extern_args(cx, unit, &mut unstable_opts)? {
for arg in extern_args(cx, unit, unstable_opts)? {
cmd.arg(arg);
}

// This will only be set if we're already using a feature
// requiring nightly rust
if unstable_opts {
cmd.arg("-Z").arg("unstable-options");
}

Ok(())
}

Expand Down
3 changes: 3 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,9 @@ features! {

// Allow specifying rustflags directly in a profile
(unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"),

// Allow specifying natvis files to embed in the PDB when using the MSVC Linker.
(unstable, natvis, "", "reference/unstable.html#natvis"),
}

pub struct Feature {
Expand Down
9 changes: 8 additions & 1 deletion src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::{BTreeMap, HashMap};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -54,6 +54,7 @@ pub struct Manifest {
default_run: Option<String>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
natvis: Option<BTreeSet<PathBuf>>,
}

/// When parsing `Cargo.toml`, some warnings should silenced
Expand Down Expand Up @@ -393,6 +394,7 @@ impl Manifest {
original: Rc<TomlManifest>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
natvis: Option<BTreeSet<PathBuf>>,
) -> Manifest {
Manifest {
summary,
Expand All @@ -418,6 +420,7 @@ impl Manifest {
default_run,
metabuild,
resolve_behavior,
natvis,
}
}

Expand Down Expand Up @@ -486,6 +489,10 @@ impl Manifest {
self.links.as_deref()
}

pub fn natvis(&self) -> &Option<BTreeSet<PathBuf>> {
&self.natvis
}

pub fn workspace_config(&self) -> &WorkspaceConfig {
&self.workspace
}
Expand Down
73 changes: 73 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::fmt;
use std::fs;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::rc::Rc;
Expand Down Expand Up @@ -326,6 +327,7 @@ pub struct TomlManifest {
replace: Option<BTreeMap<String, TomlDependency>>,
patch: Option<BTreeMap<String, BTreeMap<String, TomlDependency>>>,
workspace: Option<TomlWorkspace>,
debugger_visualizations: Option<TomlDebuggerVisualizations>,
badges: Option<BTreeMap<String, BTreeMap<String, String>>>,
}

Expand Down Expand Up @@ -934,6 +936,16 @@ pub struct TomlWorkspace {
metadata: Option<toml::Value>,
}

/// Represents the `debugger-visualizations` section of a `Cargo.toml`.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TomlDebuggerVisualizations {
natvis: Option<Vec<PathValue>>,

// Note that this field must come last due to the way toml serialization
// works which requires tables to be emitted after all values.
metadata: Option<toml::Value>,
}

impl TomlProject {
pub fn to_package_id(&self, source_id: SourceId) -> CargoResult<PackageId> {
PackageId::new(self.name, self.version.clone(), source_id)
Expand Down Expand Up @@ -1049,6 +1061,7 @@ impl TomlManifest {
replace: None,
patch: None,
workspace: None,
debugger_visualizations: self.debugger_visualizations.clone(),
badges: self.badges.clone(),
cargo_features: self.cargo_features.clone(),
});
Expand Down Expand Up @@ -1400,6 +1413,65 @@ impl TomlManifest {
.transpose()?
.map(CompileKind::Target);

let mut natvis = BTreeSet::new();
let mut natvis_manifest_override = false;
let natvis_ext = "natvis";

// Collect the Natvis files specified via the toml file, if any exist, and normalize the absolute paths.
if let Some(debugger_visualizations) = me.debugger_visualizations.clone() {
features.require(Feature::natvis())?;
if let Some(natvis_files) = debugger_visualizations.natvis {
natvis_manifest_override = true;
for file in &natvis_files {
let path = paths::normalize_path(&package_root.join(file.clone().0));
if !path.exists() {
warnings.push(format!(
"Natvis file `{}` does not exist. Skipping file.",
path.display().to_string()
));
} else {
if path.extension() != Some(natvis_ext.as_ref()) {
warnings.push(format!(
"Natvis file `{}` does not have the expected `.natvis` extension.",
path.display().to_string()
));
}
natvis.insert(path);
}
}
}
}

// If the `natvis` manifest key was not specified, append all of the Natvis files in the pre-determined
// directory under the package root, `dbgvis/natvis/**/`.
fn find_natvis_files(path: &PathBuf, natvis: &mut BTreeSet<PathBuf>) {
if let Ok(path) = fs::read_dir(&path) {
for entry in path {
match entry {
Ok(entry) => {
let path = entry.path();
if path.is_dir() {
find_natvis_files(&path, natvis);
} else if path.is_file() && path.extension() == Some("natvis".as_ref()) {
natvis.insert(path);
}
}
Err(_) => { }
}
}
}
}

if !natvis_manifest_override && features.require(Feature::natvis()).is_ok() {
let natvis_dir_path = package_root.join("dbgvis").join(natvis_ext);
find_natvis_files(&natvis_dir_path, &mut natvis);
}

let natvis = if natvis.is_empty() {
None
} else {
Some(natvis)
};
let custom_metadata = project.metadata.clone();
let mut manifest = Manifest::new(
summary,
Expand All @@ -1424,6 +1496,7 @@ impl TomlManifest {
Rc::clone(me),
project.metabuild.clone().map(|sov| sov.0),
resolve_behavior,
natvis,
);
if project.license_file.is_some() && project.license.is_some() {
manifest.warnings_mut().add_warning(
Expand Down
31 changes: 31 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Each new feature described below should explain how to use it.
* [Profile `strip` option](#profile-strip-option) — Forces the removal of debug information and symbols from executables.
* [Profile `rustflags` option](#profile-rustflags-option) — Passed directly to rustc.
* [per-package-target](#per-package-target) — Sets the `--target` to use for each individual package.
* [natvis](#natvis) — Allows the specification of Natvis`(.natvis)` files to be embedded in a PDB when linking via the MSVC Linker.
* Information and metadata
* [Build-plan](#build-plan) — Emits JSON information on which commands will be run.
* [timings](#timings) — Generates a report on how long individual dependencies took to run.
Expand Down Expand Up @@ -876,6 +877,36 @@ In this example, the crate is always built for
as a plugin for a main program that runs on the host (or provided on
the command line) target.

### natvis
* Tracking Issue: [#0000](https://github.com/rust-lang/cargo/pull/0000)
* Original Pull Request: [#0000](https://github.com/rust-lang/cargo/pull/0000)
* Original Issue: [#0000](https://github.com/rust-lang/cargo/pull/0000)

The `natvis` feature adds a new section and key to the manifest:
`[debugger-visualizations]` and `debugger-visualizations.natvis` which
takes a list of `.natvis` files. The `natvis` feature also allows Cargo
to automatically find Natvis files that live in a predetermined
directory relative to the root of the package, `dbgvis/natvis`, including
its subdirectories. This will be the default for including Natvis files in
a package and will be overridden if the manifest key is specified. The Natvis
files will then be linked into the PDB generated if using the MSVC Linker.

Example:

```toml
cargo-features = ["natvis"]

[package]
name = "foo"
version = "0.0.1"

[debugger-visualizations]
natvis = ["foo.natvis", "bar.natvis"]
```

In this example, the crate `foo` will embed `foo.natvis` and `bar.natvis`
into the PDB being generated when using the MSVC Linker.

### credential-process
* Tracking Issue: [#8933](https://github.com/rust-lang/cargo/issues/8933)
* RFC: [#2730](https://github.com/rust-lang/rfcs/pull/2730)
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ mod metabuild;
mod metadata;
mod minimal_versions;
mod multitarget;
mod natvis;
mod net_config;
mod new;
mod offline;
Expand Down
Loading