Skip to content

Commit ecc87b1

Browse files
committed
New metabuild strategy using custom src_path enum.
- Use new enum `TargertSourcePath` for Target::src_path to make it explicit that metabuild has a special path. - `cargo metadata` now skips the metabuild Target. - JSON artifacts include the true path to the metabuild source file. This may not be the best solution, but it's unclear what it should be, and I would prefer to avoid breaking the output. Alternatively it could just not emit anything? I'm not completely familiar with the use case of these artifact messages. - Place the file in `target/.metabuild/metabuild-pkgname-HASH.rs` instead of in the debug/release directory. Its contents do not depend on the profile. - Fix bug in write_if_changed. - More tests.
1 parent e685bbf commit ecc87b1

File tree

13 files changed

+463
-140
lines changed

13 files changed

+463
-140
lines changed

Diff for: src/cargo/core/compiler/context/compilation_files.rs

-9
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,6 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
161161
self.layout(unit.kind).build().join(dir).join("out")
162162
}
163163

164-
pub fn metabuild_path(&self, unit: &Unit<'a>) -> PathBuf {
165-
let metadata = self.metadata(unit).expect("metabuild metadata");
166-
self.layout(unit.kind).metabuild().join(format!(
167-
"metabuild-{}-{}.rs",
168-
unit.pkg.name(),
169-
metadata
170-
))
171-
}
172-
173164
/// Returns the file stem for a given target/profile combo (with metadata)
174165
pub fn file_stem(&self, unit: &Unit<'a>) -> String {
175166
match self.metas[unit] {

Diff for: src/cargo/core/compiler/custom_build.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,8 @@ fn prepare_metabuild<'a, 'cfg>(
562562
}
563563
output.push("}\n".to_string());
564564
let output = output.join("");
565-
let path = cx.files().metabuild_path(unit);
565+
let path = unit.pkg.manifest().metabuild_path(cx.bcx.ws.target_dir());
566+
fs::create_dir_all(path.parent().unwrap())?;
566567
paths::write_if_changed(path, &output)?;
567568
Ok(())
568569
}

Diff for: src/cargo/core/compiler/fingerprint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ fn calculate<'a, 'cfg>(
474474
profile: profile_hash,
475475
// Note that .0 is hashed here, not .1 which is the cwd. That doesn't
476476
// actually affect the output artifact so there's no need to hash it.
477-
path: util::hash_u64(&super::path_args(cx, unit).0),
477+
path: util::hash_u64(&super::path_args(&cx.bcx, unit).0),
478478
features: format!("{:?}", bcx.resolve.features_sorted(unit.pkg.package_id())),
479479
deps,
480480
local: vec![local],

Diff for: src/cargo/core/compiler/layout.rs

-7
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ pub struct Layout {
6464
deps: PathBuf,
6565
native: PathBuf,
6666
build: PathBuf,
67-
metabuild: PathBuf,
6867
incremental: PathBuf,
6968
fingerprint: PathBuf,
7069
examples: PathBuf,
@@ -113,7 +112,6 @@ impl Layout {
113112
deps: root.join("deps"),
114113
native: root.join("native"),
115114
build: root.join("build"),
116-
metabuild: root.join(".metabuild"),
117115
incremental: root.join("incremental"),
118116
fingerprint: root.join(".fingerprint"),
119117
examples: root.join("examples"),
@@ -165,7 +163,6 @@ impl Layout {
165163
mkdir(&self.fingerprint)?;
166164
mkdir(&self.examples)?;
167165
mkdir(&self.build)?;
168-
mkdir(&self.metabuild)?;
169166

170167
return Ok(());
171168

@@ -205,8 +202,4 @@ impl Layout {
205202
pub fn build(&self) -> &Path {
206203
&self.build
207204
}
208-
/// Fetch the metabuild path.
209-
pub fn metabuild(&self) -> &Path {
210-
&self.metabuild
211-
}
212205
}

Diff for: src/cargo/core/compiler/mod.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::sync::Arc;
88
use same_file::is_same_file;
99
use serde_json;
1010

11+
use core::manifest::TargetSourcePath;
1112
use core::profiles::{Lto, Profile};
1213
use core::shell::ColorChoice;
1314
use core::{PackageId, Target};
@@ -390,7 +391,6 @@ fn link_targets<'a, 'cfg>(
390391
let outputs = cx.outputs(unit)?;
391392
let export_dir = cx.files().export_dir();
392393
let package_id = unit.pkg.package_id().clone();
393-
let target = unit.target.clone();
394394
let profile = unit.profile;
395395
let unit_mode = unit.mode;
396396
let features = bcx.resolve
@@ -399,6 +399,12 @@ fn link_targets<'a, 'cfg>(
399399
.map(|s| s.to_owned())
400400
.collect();
401401
let json_messages = bcx.build_config.json_messages();
402+
let mut target = unit.target.clone();
403+
if let TargetSourcePath::Metabuild = target.src_path() {
404+
// Give it something to serialize.
405+
let path = unit.pkg.manifest().metabuild_path(cx.bcx.ws.target_dir());
406+
target.set_src_path(TargetSourcePath::Path(path));
407+
}
402408

403409
Ok(Work::new(move |_| {
404410
// If we're a "root crate", e.g. the target of this compilation, then we
@@ -582,7 +588,7 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
582588
let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg, unit.target)?;
583589
rustdoc.inherit_jobserver(&cx.jobserver);
584590
rustdoc.arg("--crate-name").arg(&unit.target.crate_name());
585-
add_path_args(cx, unit, &mut rustdoc);
591+
add_path_args(bcx, unit, &mut rustdoc);
586592
add_cap_lints(bcx, unit, &mut rustdoc);
587593
add_color(bcx, &mut rustdoc);
588594

@@ -666,13 +672,12 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
666672
//
667673
// The first returned value here is the argument to pass to rustc, and the
668674
// second is the cwd that rustc should operate in.
669-
fn path_args<'a, 'cfg>(cx: &Context<'a, 'cfg>, unit: &Unit) -> (PathBuf, PathBuf) {
670-
let ws_root = cx.bcx.ws.root();
671-
// TODO: this is a hack
675+
fn path_args(bcx: &BuildContext, unit: &Unit) -> (PathBuf, PathBuf) {
676+
let ws_root = bcx.ws.root();
672677
let src = if unit.target.is_custom_build() && unit.pkg.manifest().metabuild().is_some() {
673-
cx.files().metabuild_path(unit)
678+
unit.pkg.manifest().metabuild_path(bcx.ws.target_dir())
674679
} else {
675-
unit.target.src_path().to_path_buf()
680+
unit.target.src_path().path().to_path_buf()
676681
};
677682
assert!(src.is_absolute());
678683
if let Ok(path) = src.strip_prefix(ws_root) {
@@ -681,8 +686,8 @@ fn path_args<'a, 'cfg>(cx: &Context<'a, 'cfg>, unit: &Unit) -> (PathBuf, PathBuf
681686
(src, unit.pkg.root().to_path_buf())
682687
}
683688

684-
fn add_path_args<'a, 'cfg>(cx: &Context<'a, 'cfg>, unit: &Unit, cmd: &mut ProcessBuilder) {
685-
let (arg, cwd) = path_args(cx, unit);
689+
fn add_path_args(bcx: &BuildContext, unit: &Unit, cmd: &mut ProcessBuilder) {
690+
let (arg, cwd) = path_args(bcx, unit);
686691
cmd.arg(arg);
687692
cmd.cwd(cwd);
688693
}
@@ -741,7 +746,7 @@ fn build_base_args<'a, 'cfg>(
741746

742747
cmd.arg("--crate-name").arg(&unit.target.crate_name());
743748

744-
add_path_args(cx, unit, cmd);
749+
add_path_args(bcx, unit, cmd);
745750
add_color(bcx, cmd);
746751
add_error_format(bcx, cmd);
747752

Diff for: src/cargo/core/manifest.rs

+99-34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
#![allow(deprecated)] // for SipHasher
2+
13
use std::collections::{BTreeMap, HashMap};
24
use std::fmt;
3-
use std::hash::{Hash, Hasher};
5+
use std::hash::{Hash, Hasher, SipHasher};
46
use std::path::{Path, PathBuf};
57
use std::rc::Rc;
68

@@ -15,7 +17,7 @@ use core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary};
1517
use core::{Edition, Feature, Features, WorkspaceConfig};
1618
use util::errors::*;
1719
use util::toml::TomlManifest;
18-
use util::Config;
20+
use util::{Config, Filesystem};
1921

2022
pub enum EitherManifest {
2123
Real(Manifest),
@@ -191,7 +193,7 @@ pub struct Target {
191193
// as it's absolute currently and is otherwise a little too brittle for
192194
// causing rebuilds. Instead the hash for the path that we send to the
193195
// compiler is handled elsewhere.
194-
src_path: NonHashedPathBuf,
196+
src_path: TargetSourcePath,
195197
required_features: Option<Vec<String>>,
196198
tested: bool,
197199
benched: bool,
@@ -203,19 +205,50 @@ pub struct Target {
203205
}
204206

205207
#[derive(Clone, PartialEq, Eq)]
206-
struct NonHashedPathBuf {
207-
path: PathBuf,
208+
pub enum TargetSourcePath {
209+
Path(PathBuf),
210+
Metabuild,
211+
}
212+
213+
impl TargetSourcePath {
214+
pub fn path(&self) -> &Path {
215+
match self {
216+
TargetSourcePath::Path(path) => path.as_ref(),
217+
TargetSourcePath::Metabuild => panic!("metabuild not expected"),
218+
}
219+
}
220+
221+
pub fn is_path(&self) -> bool {
222+
match self {
223+
TargetSourcePath::Path(_) => true,
224+
_ => false,
225+
}
226+
}
208227
}
209228

210-
impl Hash for NonHashedPathBuf {
229+
impl Hash for TargetSourcePath {
211230
fn hash<H: Hasher>(&self, _: &mut H) {
212231
// ...
213232
}
214233
}
215234

216-
impl fmt::Debug for NonHashedPathBuf {
235+
impl fmt::Debug for TargetSourcePath {
217236
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
218-
self.path.fmt(f)
237+
match self {
238+
TargetSourcePath::Path(path) => path.fmt(f),
239+
TargetSourcePath::Metabuild => "metabuild".fmt(f),
240+
}
241+
}
242+
}
243+
244+
impl From<PathBuf> for TargetSourcePath {
245+
fn from(path: PathBuf) -> Self {
246+
assert!(
247+
path.is_absolute(),
248+
"`{}` is not absolute",
249+
path.display()
250+
);
251+
TargetSourcePath::Path(path)
219252
}
220253
}
221254

@@ -240,7 +273,7 @@ impl ser::Serialize for Target {
240273
kind: &self.kind,
241274
crate_types: self.rustc_crate_types(),
242275
name: &self.name,
243-
src_path: &self.src_path.path,
276+
src_path: &self.src_path.path().to_path_buf(),
244277
edition: &self.edition.to_string(),
245278
required_features: self
246279
.required_features
@@ -254,34 +287,43 @@ compact_debug! {
254287
impl fmt::Debug for Target {
255288
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256289
let (default, default_name) = {
257-
let src = self.src_path().to_path_buf();
258290
match &self.kind {
259291
TargetKind::Lib(kinds) => {
260292
(
261293
Target::lib_target(
262294
&self.name,
263295
kinds.clone(),
264-
src.clone(),
265-
Edition::Edition2015,
296+
self.src_path().path().to_path_buf(),
297+
self.edition,
266298
),
267-
format!("lib_target({:?}, {:?}, {:?})",
268-
self.name, kinds, src),
299+
format!("lib_target({:?}, {:?}, {:?}, {:?})",
300+
self.name, kinds, self.src_path, self.edition),
269301
)
270302
}
271303
TargetKind::CustomBuild => {
272-
(
273-
Target::custom_build_target(
274-
&self.name,
275-
src.clone(),
276-
Edition::Edition2015,
277-
),
278-
format!("custom_build_target({:?}, {:?})",
279-
self.name, src),
280-
)
304+
match self.src_path {
305+
TargetSourcePath::Path(ref path) => {
306+
(
307+
Target::custom_build_target(
308+
&self.name,
309+
path.to_path_buf(),
310+
self.edition,
311+
),
312+
format!("custom_build_target({:?}, {:?}, {:?})",
313+
self.name, path, self.edition),
314+
)
315+
}
316+
TargetSourcePath::Metabuild => {
317+
(
318+
Target::metabuild_target(&self.name),
319+
format!("metabuild_target({:?})", self.name),
320+
)
321+
}
322+
}
281323
}
282324
_ => (
283-
Target::with_path(src.clone(), Edition::Edition2015),
284-
format!("with_path({:?})", src),
325+
Target::new(self.src_path.clone(), self.edition),
326+
format!("with_path({:?}, {:?})", self.src_path, self.edition),
285327
),
286328
}
287329
};
@@ -471,6 +513,16 @@ impl Manifest {
471513
pub fn metabuild(&self) -> Option<&Vec<String>> {
472514
self.metabuild.as_ref()
473515
}
516+
517+
pub fn metabuild_path(&self, target_dir: Filesystem) -> PathBuf {
518+
let mut hasher = SipHasher::new_with_keys(0, 0);
519+
self.package_id().hash(&mut hasher);
520+
let hash = hasher.finish();
521+
target_dir
522+
.into_path_unlocked()
523+
.join(".metabuild")
524+
.join(format!("metabuild-{}-{:016x}.rs", self.name(), hash))
525+
}
474526
}
475527

476528
impl VirtualManifest {
@@ -515,16 +567,11 @@ impl VirtualManifest {
515567
}
516568

517569
impl Target {
518-
fn with_path(src_path: PathBuf, edition: Edition) -> Target {
519-
assert!(
520-
src_path.is_absolute(),
521-
"`{}` is not absolute",
522-
src_path.display()
523-
);
570+
fn new(src_path: TargetSourcePath, edition: Edition) -> Target {
524571
Target {
525572
kind: TargetKind::Bin,
526573
name: String::new(),
527-
src_path: NonHashedPathBuf { path: src_path },
574+
src_path,
528575
required_features: None,
529576
doc: false,
530577
doctest: false,
@@ -536,6 +583,10 @@ impl Target {
536583
}
537584
}
538585

586+
fn with_path(src_path: PathBuf, edition: Edition) -> Target {
587+
Target::new(TargetSourcePath::from(src_path), edition)
588+
}
589+
539590
pub fn lib_target(
540591
name: &str,
541592
crate_targets: Vec<LibKind>,
@@ -582,6 +633,17 @@ impl Target {
582633
}
583634
}
584635

636+
pub fn metabuild_target(name: &str) -> Target {
637+
Target {
638+
kind: TargetKind::CustomBuild,
639+
name: name.to_string(),
640+
for_host: true,
641+
benched: false,
642+
tested: false,
643+
..Target::new(TargetSourcePath::Metabuild, Edition::Edition2015)
644+
}
645+
}
646+
585647
pub fn example_target(
586648
name: &str,
587649
crate_targets: Vec<LibKind>,
@@ -641,8 +703,11 @@ impl Target {
641703
pub fn crate_name(&self) -> String {
642704
self.name.replace("-", "_")
643705
}
644-
pub fn src_path(&self) -> &Path {
645-
&self.src_path.path
706+
pub fn src_path(&self) -> &TargetSourcePath {
707+
&self.src_path
708+
}
709+
pub fn set_src_path(&mut self, src_path: TargetSourcePath) {
710+
self.src_path = src_path;
646711
}
647712
pub fn required_features(&self) -> Option<&Vec<String>> {
648713
self.required_features.as_ref()

0 commit comments

Comments
 (0)