Skip to content

Commit 0850c37

Browse files
committed
Auto merge of rust-lang#83529 - richkadel:demangler, r=tmandry
Make rust-demangler installable Adds bootstrap rules to support installing rust-demangler, as an optional, in-tree `extended` tool. It can be included by updating `config.toml`, setting `extended = true`, and then either (a) adding `"rust-demangler"` to the `tools` array, or by enabling `profiler = true`. In other words, it is a _default_ `extended` tool if `profiler = true`. When compiling with `-Z instrument-coverage`, the coverage reports are generated by `llvm-cov`. `llvm-cov` includes a built-in demangler for C++, and an option to supply an alternate demangler. For Rust, we have `rust-demangler`, currently used in `rustc` coverage tests. Fuchsia's toolchain for Rust is built via `./x.py install`. Fuchsia is adding support for Rust coverage, and we need to include the `rust-demangler` in the installed `bin` directory. r? `@tmandry`
2 parents 2616ab1 + ed89e6b commit 0850c37

File tree

12 files changed

+327
-46
lines changed

12 files changed

+327
-46
lines changed

config.toml.example

+5-4
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,11 @@ changelog-seen = 2
259259
# be built if `extended = true`.
260260
#extended = false
261261

262-
# Installs chosen set of extended tools if `extended = true`. By default builds all.
263-
# If chosen tool failed to build the installation fails. If `extended = false`, this
264-
# option is ignored.
265-
#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"]
262+
# Installs chosen set of extended tools if `extended = true`. By default builds
263+
# all extended tools except `rust-demangler`, unless the target is also being
264+
# built with `profiler = true`. If chosen tool failed to build the installation
265+
# fails. If `extended = false`, this option is ignored.
266+
#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] # + "rust-demangler" if `profiler`
266267

267268
# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
268269
#verbose = 0

src/bootstrap/builder.rs

