From 70bea01b870829dd00b9185a1dc4547d8d8b4664 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Sep 2019 10:13:59 -0700 Subject: [PATCH] Don't build libstd as a `dylib` This commit forcibly prevents Cargo from building the `std` crate as a `dylib`, even though libstd upstream lists a `dylib` crate type. We ideally want a first-class feature for doing this one day, but for now we can just hack around with the manifests to ensure that the `dylib` crate type never shows up. Note that this is only supported for libstd, and it's also all part of the unstable details of building std. Closes rust-lang/wg-cargo-std-aware#35 --- src/cargo/core/manifest.rs | 6 ++++++ src/cargo/core/package.rs | 9 +++++++++ src/cargo/ops/cargo_compile.rs | 37 ++++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index acda0e5700b..81593ea9364 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -463,6 +463,9 @@ impl Manifest { pub fn targets(&self) -> &[Target] { &self.targets } + pub fn targets_mut(&mut self) -> &mut [Target] { + &mut self.targets + } pub fn version(&self) -> &Version { self.package_id().version() } @@ -752,6 +755,9 @@ impl Target { pub fn kind(&self) -> &TargetKind { &self.kind } + pub fn kind_mut(&mut self) -> &mut TargetKind { + &mut self.kind + } pub fn tested(&self) -> bool { self.tested } diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index db6c36f5507..ec3c7faf8b9 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -464,6 +464,15 @@ impl<'cfg> PackageSet<'cfg> { let other_sources = set.sources.into_inner(); sources.add_source_map(other_sources); } + + /// Get mutable access to an already downloaded package, if it's already + /// downoaded and it's part of this set. Does not actually attempt to + /// download anything if it's not already downloaded. + pub fn lookup_mut(&mut self, id: PackageId) -> Option<&mut Package> { + self.packages + .get_mut(&id) + .and_then(|cell| cell.borrow_mut()) + } } // When dynamically linked against libcurl, we want to ignore some failures diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index cc49ef72204..e872d9409a7 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -35,7 +35,7 @@ use crate::core::compiler::{CompileMode, Kind, Unit}; use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner}; use crate::core::profiles::{Profiles, UnitFor}; use crate::core::resolver::{Resolve, ResolveOpts}; -use crate::core::{Package, Target}; +use crate::core::{LibKind, Package, PackageSet, Target}; use crate::core::{PackageId, PackageIdSpec, TargetKind, Workspace}; use crate::ops; use crate::util::config::Config; @@ -315,7 +315,8 @@ pub fn compile_ws<'a>( // requested_target to an enum, or some other approach. failure::bail!("-Zbuild-std requires --target"); } - let (std_package_set, std_resolve) = standard_lib::resolve_std(ws, crates)?; + let (mut std_package_set, std_resolve) = standard_lib::resolve_std(ws, crates)?; + remove_dylib_crate_type(&mut std_package_set)?; packages.add_set(std_package_set); Some(std_resolve) } else { @@ -988,3 +989,35 @@ fn filter_targets<'a>( } proposals } + +/// When using `-Zbuild-std` we're building the standard library, but a +/// technical detail of the standard library right now is that it builds itself +/// as both an `rlib` and a `dylib`. We don't actually want to really publicize +/// the `dylib` and in general it's a pain to work with, so when building libstd +/// we want to remove the `dylib` crate type. +/// +/// Cargo doesn't have a fantastic way of doing that right now, so let's hack +/// around it a bit and (ab)use the fact that we have mutable access to +/// `PackageSet` here to rewrite downloaded packages. We iterate over all `path` +/// packages (which should download immediately and not actually cause blocking +/// here) and edit their manifests to only list one `LibKind` for an `Rlib`. +fn remove_dylib_crate_type(set: &mut PackageSet<'_>) -> CargoResult<()> { + let ids = set + .package_ids() + .filter(|p| p.source_id().is_path()) + .collect::>(); + set.get_many(ids.iter().cloned())?; + + for id in ids { + let pkg = set.lookup_mut(id).expect("should be downloaded now"); + + for target in pkg.manifest_mut().targets_mut() { + if let TargetKind::Lib(crate_types) = target.kind_mut() { + crate_types.truncate(0); + crate_types.push(LibKind::Rlib); + } + } + } + + Ok(()) +}