Skip to content

Commit 23325ca

Browse files
committed
Make rust-demangler installable
Adds bootstrap rules to support installing rust-demangler. 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. Configured rust-demangler as an in-tree extended tool. Added tests to support `./x.py test rust-demangler`. Install with extended tools by default only if `profiler = true`.
1 parent 97717a5 commit 23325ca

File tree

12 files changed

+328
-44
lines changed

12 files changed

+328
-44
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

+86
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,50 @@ 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 = 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<'_>) -> GeneratedTarball {
1275+
let compiler = self.compiler;
1276+
let target = self.target;
1277+
assert!(builder.config.extended);
1278+
1279+
let rust_demangler = builder
1280+
.ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() })
1281+
.expect("rust-demangler expected to build - in-tree tool");
1282+
1283+
// Prepare the image directory
1284+
let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple);
1285+
tarball.set_overlay(OverlayKind::RustDemangler);
1286+
tarball.is_preview(true);
1287+
tarball.add_file(&rust_demangler, "bin", 0o755);
1288+
tarball.add_legal_and_readme_to("share/doc/rust-demangler");
1289+
tarball.generate()
1290+
}
1291+
}
1292+
12491293
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
12501294
pub struct Extended {
12511295
stage: u32,
@@ -1282,6 +1326,14 @@ impl Step for Extended {
12821326
let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
12831327
let cargo_installer = builder.ensure(Cargo { compiler, target });
12841328
let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1329+
let profiler = builder.config.profiler_enabled(target);
1330+
let install_rust_demangler =
1331+
builder.config.tools.as_ref().map_or(profiler, |t| t.contains("rust-demangler"));
1332+
let rust_demangler_installer = if install_rust_demangler {
1333+
Some(builder.ensure(RustDemangler { compiler, target }))
1334+
} else {
1335+
None
1336+
};
12851337
let rls_installer = builder.ensure(Rls { compiler, target });
12861338
let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
12871339
let llvm_tools_installer = builder.ensure(LlvmTools { target });
@@ -1312,6 +1364,9 @@ impl Step for Extended {
13121364
tarballs.push(clippy_installer);
13131365
tarballs.extend(miri_installer.clone());
13141366
tarballs.extend(rustfmt_installer.clone());
1367+
if let Some(rust_demangler_installer) = rust_demangler_installer {
1368+
tarballs.push(rust_demangler_installer);
1369+
}
13151370
tarballs.extend(llvm_tools_installer);
13161371
if let Some(analysis_installer) = analysis_installer {
13171372
tarballs.push(analysis_installer);
@@ -1413,6 +1468,9 @@ impl Step for Extended {
14131468
prepare("rust-docs");
14141469
prepare("rust-std");
14151470
prepare("rust-analysis");
1471+
if install_rust_demangler {
1472+
prepare("rust-demangler");
1473+
}
14161474
prepare("clippy");
14171475

14181476
if rls_installer.is_some() {
@@ -1476,6 +1534,9 @@ impl Step for Extended {
14761534
prepare("rustc");
14771535
prepare("cargo");
14781536
prepare("rust-analysis");
1537+
if install_rust_demangler {
1538+
prepare("rust-demangler");
1539+
}
14791540
prepare("rust-docs");
14801541
prepare("rust-std");
14811542
prepare("clippy");
@@ -1620,6 +1681,25 @@ impl Step for Extended {
16201681
.arg("-t")
16211682
.arg(etc.join("msi/remove-duplicates.xsl")),
16221683
);
1684+
if install_rust_demangler {
1685+
builder.run(
1686+
Command::new(&heat)
1687+
.current_dir(&exe)
1688+
.arg("dir")
1689+
.arg("rust-demangler")
1690+
.args(&heat_flags)
1691+
.arg("-cg")
1692+
.arg("RustDemanglerGroup")
1693+
.arg("-dr")
1694+
.arg("RustDemangler")
1695+
.arg("-var")
1696+
.arg("var.RustDemanglerDir")
1697+
.arg("-out")
1698+
.arg(exe.join("RustDemanglerGroup.wxs"))
1699+
.arg("-t")
1700+
.arg(etc.join("msi/remove-duplicates.xsl")),
1701+
);
1702+
}
16231703
if miri_installer.is_some() {
16241704
builder.run(
16251705
Command::new(&heat)
@@ -1715,6 +1795,9 @@ impl Step for Extended {
17151795
candle("CargoGroup.wxs".as_ref());
17161796
candle("StdGroup.wxs".as_ref());
17171797
candle("ClippyGroup.wxs".as_ref());
1798+
if install_rust_demangler {
1799+
candle("RustDemanglerGroup.wxs".as_ref());
1800+
}
17181801
if rls_installer.is_some() {
17191802
candle("RlsGroup.wxs".as_ref());
17201803
}
@@ -1761,6 +1844,9 @@ impl Step for Extended {
17611844
if rust_analyzer_installer.is_some() {
17621845
cmd.arg("RustAnalyzerGroup.wixobj");
17631846
}
1847+
if install_rust_demangler {
1848+
cmd.arg("RustDemanglerGroup.wixobj");
1849+
}
17641850
if miri_installer.is_some() {
17651851
cmd.arg("MiriGroup.wixobj");
17661852
}

src/bootstrap/install.rs

+20
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,26 @@ install!((self, builder, _config),
190190
);
191191
}
192192
};
193+
RustDemangler,
194+
"rust-demangler",
195+
Self::should_build(_config),
196+
only_hosts: true,
197+
{
198+
let profiler = builder.config.profiler_enabled(self.target);
199+
let install_rust_demangler =
200+
builder.config.tools.as_ref().map_or(profiler, |t| t.contains("rust-demangler"));
201+
if install_rust_demangler {
202+
let tarball = builder.ensure(
203+
dist::RustDemangler { compiler: self.compiler, target: self.target }
204+
);
205+
install_sh(builder, "rust-demangler", self.compiler.stage, Some(self.target), &tarball);
206+
} else {
207+
builder.info(
208+
&format!("skipping Install RustDemangler stage{} ({})",
209+
self.compiler.stage, self.target),
210+
);
211+
}
212+
};
193213
Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
194214
let tarball = builder.ensure(dist::Analysis {
195215
// 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.rust_version(),
6772
OverlayKind::Cargo => {
6873
builder.cargo_info.version(builder, &builder.release_num("cargo"))
6974
}

src/bootstrap/test.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,54 @@ 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+
cargo.add_rustc_lib_path(builder, compiler);
397+
398+
builder.run(&mut cargo.into());
399+
}
400+
}
401+
354402
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
355403
pub struct Miri {
356404
stage: u32,
@@ -1126,7 +1174,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the
11261174
}
11271175

11281176
if mode == "run-make" && suite.ends_with("fulldeps") {
1129-
cmd.arg("--rust-demangler-path").arg(builder.tool_exe(Tool::RustDemangler));
1177+
let rust_demangler = builder
1178+
.ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() })
1179+
.expect("in-tree tool");
1180+
cmd.arg("--rust-demangler-path").arg(rust_demangler);
11301181
}
11311182

11321183
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

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# rust-demangler
2+
3+
Demangles rustc mangled names.
4+
5+
This tool uses the [rustc-demangle](https://crates.io/crates/rustc-demangle)
6+
crate to convert an input buffer of newline-separated mangled names into their
7+
demangled translations.
8+
9+
This tool takes a list of mangled names (one per line) on standard input, and
10+
prints a corresponding list of demangled names. The tool is designed to support
11+
programs that can leverage a third-party demangler, such as `llvm-cov`, via the
12+
`-Xdemangler=<path-to-demangler>` option.
13+
14+
To use `rust-demangler` with `llvm-cov` for example, add the `-Xdemangler=...`
15+
option:
16+
17+
```shell
18+
$ TARGET="${PWD}/build/x86_64-unknown-linux-gnu"
19+
$ "${TARGET}"/llvm/bin/llvm-cov show \
20+
--Xdemangler=path/to/rust-demangler \
21+
--instr-profile=main.profdata ./main --show-line-counts-or-regions
22+
```
23+
24+
## License
25+
26+
Rust-demangler is distributed under the terms of both the MIT license and the
27+
Apache License (Version 2.0).
28+
29+
See [LICENSE-APACHE](/LICENSE-APACHE) and [LICENSE-MIT](/LICENSE-MIT) for details.

src/tools/rust-demangler/src/lib.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use regex::Regex;
2+
use rustc_demangle::demangle;
3+
4+
const REPLACE_COLONS: &str = "::";
5+
6+
pub fn create_disambiguator_re() -> Regex {
7+
Regex::new(r"\[[a-f0-9]{5,16}\]::").unwrap()
8+
}
9+
10+
pub fn demangle_lines(buffer: &str, strip_crate_disambiguators: Option<Regex>) -> Vec<String> {
11+
let lines = buffer.lines();
12+
let mut demangled_lines = Vec::new();
13+
for mangled in lines {
14+
let mut demangled = demangle(mangled).to_string();
15+
if let Some(re) = &strip_crate_disambiguators {
16+
demangled = re.replace_all(&demangled, REPLACE_COLONS).to_string();
17+
}
18+
demangled_lines.push(demangled);
19+
}
20+
demangled_lines.push("".to_string());
21+
demangled_lines
22+
}

0 commit comments

Comments
 (0)