Skip to content

Commit

Permalink
Don't build libstd as a dylib
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alexcrichton committed Sep 11, 2019
1 parent 651b1c5 commit 70bea01
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down Expand Up @@ -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
}
Expand Down
9 changes: 9 additions & 0 deletions src/cargo/core/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 35 additions & 2 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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::<Vec<_>>();
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(())
}

0 comments on commit 70bea01

Please sign in to comment.