Skip to content

Commit d1045c9

Browse files
committed
Fix renaming directory project using build scripts with cross-compiling.
1 parent b3d0b2e commit d1045c9

File tree

3 files changed

+71
-37
lines changed

3 files changed

+71
-37
lines changed

src/cargo/core/compiler/context/compilation_files.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,15 @@ fn compute_metadata<'a, 'cfg>(
402402

403403
let mut hasher = SipHasher::new_with_keys(0, 0);
404404

405+
// This is a generic version number that can be changed to make
406+
// backwards-incompatible changes to any file structures in the output
407+
// directory. For example, the fingerprint files or the build-script
408+
// output files. Normally cargo updates ship with rustc updates which will
409+
// cause a new hash due to the rustc version changing, but this allows
410+
// cargo to be extra careful to deal with different versions of cargo that
411+
// use the same rustc version.
412+
1.hash(&mut hasher);
413+
405414
// Unique metadata per (name, source, version) triple. This'll allow us
406415
// to pull crates from anywhere w/o worrying about conflicts
407416
unit.pkg

src/cargo/core/compiler/custom_build.rs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub struct BuildOutput {
2828
/// Metadata to pass to the immediate dependencies
2929
pub metadata: Vec<(String, String)>,
3030
/// Paths to trigger a rerun of this build script.
31+
/// May be absolute or relative paths (relative to package root).
3132
pub rerun_if_changed: Vec<PathBuf>,
3233
/// Environment variables which, when changed, will cause a rebuild.
3334
pub rerun_if_env_changed: Vec<String>,
@@ -129,8 +130,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
129130
.iter()
130131
.find(|d| !d.mode.is_run_custom_build() && d.target.is_custom_build())
131132
.expect("running a script not depending on an actual script");
132-
let script_output = cx.files().build_script_dir(build_script_unit);
133-
let build_output = cx.files().build_script_out_dir(unit);
133+
let script_dir = cx.files().build_script_dir(build_script_unit);
134+
let script_out_dir = cx.files().build_script_out_dir(unit);
134135
let build_plan = bcx.build_config.build_plan;
135136
let invocation_name = unit.buildkey();
136137

@@ -139,7 +140,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
139140
}
140141

141142
// Building the command to execute
142-
let to_exec = script_output.join(unit.target.name());
143+
let to_exec = script_dir.join(unit.target.name());
143144

144145
// Start preparing the process to execute, starting out with some
145146
// environment variables. Note that the profile-related environment
@@ -151,7 +152,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
151152
let to_exec = to_exec.into_os_string();
152153
let mut cmd = cx.compilation.host_process(to_exec, unit.pkg)?;
153154
let debug = unit.profile.debuginfo.unwrap_or(0) != 0;
154-
cmd.env("OUT_DIR", &build_output)
155+
cmd.env("OUT_DIR", &script_out_dir)
155156
.env("CARGO_MANIFEST_DIR", unit.pkg.root())
156157
.env("NUM_JOBS", &bcx.jobs().to_string())
157158
.env(
@@ -241,19 +242,19 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
241242
let build_state = Arc::clone(&cx.build_state);
242243
let id = unit.pkg.package_id().clone();
243244
let (output_file, err_file, root_output_file) = {
244-
let build_output_parent = build_output.parent().unwrap();
245+
let build_output_parent = script_out_dir.parent().unwrap();
245246
let output_file = build_output_parent.join("output");
246247
let err_file = build_output_parent.join("stderr");
247248
let root_output_file = build_output_parent.join("root-output");
248249
(output_file, err_file, root_output_file)
249250
};
250-
let root_output = cx.files().target_root().to_path_buf();
251+
let host_target_root = cx.files().target_root().to_path_buf();
251252
let all = (
252253
id.clone(),
253254
pkg_name.clone(),
254255
Arc::clone(&build_state),
255256
output_file.clone(),
256-
root_output.clone(),
257+
script_out_dir.clone(),
257258
);
258259
let build_scripts = super::load_build_deps(cx, unit);
259260
let kind = unit.kind;
@@ -262,16 +263,17 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
262263

263264
// Check to see if the build script has already run, and if it has keep
264265
// track of whether it has told us about some explicit dependencies
265-
let prev_root_output = paths::read_bytes(&root_output_file)
266+
let prev_script_out_dir = paths::read_bytes(&root_output_file)
266267
.and_then(|bytes| util::bytes2path(&bytes))
267-
.unwrap_or_else(|_| cmd.get_cwd().unwrap().to_path_buf());
268+
.unwrap_or_else(|_| script_out_dir.clone());
269+
268270
let prev_output =
269-
BuildOutput::parse_file(&output_file, &pkg_name, &prev_root_output, &root_output).ok();
271+
BuildOutput::parse_file(&output_file, &pkg_name, &prev_script_out_dir, &script_out_dir).ok();
270272
let deps = BuildDeps::new(&output_file, prev_output.as_ref());
271273
cx.build_explicit_deps.insert(*unit, deps);
272274

273-
fs::create_dir_all(&script_output)?;
274-
fs::create_dir_all(&build_output)?;
275+
fs::create_dir_all(&script_dir)?;
276+
fs::create_dir_all(&script_out_dir)?;
275277

276278
// Prepare the unit of "dirty work" which will actually run the custom build
277279
// command.
@@ -283,8 +285,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
283285
//
284286
// If we have an old build directory, then just move it into place,
285287
// otherwise create it!
286-
if fs::metadata(&build_output).is_err() {
287-
fs::create_dir(&build_output).chain_err(|| {
288+
if fs::metadata(&script_out_dir).is_err() {
289+
fs::create_dir(&script_out_dir).chain_err(|| {
288290
internal(
289291
"failed to create script output directory for \
290292
build command",
@@ -316,7 +318,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
316318
}
317319
}
318320
if let Some(build_scripts) = build_scripts {
319-
super::add_plugin_deps(&mut cmd, &build_state, &build_scripts, &root_output)?;
321+
super::add_plugin_deps(&mut cmd, &build_state, &build_scripts, &host_target_root)?;
320322
}
321323
}
322324

@@ -348,9 +350,9 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
348350
// well.
349351
paths::write(&output_file, &output.stdout)?;
350352
paths::write(&err_file, &output.stderr)?;
351-
paths::write(&root_output_file, util::path2bytes(&root_output)?)?;
353+
paths::write(&root_output_file, util::path2bytes(&script_out_dir)?)?;
352354
let parsed_output =
353-
BuildOutput::parse(&output.stdout, &pkg_name, &root_output, &root_output)?;
355+
BuildOutput::parse(&output.stdout, &pkg_name, &script_out_dir, &script_out_dir)?;
354356

355357
if json_messages {
356358
emit_build_output(&parsed_output, &id);
@@ -364,11 +366,11 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
364366
// itself to run when we actually end up just discarding what we calculated
365367
// above.
366368
let fresh = Work::new(move |_tx| {
367-
let (id, pkg_name, build_state, output_file, root_output) = all;
369+
let (id, pkg_name, build_state, output_file, script_out_dir) = all;
368370
let output = match prev_output {
369371
Some(output) => output,
370372
None => {
371-
BuildOutput::parse_file(&output_file, &pkg_name, &prev_root_output, &root_output)?
373+
BuildOutput::parse_file(&output_file, &pkg_name, &prev_script_out_dir, &script_out_dir)?
372374
}
373375
};
374376

@@ -406,20 +408,20 @@ impl BuildOutput {
406408
pub fn parse_file(
407409
path: &Path,
408410
pkg_name: &str,
409-
root_output_when_generated: &Path,
410-
root_output: &Path,
411+
script_out_dir_when_generated: &Path,
412+
script_out_dir: &Path,
411413
) -> CargoResult<BuildOutput> {
412414
let contents = paths::read_bytes(path)?;
413-
BuildOutput::parse(&contents, pkg_name, root_output_when_generated, root_output)
415+
BuildOutput::parse(&contents, pkg_name, script_out_dir_when_generated, script_out_dir)
414416
}
415417

416418
// Parses the output of a script.
417419
// The `pkg_name` is used for error messages.
418420
pub fn parse(
419421
input: &[u8],
420422
pkg_name: &str,
421-
root_output_when_generated: &Path,
422-
root_output: &Path,
423+
script_out_dir_when_generated: &Path,
424+
script_out_dir: &Path,
423425
) -> CargoResult<BuildOutput> {
424426
let mut library_paths = Vec::new();
425427
let mut library_links = Vec::new();
@@ -456,23 +458,24 @@ impl BuildOutput {
456458
_ => bail!("Wrong output in {}: `{}`", whence, line),
457459
};
458460

459-
let path = |val: &str| match Path::new(val).strip_prefix(root_output_when_generated) {
460-
Ok(path) => root_output.join(path),
461-
Err(_) => PathBuf::from(val),
462-
};
461+
// This will rewrite paths if the target directory has been moved.
462+
let value = value.replace(
463+
script_out_dir_when_generated.to_str().unwrap(),
464+
script_out_dir.to_str().unwrap(),
465+
);
463466

464467
match key {
465468
"rustc-flags" => {
466-
let (paths, links) = BuildOutput::parse_rustc_flags(value, &whence)?;
469+
let (paths, links) = BuildOutput::parse_rustc_flags(&value, &whence)?;
467470
library_links.extend(links.into_iter());
468471
library_paths.extend(paths.into_iter());
469472
}
470473
"rustc-link-lib" => library_links.push(value.to_string()),
471-
"rustc-link-search" => library_paths.push(path(value)),
474+
"rustc-link-search" => library_paths.push(PathBuf::from(value)),
472475
"rustc-cfg" => cfgs.push(value.to_string()),
473-
"rustc-env" => env.push(BuildOutput::parse_rustc_env(value, &whence)?),
476+
"rustc-env" => env.push(BuildOutput::parse_rustc_env(&value, &whence)?),
474477
"warning" => warnings.push(value.to_string()),
475-
"rerun-if-changed" => rerun_if_changed.push(path(value)),
478+
"rerun-if-changed" => rerun_if_changed.push(PathBuf::from(value)),
476479
"rerun-if-env-changed" => rerun_if_env_changed.push(value.to_string()),
477480
_ => metadata.push((key.to_string(), value.to_string())),
478481
}

tests/testsuite/build_script.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,6 +3191,24 @@ failed to select a version for `a` which could resolve this conflict
31913191

31923192
#[test]
31933193
fn rename_with_link_search_path() {
3194+
_rename_with_link_search_path(false);
3195+
}
3196+
3197+
#[test]
3198+
fn rename_with_link_search_path_cross() {
3199+
if cross_compile::disabled() {
3200+
return;
3201+
}
3202+
3203+
_rename_with_link_search_path(true);
3204+
}
3205+
3206+
fn _rename_with_link_search_path(cross: bool) {
3207+
let target_arg = if cross {
3208+
format!(" --target={}", cross_compile::alternate())
3209+
} else {
3210+
"".to_string()
3211+
};
31943212
let p = project()
31953213
.file(
31963214
"Cargo.toml",
@@ -3209,7 +3227,7 @@ fn rename_with_link_search_path() {
32093227
);
32103228
let p = p.build();
32113229

3212-
p.cargo("build").run();
3230+
p.cargo(&format!("build{}", target_arg)).run();
32133231

32143232
let p2 = project()
32153233
.at("bar")
@@ -3242,7 +3260,7 @@ fn rename_with_link_search_path() {
32423260
} else {
32433261
println!("cargo:rustc-link-lib=foo");
32443262
}
3245-
println!("cargo:rustc-link-search={}",
3263+
println!("cargo:rustc-link-search=all={}",
32463264
dst.parent().unwrap().display());
32473265
}
32483266
"#,
@@ -3265,7 +3283,11 @@ fn rename_with_link_search_path() {
32653283
// the `p` project. On OSX the `libfoo.dylib` artifact references the
32663284
// original path in `p` so we want to make sure that it can't find it (hence
32673285
// the deletion).
3268-
let root = p.root().join("target").join("debug").join("deps");
3286+
let root = if cross {
3287+
p.root().join("target").join(cross_compile::alternate()).join("debug").join("deps")
3288+
} else {
3289+
p.root().join("target").join("debug").join("deps")
3290+
};
32693291
let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);
32703292
let src = root.join(&file);
32713293

@@ -3280,7 +3302,7 @@ fn rename_with_link_search_path() {
32803302
remove_dir_all(p.root()).unwrap();
32813303

32823304
// Everything should work the first time
3283-
p2.cargo("run").run();
3305+
p2.cargo(&format!("run{}", target_arg)).run();
32843306

32853307
// Now rename the root directory and rerun `cargo run`. Not only should we
32863308
// not build anything but we also shouldn't crash.
@@ -3309,7 +3331,7 @@ fn rename_with_link_search_path() {
33093331
thread::sleep(Duration::from_millis(100));
33103332
}
33113333

3312-
p2.cargo("run")
3334+
p2.cargo(&format!("run{}", target_arg))
33133335
.cwd(&new)
33143336
.with_stderr(
33153337
"\

0 commit comments

Comments
 (0)