4296: Support cargo:rustc-cfg in build.rs r=matklad a=robojumper

Fixes #4238.

Co-authored-by: robojumper <robojumper@gmail.com>
This commit is contained in:
bors[bot] 2020-05-07 18:50:00 +00:00 committed by GitHub
commit 1b136aae0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 130 additions and 5 deletions

View file

@ -53,4 +53,13 @@ impl CfgOptions {
pub fn insert_features(&mut self, iter: impl IntoIterator<Item = SmolStr>) { pub fn insert_features(&mut self, iter: impl IntoIterator<Item = SmolStr>) {
iter.into_iter().for_each(|feat| self.insert_key_value("feature".into(), feat)); iter.into_iter().for_each(|feat| self.insert_key_value("feature".into(), feat));
} }
/// Shortcut to set cfgs
pub fn insert_cfgs(&mut self, iter: impl IntoIterator<Item = SmolStr>) {
iter.into_iter().for_each(|cfg| match cfg.find('=') {
Some(split) => self
.insert_key_value(cfg[0..split].into(), cfg[split + 1..].trim_matches('"').into()),
None => self.insert_atom(cfg),
});
}
} }

View file

@ -87,6 +87,7 @@ pub struct PackageData {
pub dependencies: Vec<PackageDependency>, pub dependencies: Vec<PackageDependency>,
pub edition: Edition, pub edition: Edition,
pub features: Vec<String>, pub features: Vec<String>,
pub cfgs: Vec<String>,
pub out_dir: Option<PathBuf>, pub out_dir: Option<PathBuf>,
pub proc_macro_dylib_path: Option<PathBuf>, pub proc_macro_dylib_path: Option<PathBuf>,
} }
@ -172,10 +173,12 @@ impl CargoWorkspace {
})?; })?;
let mut out_dir_by_id = FxHashMap::default(); let mut out_dir_by_id = FxHashMap::default();
let mut cfgs = FxHashMap::default();
let mut proc_macro_dylib_paths = FxHashMap::default(); let mut proc_macro_dylib_paths = FxHashMap::default();
if cargo_features.load_out_dirs_from_check { if cargo_features.load_out_dirs_from_check {
let resources = load_extern_resources(cargo_toml, cargo_features)?; let resources = load_extern_resources(cargo_toml, cargo_features)?;
out_dir_by_id = resources.out_dirs; out_dir_by_id = resources.out_dirs;
cfgs = resources.cfgs;
proc_macro_dylib_paths = resources.proc_dylib_paths; proc_macro_dylib_paths = resources.proc_dylib_paths;
} }
@ -201,6 +204,7 @@ impl CargoWorkspace {
edition, edition,
dependencies: Vec::new(), dependencies: Vec::new(),
features: Vec::new(), features: Vec::new(),
cfgs: cfgs.get(&id).cloned().unwrap_or_default(),
out_dir: out_dir_by_id.get(&id).cloned(), out_dir: out_dir_by_id.get(&id).cloned(),
proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(), proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(),
}); });
@ -282,6 +286,7 @@ impl CargoWorkspace {
pub struct ExternResources { pub struct ExternResources {
out_dirs: FxHashMap<PackageId, PathBuf>, out_dirs: FxHashMap<PackageId, PathBuf>,
proc_dylib_paths: FxHashMap<PackageId, PathBuf>, proc_dylib_paths: FxHashMap<PackageId, PathBuf>,
cfgs: FxHashMap<PackageId, Vec<String>>,
} }
pub fn load_extern_resources( pub fn load_extern_resources(
@ -307,8 +312,14 @@ pub fn load_extern_resources(
for message in cargo_metadata::parse_messages(output.stdout.as_slice()) { for message in cargo_metadata::parse_messages(output.stdout.as_slice()) {
if let Ok(message) = message { if let Ok(message) = message {
match message { match message {
Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => {
res.out_dirs.insert(package_id, out_dir); res.out_dirs.insert(package_id.clone(), out_dir);
res.cfgs.insert(
package_id,
// FIXME: Current `cargo_metadata` uses `PathBuf` instead of `String`,
// change when https://github.com/oli-obk/cargo_metadata/pulls/112 reaches crates.io
cfgs.iter().filter_map(|c| c.to_str().map(|s| s.to_owned())).collect(),
);
} }
Message::CompilerArtifact(message) => { Message::CompilerArtifact(message) => {

View file

@ -399,6 +399,7 @@ impl ProjectWorkspace {
let cfg_options = { let cfg_options = {
let mut opts = default_cfg_options.clone(); let mut opts = default_cfg_options.clone();
opts.insert_features(cargo[pkg].features.iter().map(Into::into)); opts.insert_features(cargo[pkg].features.iter().map(Into::into));
opts.insert_cfgs(cargo[pkg].cfgs.iter().map(Into::into));
opts opts
}; };
let mut env = Env::default(); let mut env = Env::default();

View file

@ -9,7 +9,8 @@ use lsp_types::{
}; };
use rust_analyzer::req::{ use rust_analyzer::req::{
CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument,
Formatting, GotoDefinition, HoverRequest, OnEnter, Runnables, RunnablesParams, Formatting, GotoDefinition, GotoTypeDefinition, HoverRequest, OnEnter, Runnables,
RunnablesParams,
}; };
use serde_json::json; use serde_json::json;
use tempfile::TempDir; use tempfile::TempDir;
@ -574,7 +575,7 @@ version = \"0.0.0\"
} }
#[test] #[test]
fn resolve_include_concat_env() { fn out_dirs_check() {
if skip_slow_tests() { if skip_slow_tests() {
return; return;
} }
@ -597,11 +598,28 @@ fn main() {
r#"pub fn message() -> &'static str { "Hello, World!" }"#, r#"pub fn message() -> &'static str { "Hello, World!" }"#,
) )
.unwrap(); .unwrap();
println!("cargo:rustc-cfg=atom_cfg");
println!("cargo:rustc-cfg=featlike=\"set\"");
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
} }
//- src/main.rs //- src/main.rs
include!(concat!(env!("OUT_DIR"), "/hello.rs")); include!(concat!(env!("OUT_DIR"), "/hello.rs"));
#[cfg(atom_cfg)]
struct A;
#[cfg(bad_atom_cfg)]
struct A;
#[cfg(featlike = "set")]
struct B;
#[cfg(featlike = "not_set")]
struct B;
fn main() {
let va = A;
let vb = B;
message();
}
fn main() { message(); } fn main() { message(); }
"###, "###,
) )
@ -613,12 +631,98 @@ fn main() { message(); }
let res = server.send_request::<GotoDefinition>(GotoDefinitionParams { let res = server.send_request::<GotoDefinition>(GotoDefinitionParams {
text_document_position_params: TextDocumentPositionParams::new( text_document_position_params: TextDocumentPositionParams::new(
server.doc_id("src/main.rs"), server.doc_id("src/main.rs"),
Position::new(2, 15), Position::new(14, 8),
), ),
work_done_progress_params: Default::default(), work_done_progress_params: Default::default(),
partial_result_params: Default::default(), partial_result_params: Default::default(),
}); });
assert!(format!("{}", res).contains("hello.rs")); assert!(format!("{}", res).contains("hello.rs"));
server.request::<GotoTypeDefinition>(
GotoDefinitionParams {
text_document_position_params: TextDocumentPositionParams::new(
server.doc_id("src/main.rs"),
Position::new(12, 9),
),
work_done_progress_params: Default::default(),
partial_result_params: Default::default(),
},
json!([{
"originSelectionRange": {
"end": {
"character": 10,
"line": 12
},
"start": {
"character": 8,
"line": 12
}
},
"targetRange": {
"end": {
"character": 9,
"line": 3
},
"start": {
"character": 0,
"line": 2
}
},
"targetSelectionRange": {
"end": {
"character": 8,
"line": 3
},
"start": {
"character": 7,
"line": 3
}
},
"targetUri": "file:///[..]src/main.rs"
}]),
);
server.request::<GotoTypeDefinition>(
GotoDefinitionParams {
text_document_position_params: TextDocumentPositionParams::new(
server.doc_id("src/main.rs"),
Position::new(13, 9),
),
work_done_progress_params: Default::default(),
partial_result_params: Default::default(),
},
json!([{
"originSelectionRange": {
"end": {
"character": 10,
"line": 13
},
"start": {
"character": 8,
"line":13
}
},
"targetRange": {
"end": {
"character": 9,
"line": 7
},
"start": {
"character": 0,
"line":6
}
},
"targetSelectionRange": {
"end": {
"character": 8,
"line": 7
},
"start": {
"character": 7,
"line": 7
}
},
"targetUri": "file:///[..]src/main.rs"
}]),
);
} }
#[test] #[test]