diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-12-11 10:10:44 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-11 10:10:44 +0100 |
| commit | 4c3e95e84b0924f0b7e45a2bb1c74f3d7bec4691 (patch) | |
| tree | f32ac318e97210fb64d874b9c4c2b4292074f333 /src/tools | |
| parent | 04e0512c7a94736e104e5d25a4705c37fa93a7e2 (diff) | |
| parent | 60d4e20ff07ac4546f47f09094c7c04b577f0966 (diff) | |
| download | rust-4c3e95e84b0924f0b7e45a2bb1c74f3d7bec4691.tar.gz rust-4c3e95e84b0924f0b7e45a2bb1c74f3d7bec4691.zip | |
Rollup merge of #67074 - ehuss:extern-options, r=petrochenkov
Add options to --extern flag. This changes the `--extern` flag so that it can take a series of options that changes its behavior. The general syntax is `[opts ':'] name ['=' path]` where `opts` is a comma separated list of options. Two options are supported, `priv` which replaces `--extern-private` and `noprelude` which avoids adding the crate to the extern prelude. ```text --extern priv:mylib=/path/to/libmylib.rlib --extern noprelude:alloc=/path/to/liballoc.rlib ``` `noprelude` is to be used by Cargo's build-std feature in order to use `--extern` to reference standard library crates. This also includes a second commit which adds the `aux-crate` directive to compiletest. I can split this off into a separate PR if desired, but it helps with defining these kinds of tests. It is based on #54020, and can be used in the future to replace and simplify some of the Makefile tests.
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/compiletest/src/header.rs | 29 | ||||
| -rw-r--r-- | src/tools/compiletest/src/runtest.rs | 159 |
2 files changed, 95 insertions, 93 deletions
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index dc4811e5d24..46cce6394e6 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -71,6 +71,7 @@ pub struct EarlyProps { pub ignore: Ignore, pub should_fail: bool, pub aux: Vec<String>, + pub aux_crate: Vec<(String, String)>, pub revisions: Vec<String>, } @@ -80,6 +81,7 @@ impl EarlyProps { ignore: Ignore::Run, should_fail: false, aux: Vec::new(), + aux_crate: Vec::new(), revisions: vec![], }; @@ -157,6 +159,10 @@ impl EarlyProps { props.aux.push(s); } + if let Some(ac) = config.parse_aux_crate(ln) { + props.aux_crate.push(ac); + } + if let Some(r) = config.parse_revisions(ln) { props.revisions.extend(r); } @@ -311,10 +317,9 @@ pub struct TestProps { // directory as the test, but for backwards compatibility reasons // we also check the auxiliary directory) pub aux_builds: Vec<String>, - // A list of crates to pass '--extern-private name:PATH' flags for - // This should be a subset of 'aux_build' - // FIXME: Replace this with a better solution: https://github.com/rust-lang/rust/pull/54020 - pub extern_private: Vec<String>, + // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies + // to build and pass with the `--extern` flag. + pub aux_crates: Vec<(String, String)>, // Environment settings to use for compiling pub rustc_env: Vec<(String, String)>, // Environment variables to unset prior to compiling. @@ -387,7 +392,7 @@ impl TestProps { run_flags: None, pp_exact: None, aux_builds: vec![], - extern_private: vec![], + aux_crates: vec![], revisions: vec![], rustc_env: vec![], unset_rustc_env: vec![], @@ -514,8 +519,8 @@ impl TestProps { self.aux_builds.push(ab); } - if let Some(ep) = config.parse_extern_private(ln) { - self.extern_private.push(ep); + if let Some(ac) = config.parse_aux_crate(ln) { + self.aux_crates.push(ac); } if let Some(ee) = config.parse_env(ln, "exec-env") { @@ -713,8 +718,14 @@ impl Config { .map(|r| r.trim().to_string()) } - fn parse_extern_private(&self, line: &str) -> Option<String> { - self.parse_name_value_directive(line, "extern-private") + fn parse_aux_crate(&self, line: &str) -> Option<(String, String)> { + self.parse_name_value_directive(line, "aux-crate").map(|r| { + let mut parts = r.trim().splitn(2, '='); + ( + parts.next().expect("aux-crate name").to_string(), + parts.next().expect("aux-crate value").to_string(), + ) + }) } fn parse_compile_flags(&self, line: &str) -> Option<String> { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 15ae67fb12c..480868440b8 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1776,93 +1776,16 @@ impl<'test> TestCx<'test> { create_dir_all(&aux_dir).unwrap(); } - // Use a Vec instead of a HashMap to preserve original order - let mut extern_priv = self.props.extern_private.clone(); - - let mut add_extern_priv = |priv_dep: &str, dylib: bool| { - let lib_name = get_lib_name(priv_dep, dylib); - rustc - .arg("--extern-private") - .arg(format!("{}={}", priv_dep, aux_dir.join(lib_name).to_str().unwrap())); - }; - for rel_ab in &self.props.aux_builds { - let aux_testpaths = self.compute_aux_test_paths(rel_ab); - let aux_props = - self.props - .from_aux_file(&aux_testpaths.file, self.revision, self.config); - let aux_output = TargetLocation::ThisDirectory(self.aux_output_dir_name()); - let aux_cx = TestCx { - config: self.config, - props: &aux_props, - testpaths: &aux_testpaths, - revision: self.revision, - }; - // Create the directory for the stdout/stderr files. - create_dir_all(aux_cx.output_base_dir()).unwrap(); - let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output); - - let (dylib, crate_type) = if aux_props.no_prefer_dynamic { - (true, None) - } else if self.config.target.contains("cloudabi") - || self.config.target.contains("emscripten") - || (self.config.target.contains("musl") - && !aux_props.force_host - && !self.config.host.contains("musl")) - || self.config.target.contains("wasm32") - || self.config.target.contains("nvptx") - || self.is_vxworks_pure_static() - { - // We primarily compile all auxiliary libraries as dynamic libraries - // to avoid code size bloat and large binaries as much as possible - // for the test suite (otherwise including libstd statically in all - // executables takes up quite a bit of space). - // - // For targets like MUSL or Emscripten, however, there is no support for - // dynamic libraries so we just go back to building a normal library. Note, - // however, that for MUSL if the library is built with `force_host` then - // it's ok to be a dylib as the host should always support dylibs. - (false, Some("lib")) - } else { - (true, Some("dylib")) - }; - - let trimmed = rel_ab.trim_end_matches(".rs").to_string(); - - // Normally, every 'extern-private' has a correspodning 'aux-build' - // entry. If so, we remove it from our list of private crates, - // and add an '--extern-private' flag to rustc - if extern_priv.remove_item(&trimmed).is_some() { - add_extern_priv(&trimmed, dylib); - } - - if let Some(crate_type) = crate_type { - aux_rustc.args(&["--crate-type", crate_type]); - } - - aux_rustc.arg("-L").arg(&aux_dir); - - let auxres = aux_cx.compose_and_run( - aux_rustc, - aux_cx.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), - None, - ); - if !auxres.status.success() { - self.fatal_proc_rec( - &format!( - "auxiliary build of {:?} failed to compile: ", - aux_testpaths.file.display() - ), - &auxres, - ); - } + self.build_auxiliary(rel_ab, &aux_dir); } - // Add any '--extern-private' entries without a matching - // 'aux-build' - for private_lib in extern_priv { - add_extern_priv(&private_lib, true); + for (aux_name, aux_path) in &self.props.aux_crates { + let is_dylib = self.build_auxiliary(&aux_path, &aux_dir); + let lib_name = get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), + is_dylib); + rustc.arg("--extern") + .arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name)); } self.props.unset_rustc_env.clone() @@ -1877,6 +1800,74 @@ impl<'test> TestCx<'test> { ) } + /// Builds an aux dependency. + /// + /// Returns whether or not it is a dylib. + fn build_auxiliary(&self, source_path: &str, aux_dir: &Path) -> bool { + let aux_testpaths = self.compute_aux_test_paths(source_path); + let aux_props = + self.props + .from_aux_file(&aux_testpaths.file, self.revision, self.config); + let aux_output = TargetLocation::ThisDirectory(self.aux_output_dir_name()); + let aux_cx = TestCx { + config: self.config, + props: &aux_props, + testpaths: &aux_testpaths, + revision: self.revision, + }; + // Create the directory for the stdout/stderr files. + create_dir_all(aux_cx.output_base_dir()).unwrap(); + let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output); + + let (dylib, crate_type) = if aux_props.no_prefer_dynamic { + (true, None) + } else if self.config.target.contains("cloudabi") + || self.config.target.contains("emscripten") + || (self.config.target.contains("musl") + && !aux_props.force_host + && !self.config.host.contains("musl")) + || self.config.target.contains("wasm32") + || self.config.target.contains("nvptx") + || self.is_vxworks_pure_static() + { + // We primarily compile all auxiliary libraries as dynamic libraries + // to avoid code size bloat and large binaries as much as possible + // for the test suite (otherwise including libstd statically in all + // executables takes up quite a bit of space). + // + // For targets like MUSL or Emscripten, however, there is no support for + // dynamic libraries so we just go back to building a normal library. Note, + // however, that for MUSL if the library is built with `force_host` then + // it's ok to be a dylib as the host should always support dylibs. + (false, Some("lib")) + } else { + (true, Some("dylib")) + }; + + if let Some(crate_type) = crate_type { + aux_rustc.args(&["--crate-type", crate_type]); + } + + aux_rustc.arg("-L").arg(&aux_dir); + + let auxres = aux_cx.compose_and_run( + aux_rustc, + aux_cx.config.compile_lib_path.to_str().unwrap(), + Some(aux_dir.to_str().unwrap()), + None, + ); + if !auxres.status.success() { + self.fatal_proc_rec( + &format!( + "auxiliary build of {:?} failed to compile: ", + aux_testpaths.file.display() + ), + &auxres, + ); + } + dylib + } + fn compose_and_run( &self, mut command: Command, |
