-
Notifications
You must be signed in to change notification settings - Fork 369
Expand file tree
/
Copy pathsysroot.rs
More file actions
137 lines (123 loc) · 4.81 KB
/
Copy pathsysroot.rs
File metadata and controls
137 lines (123 loc) · 4.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is dual-licensed under either the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree or the Apache
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
* of this source tree. You may select, at your option, one of the
* above-listed licenses.
*/
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::process::Stdio;
use anyhow::Context;
use tracing::instrument;
use crate::buck::Buck;
use crate::buck::truncate_line_ending;
use crate::buck::utf8_output;
use crate::cli::develop_with_sysroot;
use crate::project_json::Sysroot;
use crate::target::Target;
#[derive(Debug)]
pub(crate) enum SysrootConfig {
Sysroot(PathBuf),
BuckConfig,
Rustup,
}
/// Choose sysroot and sysroot_src based on platform.
///
/// `sysroot` is the directory that contains std crates:
/// <https://doc.rust-lang.org/rustc/command-line-arguments.html#--sysroot-override-the-system-root>
/// and also contains libexec helpers such as rust-analyzer-proc-macro-srv.
///
/// `sysroot_src` is the directory that contains the source to std crates:
/// <https://rust-analyzer.github.io/manual.html#non-cargo-based-projects>
#[instrument(skip_all)]
pub(crate) fn resolve_buckconfig_sysroot(
buck: &Buck,
project_root: &Path,
universe_targets: &[Target],
) -> Result<Sysroot, anyhow::Error> {
let sysroot: PathBuf = {
// TODO(diliopoulos): remove hardcoded path to toolchain sysroot and replace with something
// derived from buck, e.g.
//
// $ buck cquery -u fbcode//buck2/integrations/rust-project:rust-project -a compiler fbcode//buck2/platform/rust:rust_bootstrap
// ...
// "compiler": "fbcode//tools/build/buck/wrappers:rust-platform010-clang-17-nosan-compiler (fbcode//buck2/platform/execution:linux-x86_64#54c5d1cbad5316cb)"
// $ buck cquery -u fbcode//buck2/integrations/rust-project:rust-project -a exe fbcode//tools/build/buck/wrappers:rust-platform010-clang-17-nosan-compiler
// ...
// "exe": "fbcode//third-party-buck/platform010/build/rust/llvm-fb-17:bin/rustc (fbcode//buck2/platform/execution:linux-x86_64#54c5d1cbad5316cb)",
let fbsource_rustc = project_root.join("xplat/rust/toolchain/current/basic/bin/rustc");
let mut sysroot_cmd = Command::new(fbsource_rustc);
sysroot_cmd
.arg("--print=sysroot")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped());
let sysroot_child = sysroot_cmd.spawn()?;
let mut sysroot = utf8_output(sysroot_child.wait_with_output(), &sysroot_cmd)
.context("error asking rustc for sysroot")?;
truncate_line_ending(&mut sysroot);
sysroot.into()
};
let sysroot_src = buck.resolve_sysroot_src()?;
let sysroot_targets = buck.query_sysroot_targets(
&format!("fbsource//{}:", sysroot_src.to_string_lossy()),
universe_targets,
);
// the `library` path component needs to be appended to the `sysroot_src_path`
// so that rust-analyzer will be able to find standard library sources.
let sysroot_src = project_root.join(sysroot_src).join("library");
let mut sysroot_project = develop_with_sysroot(
buck,
sysroot_targets,
Sysroot {
sysroot: sysroot.clone(),
sysroot_src: Some(sysroot_src.clone()),
sysroot_project: None,
},
true,
false,
false,
&[], // sysroot doesn't get any extra cfgs
None, // sysroot doesn't get any extra cfgs
)?;
for krate in &mut sysroot_project.crates {
if let Some(display_name) = &mut krate.display_name {
*display_name = display_name
.strip_suffix("-0.0.0") // rust-analyzer identifies lang crates by name, so we need `core-0.0.0` to be `core`
.unwrap_or(display_name)
.to_owned();
}
}
Ok(Sysroot {
sysroot,
sysroot_src: Some(sysroot_src),
sysroot_project: Some(sysroot_project),
})
}
#[instrument(ret)]
pub(crate) fn resolve_rustup_sysroot() -> Result<Sysroot, anyhow::Error> {
let mut cmd = Command::new("rustc");
cmd.arg("--print=sysroot")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped());
let mut output = utf8_output(cmd.output(), &cmd)?;
truncate_line_ending(&mut output);
let sysroot = PathBuf::from(output);
let sysroot_src = sysroot
.join("lib")
.join("rustlib")
.join("src")
.join("rust")
.join("library");
let sysroot = Sysroot {
sysroot,
sysroot_src: Some(sysroot_src),
sysroot_project: None, // rustup sysroot is not buckified
};
Ok(sysroot)
}