+3
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ impl<'a> Builder<'a> {
420420
test::Rustfmt,
421421
test::Miri,
422422
test::Clippy,
423+
test::RustDemangler,
423424
test::CompiletestTest,
424425
test::RustdocJSStd,
425426
test::RustdocJSNotStd,
@@ -466,6 +467,7 @@ impl<'a> Builder<'a> {
466467
dist::Rls,
467468
dist::RustAnalyzer,
468469
dist::Rustfmt,
470+
dist::RustDemangler,
469471
dist::Clippy,
470472
dist::Miri,
471473
dist::LlvmTools,
@@ -481,6 +483,7 @@ impl<'a> Builder<'a> {
481483
install::Rls,
482484
install::RustAnalyzer,
483485
install::Rustfmt,
486+
install::RustDemangler,
484487
install::Clippy,
485488
install::Miri,
486489
install::Analysis,

src/bootstrap/dist.rs

+92-2
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,56 @@ impl Step for Rustfmt {
12461246
}
12471247
}
12481248

1249+
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1250+
pub struct RustDemangler {
1251+
pub compiler: Compiler,
1252+
pub target: TargetSelection,
1253+
}
1254+
1255+
impl Step for RustDemangler {
1256+
type Output = Option<GeneratedTarball>;
1257+
const ONLY_HOSTS: bool = true;
1258+
1259+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1260+
run.path("rust-demangler")
1261+
}
1262+
1263+
fn make_run(run: RunConfig<'_>) {
1264+
run.builder.ensure(RustDemangler {
1265+
compiler: run.builder.compiler_for(
1266+
run.builder.top_stage,
1267+
run.builder.config.build,
1268+
run.target,
1269+
),
1270+
target: run.target,
1271+
});
1272+
}
1273+
1274+
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1275+
let compiler = self.compiler;
1276+
let target = self.target;
1277+
assert!(builder.config.extended);
1278+
1279+
// Only build this extended tool if explicitly included in `tools`, or if `profiler = true`
1280+
let profiler = builder.config.profiler_enabled(target);
1281+
if !builder.config.tools.as_ref().map_or(profiler, |t| t.contains("rust-demangler")) {
1282+
return None;
1283+
}
1284+
1285+
let rust_demangler = builder
1286+
.ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() })
1287+
.expect("rust-demangler expected to build - in-tree tool");
1288+
1289+
// Prepare the image directory
1290+
let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple);
1291+
tarball.set_overlay(OverlayKind::RustDemangler);
1292+
tarball.is_preview(true);
1293+
tarball.add_file(&rust_demangler, "bin", 0o755);
1294+
tarball.add_legal_and_readme_to("share/doc/rust-demangler");
1295+
Some(tarball.generate())
1296+
}
1297+
}
1298+
12491299
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
12501300
pub struct Extended {
12511301
stage: u32,
@@ -1282,6 +1332,7 @@ impl Step for Extended {
12821332
let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
12831333
let cargo_installer = builder.ensure(Cargo { compiler, target });
12841334
let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1335+
let rust_demangler_installer = builder.ensure(RustDemangler { compiler, target });
12851336
let rls_installer = builder.ensure(Rls { compiler, target });
12861337
let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
12871338
let llvm_tools_installer = builder.ensure(LlvmTools { target });
@@ -1307,9 +1358,10 @@ impl Step for Extended {
13071358
let mut tarballs = Vec::new();
13081359
tarballs.push(rustc_installer);
13091360
tarballs.push(cargo_installer);
1361+
tarballs.push(clippy_installer);
1362+
tarballs.extend(rust_demangler_installer.clone());
13101363
tarballs.extend(rls_installer.clone());
13111364
tarballs.extend(rust_analyzer_installer.clone());
1312-
tarballs.push(clippy_installer);
13131365
tarballs.extend(miri_installer.clone());
13141366
tarballs.extend(rustfmt_installer.clone());
13151367
tarballs.extend(llvm_tools_installer);
@@ -1366,6 +1418,9 @@ impl Step for Extended {
13661418

13671419
let xform = |p: &Path| {
13681420
let mut contents = t!(fs::read_to_string(p));
1421+
if rust_demangler_installer.is_none() {
1422+
contents = filter(&contents, "rust-demangler");
1423+
}
13691424
if rls_installer.is_none() {
13701425
contents = filter(&contents, "rls");
13711426
}
@@ -1414,7 +1469,9 @@ impl Step for Extended {
14141469
prepare("rust-std");
14151470
prepare("rust-analysis");
14161471
prepare("clippy");
1417-
1472+
if rust_demangler_installer.is_some() {
1473+
prepare("rust-demangler");
1474+
}
14181475
if rls_installer.is_some() {
14191476
prepare("rls");
14201477
}
@@ -1462,6 +1519,8 @@ impl Step for Extended {
14621519
"rust-analyzer-preview".to_string()
14631520
} else if name == "clippy" {
14641521
"clippy-preview".to_string()
1522+
} else if name == "rust-demangler" {
1523+
"rust-demangler-preview".to_string()
14651524
} else if name == "miri" {
14661525
"miri-preview".to_string()
14671526
} else {
@@ -1479,6 +1538,9 @@ impl Step for Extended {
14791538
prepare("rust-docs");
14801539
prepare("rust-std");
14811540
prepare("clippy");
1541+
if rust_demangler_installer.is_some() {
1542+
prepare("rust-demangler");
1543+
}
14821544
if rls_installer.is_some() {
14831545
prepare("rls");
14841546
}
@@ -1620,6 +1682,25 @@ impl Step for Extended {
16201682
.arg("-t")
16211683
.arg(etc.join("msi/remove-duplicates.xsl")),
16221684
);
1685+
if rust_demangler_installer.is_some() {
1686+
builder.run(
1687+
Command::new(&heat)
1688+
.current_dir(&exe)
1689+
.arg("dir")
1690+
.arg("rust-demangler")
1691+
.args(&heat_flags)
1692+
.arg("-cg")
1693+
.arg("RustDemanglerGroup")
1694+
.arg("-dr")
1695+
.arg("RustDemangler")
1696+
.arg("-var")
1697+
.arg("var.RustDemanglerDir")
1698+
.arg("-out")
1699+
.arg(exe.join("RustDemanglerGroup.wxs"))
1700+
.arg("-t")
1701+
.arg(etc.join("msi/remove-duplicates.xsl")),
1702+
);
1703+
}
16231704
if miri_installer.is_some() {
16241705
builder.run(
16251706
Command::new(&heat)
@@ -1693,6 +1774,9 @@ impl Step for Extended {
16931774
.arg(&input);
16941775
add_env(builder, &mut cmd, target);
16951776

1777+
if rust_demangler_installer.is_some() {
1778+
cmd.arg("-dRustDemanglerDir=rust-demangler");
1779+
}
16961780
if rls_installer.is_some() {
16971781
cmd.arg("-dRlsDir=rls");
16981782
}
@@ -1715,6 +1799,9 @@ impl Step for Extended {
17151799
candle("CargoGroup.wxs".as_ref());
17161800
candle("StdGroup.wxs".as_ref());
17171801
candle("ClippyGroup.wxs".as_ref());
1802+
if rust_demangler_installer.is_some() {
1803+
candle("RustDemanglerGroup.wxs".as_ref());
1804+
}
17181805
if rls_installer.is_some() {
17191806
candle("RlsGroup.wxs".as_ref());
17201807
}
@@ -1761,6 +1848,9 @@ impl Step for Extended {
17611848
if rust_analyzer_installer.is_some() {
17621849
cmd.arg("RustAnalyzerGroup.wixobj");
17631850
}
1851+
if rust_demangler_installer.is_some() {
1852+
cmd.arg("RustDemanglerGroup.wixobj");
1853+
}
17641854
if miri_installer.is_some() {
17651855
cmd.arg("MiriGroup.wixobj");
17661856
}

src/bootstrap/install.rs

+16
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,22 @@ install!((self, builder, _config),
190190
);
191191
}
192192
};
193+
RustDemangler, "rust-demangler", Self::should_build(_config), only_hosts: true, {
194+
// Note: Even though `should_build` may return true for `extended` default tools,
195+
// dist::RustDemangler may still return None, unless the target-dependent `profiler` config
196+
// is also true, or the `tools` array explicitly includes "rust-demangler".
197+
if let Some(tarball) = builder.ensure(dist::RustDemangler {
198+
compiler: self.compiler,
199+
target: self.target
200+
}) {
201+
install_sh(builder, "rust-demangler", self.compiler.stage, Some(self.target), &tarball);
202+
} else {
203+
builder.info(
204+
&format!("skipping Install RustDemangler stage{} ({})",
205+
self.compiler.stage, self.target),
206+
);
207+
}
208+
};
193209
Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
194210
let tarball = builder.ensure(dist::Analysis {
195211
// Find the actual compiler (handling the full bootstrap option) which

src/bootstrap/tarball.rs

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub(crate) enum OverlayKind {
1515
Clippy,
1616
Miri,
1717
Rustfmt,
18+
RustDemangler,
1819
RLS,
1920
RustAnalyzer,
2021
}
@@ -47,6 +48,9 @@ impl OverlayKind {
4748
"src/tools/rustfmt/LICENSE-APACHE",
4849
"src/tools/rustfmt/LICENSE-MIT",
4950
],
51+
OverlayKind::RustDemangler => {
52+
&["src/tools/rust-demangler/README.md", "LICENSE-APACHE", "LICENSE-MIT"]
53+
}
5054
OverlayKind::RLS => &[
5155
"src/tools/rls/README.md",
5256
"src/tools/rls/LICENSE-APACHE",
@@ -64,6 +68,7 @@ impl OverlayKind {
6468
match self {
6569
OverlayKind::Rust => builder.rust_version(),
6670
OverlayKind::LLVM => builder.rust_version(),
71+
OverlayKind::RustDemangler => builder.release_num("rust-demangler"),
6772
OverlayKind::Cargo => {
6873
builder.cargo_info.version(builder, &builder.release_num("cargo"))
6974
}

src/bootstrap/test.rs

+55-1
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,57 @@ impl Step for Rustfmt {
351351
}
352352
}
353353

354+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
355+
pub struct RustDemangler {
356+
stage: u32,
357+
host: TargetSelection,
358+
}
359+
360+
impl Step for RustDemangler {
361+
type Output = ();
362+
const ONLY_HOSTS: bool = true;
363+
364+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
365+
run.path("src/tools/rust-demangler")
366+
}
367+
368+
fn make_run(run: RunConfig<'_>) {
369+
run.builder.ensure(RustDemangler { stage: run.builder.top_stage, host: run.target });
370+
}
371+
372+
/// Runs `cargo test` for rust-demangler.
373+
fn run(self, builder: &Builder<'_>) {
374+
let stage = self.stage;
375+
let host = self.host;
376+
let compiler = builder.compiler(stage, host);
377+
378+
let rust_demangler = builder
379+
.ensure(tool::RustDemangler { compiler, target: self.host, extra_features: Vec::new() })
380+
.expect("in-tree tool");
381+
let mut cargo = tool::prepare_tool_cargo(
382+
builder,
383+
compiler,
384+
Mode::ToolRustc,
385+
host,
386+
"test",
387+
"src/tools/rust-demangler",
388+
SourceType::InTree,
389+
&[],
390+
);
391+
392+
let dir = testdir(builder, compiler.host);
393+
t!(fs::create_dir_all(&dir));
394+
395+
cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler);
396+
397+
cargo.arg("--").args(builder.config.cmd.test_args());
398+
399+
cargo.add_rustc_lib_path(builder, compiler);
400+
401+
builder.run(&mut cargo.into());
402+
}
403+
}
404+
354405
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
355406
pub struct Miri {
356407
stage: u32,
@@ -1126,7 +1177,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the
11261177
}
11271178

11281179
if mode == "run-make" && suite.ends_with("fulldeps") {
1129-
cmd.arg("--rust-demangler-path").arg(builder.tool_exe(Tool::RustDemangler));
1180+
let rust_demangler = builder
1181+
.ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() })
1182+
.expect("in-tree tool");
1183+
cmd.arg("--rust-demangler-path").arg(rust_demangler);
11301184
}
11311185

11321186
cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite));

src/bootstrap/tool.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,6 @@ bootstrap_tool!(
368368
Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true;
369369
BuildManifest, "src/tools/build-manifest", "build-manifest";
370370
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
371-
RustDemangler, "src/tools/rust-demangler", "rust-demangler";
372371
RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true;
373372
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes";
374373
ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors";
@@ -719,6 +718,7 @@ tool_extended!((self, builder),
719718
});
720719
self.extra_features.push("clippy".to_owned());
721720
};
721+
RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, {};
722722
Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, {};
723723
RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, {};
724724
);

src/tools/rust-demangler/Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ edition = "2018"
88
regex = "1.0"
99
rustc-demangle = "0.1.17"
1010

11+
[lib]
12+
name = "rust_demangler"
13+
doctest = false
14+
1115
[[bin]]
1216
name = "rust-demangler"
13-
path = "main.rs"
17+
test = false

src/tools/rust-demangler/README.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# rust-demangler
2+
3+
_Demangles rustc mangled names._
4+
5+
`rust-demangler` supports the requirements of the [`llvm-cov show -Xdemangler`
6+
option](https://llvm.org/docs/CommandGuide/llvm-cov.html#cmdoption-llvm-cov-show-xdemangler),
7+
to perform Rust-specific symbol demangling:
8+
9+
> _The demangler is expected to read a newline-separated list of symbols from
10+
> stdin and write a newline-separated list of the same length to stdout._
11+
12+
To use `rust-demangler` with `llvm-cov` for example:
13+
14+
```shell
15+
$ TARGET="${PWD}/build/x86_64-unknown-linux-gnu"
16+
$ "${TARGET}"/llvm/bin/llvm-cov show \
17+
--Xdemangler=path/to/rust-demangler \
18+
--instr-profile=main.profdata ./main --show-line-counts-or-regions
19+
```
20+
21+
`rust-demangler` is a Rust "extended tool", used in Rust compiler tests, and
22+
optionally included in Rust distributions that enable coverage profiling. Symbol
23+
demangling is implemented using the
24+
[rustc-demangle](https://crates.io/crates/rustc-demangle) crate.
25+
26+
_(Note, for Rust developers, the third-party tool
27+
[`rustfilt`](https://crates.io/crates/rustfilt) also supports `llvm-cov` symbol
28+
demangling. `rustfilt` is a more generalized tool that searches any body of
29+
text, using pattern matching, to find and demangle Rust symbols.)_
30+
31+
## License
32+
33+
Rust-demangler is distributed under the terms of both the MIT license and the
34+
Apache License (Version 2.0).
35+
36+
See [LICENSE-APACHE](/LICENSE-APACHE) and [LICENSE-MIT](/LICENSE-MIT) for details.

0 commit comments

Comments
 (0)