Skip to content

[Request for Experiment] Sysroot building functionalityΒ #4959

Open
@japaric

Description

@japaric

Summary

This RFE proposes adding Xargo's functionality of building a sysroot on the fly to Cargo as a nightly-only feature.

Motivation

Many (all?) no-std / embedded developers have to Install One More Tool because the ability to build core / std from source is missing in Cargo. Apart from the inconvenience, the Xargo wrapper is from for perfect: it can trigger unnecessary sysroot rebuilds because it doesn't replicate Cargo fingerprinting mechanism; it can sometimes fail to trigger a necessary sysroot rebuild (japaric/xargo#189); it doesn't track changes in the sysroot source code (japaric/xargo#139); and it doesn't understand the +nightly command line argument because it's not a rustup shim (japaric/xargo#123) among other deviations from the behavior users expect from a built-in Cargo subcommand.

Apart from all the issues Xargo also ties no-std / embedded development to the nightly channel. This experiment will hopefully be a first step towards enabling no-std / embedded development on the stable channel.

Implementation details

User interface: [sysroot]

A [sysroot] section will be added to Cargo configuration file:

# .cargo/config
[sysroot]
rust-src = "~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src"

[sysroot.core]
path = "libcore" # paths are relative to `rust-src` when not absolute
stage = 1 # see multi-stage builds section below

[sysroot.compiler_builtins]
git = "https://github.com/rust-lang-nursery/compiler-builtins"
features = ["mem"]
stage = 2

There the user can specify the crates that will be included in the sysroot. Only path and git dependencies are allowed. The [sysroot.rust-src] setting is a convenience that lets the user use relative paths.

Behavior

If a [sysroot] setting is found in Cargo configuration file:

Cargo will (re)build the sysroot crates for the target and place the build artifacts in $TARGET_DIR/sysroot/lib/rustlib/$TARGET before executing subcommands that involve invoking rustc or rustdoc. Then when invoking the actual subcommand Cargo will append the argument --sysroot=$TARGET_DIR/sysroot to all its rustc and rustdoc invocations except the ones used to build build scripts (build.rs).

The usual fingerprinting mechanism applies to the sysroot build: for example changes to [profile] in Cargo.toml and changes in the sysroot source code will trigger a sysroot rebuild.

The sysroot crates will always be built using the release profile to not regress the performance and binary size of dev builds when switching to builds that use [sysroot].

Multi-stage builds

There are crates in the std facade, like the test crate, that have implicit dependencies on other members of the facade. Building sysroots that include these crates require multi-stage builds.

In multi-stage builds the sysroot will be build as follows: all the crates in the first stage are build against the default sysroot; then all the crates in the second stage are build using the stage 1 artifacts as a custom sysroot (i.e. --sysroot is passed to rustc); then all the crates in the third stage are build using the stage 1 and 2 artifacts as a custom sysroot; the process continues until all stages are built; finally the artifacts of all the stages are placed in $TARGET_DIR/sysroot/lib/rustlib/$TARGET.

Potential additions / tweaks

Xargo doesn't require the user to specify a rust-src setting because it assumes that both rustup and the rust-src component are installed and it uses rustc --print sysroot to get the path to the Rust source. We could do the same here by either: (a) probing for the existence of rust-src and printing a helpful error message when it's not installed, or (b) committing to always ship rust-src with the toolchain.

Xargo always rebuilds the sysroot in release mode but we could have the Cargo implementation use the dev profile when --release is not passed to the subcommand.

Future steps

Revisit rust-lang/rfcs#1133 to see if there's a desire for the changes proposed there that aren't included in this RFE: eliminating the concept of the sysroot, versioning the crates in the std facade, etc.

UPDATE(2018-01-20): Don't pass --sysroot to rustc when building build scripts (build.rs). Those should be build against the default sysroot because they always run on the host. If the build scripts were to be build against the custom sysroot the sysroot would need to contain the rust-std artifacts of the host and that would require copying (or linking) those into $TARGET_DIR/sysroot/lib/rustlib/$HOST, which is a waste of space.


cc @alexcrichton @nrc @Ericson2314

Metadata

Metadata

Assignees

No one assigned

    Labels

    S-triageStatus: This issue is waiting on initial triage.Z-build-stdNightly: build-std

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions