Skip to content

Commit 6c04032

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

File tree

7 files changed

+220
-138
lines changed

7 files changed

+220
-138
lines changed

src/cargo/core/compiler/compilation.rs

Lines changed: 4 additions & 30 deletions
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

Lines changed: 5 additions & 1 deletion
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/dirty_reason.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ pub enum DirtyReason {
2626
old: Vec<String>,
2727
new: Vec<String>,
2828
},
29-
MetadataChanged,
3029
ConfigSettingsChanged,
3130
CompileKindChanged,
3231
LocalLengthsChanged,
@@ -168,7 +167,6 @@ impl DirtyReason {
168167
s.dirty_because(unit, "the profile configuration changed")
169168
}
170169
DirtyReason::RustflagsChanged { .. } => s.dirty_because(unit, "the rustflags changed"),
171-
DirtyReason::MetadataChanged => s.dirty_because(unit, "the metadata changed"),
172170
DirtyReason::ConfigSettingsChanged => {
173171
s.dirty_because(unit, "the config settings changed")
174172
}

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
//! [`CompileKind`] (host/target) | ✓ | ✓ | ✓ | ✓
7979
//! `__CARGO_DEFAULT_LIB_METADATA`[^4] | | ✓ | ✓ | ✓
8080
//! `package_id` | | ✓ | ✓ | ✓
81-
//! authors, description, homepage, repo | ✓ | | |
8281
//! Target src path relative to ws | ✓ | | |
8382
//! Target flags (test/bench/for_host/edition) | ✓ | | |
8483
//! -C incremental=… flag | ✓ | | |
@@ -189,6 +188,8 @@
189188
//! files to learn about environment variables that the rustc compile depends on.
190189
//! Cargo then later uses this to trigger a recompile if a referenced env var
191190
//! changes (even if the source didn't change).
191+
//! This also includes env vars generated from Cargo metadata like `CARGO_PKG_DESCRIPTION`.
192+
//! (See [`EmittableManifestMetadata`])
192193
//!
193194
//! #### dep-info files for build system integration.
194195
//!
@@ -378,6 +379,7 @@ use std::fs::File;
378379
use std::hash::{self, Hash, Hasher};
379380
use std::io::{self};
380381
use std::path::{Path, PathBuf};
382+
use std::str::FromStr;
381383
use std::sync::{Arc, Mutex};
382384
use std::time::SystemTime;
383385

@@ -391,6 +393,7 @@ use serde::{Deserialize, Serialize};
391393
use tracing::{debug, info};
392394

