Skip to content

Commit ee10f9f

Browse files
committed
Cleanup cfg and env handling in project-model
1 parent 2e54c0a commit ee10f9f

File tree

9 files changed

+193
-114
lines changed

9 files changed

+193
-114
lines changed

crates/base-db/src/input.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,11 @@ impl CrateGraph {
331331
version: Option<String>,
332332
cfg_options: Arc<CfgOptions>,
333333
potential_cfg_options: Option<Arc<CfgOptions>>,
334-
env: Env,
334+
mut env: Env,
335335
is_proc_macro: bool,
336336
origin: CrateOrigin,
337337
) -> CrateId {
338+
env.entries.shrink_to_fit();
338339
let data = CrateData {
339340
root_file_id,
340341
edition,
@@ -651,8 +652,8 @@ impl FromIterator<(String, String)> for Env {
651652
}
652653

653654
impl Env {
654-
pub fn set(&mut self, env: &str, value: String) {
655-
self.entries.insert(env.to_owned(), value);
655+
pub fn set(&mut self, env: &str, value: impl Into<String>) {
656+
self.entries.insert(env.to_owned(), value.into());
656657
}
657658

658659
pub fn get(&self, env: &str) -> Option<String> {

crates/project-model/src/build_scripts.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,18 @@ use serde::Deserialize;
2323
use toolchain::Tool;
2424

2525
use crate::{
26-
cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
26+
cfg::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
2727
InvocationStrategy, Package, Sysroot, TargetKind,
2828
};
2929

30+
/// Output of the build script and proc-macro building steps for a workspace.
3031
#[derive(Debug, Default, Clone, PartialEq, Eq)]
3132
pub struct WorkspaceBuildScripts {
3233
outputs: ArenaMap<Package, BuildScriptOutput>,
3334
error: Option<String>,
3435
}
3536

37+
/// Output of the build script and proc-macro building step for a concrete package.
3638
#[derive(Debug, Clone, Default, PartialEq, Eq)]
3739
pub(crate) struct BuildScriptOutput {
3840
/// List of config flags defined by this package's build script.

crates/project-model/src/cargo_workspace.rs

+32
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,20 @@ pub struct PackageData {
135135
pub active_features: Vec<String>,
136136
/// String representation of package id
137137
pub id: String,
138+
/// Authors as given in the `Cargo.toml`
139+
pub authors: Vec<String>,
140+
/// Description as given in the `Cargo.toml`
141+
pub description: Option<String>,
142+
/// Homepage as given in the `Cargo.toml`
143+
pub homepage: Option<String>,
144+
/// License as given in the `Cargo.toml`
145+
pub license: Option<String>,
146+
/// License file as given in the `Cargo.toml`
147+
pub license_file: Option<Utf8PathBuf>,
148+
/// Readme file as given in the `Cargo.toml`
149+
pub readme: Option<Utf8PathBuf>,
150+
/// Rust version as given in the `Cargo.toml`
151+
pub rust_version: Option<semver::Version>,
138152
/// The contents of [package.metadata.rust-analyzer]
139153
pub metadata: RustAnalyzerPackageMetaData,
140154
}
@@ -225,6 +239,10 @@ impl TargetKind {
225239
}
226240
TargetKind::Other
227241
}
242+
243+
pub fn is_executable(self) -> bool {
244+
matches!(self, TargetKind::Bin | TargetKind::Example)
245+
}
228246
}
229247

230248
// Deserialize helper for the cargo metadata
@@ -330,6 +348,13 @@ impl CargoWorkspace {
330348
repository,
331349
edition,
332350
metadata,
351+
authors,
352+
description,
353+
homepage,
354+
license,
355+
license_file,
356+
readme,
357+
rust_version,
333358
..
334359
} = meta_pkg;
335360
let meta = from_value::<PackageMetadata>(metadata).unwrap_or_default();
@@ -358,6 +383,13 @@ impl CargoWorkspace {
358383
is_member,
359384
edition,
360385
repository,
386+
authors,
387+
description,
388+
homepage,
389+
license,
390+
license_file,
391+
readme,
392+
rust_version,
361393
dependencies: Vec::new(),
362394
features: features.into_iter().collect(),
363395
active_features: Vec::new(),

crates/project-model/src/cfg_flag.rs renamed to crates/project-model/src/cfg.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
//! rustc main.rs --cfg foo --cfg 'feature="bar"'
44
use std::{fmt, str::FromStr};
55

6-
use cfg::CfgOptions;
6+
use cfg::{CfgDiff, CfgOptions};
7+
use rustc_hash::FxHashMap;
78
use serde::Serialize;
89

910
#[derive(Clone, Eq, PartialEq, Debug, Serialize)]
@@ -70,3 +71,27 @@ impl fmt::Display for CfgFlag {
7071
}
7172
}
7273
}
74+
75+
/// A set of cfg-overrides per crate.
76+
#[derive(Default, Debug, Clone, Eq, PartialEq)]
77+
pub struct CfgOverrides {
78+
/// A global set of overrides matching all crates.
79+
pub global: CfgDiff,
80+
/// A set of overrides matching specific crates.
81+
pub selective: FxHashMap<String, CfgDiff>,
82+
}
83+
84+
impl CfgOverrides {
85+
pub fn len(&self) -> usize {
86+
self.global.len() + self.selective.values().map(|it| it.len()).sum::<usize>()
87+
}
88+
89+
pub fn apply(&self, cfg_options: &mut CfgOptions, name: &str) {
90+
if !self.global.is_empty() {
91+
cfg_options.apply_diff(self.global.clone());
92+
};
93+
if let Some(diff) = self.selective.get(name) {
94+
cfg_options.apply_diff(diff.clone());
95+
};
96+
}
97+
}

crates/project-model/src/env.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use base_db::Env;
2+
use rustc_hash::FxHashMap;
3+
use toolchain::Tool;
4+
5+
use crate::{utf8_stdout, ManifestPath, PackageData, Sysroot, TargetKind};
6+
7+
/// Recreates the compile-time environment variables that Cargo sets.
8+
///
9+
/// Should be synced with
10+
/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>
11+
///
12+
/// FIXME: ask Cargo to provide this data instead of re-deriving.
13+
pub(crate) fn inject_cargo_package_env(env: &mut Env, package: &PackageData) {
14+
// FIXME: Missing variables:
15+
// CARGO_BIN_NAME, CARGO_BIN_EXE_<name>
16+
17+
let manifest_dir = package.manifest.parent();
18+
env.set("CARGO_MANIFEST_DIR", manifest_dir.as_str());
19+
20+
env.set("CARGO_PKG_VERSION", package.version.to_string());
21+
env.set("CARGO_PKG_VERSION_MAJOR", package.version.major.to_string());
22+
env.set("CARGO_PKG_VERSION_MINOR", package.version.minor.to_string());
23+
env.set("CARGO_PKG_VERSION_PATCH", package.version.patch.to_string());
24+
env.set("CARGO_PKG_VERSION_PRE", package.version.pre.to_string());
25+
26+
env.set("CARGO_PKG_AUTHORS", package.authors.join(":").clone());
27+
28+
env.set("CARGO_PKG_NAME", package.name.clone());
29+
env.set("CARGO_PKG_DESCRIPTION", package.description.as_deref().unwrap_or_default());
30+
env.set("CARGO_PKG_HOMEPAGE", package.homepage.as_deref().unwrap_or_default());
31+
env.set("CARGO_PKG_REPOSITORY", package.repository.as_deref().unwrap_or_default());
32+
env.set("CARGO_PKG_LICENSE", package.license.as_deref().unwrap_or_default());
33+
env.set(
34+
"CARGO_PKG_LICENSE_FILE",
35+
package.license_file.as_ref().map(ToString::to_string).unwrap_or_default(),
36+
);
37+
env.set(
38+
"CARGO_PKG_README",
39+
package.readme.as_ref().map(ToString::to_string).unwrap_or_default(),
40+
);
41+
42+
env.set(
43+
"CARGO_PKG_RUST_VERSION",
44+
package.rust_version.as_ref().map(ToString::to_string).unwrap_or_default(),
45+
);
46+
}
47+
48+
pub(crate) fn inject_cargo_env(env: &mut Env) {
49+
env.set("CARGO", Tool::Cargo.path().to_string());
50+
}
51+
52+
pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: TargetKind) {
53+
_ = kind;
54+
// FIXME
55+
// if kind.is_executable() {
56+
// env.set("CARGO_BIN_NAME", cargo_name);
57+
// }
58+
env.set("CARGO_CRATE_NAME", cargo_name.replace('-', "_"));
59+
}
60+
61+
pub(crate) fn cargo_config_env(
62+
cargo_toml: &ManifestPath,
63+
extra_env: &FxHashMap<String, String>,
64+
sysroot: Option<&Sysroot>,
65+
) -> FxHashMap<String, String> {
66+
let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
67+
cargo_config.envs(extra_env);
68+
cargo_config
69+
.current_dir(cargo_toml.parent())
70+
.args(["-Z", "unstable-options", "config", "get", "env"])
71+
.env("RUSTC_BOOTSTRAP", "1");
72+
// if successful we receive `env.key.value = "value" per entry
73+
tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
74+
utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()
75+
}
76+
77+
fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
78+
stdout
79+
.lines()
80+
.filter_map(|l| l.strip_prefix("env."))
81+
.filter_map(|l| l.split_once(".value = "))
82+
.map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
83+
.collect()
84+
}

crates/project-model/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
mod build_scripts;
2121
mod cargo_workspace;
22-
mod cfg_flag;
22+
mod cfg;
23+
mod env;
2324
mod manifest_path;
2425
mod project_json;
2526
mod rustc_cfg;
@@ -47,10 +48,11 @@ pub use crate::{
4748
CargoConfig, CargoFeatures, CargoWorkspace, Package, PackageData, PackageDependency,
4849
RustLibSource, Target, TargetData, TargetKind,
4950
},
51+
cfg::CfgOverrides,
5052
manifest_path::ManifestPath,
5153
project_json::{ProjectJson, ProjectJsonData},
5254
sysroot::Sysroot,
53-
workspace::{CfgOverrides, PackageRoot, ProjectWorkspace},
55+
workspace::{FileLoader, PackageRoot, ProjectWorkspace},
5456
};
5557

5658
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]

crates/project-model/src/project_json.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use rustc_hash::FxHashMap;
5555
use serde::{de, Deserialize, Serialize};
5656
use span::Edition;
5757

58-
use crate::cfg_flag::CfgFlag;
58+
use crate::cfg::CfgFlag;
5959

6060
/// Roots and crates that compose this Rust project.
6161
#[derive(Clone, Debug, Eq, PartialEq)]

crates/project-model/src/rustc_cfg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use anyhow::Context;
44
use rustc_hash::FxHashMap;
55
use toolchain::Tool;
66

7-
use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
7+
use crate::{cfg::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
88

99
/// Determines how `rustc --print cfg` is discovered and invoked.
1010
pub(crate) enum RustcCfgConfig<'a> {

0 commit comments

Comments
 (0)