Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow cfg(...)ing targets in Cargo.toml #5367

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/cargo/core/compiler/build_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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)
Expand Down
Empty file modified src/cargo/core/compiler/context/mod.rs
100644 → 100755
Empty file.
21 changes: 19 additions & 2 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Platform>,
}

#[derive(Clone, PartialEq, Eq, Debug)]
Expand All @@ -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 {
Expand All @@ -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)
}
}
Expand Down Expand Up @@ -417,6 +423,7 @@ impl Target {
for_host: false,
tested: true,
benched: true,
platform: None,
}
}

Expand Down Expand Up @@ -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
Expand All @@ -552,7 +565,7 @@ impl Target {

pub fn is_lib(&self) -> bool {
match self.kind {
TargetKind::Lib(_) => true,
TargetKind::Lib(..) => true,
_ => false,
}
}
Expand Down Expand Up @@ -659,6 +672,10 @@ impl Target {
self.doc = doc;
self
}
pub fn set_platform(&mut self, platform: Option<Platform>) -> &mut Target {
self.platform = platform;
self
}
}

impl fmt::Display for Target {
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/mod.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down
58 changes: 54 additions & 4 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
//! previously compiled dependency
//!

use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
use std::sync::Arc;

Expand Down Expand Up @@ -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,
Expand All @@ -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!(
Expand All @@ -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,
Expand All @@ -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::<Vec<_>>();

// Ensure that there is only one [lib] activated per crate.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where the unique [lib] checking happens, fwiw.

{
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)?
};

Expand Down
2 changes: 1 addition & 1 deletion src/cargo/util/errors.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
11 changes: 11 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
},
))
})
Expand Down Expand Up @@ -1373,6 +1378,12 @@ struct TomlPlatform {
dev_dependencies: Option<BTreeMap<String, TomlDependency>>,
#[serde(rename = "dev_dependencies")]
dev_dependencies2: Option<BTreeMap<String, TomlDependency>>,

lib: Option<TomlLibTarget>,
bin: Option<Vec<TomlBinTarget>>,
example: Option<Vec<TomlExampleTarget>>,
test: Option<Vec<TomlTestTarget>>,
bench: Option<Vec<TomlBenchTarget>>,
}

impl TomlTarget {
Expand Down
Loading