393395
use crate::core::compiler::unit_graph::UnitDep;
396+
use crate::core::manifest::EmittableManifestMetadata;
394397
use crate::core::Package;
395398
use crate::util;
396399
use crate::util::errors::CargoResult;
@@ -612,10 +615,6 @@ pub struct Fingerprint {
612615
memoized_hash: Mutex<Option<u64>>,
613616
/// RUSTFLAGS/RUSTDOCFLAGS environment variable value (or config value).
614617
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,
619618
/// Hash of various config settings that change how things are compiled.
620619
config: u64,
621620
/// The rustc target. This is only relevant for `.json` files, otherwise
@@ -831,11 +830,12 @@ impl LocalFingerprint {
831830
&self,
832831
mtime_cache: &mut HashMap<PathBuf, FileTime>,
833832
checksum_cache: &mut HashMap<PathBuf, Checksum>,
834-
pkg_root: &Path,
833+
pkg: &Package,
835834
target_root: &Path,
836835
cargo_exe: &Path,
837836
gctx: &GlobalContext,
838837
) -> CargoResult<Option<StaleItem>> {
838+
let pkg_root = pkg.root();
839839
match self {
840840
// We need to parse `dep_info`, learn about the crate's dependencies.
841841
//
@@ -848,7 +848,16 @@ impl LocalFingerprint {
848848
let Some(info) = parse_dep_info(pkg_root, target_root, &dep_info)? else {
849849
return Ok(Some(StaleItem::MissingFile(dep_info)));
850850
};
851+
let metadata = pkg.manifest().metadata();
851852
for (key, previous) in info.env.iter() {
853+
if let Ok(t) = EmittableManifestMetadata::from_str(key.as_str()) {
854+
let value = metadata.emitted_env_var(&t);
855+
856+
if Some(value.as_str()) == previous.as_deref() {
857+
continue;
858+
}
859+
}
860+
852861
let current = if key == CARGO_ENV {
853862
Some(cargo_exe.to_str().ok_or_else(|| {
854863
format_err!(
@@ -932,7 +941,6 @@ impl Fingerprint {
932941
local: Mutex::new(Vec::new()),
933942
memoized_hash: Mutex::new(None),
934943
rustflags: Vec::new(),
935-
metadata: 0,
936944
config: 0,
937945
compile_kind: 0,
938946
fs_status: FsStatus::Stale,
@@ -995,9 +1003,6 @@ impl Fingerprint {
9951003
new: self.rustflags.clone(),
9961004
};
9971005
}
998-
if self.metadata != old.metadata {
999-
return DirtyReason::MetadataChanged;
1000-
}
10011006
if self.config != old.config {
10021007
return DirtyReason::ConfigSettingsChanged;
10031008
}
@@ -1142,13 +1147,14 @@ impl Fingerprint {
11421147
&mut self,
11431148
mtime_cache: &mut HashMap<PathBuf, FileTime>,
11441149
checksum_cache: &mut HashMap<PathBuf, Checksum>,
1145-
pkg_root: &Path,
1150+
pkg: &Package,
11461151
target_root: &Path,
11471152
cargo_exe: &Path,
11481153
gctx: &GlobalContext,
11491154
) -> CargoResult<()> {
11501155
assert!(!self.fs_status.up_to_date());
11511156

1157+
let pkg_root = pkg.root();
11521158
let mut mtimes = HashMap::new();
11531159

11541160
// Get the `mtime` of all outputs. Optionally update their mtime
@@ -1249,7 +1255,7 @@ impl Fingerprint {
12491255
if let Some(item) = local.find_stale_item(
12501256
mtime_cache,
12511257
checksum_cache,
1252-
pkg_root,
1258+
pkg,
12531259
target_root,
12541260
cargo_exe,
12551261
gctx,
@@ -1279,7 +1285,6 @@ impl hash::Hash for Fingerprint {
12791285
profile,
12801286
ref deps,
12811287
ref local,
1282-
metadata,
12831288
config,
12841289
compile_kind,
12851290
ref rustflags,
@@ -1294,7 +1299,6 @@ impl hash::Hash for Fingerprint {
12941299
path,
12951300
profile,
12961301
&*local,
1297-
metadata,
12981302
config,
12991303
compile_kind,
13001304
rustflags,
@@ -1445,7 +1449,7 @@ fn calculate(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult
14451449
fingerprint.check_filesystem(
14461450
&mut build_runner.mtime_cache,
14471451
&mut build_runner.checksum_cache,
1448-
unit.pkg.root(),
1452+
&unit.pkg,
14491453
&target_root,
14501454
cargo_exe,
14511455
build_runner.bcx.gctx,
@@ -1529,9 +1533,6 @@ fn calculate_normal(
15291533
build_runner.lto[unit],
15301534
unit.pkg.manifest().lint_rustflags(),
15311535
));
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));
15351536
let mut config = StableHasher::new();
15361537
if let Some(linker) = build_runner.compilation.target_linker(unit.kind) {
15371538
linker.hash(&mut config);
@@ -1560,7 +1561,6 @@ fn calculate_normal(
15601561
deps,
15611562
local: Mutex::new(local),
15621563
memoized_hash: Mutex::new(None),
1563-
metadata,
15641564
config: Hasher::finish(&config),
15651565
compile_kind,
15661566
rustflags: extra_flags,

src/cargo/core/manifest.rs

Lines changed: 92 additions & 0 deletions
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)