From 229c48a0b9cc3b3e1a40d88f97018773dc6a6446 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 13 Feb 2022 17:33:30 +0800 Subject: [PATCH 1/3] Avoid assertion against default value in crate-type tests `--crate-type` usually defaults to `lib`, so the original assertion is somehow unuseful. Change to `cdylib` to make the test more robust. --- tests/testsuite/rustc.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/testsuite/rustc.rs b/tests/testsuite/rustc.rs index 43a158199af..f1e72c0a5c5 100644 --- a/tests/testsuite/rustc.rs +++ b/tests/testsuite/rustc.rs @@ -217,17 +217,14 @@ Binaries, tests, and benchmarks are always the `bin` crate type", #[cargo_test] fn build_with_crate_type_for_foo() { - let p = project() - .file("src/main.rs", "fn main() {}") - .file("src/lib.rs", r#" "#) - .build(); + let p = project().file("src/lib.rs", "").build(); - p.cargo("rustc -v --lib --crate-type lib -Zunstable-options") + p.cargo("rustc -v --crate-type cdylib -Zunstable-options") .masquerade_as_nightly_cargo() .with_stderr( "\ [COMPILING] foo v0.0.1 ([CWD]) -[RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type lib [..] +[RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type cdylib [..] [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", ) @@ -236,12 +233,9 @@ fn build_with_crate_type_for_foo() { #[cargo_test] fn build_with_crate_types_for_foo() { - let p = project() - .file("src/main.rs", "fn main() {}") - .file("src/lib.rs", r#" "#) - .build(); + let p = project().file("src/lib.rs", "").build(); - p.cargo("rustc -v --lib --crate-type lib,cdylib -Zunstable-options") + p.cargo("rustc -v --crate-type lib,cdylib -Zunstable-options") .masquerade_as_nightly_cargo() .with_stderr( "\ From 497051a7433022a80cbeeaac14ef3f258b763a1f Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 13 Feb 2022 17:42:12 +0800 Subject: [PATCH 2/3] New test for `cargo rustc --crate-type` with dependency --- tests/testsuite/rustc.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/testsuite/rustc.rs b/tests/testsuite/rustc.rs index f1e72c0a5c5..57cec8689a1 100644 --- a/tests/testsuite/rustc.rs +++ b/tests/testsuite/rustc.rs @@ -231,6 +231,46 @@ fn build_with_crate_type_for_foo() { .run(); } +#[cargo_test] +fn build_with_crate_type_for_foo_with_deps() { + let p = project() + .file( + "src/lib.rs", + r#" + extern crate a; + pub fn foo() { a::hello(); } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "pub fn hello() {}") + .build(); + + p.cargo("rustc -v --crate-type cdylib -Zunstable-options") + .masquerade_as_nightly_cargo() + .with_stderr( + "\ +[COMPILING] a v0.1.0 ([CWD]/a) +[RUNNING] `rustc --crate-name a a/src/lib.rs [..]--crate-type lib [..] +[COMPILING] foo v0.0.1 ([CWD]) +[RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type cdylib [..] +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", + ) + .run(); +} + #[cargo_test] fn build_with_crate_types_for_foo() { let p = project().file("src/lib.rs", "").build(); From b8336433a91f668d5514cf5f15d2fac97eea584d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 13 Feb 2022 17:51:10 +0800 Subject: [PATCH 3/3] 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. --- src/cargo/core/compiler/build_context/mod.rs | 9 --- src/cargo/core/compiler/mod.rs | 15 +--- src/cargo/ops/cargo_compile.rs | 76 +++++++++++++------- 3 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 9141314a9c7..624a6e88ae6 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -33,9 +33,6 @@ pub struct BuildContext<'a, 'cfg> { /// Extra compiler args for either `rustc` or `rustdoc`. pub extra_compiler_args: HashMap>, - // Crate types for `rustc`. - pub target_rustc_crate_types: HashMap>, - /// 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>, - target_rustc_crate_types: HashMap>, target_data: RustcTargetData<'cfg>, roots: Vec, 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> { self.extra_compiler_args.get(unit) } - - pub fn rustc_crate_types_args_for(&self, unit: &Unit) -> Option<&Vec> { - self.target_rustc_crate_types.get(unit) - } } diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 4be5034e666..90b126571a8 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -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::>(); - 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; } } diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 3b247c9f7a7..0dd03da81ee 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -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) -> 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(()) +}