|
| 1 | +use bstr::ByteSlice; |
1 | 2 | use cargo_metadata::{camino::Utf8PathBuf, DependencyKind};
|
2 | 3 | use cargo_platform::Cfg;
|
3 | 4 | use color_eyre::eyre::{bail, eyre, Result};
|
4 | 5 | use std::{
|
5 | 6 | collections::{hash_map::Entry, HashMap, HashSet},
|
6 | 7 | ffi::OsString,
|
7 |
| - path::PathBuf, |
| 8 | + path::{Path, PathBuf}, |
8 | 9 | process::Command,
|
9 | 10 | str::FromStr,
|
10 | 11 | sync::{Arc, OnceLock, RwLock},
|
11 | 12 | };
|
12 | 13 |
|
13 | 14 | use crate::{
|
14 |
| - build_aux, status_emitter::StatusEmitter, test_result::Errored, Config, Mode, |
15 |
| - OutputConflictHandling, |
| 15 | + crate_type, default_per_file_config, |
| 16 | + per_test_config::{Comments, TestConfig}, |
| 17 | + rustc_stderr, |
| 18 | + status_emitter::StatusEmitter, |
| 19 | + test_result::Errored, |
| 20 | + Config, CrateType, Error, Mode, OutputConflictHandling, |
16 | 21 | };
|
17 | 22 |
|
18 | 23 | #[derive(Default, Debug)]
|
@@ -291,7 +296,7 @@ impl<'a> BuildManager<'a> {
|
291 | 296 | Err(())
|
292 | 297 | }
|
293 | 298 | },
|
294 |
| - Build::Aux { aux_file } => match build_aux(aux_file, config, self) { |
| 299 | + Build::Aux { aux_file } => match self.build_aux(aux_file, config) { |
295 | 300 | Ok(args) => Ok(args.iter().map(Into::into).collect()),
|
296 | 301 | Err(e) => {
|
297 | 302 | err = Some(e);
|
@@ -321,4 +326,104 @@ impl<'a> BuildManager<'a> {
|
321 | 326 | })
|
322 | 327 | })
|
323 | 328 | }
|
| 329 | + |
| 330 | + fn build_aux( |
| 331 | + &self, |
| 332 | + aux_file: &Path, |
| 333 | + config: &Config, |
| 334 | + ) -> std::result::Result<Vec<OsString>, Errored> { |
| 335 | + let file_contents = std::fs::read(aux_file).map_err(|err| Errored { |
| 336 | + command: Command::new(format!("reading aux file `{}`", aux_file.display())), |
| 337 | + errors: vec![], |
| 338 | + stderr: err.to_string().into_bytes(), |
| 339 | + stdout: vec![], |
| 340 | + })?; |
| 341 | + let comments = Comments::parse(&file_contents, config.comment_defaults.clone(), aux_file) |
| 342 | + .map_err(|errors| Errored::new(errors, "parse aux comments"))?; |
| 343 | + assert_eq!( |
| 344 | + comments.revisions, None, |
| 345 | + "aux builds cannot specify revisions" |
| 346 | + ); |
| 347 | + |
| 348 | + let mut config = config.clone(); |
| 349 | + |
| 350 | + // Strip any `crate-type` flags from the args, as we need to set our own, |
| 351 | + // and they may conflict (e.g. `lib` vs `proc-macro`); |
| 352 | + let mut prev_was_crate_type = false; |
| 353 | + config.program.args.retain(|arg| { |
| 354 | + if prev_was_crate_type { |
| 355 | + prev_was_crate_type = false; |
| 356 | + return false; |
| 357 | + } |
| 358 | + if arg == "--test" { |
| 359 | + false |
| 360 | + } else if arg == "--crate-type" { |
| 361 | + prev_was_crate_type = true; |
| 362 | + false |
| 363 | + } else if let Some(arg) = arg.to_str() { |
| 364 | + !arg.starts_with("--crate-type=") |
| 365 | + } else { |
| 366 | + true |
| 367 | + } |
| 368 | + }); |
| 369 | + |
| 370 | + default_per_file_config(&mut config, aux_file, &file_contents); |
| 371 | + |
| 372 | + match crate_type(&file_contents) { |
| 373 | + // Proc macros must be run on the host |
| 374 | + CrateType::ProcMacro => config.target = config.host.clone(), |
| 375 | + CrateType::Test | CrateType::Bin | CrateType::Lib => {} |
| 376 | + } |
| 377 | + |
| 378 | + let mut config = TestConfig { |
| 379 | + config, |
| 380 | + revision: "", |
| 381 | + comments: &comments, |
| 382 | + path: aux_file, |
| 383 | + }; |
| 384 | + |
| 385 | + config.patch_out_dir(); |
| 386 | + |
| 387 | + let mut aux_cmd = config.build_command()?; |
| 388 | + |
| 389 | + let mut extra_args = config.build_aux_files(aux_file.parent().unwrap(), self)?; |
| 390 | + // Make sure we see our dependencies |
| 391 | + aux_cmd.args(extra_args.iter()); |
| 392 | + |
| 393 | + aux_cmd.arg("--emit=link"); |
| 394 | + let filename = aux_file.file_stem().unwrap().to_str().unwrap(); |
| 395 | + let output = aux_cmd.output().unwrap(); |
| 396 | + if !output.status.success() { |
| 397 | + let error = Error::Command { |
| 398 | + kind: "compilation of aux build failed".to_string(), |
| 399 | + status: output.status, |
| 400 | + }; |
| 401 | + return Err(Errored { |
| 402 | + command: aux_cmd, |
| 403 | + errors: vec![error], |
| 404 | + stderr: rustc_stderr::process(aux_file, &output.stderr).rendered, |
| 405 | + stdout: output.stdout, |
| 406 | + }); |
| 407 | + } |
| 408 | + |
| 409 | + // Now run the command again to fetch the output filenames |
| 410 | + aux_cmd.arg("--print").arg("file-names"); |
| 411 | + let output = aux_cmd.output().unwrap(); |
| 412 | + assert!(output.status.success()); |
| 413 | + |
| 414 | + for file in output.stdout.lines() { |
| 415 | + let file = std::str::from_utf8(file).unwrap(); |
| 416 | + let crate_name = filename.replace('-', "_"); |
| 417 | + let path = config.config.out_dir.join(file); |
| 418 | + extra_args.push("--extern".into()); |
| 419 | + let mut cname = OsString::from(&crate_name); |
| 420 | + cname.push("="); |
| 421 | + cname.push(path); |
| 422 | + extra_args.push(cname); |
| 423 | + // Help cargo find the crates added with `--extern`. |
| 424 | + extra_args.push("-L".into()); |
| 425 | + extra_args.push(config.config.out_dir.as_os_str().to_os_string()); |
| 426 | + } |
| 427 | + Ok(extra_args) |
| 428 | + } |
324 | 429 | }
|
0 commit comments