From 2f2b827b36d0effee216eb928ff83615f2ae030a Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 12 Apr 2018 16:00:13 -0700 Subject: [PATCH] Allow toml targets to be conditionally compiled with cfg(..) Fix #4900 Sort of addresses #4881 as well. --- src/cargo/core/compiler/build_context/mod.rs | 14 +- src/cargo/core/compiler/context/mod.rs | 0 src/cargo/core/manifest.rs | 21 +- src/cargo/core/mod.rs | 2 +- src/cargo/ops/cargo_compile.rs | 58 +++- src/cargo/util/errors.rs | 2 +- src/cargo/util/toml/mod.rs | 11 + src/cargo/util/toml/targets.rs | 347 ++++++++++++++----- tests/testsuite/build.rs | 8 + tests/testsuite/cargotest/support/mod.rs | 4 + tests/testsuite/cfg.rs | 242 ++++++++++++- tests/testsuite/metadata.rs | 16 + tests/testsuite/read_manifest.rs | 1 + tests/testsuite/test.rs | 2 + 14 files changed, 638 insertions(+), 90 deletions(-) mode change 100644 => 100755 src/cargo/core/compiler/context/mod.rs mode change 100644 => 100755 src/cargo/util/errors.rs diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 1e7112b9abe..783977d0e05 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; use core::profiles::Profiles; -use core::{Dependency, Workspace}; +use core::{Dependency, Target, Workspace}; use core::{Package, PackageId, PackageSet, Resolve}; use util::errors::CargoResult; use util::{profile, Cfg, CfgExpr, Config, Rustc}; @@ -133,6 +133,18 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { platform.matches(name, info.cfg()) } + pub fn target_platform_activated(&self, target: &Target, kind: Kind) -> bool { + let platform = match target.platform() { + Some(p) => p, + None => return true, + }; + let (name, info) = match kind { + Kind::Host => (self.host_triple(), &self.host_info), + Kind::Target => (self.target_triple(), &self.target_info), + }; + platform.matches(name, info.cfg()) + } + /// Gets a package for the given package id. pub fn get_package(&self, id: &PackageId) -> CargoResult<&'a Package> { self.packages.get(id) diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs old mode 100644 new mode 100755 diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 5e42103862c..24793d8c648 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -11,7 +11,7 @@ use url::Url; use core::interning::InternedString; use core::profiles::Profiles; -use core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary}; +use core::{Dependency, PackageId, PackageIdSpec, Platform, SourceId, Summary}; use core::{Edition, Feature, Features, WorkspaceConfig}; use util::errors::*; use util::toml::TomlManifest; @@ -171,6 +171,10 @@ pub struct Target { doctest: bool, harness: bool, // whether to use the test harness (--test) for_host: bool, + + // This target should only be built for this platform. `None` means *all + // platforms*. + platform: Option, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -194,6 +198,7 @@ struct SerializedTarget<'a> { crate_types: Vec<&'a str>, name: &'a str, src_path: &'a PathBuf, + platform: Option<&'a Platform>, } impl ser::Serialize for Target { @@ -203,6 +208,7 @@ impl ser::Serialize for Target { crate_types: self.rustc_crate_types(), name: &self.name, src_path: &self.src_path.path, + platform: self.platform(), }.serialize(s) } } @@ -417,6 +423,7 @@ impl Target { for_host: false, tested: true, benched: true, + platform: None, } } @@ -537,6 +544,12 @@ impl Target { self.benched } + /// If none, this target must be built for all platforms. + /// If some, it must only be built for the specified platform. + pub fn platform(&self) -> Option<&Platform> { + self.platform.as_ref() + } + pub fn doctested(&self) -> bool { self.doctest && match self.kind { TargetKind::Lib(ref kinds) => kinds @@ -552,7 +565,7 @@ impl Target { pub fn is_lib(&self) -> bool { match self.kind { - TargetKind::Lib(_) => true, + TargetKind::Lib(..) => true, _ => false, } } @@ -659,6 +672,10 @@ impl Target { self.doc = doc; self } + pub fn set_platform(&mut self, platform: Option) -> &mut Target { + self.platform = platform; + self + } } impl fmt::Display for Target { diff --git a/src/cargo/core/mod.rs b/src/cargo/core/mod.rs index 67578c8223c..447cc8eb924 100644 --- a/src/cargo/core/mod.rs +++ b/src/cargo/core/mod.rs @@ -1,4 +1,4 @@ -pub use self::dependency::Dependency; +pub use self::dependency::{Dependency, Platform}; pub use self::features::{CliUnstable, Edition, Feature, Features}; pub use self::manifest::{EitherManifest, VirtualManifest}; pub use self::manifest::{LibKind, Manifest, Target, TargetKind}; diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 0703b0873a5..0859d826d92 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -22,7 +22,7 @@ //! previously compiled dependency //! -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::sync::Arc; @@ -256,8 +256,6 @@ pub fn compile_ws<'a>( let profiles = ws.profiles(); profiles.validate_packages(&mut config.shell(), &packages)?; - let mut extra_compiler_args = None; - let units = generate_targets( ws, profiles, @@ -268,6 +266,8 @@ pub fn compile_ws<'a>( build_config, )?; + let mut extra_compiler_args = None; + if let Some(args) = extra_args { if units.len() != 1 { bail!( @@ -281,7 +281,6 @@ pub fn compile_ws<'a>( } let mut ret = { - let _p = profile::start("compiling"); let bcx = BuildContext::new( ws, &resolve_with_overrides, @@ -292,6 +291,57 @@ pub fn compile_ws<'a>( extra_compiler_args, )?; let mut cx = Context::new(config, &bcx)?; + + // Filter to just the units whose target is activated. + let units = units + .into_iter() + .filter(|u| { + let kind = if u.target.for_host() { + Kind::Host + } else { + Kind::Target + }; + + cx.bcx.target_platform_activated(&u.target, kind) + }) + .collect::>(); + + // Ensure that there is only one [lib] activated per crate. + { + let mut pkg_libs: HashMap<(&PackageId, &str), Vec<&Unit>> = Default::default(); + + for unit in &units { + if let TargetKind::Lib(_) = *unit.target.kind() { + let pkgid = unit.pkg.package_id(); + pkg_libs + .entry((pkgid, &unit.profile.name)) + .or_insert(vec![]) + .push(unit); + } + } + + for ((pkg, profile), libs) in pkg_libs { + if libs.len() > 1 { + let mut msg = format!( + "Can only have one [lib] per crate and profile pair! \ + For crate {} and profile {}, found ", + pkg, + profile + ); + + for (i, u) in libs.into_iter().enumerate() { + if i > 0 { + msg.push_str(", "); + } + msg.push_str(&format!("{}", u.target)); + } + + bail!(msg); + } + } + } + + let _p = profile::start("compiling"); cx.compile(&units, export_dir.clone(), &exec)? }; diff --git a/src/cargo/util/errors.rs b/src/cargo/util/errors.rs old mode 100644 new mode 100755 index d3b1d43d02b..6e2f39f9911 --- a/src/cargo/util/errors.rs +++ b/src/cargo/util/errors.rs @@ -141,7 +141,7 @@ impl CargoTestError { TargetKind::Bin => { format!("test failed, to rerun pass '{}--bin {}'", pkg_info, name) } - TargetKind::Lib(_) => format!("test failed, to rerun pass '{}--lib'", pkg_info), + TargetKind::Lib(..) => format!("test failed, to rerun pass '{}--lib'", pkg_info), TargetKind::Test => { format!("test failed, to rerun pass '{}--test {}'", pkg_info, name) } diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index fd664572ecf..edf1f8d1f57 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -679,6 +679,11 @@ impl TomlManifest { .or_else(|| v.build_dependencies2.as_ref()), )?, build_dependencies2: None, + lib: v.lib.clone(), + bin: v.bin.clone(), + bench: v.bench.clone(), + test: v.test.clone(), + example: v.example.clone(), }, )) }) @@ -1373,6 +1378,12 @@ struct TomlPlatform { dev_dependencies: Option>, #[serde(rename = "dev_dependencies")] dev_dependencies2: Option>, + + lib: Option, + bin: Option>, + example: Option>, + test: Option>, + bench: Option>, } impl TomlTarget { diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs index 1bbdf20e754..346f2811648 100644 --- a/src/cargo/util/toml/targets.rs +++ b/src/cargo/util/toml/targets.rs @@ -12,12 +12,13 @@ use std::path::{Path, PathBuf}; use std::fs::{self, DirEntry}; -use std::collections::HashSet; +use std::collections::{BTreeMap, HashSet}; use core::{compiler, Edition, Target}; +use core::dependency::Platform; use util::errors::CargoResult; use super::{LibKind, PathValue, StringOrBool, TomlBenchTarget, TomlBinTarget, TomlExampleTarget, - TomlLibTarget, TomlManifest, TomlTarget, TomlTestTarget}; + TomlLibTarget, TomlManifest, TomlPlatform, TomlTarget, TomlTestTarget}; pub fn targets( manifest: &TomlManifest, @@ -28,22 +29,16 @@ pub fn targets( warnings: &mut Vec, errors: &mut Vec, ) -> CargoResult> { - let mut targets = Vec::new(); - - let has_lib; - - if let Some(target) = clean_lib( + let mut targets = clean_lib( manifest.lib.as_ref(), + manifest.target.as_ref(), package_root, package_name, edition, - warnings, - )? { - targets.push(target); - has_lib = true; - } else { - has_lib = false; - } + warnings + )?; + + let has_lib = !targets.is_empty(); let package = manifest .package @@ -53,6 +48,7 @@ pub fn targets( targets.extend(clean_bins( manifest.bin.as_ref(), + manifest.target.as_ref(), package_root, package_name, edition, @@ -64,6 +60,7 @@ pub fn targets( targets.extend(clean_examples( manifest.example.as_ref(), + manifest.target.as_ref(), package_root, edition, package.autoexamples, @@ -73,6 +70,7 @@ pub fn targets( targets.extend(clean_tests( manifest.test.as_ref(), + manifest.target.as_ref(), package_root, edition, package.autotests, @@ -82,6 +80,7 @@ pub fn targets( targets.extend(clean_benches( manifest.bench.as_ref(), + manifest.target.as_ref(), package_root, edition, package.autobenches, @@ -109,11 +108,12 @@ pub fn targets( fn clean_lib( toml_lib: Option<&TomlLibTarget>, + toml_targets: Option<&BTreeMap>, package_root: &Path, package_name: &str, edition: Edition, warnings: &mut Vec, -) -> CargoResult> { +) -> CargoResult> { let inferred = inferred_lib(package_root); let lib = match toml_lib { Some(lib) => { @@ -135,60 +135,78 @@ fn clean_lib( }), }; - let lib = match lib { - Some(ref lib) => lib, - None => return Ok(None), - }; + let libs: CargoResult> = lib.into_iter() + .map(|lib| (None, lib)) + .chain(toml_targets.iter().flat_map(|ps| { + ps.iter() + .filter_map(|(cfg, platform)| { + platform.lib.as_ref().cloned().map(|lib| { + (Some(cfg), lib) + }) + }) + .collect::>() + })) + .map(|(cfg, lib)| { + validate_has_name(&lib, "library", "lib")?; + + let path = match (lib.path.as_ref(), inferred.clone()) { + (Some(path), _) => package_root.join(&path.0), + (None, Some(path)) => path, + (None, None) => { + let legacy_path = package_root.join("src").join(format!("{}.rs", lib.name())); + if edition < Edition::Edition2018 && legacy_path.exists() { + warnings.push(format!( + "path `{}` was erroneously implicitly accepted for library `{}`,\n\ + please rename the file to `src/lib.rs` or set lib.path in Cargo.toml", + legacy_path.display(), + lib.name() + )); + legacy_path + } else { + bail!( + "can't find library `{}`, \ + rename file to `src/lib.rs` or specify lib.path", + lib.name() + ) + } + } + }; - validate_has_name(lib, "library", "lib")?; + // Per the Macros 1.1 RFC: + // + // > Initially if a crate is compiled with the proc-macro crate type + // > (and possibly others) it will forbid exporting any items in the + // > crate other than those functions tagged #[proc_macro_derive] and + // > those functions must also be placed at the crate root. + // + // A plugin requires exporting plugin_registrar so a crate cannot be + // both at once. + let crate_types = match (lib.crate_types(), lib.plugin, lib.proc_macro()) { + (_, Some(true), Some(true)) => bail!("lib.plugin and lib.proc-macro cannot both be true"), + (Some(kinds), _, _) => kinds.iter().map(|s| LibKind::from_str(s)).collect(), + (None, Some(true), _) => vec![LibKind::Dylib], + (None, _, Some(true)) => vec![LibKind::ProcMacro], + (None, _, _) => vec![LibKind::Lib], + }; - let path = match (lib.path.as_ref(), inferred) { - (Some(path), _) => package_root.join(&path.0), - (None, Some(path)) => path, - (None, None) => { - let legacy_path = package_root.join("src").join(format!("{}.rs", lib.name())); - if edition < Edition::Edition2018 && legacy_path.exists() { - warnings.push(format!( - "path `{}` was erroneously implicitly accepted for library `{}`,\n\ - please rename the file to `src/lib.rs` or set lib.path in Cargo.toml", - legacy_path.display(), - lib.name() - )); - legacy_path + let mut target = Target::lib_target(&lib.name(), crate_types, path); + let cfg = if let Some(cfg) = cfg { + Some(cfg.parse()?) } else { - bail!( - "can't find library `{}`, \ - rename file to `src/lib.rs` or specify lib.path", - lib.name() - ) - } - } - }; + None + }; + configure(&lib, cfg, &mut target); - // Per the Macros 1.1 RFC: - // - // > Initially if a crate is compiled with the proc-macro crate type - // > (and possibly others) it will forbid exporting any items in the - // > crate other than those functions tagged #[proc_macro_derive] and - // > those functions must also be placed at the crate root. - // - // A plugin requires exporting plugin_registrar so a crate cannot be - // both at once. - let crate_types = match (lib.crate_types(), lib.plugin, lib.proc_macro()) { - (_, Some(true), Some(true)) => bail!("lib.plugin and lib.proc-macro cannot both be true"), - (Some(kinds), _, _) => kinds.iter().map(|s| LibKind::from_str(s)).collect(), - (None, Some(true), _) => vec![LibKind::Dylib], - (None, _, Some(true)) => vec![LibKind::ProcMacro], - (None, _, _) => vec![LibKind::Lib], - }; + Ok(target) + }) + .collect(); - let mut target = Target::lib_target(&lib.name(), crate_types, path); - configure(lib, &mut target); - Ok(Some(target)) + Ok(libs?) } fn clean_bins( toml_bins: Option<&Vec>, + toml_targets: Option<&BTreeMap>, package_root: &Path, package_name: &str, edition: Edition, @@ -197,7 +215,16 @@ fn clean_bins( errors: &mut Vec, has_lib: bool, ) -> CargoResult> { - let inferred = inferred_bins(package_root, package_name); + let any_platform_bins = toml_targets.map_or( + false, + |ps| ps.iter().any(|(_, p)| p.bin.is_some()) + ); + + let inferred = if any_platform_bins { + vec![] + } else { + inferred_bins(package_root, package_name) + }; let bins = toml_targets_and_inferred( toml_bins, @@ -211,7 +238,18 @@ fn clean_bins( "autobins", ); - for bin in &bins { + let mut bins: Vec<_> = bins.iter().cloned().map(|b| (None, b)).collect(); + + if let Some(toml_targets) = toml_targets { + bins.extend(toml_targets.iter().flat_map(|(cfg, platform)| { + platform.bin.as_ref().map_or( + vec![], + |bins| bins.iter().map(|bin| (Some(cfg.clone()), bin.clone())).collect() + ) + })); + } + + for &(_, ref bin) in &bins { validate_has_name(bin, "binary", "bin")?; let name = bin.name(); @@ -240,10 +278,10 @@ fn clean_bins( } } - validate_unique_names(&bins, "binary")?; + validate_unique_names(bins.iter().map(|pair| &pair.1), "binary")?; let mut result = Vec::new(); - for bin in &bins { + for &(ref cfg, ref bin) in &bins { let path = target_path(bin, &inferred, "bin", package_root, edition, &mut |_| { if let Some(legacy_path) = legacy_bin_path(package_root, &bin.name(), has_lib) { warnings.push(format!( @@ -263,7 +301,12 @@ fn clean_bins( }; let mut target = Target::bin_target(&bin.name(), path, bin.required_features.clone()); - configure(bin, &mut target); + let cfg = if let Some(cfg) = cfg { + Some(cfg.parse()?) + } else { + None + }; + configure(bin, cfg, &mut target); result.push(target); } return Ok(result); @@ -290,13 +333,23 @@ fn clean_bins( fn clean_examples( toml_examples: Option<&Vec>, + toml_platforms: Option<&BTreeMap>, package_root: &Path, edition: Edition, autodiscover: Option, warnings: &mut Vec, errors: &mut Vec, ) -> CargoResult> { - let inferred = infer_from_directory(&package_root.join("examples")); + let any_platform_examples = toml_platforms.map_or( + false, + |ps| ps.iter().any(|p| p.1.example.is_some()) + ); + + let inferred = if any_platform_examples { + vec![] + } else { + infer_from_directory(&package_root.join("examples")) + }; let targets = clean_targets( "example", @@ -311,8 +364,24 @@ fn clean_examples( "autoexamples", )?; + let mut targets: Vec<_> = targets.into_iter() + .map(|(path, target)| (path, None, target)) + .collect(); + + targets.extend( + get_platform_targets( + toml_platforms.as_ref().map(|t| *t), + |t| t.example.as_ref().map(|t| &t[..]), + &inferred, + "example", + package_root, + edition, + errors + ) + ); + let mut result = Vec::new(); - for (path, toml) in targets { + for (path, cfg, toml) in targets { let crate_types = match toml.crate_types() { Some(kinds) => kinds.iter().map(|s| LibKind::from_str(s)).collect(), None => Vec::new(), @@ -324,22 +393,83 @@ fn clean_examples( path, toml.required_features.clone(), ); - configure(&toml, &mut target); + let cfg = if let Some(cfg) = cfg { + Some(cfg.parse()?) + } else { + None + }; + configure(&toml, cfg, &mut target); result.push(target); } Ok(result) } +fn get_platform_targets( + toml_platforms: Option<&BTreeMap>, + get_targets: F, + inferred: &[(String, PathBuf)], + target_kind: &str, + package_root: &Path, + edition: Edition, + errors: &mut Vec, +) -> Vec<(PathBuf, Option, TomlTarget)> +where + F: Fn(&TomlPlatform) -> Option<&[TomlTarget]> +{ + toml_platforms.iter() + .flat_map(|targets| { + targets.iter() + .flat_map(|(cfg, platform)| { + get_targets(platform) + .iter() + .flat_map(|tests| { + tests.iter() + .filter_map(|test| { + let path = target_path( + test, + inferred, + target_kind, + package_root, + edition, + &mut |_| None + ); + match path { + Ok(path) => Some((path, Some(cfg.clone()), test.clone())), + Err(e) => { + errors.push(e); + None + } + } + }) + .collect::>() + }) + .collect::>() + }) + .collect::>() + }) + .collect() +} + fn clean_tests( toml_tests: Option<&Vec>, + toml_targets: Option<&BTreeMap>, package_root: &Path, edition: Edition, autodiscover: Option, warnings: &mut Vec, errors: &mut Vec, ) -> CargoResult> { - let inferred = infer_from_directory(&package_root.join("tests")); + let any_platform_tests = toml_targets.map_or( + false, + |ps| ps.iter().any(|p| p.1.test.is_some()) + ); + + let inferred = if any_platform_tests { + vec![] + } else { + infer_from_directory(&package_root.join("tests")) + }; let targets = clean_targets( "test", @@ -354,10 +484,31 @@ fn clean_tests( "autotests", )?; + let mut targets: Vec<_> = targets.into_iter() + .map(|(path, target)| (path, None, target)) + .collect(); + + targets.extend( + get_platform_targets( + toml_targets.as_ref().map(|t| *t), + |t| t.test.as_ref().map(|t| &t[..]), + &inferred, + "example", + package_root, + edition, + errors + ) + ); + let mut result = Vec::new(); - for (path, toml) in targets { + for (path, cfg, toml) in targets { let mut target = Target::test_target(&toml.name(), path, toml.required_features.clone()); - configure(&toml, &mut target); + let cfg = if let Some(cfg) = cfg { + Some(cfg.parse()?) + } else { + None + }; + configure(&toml, cfg, &mut target); result.push(target); } Ok(result) @@ -365,6 +516,7 @@ fn clean_tests( fn clean_benches( toml_benches: Option<&Vec>, + toml_targets: Option<&BTreeMap>, package_root: &Path, edition: Edition, autodiscover: Option, @@ -388,9 +540,17 @@ fn clean_benches( Some(legacy_path) }; - let inferred = infer_from_directory(&package_root.join("benches")); + let any_platform_benches = toml_targets.map_or( + false, + |ps| ps.iter().any(|p| p.1.bench.is_some()) + ); + let inferred = if any_platform_benches { + vec![] + } else { + infer_from_directory(&package_root.join("benches")) + }; - clean_targets_with_legacy_path( + let targets = clean_targets_with_legacy_path( "benchmark", "bench", toml_benches, @@ -402,15 +562,38 @@ fn clean_benches( errors, &mut legacy_bench_path, "autobenches", - )? + )?; + + let mut targets: Vec<_> = targets.into_iter() + .map(|(path, target)| (path, None, target)) + .collect(); + + targets.extend( + get_platform_targets( + toml_targets.as_ref().map(|t| *t), + |t| t.bench.as_ref().map(|t| &t[..]), + &inferred, + "bench", + package_root, + edition, + errors + ) + ); + + targets }; warnings.append(&mut legacy_warnings); let mut result = Vec::new(); - for (path, toml) in targets { + for (path, cfg, toml) in targets { let mut target = Target::bench_target(&toml.name(), path, toml.required_features.clone()); - configure(&toml, &mut target); + let cfg = if let Some(cfg) = cfg { + Some(cfg.parse()?) + } else { + None + }; + configure(&toml, cfg, &mut target); result.push(target); } @@ -667,9 +850,12 @@ fn validate_has_name( } /// Will check a list of toml targets, and make sure the target names are unique within a vector. -fn validate_unique_names(targets: &[TomlTarget], target_kind: &str) -> CargoResult<()> { +fn validate_unique_names<'a, I>(targets: I, target_kind: &str) -> CargoResult<()> +where + I: IntoIterator +{ let mut seen = HashSet::new(); - for name in targets.iter().map(|e| e.name()) { + for name in targets.into_iter().map(|e| e.name()) { if !seen.insert(name.clone()) { bail!( "found duplicate {target_kind} name {name}, \ @@ -682,7 +868,7 @@ fn validate_unique_names(targets: &[TomlTarget], target_kind: &str) -> CargoResu Ok(()) } -fn configure(toml: &TomlTarget, target: &mut Target) { +fn configure(toml: &TomlTarget, cfg: Option, target: &mut Target) { let t2 = target.clone(); target .set_tested(toml.test.unwrap_or_else(|| t2.tested())) @@ -694,7 +880,8 @@ fn configure(toml: &TomlTarget, target: &mut Target) { (None, None) => t2.for_host(), (Some(true), _) | (_, Some(true)) => true, (Some(false), _) | (_, Some(false)) => false, - }); + }) + .set_platform(cfg.or_else(|| t2.platform().cloned())); } fn target_path( diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index bba6fd2639f..9b33b4f6521 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -4034,6 +4034,7 @@ fn compiler_json_error_format() { "kind":["lib"], "crate_types":["lib"], "name":"bar", + "platform":null, "src_path":"[..]lib.rs" }, "message":"{...}" @@ -4054,6 +4055,7 @@ fn compiler_json_error_format() { "kind":["lib"], "crate_types":["lib"], "name":"bar", + "platform":null, "src_path":"[..]lib.rs" }, "filenames":["[..].rlib"], @@ -4067,6 +4069,7 @@ fn compiler_json_error_format() { "kind":["bin"], "crate_types":["bin"], "name":"foo", + "platform":null, "src_path":"[..]main.rs" }, "message":"{...}" @@ -4079,6 +4082,7 @@ fn compiler_json_error_format() { "kind":["bin"], "crate_types":["bin"], "name":"foo", + "platform":null, "src_path":"[..]main.rs" }, "profile": { @@ -4120,6 +4124,7 @@ fn compiler_json_error_format() { "kind":["lib"], "crate_types":["lib"], "name":"bar", + "platform":null, "src_path":"[..]lib.rs" }, "filenames":["[..].rlib"], @@ -4133,6 +4138,7 @@ fn compiler_json_error_format() { "kind":["bin"], "crate_types":["bin"], "name":"foo", + "platform":null, "src_path":"[..]main.rs" }, "profile": { @@ -4192,6 +4198,7 @@ fn message_format_json_forward_stderr() { "kind":["bin"], "crate_types":["bin"], "name":"foo", + "platform":null, "src_path":"[..]" }, "message":"{...}" @@ -4204,6 +4211,7 @@ fn message_format_json_forward_stderr() { "kind":["bin"], "crate_types":["bin"], "name":"foo", + "platform":null, "src_path":"[..]" }, "profile":{ diff --git a/tests/testsuite/cargotest/support/mod.rs b/tests/testsuite/cargotest/support/mod.rs index 4ae3aeabc51..8895cc5eaf6 100644 --- a/tests/testsuite/cargotest/support/mod.rs +++ b/tests/testsuite/cargotest/support/mod.rs @@ -329,6 +329,10 @@ pub fn main_file(println: &str, deps: &[&str]) -> String { buf.to_string() } +pub fn bench_file() -> &'static str { + "" +} + trait ErrMsg { fn with_err_msg(self, val: String) -> Result; } diff --git a/tests/testsuite/cfg.rs b/tests/testsuite/cfg.rs index fa86db83630..61b7f025c0a 100644 --- a/tests/testsuite/cfg.rs +++ b/tests/testsuite/cfg.rs @@ -4,7 +4,7 @@ use std::fmt; use cargo::util::{Cfg, CfgExpr}; use cargotest::rustc_host; use cargotest::support::registry::Package; -use cargotest::support::{execs, project}; +use cargotest::support::{bench_file, execs, main_file, project}; use hamcrest::assert_that; macro_rules! c { @@ -490,3 +490,243 @@ fn cfg_looks_at_rustflags_for_target() { execs().with_status(0), ); } + +#[test] +fn target_cfg_bin() { + let p = project("target_cfg_bin") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [[target.'cfg(target_pointer_width = "1")'.bin]] + name = "never" + path = "src/never.rs" + + [[target.'cfg(not(target_pointer_width = "1"))'.bin]] + name = "always" + path = "src/always.rs" + "#, + ) + .file("src/main.rs", &main_file("\"main\"", &[])) + .file("src/never.rs", &main_file("\"never\"", &[])) + .file("src/always.rs", &main_file("\"always\"", &[])) + .build(); + + assert_that( + p.cargo("build").arg("-v"), + execs().with_status(0) + .with_stderr_contains("\ + [RUNNING] `rustc --crate-name always src[/]always.rs [..]") + .with_stderr_does_not_contain("\ + [RUNNING] `rustc --crate-name never src[/]never.rs [..]"), + ); +} + +#[test] +fn target_cfg_lib() { + let p = project("target_cfg_lib") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [target.'cfg(target_pointer_width = "1")'.lib] + name = "never" + path = "src/never.rs" + + [target.'cfg(not(target_pointer_width = "1"))'.lib] + name = "always" + path = "src/always.rs" + "#, + ) + .file("src/never.rs", "pub fn never() {{}}") + .file("src/always.rs", "pub fn always() {{}}") + .build(); + + assert_that( + p.cargo("build").arg("-v"), + execs().with_status(0) + .with_stderr_contains("\ + [RUNNING] `rustc --crate-name always src[/]always.rs [..]") + .with_stderr_does_not_contain("\ + [RUNNING] `rustc --crate-name never src[/]never.rs [..]"), + ); +} + +#[test] +fn target_cfg_example() { + let p = project("target_cfg_example") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [[target.'cfg(target_pointer_width = "1")'.example]] + name = "never" + path = "examples/never.rs" + + [[target.'cfg(not(target_pointer_width = "1"))'.example]] + name = "always" + path = "examples/always.rs" + "#, + ) + .file("src/main.rs", &main_file("\"main\"", &[])) + .file("examples/never.rs", &main_file("\"never\"", &[])) + .file("examples/always.rs", &main_file("\"always\"", &[])) + .build(); + + assert_that( + p.cargo("build").arg("--examples").arg("-v"), + execs().with_status(0) + .with_stderr_contains("\ + [RUNNING] `rustc --crate-name always examples[/]always.rs [..]") + .with_stderr_does_not_contain("\ + [RUNNING] `rustc --crate-name never examples[/]never.rs [..]"), + ); +} + +#[test] +fn target_cfg_bench() { + let p = project("target_cfg_bench") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [[target.'cfg(target_pointer_width = "1")'.bench]] + name = "never" + path = "benches/never.rs" + + [[target.'cfg(not(target_pointer_width = "1"))'.bench]] + name = "always" + path = "benches/always.rs" + "#, + ) + .file("src/main.rs", &main_file("\"main\"", &[])) + .file("benches/never.rs", bench_file()) + .file("benches/always.rs", bench_file()) + .build(); + + assert_that( + p.cargo("bench").arg("-v"), + execs().with_status(0) + .with_stderr_contains("\ + [RUNNING] `rustc --crate-name always benches[/]always.rs [..]") + .with_stderr_does_not_contain("\ + [RUNNING] `rustc --crate-name never benches[/]never.rs [..]"), + ); +} + +#[test] +fn target_cfg_test() { + let p = project("target_cfg_test") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [[target.'cfg(target_pointer_width = "1")'.test]] + name = "never" + path = "tests/never.rs" + + [[target.'cfg(not(target_pointer_width = "1"))'.test]] + name = "always" + path = "tests/always.rs" + "#, + ) + .file("src/main.rs", &main_file("\"main\"", &[])) + .file("tests/never.rs", "") + .file("tests/always.rs", "") + .build(); + + assert_that( + p.cargo("test").arg("-v"), + execs().with_status(0) + .with_stderr_contains("\ + [RUNNING] `rustc --crate-name always tests[/]always.rs [..]") + .with_stderr_does_not_contain("\ + [RUNNING] `rustc --crate-name never tests[/]never.rs [..]"), + ); +} + +#[test] +fn target_cfg_test_multiple() { + let p = project("target_cfg_test_multiple") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [[target.'cfg(not(target_pointer_width = "1"))'.test]] + name = "always1" + path = "tests/always.rs" + + [[target.'cfg(not(target_pointer_width = "2"))'.test]] + name = "always2" + path = "tests/always.rs" + "#, + ) + .file("src/main.rs", &main_file("\"main\"", &[])) + .file("tests/always.rs", "") + .build(); + + assert_that( + p.cargo("test").arg("-v"), + execs().with_status(0) + .with_stderr_contains("\ + [RUNNING] `rustc --crate-name always1 tests[/]always.rs [..]") + .with_stderr_contains("\ + [RUNNING] `rustc --crate-name always2 tests[/]always.rs [..]"), + ); +} + +#[test] +fn target_cfg_only_one_lib() { + let p = project("target_cfg_only_one_lib") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [target.'cfg(not(target_pointer_width = "1"))'.lib] + name = "lib1" + path = "src/lib1.rs" + + [target.'cfg(not(target_pointer_width = "2"))'.lib] + name = "lib2" + path = "src/lib2.rs" + "#, + ) + .file("src/lib1.rs", "pub fn hi() {{}}") + .file("src/lib2.rs", "pub fn hi() {{}}") + .build(); + + assert_that( + p.cargo("build").arg("-v"), + execs().with_status(101) + .with_stderr_contains("\ + [..] Can only have one [lib] [..]"), + ); +} diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index de0c0afb41d..e2e50c08479 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -41,6 +41,7 @@ fn cargo_metadata_simple() { "bin" ], "name": "foo", + "platform":null, "src_path": "[..][/]foo[/]src[/]foo.rs" } ], @@ -331,6 +332,7 @@ crate-type = ["lib", "staticlib"] "staticlib" ], "name": "foo", + "platform":null, "src_path": "[..][/]foo[/]src[/]lib.rs" } ], @@ -407,6 +409,7 @@ optional_feat = [] "lib" ], "name": "foo", + "platform":null, "src_path": "[..][/]foo[/]src[/]lib.rs" } ], @@ -503,6 +506,7 @@ fn cargo_metadata_with_deps_and_version() { "lib" ], "name": "baz", + "platform":null, "src_path": "[..]lib.rs" } ], @@ -545,6 +549,7 @@ fn cargo_metadata_with_deps_and_version() { "lib" ], "name": "bar", + "platform":null, "src_path": "[..]lib.rs" } ], @@ -587,6 +592,7 @@ fn cargo_metadata_with_deps_and_version() { "bin" ], "name": "foo", + "platform":null, "src_path": "[..]foo.rs" } ], @@ -685,12 +691,14 @@ name = "ex" "kind": [ "lib" ], "crate_types": [ "lib" ], "name": "foo", + "platform":null, "src_path": "[..][/]foo[/]src[/]lib.rs" }, { "kind": [ "example" ], "crate_types": [ "bin" ], "name": "ex", + "platform":null, "src_path": "[..][/]foo[/]examples[/]ex.rs" } ], @@ -765,12 +773,14 @@ crate-type = ["rlib", "dylib"] "kind": [ "lib" ], "crate_types": [ "lib" ], "name": "foo", + "platform":null, "src_path": "[..][/]foo[/]src[/]lib.rs" }, { "kind": [ "example" ], "crate_types": [ "rlib", "dylib" ], "name": "ex", + "platform":null, "src_path": "[..][/]foo[/]examples[/]ex.rs" } ], @@ -844,6 +854,7 @@ fn workspace_metadata() { "kind": [ "lib" ], "crate_types": [ "lib" ], "name": "bar", + "platform":null, "src_path": "[..]bar[/]src[/]lib.rs" } ], @@ -872,6 +883,7 @@ fn workspace_metadata() { "kind": [ "lib" ], "crate_types": [ "lib" ], "name": "baz", + "platform":null, "src_path": "[..]baz[/]src[/]lib.rs" } ], @@ -949,6 +961,7 @@ fn workspace_metadata_no_deps() { "kind": [ "lib" ], "crate_types": [ "lib" ], "name": "bar", + "platform":null, "src_path": "[..]bar[/]src[/]lib.rs" } ], @@ -977,6 +990,7 @@ fn workspace_metadata_no_deps() { "kind": [ "lib" ], "crate_types": ["lib"], "name": "baz", + "platform":null, "src_path": "[..]baz[/]src[/]lib.rs" } ], @@ -1031,6 +1045,7 @@ const MANIFEST_OUTPUT: &str = r#" "kind":["bin"], "crate_types":["bin"], "name":"foo", + "platform":null, "src_path":"[..][/]foo[/]src[/]foo.rs" }], "features":{}, @@ -1227,6 +1242,7 @@ fn package_metadata() { "kind": [ "lib" ], "crate_types": [ "lib" ], "name": "foo", + "platform": null, "src_path": "[..]foo[/]src[/]lib.rs" } ], diff --git a/tests/testsuite/read_manifest.rs b/tests/testsuite/read_manifest.rs index b3d512d8e70..9e524b9ba99 100644 --- a/tests/testsuite/read_manifest.rs +++ b/tests/testsuite/read_manifest.rs @@ -22,6 +22,7 @@ static MANIFEST_OUTPUT: &'static str = r#" "kind":["bin"], "crate_types":["bin"], "name":"foo", + "platform": null, "src_path":"[..][/]foo[/]src[/]foo.rs" }], "features":{}, diff --git a/tests/testsuite/test.rs b/tests/testsuite/test.rs index c48dbf2bb2c..817aacd07d2 100644 --- a/tests/testsuite/test.rs +++ b/tests/testsuite/test.rs @@ -4108,6 +4108,7 @@ fn json_artifact_includes_test_flag() { "kind":["lib"], "crate_types":["lib"], "name":"foo", + "platform":null, "src_path":"[..]lib.rs" }, "filenames":["[..].rlib"], @@ -4129,6 +4130,7 @@ fn json_artifact_includes_test_flag() { "kind":["lib"], "crate_types":["lib"], "name":"foo", + "platform":null, "src_path":"[..]lib.rs" }, "filenames":["[..][/]foo-[..]"],