Override target crate-type for cargo rustc --crate-type

Instead of writing override rules all over the compilation logic, this
commit simply override the unit created by `generate_targets`.
As a result, `cargo rustc --crate-type` behaves exactly as expected.
This commit is contained in:
Weihang Lo 2022-02-13 17:51:10 +08:00
parent 497051a743
commit b8336433a9
No known key found for this signature in database
GPG key ID: D7DBF189825E82E7
3 changed files with 55 additions and 45 deletions

View file

@ -33,9 +33,6 @@ pub struct BuildContext<'a, 'cfg> {
/// Extra compiler args for either `rustc` or `rustdoc`.
pub extra_compiler_args: HashMap<Unit, Vec<String>>,
// Crate types for `rustc`.
pub target_rustc_crate_types: HashMap<Unit, Vec<String>>,
/// Package downloader.
///
/// This holds ownership of the `Package` objects.
@ -64,7 +61,6 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
build_config: &'a BuildConfig,
profiles: Profiles,
extra_compiler_args: HashMap<Unit, Vec<String>>,
target_rustc_crate_types: HashMap<Unit, Vec<String>>,
target_data: RustcTargetData<'cfg>,
roots: Vec<Unit>,
unit_graph: UnitGraph,
@ -84,7 +80,6 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
build_config,
profiles,
extra_compiler_args,
target_rustc_crate_types,
target_data,
roots,
unit_graph,
@ -132,8 +127,4 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
pub fn extra_args_for(&self, unit: &Unit) -> Option<&Vec<String>> {
self.extra_compiler_args.get(unit)
}
pub fn rustc_crate_types_args_for(&self, unit: &Unit) -> Option<&Vec<String>> {
self.target_rustc_crate_types.get(unit)
}
}

View file

@ -890,18 +890,9 @@ fn build_base_args(
let mut contains_dy_lib = false;
if !test {
let mut crate_types = &crate_types
.iter()
.map(|t| t.as_str().to_string())
.collect::<Vec<String>>();
if let Some(types) = cx.bcx.rustc_crate_types_args_for(unit) {
crate_types = types;
}
for crate_type in crate_types.iter() {
cmd.arg("--crate-type").arg(crate_type);
if crate_type == CrateType::Dylib.as_str() {
contains_dy_lib = true;
}
for crate_type in crate_types {
cmd.arg("--crate-type").arg(crate_type.as_str());
contains_dy_lib |= crate_type == &CrateType::Dylib;
}
}

View file

@ -28,7 +28,7 @@ use std::sync::Arc;
use crate::core::compiler::unit_dependencies::{build_unit_dependencies, IsArtifact};
use crate::core::compiler::unit_graph::{self, UnitDep, UnitGraph};
use crate::core::compiler::{standard_lib, TargetInfo};
use crate::core::compiler::{standard_lib, CrateType, TargetInfo};
use crate::core::compiler::{BuildConfig, BuildContext, Compilation, Context};
use crate::core::compiler::{CompileKind, CompileMode, CompileTarget, RustcTargetData, Unit};
use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};
@ -505,6 +505,10 @@ pub fn create_bcx<'a, 'cfg>(
interner,
)?;
if let Some(args) = target_rustc_crate_types {
override_rustc_crate_types(&mut units, args, interner)?;
}
let mut scrape_units = match rustdoc_scrape_examples {
Some(arg) => {
let filter = match arg.as_str() {
@ -648,28 +652,6 @@ pub fn create_bcx<'a, 'cfg>(
}
}
let mut crate_types = HashMap::new();
if let Some(args) = target_rustc_crate_types {
if units.len() != 1 {
anyhow::bail!(
"crate types to rustc can only be passed to one \
target, consider filtering\nthe package by passing, \
e.g., `--lib` or `--example` to specify a single target"
);
}
match units[0].target.kind() {
TargetKind::Lib(_) | TargetKind::ExampleLib(_) => {
crate_types.insert(units[0].clone(), args.clone());
}
_ => {
anyhow::bail!(
"crate types can only be specified for libraries and example libraries.\n\
Binaries, tests, and benchmarks are always the `bin` crate type"
);
}
}
}
if honor_rust_version {
// Remove any pre-release identifiers for easier comparison
let current_version = &target_data.rustc.version;
@ -706,7 +688,6 @@ pub fn create_bcx<'a, 'cfg>(
build_config,
profiles,
extra_compiler_args,
crate_types,
target_data,
units,
unit_graph,
@ -1871,3 +1852,50 @@ fn remove_duplicate_doc(
}
unit_graph.retain(|unit, _| visited.contains(unit));
}
/// Override crate types for given units.
///
/// This is primarily used by `cargo rustc --crate-type`.
fn override_rustc_crate_types(
units: &mut [Unit],
args: &[String],
interner: &UnitInterner,
) -> CargoResult<()> {
if units.len() != 1 {
anyhow::bail!(
"crate types to rustc can only be passed to one \
target, consider filtering\nthe package by passing, \
e.g., `--lib` or `--example` to specify a single target"
);
}
let unit = &units[0];
let override_unit = |f: fn(Vec<CrateType>) -> TargetKind| {
let crate_types = args.iter().map(|s| s.into()).collect();
let mut target = unit.target.clone();
target.set_kind(f(crate_types));
interner.intern(
&unit.pkg,
&target,
unit.profile.clone(),
unit.kind,
unit.mode,
unit.features.clone(),
unit.is_std,
unit.dep_hash,
unit.artifact,
)
};
units[0] = match unit.target.kind() {
TargetKind::Lib(_) => override_unit(TargetKind::Lib),
TargetKind::ExampleLib(_) => override_unit(TargetKind::ExampleLib),
_ => {
anyhow::bail!(
"crate types can only be specified for libraries and example libraries.\n\
Binaries, tests, and benchmarks are always the `bin` crate type"
);
}
};
Ok(())
}