Skip to content

Commit 44931d7

Browse files
committed
Moved manifest metadata tracking from fingerprint to dep info
1 parent 652623b commit 44931d7

File tree

6 files changed

+218
-135
lines changed

6 files changed

+218
-135
lines changed

src/cargo/core/compiler/compilation.rs

+4-30
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,11 @@ impl<'gctx> Compilation<'gctx> {
351351
}
352352
}
353353

354+
// Add manifest metadata related keys
354355
let metadata = pkg.manifest().metadata();
356+
for (key, value) in metadata.emitted_env_vars() {
357+
cmd.env(key, value);
358+
}
355359

356360
let cargo_exe = self.gctx.cargo_exe()?;
357361
cmd.env(crate::CARGO_ENV, cargo_exe);
@@ -360,7 +364,6 @@ impl<'gctx> Compilation<'gctx> {
360364
// crate properties which might require rebuild upon change
361365
// consider adding the corresponding properties to the hash
362366
// in BuildContext::target_metadata()
363-
let rust_version = pkg.rust_version().as_ref().map(ToString::to_string);
364367
cmd.env("CARGO_MANIFEST_DIR", pkg.root())
365368
.env("CARGO_MANIFEST_PATH", pkg.manifest_path())
366369
.env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
@@ -369,35 +372,6 @@ impl<'gctx> Compilation<'gctx> {
369372
.env("CARGO_PKG_VERSION_PRE", pkg.version().pre.as_str())
370373
.env("CARGO_PKG_VERSION", &pkg.version().to_string())
371374
.env("CARGO_PKG_NAME", &*pkg.name())
372-
.env(
373-
"CARGO_PKG_DESCRIPTION",
374-
metadata.description.as_ref().unwrap_or(&String::new()),
375-
)
376-
.env(
377-
"CARGO_PKG_HOMEPAGE",
378-
metadata.homepage.as_ref().unwrap_or(&String::new()),
379-
)
380-
.env(
381-
"CARGO_PKG_REPOSITORY",
382-
metadata.repository.as_ref().unwrap_or(&String::new()),
383-
)
384-
.env(
385-
"CARGO_PKG_LICENSE",
386-
metadata.license.as_ref().unwrap_or(&String::new()),
387-
)
388-
.env(
389-
"CARGO_PKG_LICENSE_FILE",
390-
metadata.license_file.as_ref().unwrap_or(&String::new()),
391-
)
392-
.env("CARGO_PKG_AUTHORS", &pkg.authors().join(":"))
393-
.env(
394-
"CARGO_PKG_RUST_VERSION",
395-
&rust_version.as_deref().unwrap_or_default(),
396-
)
397-
.env(
398-
"CARGO_PKG_README",
399-
metadata.readme.as_ref().unwrap_or(&String::new()),
400-
)
401375
.cwd(pkg.root());
402376

403377
apply_env_config(self.gctx, &mut cmd)?;

src/cargo/core/compiler/fingerprint/dep_info.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use cargo_util::paths;
1919
use cargo_util::ProcessBuilder;
2020
use cargo_util::Sha256;
2121

22+
use crate::core::manifest::ManifestMetadata;
2223
use crate::CargoResult;
2324
use crate::CARGO_ENV;
2425

@@ -334,7 +335,10 @@ pub fn translate_dep_info(
334335
//
335336
// For cargo#13280, We trace env vars that are defined in the `[env]` config table.
336337
on_disk_info.env.retain(|(key, _)| {
337-
env_config.contains_key(key) || !rustc_cmd.get_envs().contains_key(key) || key == CARGO_ENV
338+
ManifestMetadata::is_emittable_env_var(key)
339+
|| env_config.contains_key(key)
340+
|| !rustc_cmd.get_envs().contains_key(key)
341+
|| key == CARGO_ENV
338342
});
339343

340344
let serialize_path = |file| {

src/cargo/core/compiler/fingerprint/mod.rs

+17-18
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ use std::fs::File;
378378
use std::hash::{self, Hash, Hasher};
379379
use std::io::{self};
380380
use std::path::{Path, PathBuf};
381+
use std::str::FromStr;
381382
use std::sync::{Arc, Mutex};
382383
use std::time::SystemTime;
383384

@@ -391,6 +392,7 @@ use serde::{Deserialize, Serialize};
391392
use tracing::{debug, info};
392393

393394
use crate::core::compiler::unit_graph::UnitDep;
395+
use crate::core::manifest::EmittableManifestMetadata;
394396
use crate::core::Package;
395397
use crate::util;
396398
use crate::util::errors::CargoResult;
@@ -612,10 +614,6 @@ pub struct Fingerprint {
612614
memoized_hash: Mutex<Option<u64>>,
613615
/// RUSTFLAGS/RUSTDOCFLAGS environment variable value (or config value).
614616
rustflags: Vec<String>,
615-
/// Hash of some metadata from the manifest, such as "authors", or
616-
/// "description", which are exposed as environment variables during
617-
/// compilation.
618-
metadata: u64,
619617
/// Hash of various config settings that change how things are compiled.
620618
config: u64,
621619
/// The rustc target. This is only relevant for `.json` files, otherwise
@@ -831,11 +829,12 @@ impl LocalFingerprint {
831829
&self,
832830
mtime_cache: &mut HashMap<PathBuf, FileTime>,
833831
checksum_cache: &mut HashMap<PathBuf, Checksum>,
834-
pkg_root: &Path,
832+
pkg: &Package,
835833
target_root: &Path,
836834
cargo_exe: &Path,
837835
gctx: &GlobalContext,
838836
) -> CargoResult<Option<StaleItem>> {
837+
let pkg_root = pkg.root();
839838
match self {
840839
// We need to parse `dep_info`, learn about the crate's dependencies.
841840
//
@@ -848,7 +847,16 @@ impl LocalFingerprint {
848847
let Some(info) = parse_dep_info(pkg_root, target_root, &dep_info)? else {
849848
return Ok(Some(StaleItem::MissingFile(dep_info)));
850849
};
850+
let metadata = pkg.manifest().metadata();
851851
for (key, previous) in info.env.iter() {
852+
if let Ok(t) = EmittableManifestMetadata::from_str(key.as_str()) {
853+
let value = metadata.emitted_env_var(&t);
854+
855+
if Some(value.as_str()) == previous.as_deref() {
856+
continue;
857+
}
858+
}
859+
852860
let current = if key == CARGO_ENV {
853861
Some(cargo_exe.to_str().ok_or_else(|| {
854862
format_err!(
@@ -932,7 +940,6 @@ impl Fingerprint {
932940
local: Mutex::new(Vec::new()),
933941
memoized_hash: Mutex::new(None),
934942
rustflags: Vec::new(),
935-
metadata: 0,
936943
config: 0,
937944
compile_kind: 0,
938945
fs_status: FsStatus::Stale,
@@ -995,9 +1002,6 @@ impl Fingerprint {
9951002
new: self.rustflags.clone(),
9961003
};
9971004
}
998-
if self.metadata != old.metadata {
999-
return DirtyReason::MetadataChanged;
1000-
}
10011005
if self.config != old.config {
10021006
return DirtyReason::ConfigSettingsChanged;
10031007
}
@@ -1142,13 +1146,14 @@ impl Fingerprint {
11421146
&mut self,
11431147
mtime_cache: &mut HashMap<PathBuf, FileTime>,
11441148
checksum_cache: &mut HashMap<PathBuf, Checksum>,
1145-
pkg_root: &Path,
1149+
pkg: &Package,
11461150
target_root: &Path,
11471151
cargo_exe: &Path,
11481152
gctx: &GlobalContext,
11491153
) -> CargoResult<()> {
11501154
assert!(!self.fs_status.up_to_date());
11511155

1156+
let pkg_root = pkg.root();
11521157
let mut mtimes = HashMap::new();
11531158

11541159
// Get the `mtime` of all outputs. Optionally update their mtime
@@ -1249,7 +1254,7 @@ impl Fingerprint {
12491254
if let Some(item) = local.find_stale_item(
12501255
mtime_cache,
12511256
checksum_cache,
1252-
pkg_root,
1257+
pkg,
12531258
target_root,
12541259
cargo_exe,
12551260
gctx,
@@ -1279,7 +1284,6 @@ impl hash::Hash for Fingerprint {
12791284
profile,
12801285
ref deps,
12811286
ref local,
1282-
metadata,
12831287
config,
12841288
compile_kind,
12851289
ref rustflags,
@@ -1294,7 +1298,6 @@ impl hash::Hash for Fingerprint {
12941298
path,
12951299
profile,
12961300
&*local,
1297-
metadata,
12981301
config,
12991302
compile_kind,
13001303
rustflags,
@@ -1445,7 +1448,7 @@ fn calculate(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult
14451448
fingerprint.check_filesystem(
14461449
&mut build_runner.mtime_cache,
14471450
&mut build_runner.checksum_cache,
1448-
unit.pkg.root(),
1451+
&unit.pkg,
14491452
&target_root,
14501453
cargo_exe,
14511454
build_runner.bcx.gctx,
@@ -1529,9 +1532,6 @@ fn calculate_normal(
15291532
build_runner.lto[unit],
15301533
unit.pkg.manifest().lint_rustflags(),
15311534
));
1532-
// Include metadata since it is exposed as environment variables.
1533-
let m = unit.pkg.manifest().metadata();
1534-
let metadata = util::hash_u64((&m.authors, &m.description, &m.homepage, &m.repository));
15351535
let mut config = StableHasher::new();
15361536
if let Some(linker) = build_runner.compilation.target_linker(unit.kind) {
15371537
linker.hash(&mut config);
@@ -1560,7 +1560,6 @@ fn calculate_normal(
15601560
deps,
15611561
local: Mutex::new(local),
15621562
memoized_hash: Mutex::new(None),
1563-
metadata,
15641563
config: Hasher::finish(&config),
15651564
compile_kind,
15661565
rustflags: extra_flags,

src/cargo/core/manifest.rs

+92
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::fmt;
33
use std::hash::{Hash, Hasher};
44
use std::path::{Path, PathBuf};
55
use std::rc::Rc;
6+
use std::str::FromStr;
67
use std::sync::Arc;
78

89
use anyhow::Context as _;
@@ -146,6 +147,97 @@ pub struct ManifestMetadata {
146147
pub rust_version: Option<RustVersion>,
147148
}
148149

150+
/// "Emittable" here meaning emitted to rustc as enviromental variables. Usable by `env!()`
151+
/// If these change we need to trigger a rebuild
152+
pub enum EmittableManifestMetadata {
153+
Description,
154+
Homepage,
155+
Repository,
156+
License,
157+
LicenseFile,
158+
Authors,
159+
RustVersion,
160+
Readme,
161+
}
162+
163+
const EMITTED_MANIFEST_METADATA: [EmittableManifestMetadata; 8] = [
164+
EmittableManifestMetadata::Description,
165+
EmittableManifestMetadata::Homepage,
166+
EmittableManifestMetadata::Repository,
167+
EmittableManifestMetadata::License,
168+
EmittableManifestMetadata::LicenseFile,
169+
EmittableManifestMetadata::Authors,
170+
EmittableManifestMetadata::RustVersion,
171+
EmittableManifestMetadata::Readme,
172+
];
173+
174+
impl FromStr for EmittableManifestMetadata {
175+
type Err = String;
176+
177+
fn from_str(value: &str) -> Result<Self, Self::Err> {
178+
Ok(match value {
179+
"CARGO_PKG_DESCRIPTION" => EmittableManifestMetadata::Description,
180+
"CARGO_PKG_HOMEPAGE" => EmittableManifestMetadata::Homepage,
181+
"CARGO_PKG_REPOSITORY" => EmittableManifestMetadata::Repository,
182+
"CARGO_PKG_LICENSE" => EmittableManifestMetadata::License,
183+
"CARGO_PKG_LICENSE_FILE" => EmittableManifestMetadata::LicenseFile,
184+
"CARGO_PKG_AUTHORS" => EmittableManifestMetadata::Authors,
185+
"CARGO_PKG_RUST_VERSION" => EmittableManifestMetadata::RustVersion,
186+
"CARGO_PKG_README" => EmittableManifestMetadata::Readme,
187+
other => return Err(format!("Invalid emittable manifest metadata key {other}")),
188+
})
189+
}
190+
}
191+
192+
impl From<EmittableManifestMetadata> for &'static str {
193+
fn from(value: EmittableManifestMetadata) -> Self {
194+
match value {
195+
EmittableManifestMetadata::Description => "CARGO_PKG_DESCRIPTION",
196+
EmittableManifestMetadata::Homepage => "CARGO_PKG_HOMEPAGE",
197+
EmittableManifestMetadata::Repository => "CARGO_PKG_REPOSITORY",
198+
EmittableManifestMetadata::License => "CARGO_PKG_LICENSE",
199+
EmittableManifestMetadata::LicenseFile => "CARGO_PKG_LICENSE_FILE",
200+
EmittableManifestMetadata::Authors => "CARGO_PKG_AUTHORS",
201+
EmittableManifestMetadata::RustVersion => "CARGO_PKG_RUST_VERSION",
202+
EmittableManifestMetadata::Readme => "CARGO_PKG_README",
203+
}
204+
}
205+
}
206+
207+
impl ManifestMetadata {
208+
pub fn is_emittable_env_var(key: &str) -> bool {
209+
EmittableManifestMetadata::from_str(key).is_ok()
210+
}
211+
212+
pub fn emitted_env_var<'a>(&'a self, key: &EmittableManifestMetadata) -> String {
213+
match key {
214+
EmittableManifestMetadata::Description => self.description.clone().unwrap_or_default(),
215+
EmittableManifestMetadata::Homepage => self.homepage.clone().unwrap_or_default(),
216+
EmittableManifestMetadata::Repository => self.repository.clone().unwrap_or_default(),
217+
EmittableManifestMetadata::License => self.license.clone().unwrap_or_default(),
218+
EmittableManifestMetadata::LicenseFile => self.license_file.clone().unwrap_or_default(),
219+
EmittableManifestMetadata::Authors => self.authors.join(":"),
220+
EmittableManifestMetadata::RustVersion => {
221+
let rust_version = self.rust_version.as_ref().map(ToString::to_string);
222+
rust_version.unwrap_or_default()
223+
}
224+
EmittableManifestMetadata::Readme => self.readme.clone().unwrap_or_default(),
225+
}
226+
}
227+
228+
// k/v pairs of the metadata environmental variables emitted to rustc.
229+
pub fn emitted_env_vars(&self) -> Vec<(&'static str, String)> {
230+
let mut vars = Vec::with_capacity(EMITTED_MANIFEST_METADATA.len());
231+
232+
for key in EMITTED_MANIFEST_METADATA {
233+
let value = self.emitted_env_var(&key);
234+
vars.push((key.into(), value));
235+
}
236+
237+
return vars;
238+
}
239+
}
240+
149241
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
150242
pub enum TargetKind {
151243
Lib(Vec<CrateType>),

0 commit comments

Comments
 (0)