Skip to content
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

Support cargo:rustc-cfg in build.rs #4296

Merged
merged 3 commits into from May 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions crates/ra_cfg/src/lib.rs
Expand Up @@ -53,4 +53,13 @@ impl CfgOptions {
pub fn insert_features(&mut self, iter: impl IntoIterator<Item = SmolStr>) {
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>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this does not belong here (and the above inseret_features probably as well) -- CfgOptions should a be pretty abstract thing, exactly what rustc sees.

Lowering various command-line args to this data structure should happen where we get the args.

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()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, we should unescape the RHS here, but in practice, I don't think it is relevant here, right?

None => self.insert_atom(cfg),
});
}
}
15 changes: 13 additions & 2 deletions crates/ra_project_model/src/cargo_workspace.rs
Expand Up @@ -83,6 +83,7 @@ pub struct PackageData {
pub dependencies: Vec<PackageDependency>,
pub edition: Edition,
pub features: Vec<String>,
pub cfgs: Vec<String>,
pub out_dir: Option<PathBuf>,
pub proc_macro_dylib_path: Option<PathBuf>,
}
Expand Down Expand Up @@ -165,10 +166,12 @@ impl CargoWorkspace {
})?;

let mut out_dir_by_id = FxHashMap::default();
let mut cfgs = FxHashMap::default();
let mut proc_macro_dylib_paths = FxHashMap::default();
if cargo_features.load_out_dirs_from_check {
let resources = load_extern_resources(cargo_toml, cargo_features)?;
out_dir_by_id = resources.out_dirs;
cfgs = resources.cfgs;
proc_macro_dylib_paths = resources.proc_dylib_paths;
}

Expand All @@ -194,6 +197,7 @@ impl CargoWorkspace {
edition,
dependencies: Vec::new(),
features: Vec::new(),
cfgs: cfgs.get(&id).cloned().unwrap_or_default(),
out_dir: out_dir_by_id.get(&id).cloned(),
proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(),
});
Expand Down Expand Up @@ -275,6 +279,7 @@ impl CargoWorkspace {
pub struct ExternResources {
out_dirs: FxHashMap<PackageId, PathBuf>,
proc_dylib_paths: FxHashMap<PackageId, PathBuf>,
cfgs: FxHashMap<PackageId, Vec<String>>,
}

pub fn load_extern_resources(
Expand All @@ -300,8 +305,14 @@ pub fn load_extern_resources(
for message in cargo_metadata::parse_messages(output.stdout.as_slice()) {
if let Ok(message) = message {
match message {
Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => {
res.out_dirs.insert(package_id, out_dir);
Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => {
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) => {
Expand Down
1 change: 1 addition & 0 deletions crates/ra_project_model/src/lib.rs
Expand Up @@ -399,6 +399,7 @@ impl ProjectWorkspace {
let cfg_options = {
let mut opts = default_cfg_options.clone();
opts.insert_features(cargo[pkg].features.iter().map(Into::into));
opts.insert_cfgs(cargo[pkg].cfgs.iter().map(Into::into));
opts
};
let mut env = Env::default();
Expand Down
110 changes: 107 additions & 3 deletions crates/rust-analyzer/tests/heavy_tests/main.rs
Expand Up @@ -9,7 +9,8 @@ use lsp_types::{
};
use rust_analyzer::req::{
CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument,
Formatting, GotoDefinition, HoverRequest, OnEnter, Runnables, RunnablesParams,
Formatting, GotoDefinition, GotoTypeDefinition, HoverRequest, OnEnter, Runnables,
RunnablesParams,
};
use serde_json::json;
use tempfile::TempDir;
Expand Down Expand Up @@ -574,7 +575,7 @@ version = \"0.0.0\"
}

#[test]
fn resolve_include_concat_env() {
fn out_dirs_check() {
if skip_slow_tests() {
return;
}
Expand All @@ -597,11 +598,28 @@ fn main() {
r#"pub fn message() -> &'static str { "Hello, World!" }"#,
)
.unwrap();
println!("cargo:rustc-cfg=atom_cfg");
println!("cargo:rustc-cfg=featlike=\"set\"");
println!("cargo:rerun-if-changed=build.rs");
}
//- src/main.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(); }
"###,
)
Expand All @@ -613,12 +631,98 @@ fn main() { message(); }
let res = server.send_request::<GotoDefinition>(GotoDefinitionParams {
text_document_position_params: TextDocumentPositionParams::new(
server.doc_id("src/main.rs"),
Position::new(2, 15),
Position::new(14, 8),
),
work_done_progress_params: Default::default(),
partial_result_params: Default::default(),
});
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]
Expand Down