2016-05-03 00:16:15 +02:00
|
|
|
//! Implementation of compiling various phases of the compiler and standard
|
|
|
|
//! library.
|
|
|
|
//!
|
|
|
|
//! This module contains some of the real meat in the rustbuild build system
|
|
|
|
//! which is where Cargo is used to compiler the standard library, libtest, and
|
|
|
|
//! compiler. This module is also responsible for assembling the sysroot as it
|
|
|
|
//! goes along from the output of the previous stage.
|
|
|
|
|
2018-03-15 18:58:02 +01:00
|
|
|
use std::borrow::Cow;
|
2017-05-27 19:19:43 +02:00
|
|
|
use std::env;
|
2018-11-16 22:22:06 +01:00
|
|
|
use std::fs;
|
2017-05-27 19:19:43 +02:00
|
|
|
use std::io::prelude::*;
|
2019-12-22 23:42:04 +01:00
|
|
|
use std::io::BufReader;
|
2015-11-20 00:20:12 +01:00
|
|
|
use std::path::{Path, PathBuf};
|
2019-12-22 23:42:04 +01:00
|
|
|
use std::process::{exit, Command, Stdio};
|
2017-05-27 19:19:43 +02:00
|
|
|
use std::str;
|
2015-11-20 00:20:12 +01:00
|
|
|
|
2019-08-11 19:00:32 +02:00
|
|
|
use build_helper::{output, t, up_to_date};
|
2016-09-13 06:46:35 +02:00
|
|
|
use filetime::FileTime;
|
2019-05-09 18:03:13 +02:00
|
|
|
use serde::Deserialize;
|
2015-11-20 00:20:12 +01:00
|
|
|
|
2019-09-09 19:17:38 +02:00
|
|
|
use crate::builder::Cargo;
|
2019-12-22 23:42:04 +01:00
|
|
|
use crate::dist;
|
2018-12-07 13:21:05 +01:00
|
|
|
use crate::native;
|
2020-04-01 03:00:52 +02:00
|
|
|
use crate::util::{exe, is_dylib, symlink_dir};
|
2019-12-22 23:42:04 +01:00
|
|
|
use crate::{Compiler, GitRepo, Mode};
|
2017-07-05 18:46:41 +02:00
|
|
|
|
2019-12-22 23:42:04 +01:00
|
|
|
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
|
|
|
|
use crate::cache::{Interned, INTERNER};
|
2015-11-20 00:20:12 +01:00
|
|
|
|
2018-03-10 15:01:06 +01:00
|
|
|
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
|
2017-07-14 02:48:44 +02:00
|
|
|
pub struct Std {
|
|
|
|
pub target: Interned<String>,
|
|
|
|
pub compiler: Compiler,
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
2017-03-13 19:36:44 +01:00
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
impl Step for Std {
|
2017-07-05 03:41:43 +02:00
|
|
|
type Output = ();
|
2017-07-05 14:41:27 +02:00
|
|
|
const DEFAULT: bool = true;
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
2019-08-27 17:32:21 +02:00
|
|
|
run.all_krates("test")
|
2017-07-05 14:41:27 +02:00
|
|
|
}
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn make_run(run: RunConfig<'_>) {
|
2017-07-21 01:51:07 +02:00
|
|
|
run.builder.ensure(Std {
|
|
|
|
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
|
|
|
target: run.target,
|
2017-07-14 02:48:44 +02:00
|
|
|
});
|
2017-07-05 14:41:27 +02:00
|
|
|
}
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Builds the standard library.
|
2017-07-05 03:41:43 +02:00
|
|
|
///
|
|
|
|
/// This will build the standard library for a particular stage of the build
|
|
|
|
/// using the `compiler` targeting the `target` architecture. The artifacts
|
|
|
|
/// created will also be linked into the sysroot directory.
|
2019-02-25 11:30:32 +01:00
|
|
|
fn run(self, builder: &Builder<'_>) {
|
2017-07-05 03:41:43 +02:00
|
|
|
let target = self.target;
|
|
|
|
let compiler = self.compiler;
|
2017-07-05 14:41:27 +02:00
|
|
|
|
2018-07-14 18:58:10 +02:00
|
|
|
if builder.config.keep_stage.contains(&compiler.stage) {
|
|
|
|
builder.info("Warning: Using a potentially old libstd. This may not behave well.");
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.ensure(StdLink { compiler, target_compiler: compiler, target });
|
2018-07-14 18:58:10 +02:00
|
|
|
return;
|
2018-07-03 00:04:58 +02:00
|
|
|
}
|
|
|
|
|
2019-10-12 16:01:59 +02:00
|
|
|
let mut target_deps = builder.ensure(StartupObjects { compiler, target });
|
2017-07-05 14:41:27 +02:00
|
|
|
|
2019-05-28 19:00:53 +02:00
|
|
|
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
|
|
|
|
if compiler_to_use != compiler {
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.ensure(Std { compiler: compiler_to_use, target });
|
2019-05-28 19:00:53 +02:00
|
|
|
builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target));
|
2017-08-22 23:24:29 +02:00
|
|
|
|
|
|
|
// Even if we're not building std this stage, the new sysroot must
|
2018-12-26 08:02:45 +01:00
|
|
|
// still contain the third party objects needed by various targets.
|
|
|
|
copy_third_party_objects(builder, &compiler, target);
|
2020-06-02 22:35:31 +02:00
|
|
|
copy_self_contained_objects(builder, &compiler, target);
|
2017-08-22 23:24:29 +02:00
|
|
|
|
2017-07-05 14:41:27 +02:00
|
|
|
builder.ensure(StdLink {
|
2019-05-28 19:00:53 +02:00
|
|
|
compiler: compiler_to_use,
|
2017-07-05 14:41:27 +02:00
|
|
|
target_compiler: compiler,
|
2017-08-07 07:54:09 +02:00
|
|
|
target,
|
2017-07-05 14:41:27 +02:00
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2019-10-12 16:01:59 +02:00
|
|
|
target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter());
|
2020-06-02 22:35:31 +02:00
|
|
|
target_deps.extend(copy_self_contained_objects(builder, &compiler, target));
|
2017-08-22 23:24:29 +02:00
|
|
|
|
2018-05-19 22:04:41 +02:00
|
|
|
let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
|
2020-04-19 13:17:38 +02:00
|
|
|
std_cargo(builder, target, compiler.stage, &mut cargo);
|
2018-03-16 16:35:03 +01:00
|
|
|
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.info(&format!(
|
|
|
|
"Building stage{} std artifacts ({} -> {})",
|
|
|
|
compiler.stage, &compiler.host, target
|
|
|
|
));
|
|
|
|
run_cargo(
|
|
|
|
builder,
|
|
|
|
cargo,
|
|
|
|
vec![],
|
|
|
|
&libstd_stamp(builder, compiler, target),
|
|
|
|
target_deps,
|
|
|
|
false,
|
|
|
|
);
|
2017-07-05 14:41:27 +02:00
|
|
|
|
|
|
|
builder.ensure(StdLink {
|
2018-04-15 01:27:57 +02:00
|
|
|
compiler: builder.compiler(compiler.stage, builder.config.build),
|
2017-07-05 14:41:27 +02:00
|
|
|
target_compiler: compiler,
|
2017-08-07 07:54:09 +02:00
|
|
|
target,
|
2017-07-05 14:41:27 +02:00
|
|
|
});
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
2016-02-25 08:50:32 +01:00
|
|
|
}
|
|
|
|
|
2020-06-02 22:35:31 +02:00
|
|
|
fn copy_and_stamp(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
libdir: &Path,
|
|
|
|
sourcedir: &Path,
|
|
|
|
name: &str,
|
|
|
|
target_deps: &mut Vec<PathBuf>,
|
|
|
|
) {
|
|
|
|
let target = libdir.join(name);
|
|
|
|
builder.copy(&sourcedir.join(name), &target);
|
|
|
|
|
|
|
|
target_deps.push((target, dependency_type));
|
|
|
|
}
|
|
|
|
|
2019-11-27 04:19:54 +01:00
|
|
|
/// Copies third party objects needed by various targets.
|
2019-12-22 23:42:04 +01:00
|
|
|
fn copy_third_party_objects(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
compiler: &Compiler,
|
|
|
|
target: Interned<String>,
|
|
|
|
) -> Vec<PathBuf> {
|
2018-12-26 08:02:45 +01:00
|
|
|
let libdir = builder.sysroot_libdir(*compiler, target);
|
2019-10-12 16:01:59 +02:00
|
|
|
let mut target_deps = vec![];
|
|
|
|
|
2020-03-06 12:13:55 +01:00
|
|
|
// Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
|
2018-12-26 08:02:45 +01:00
|
|
|
//
|
|
|
|
// This target needs to be linked to Fortanix's port of llvm's libunwind.
|
|
|
|
// libunwind requires support for rwlock and printing to stderr,
|
|
|
|
// which is provided by std for this target.
|
|
|
|
if target == "x86_64-fortanix-unknown-sgx" {
|
|
|
|
let src_path_env = "X86_FORTANIX_SGX_LIBS";
|
2020-02-03 20:13:30 +01:00
|
|
|
let src =
|
|
|
|
env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env));
|
2020-06-02 22:35:31 +02:00
|
|
|
copy_and_stamp(
|
|
|
|
builder,
|
|
|
|
&*libdir,
|
|
|
|
Path::new(&src),
|
|
|
|
"libunwind.a",
|
|
|
|
&mut target_deps,
|
|
|
|
);
|
2017-08-22 23:24:29 +02:00
|
|
|
}
|
2019-10-12 16:01:59 +02:00
|
|
|
|
2019-11-07 01:00:00 +01:00
|
|
|
if builder.config.sanitizers && compiler.stage != 0 {
|
|
|
|
// The sanitizers are only copied in stage1 or above,
|
|
|
|
// to avoid creating dependency on LLVM.
|
|
|
|
target_deps.extend(copy_sanitizers(builder, &compiler, target));
|
|
|
|
}
|
|
|
|
|
2019-10-12 16:01:59 +02:00
|
|
|
target_deps
|
2017-08-22 23:24:29 +02:00
|
|
|
}
|
|
|
|
|
2020-06-02 22:35:31 +02:00
|
|
|
/// Copies third party objects needed by various targets for self-contained linkage.
|
|
|
|
fn copy_self_contained_objects(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
compiler: &Compiler,
|
|
|
|
target: Interned<String>,
|
|
|
|
) -> Vec<PathBuf> {
|
|
|
|
let libdir = builder.sysroot_libdir(*compiler, target);
|
|
|
|
let mut target_deps = vec![];
|
|
|
|
|
|
|
|
// Copies the CRT objects.
|
|
|
|
//
|
|
|
|
// rustc historically provides a more self-contained installation for musl targets
|
|
|
|
// not requiring the presence of a native musl toolchain. For example, it can fall back
|
|
|
|
// to using gcc from a glibc-targeting toolchain for linking.
|
|
|
|
// To do that we have to distribute musl startup objects as a part of Rust toolchain
|
|
|
|
// and link with them manually in the self-contained mode.
|
|
|
|
if target.contains("musl") {
|
|
|
|
let srcdir = builder.musl_root(target).unwrap().join("lib");
|
|
|
|
for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
|
|
|
|
copy_and_stamp(
|
|
|
|
builder,
|
|
|
|
&libdir_self_contained,
|
|
|
|
&srcdir,
|
|
|
|
obj,
|
|
|
|
&mut target_deps,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else if target.ends_with("-wasi") {
|
|
|
|
let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
|
|
|
|
copy_and_stamp(
|
|
|
|
builder,
|
|
|
|
&libdir_self_contained,
|
|
|
|
&srcdir,
|
|
|
|
"crt1.o",
|
|
|
|
&mut target_deps,
|
|
|
|
);
|
2020-06-02 23:18:41 +02:00
|
|
|
} else if target.contains("windows-gnu") {
|
|
|
|
for obj in ["crt2.o", "dllcrt2.o"].iter() {
|
|
|
|
let src = compiler_file(builder, builder.cc(target), target, obj);
|
|
|
|
let target = libdir.join(obj);
|
|
|
|
builder.copy(&src, &target);
|
|
|
|
target_deps.push(target);
|
|
|
|
}
|
2020-06-02 22:35:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
target_deps
|
|
|
|
}
|
|
|
|
|
2017-07-17 18:32:08 +02:00
|
|
|
/// Configure cargo to compile the standard library, adding appropriate env vars
|
|
|
|
/// and such.
|
2020-04-19 13:17:38 +02:00
|
|
|
pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, stage: u32, cargo: &mut Cargo) {
|
2017-07-17 18:32:08 +02:00
|
|
|
if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
|
|
|
|
cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
|
|
|
|
}
|
|
|
|
|
2019-05-20 20:00:34 +02:00
|
|
|
// Determine if we're going to compile in optimized C intrinsics to
|
|
|
|
// the `compiler-builtins` crate. These intrinsics live in LLVM's
|
|
|
|
// `compiler-rt` repository, but our `src/llvm-project` submodule isn't
|
|
|
|
// always checked out, so we need to conditionally look for this. (e.g. if
|
|
|
|
// an external LLVM is used we skip the LLVM submodule checkout).
|
|
|
|
//
|
|
|
|
// Note that this shouldn't affect the correctness of `compiler-builtins`,
|
|
|
|
// but only its speed. Some intrinsics in C haven't been translated to Rust
|
|
|
|
// yet but that's pretty rare. Other intrinsics have optimized
|
|
|
|
// implementations in C which have only had slower versions ported to Rust,
|
|
|
|
// so we favor the C version where we can, but it's not critical.
|
|
|
|
//
|
|
|
|
// If `compiler-rt` is available ensure that the `c` feature of the
|
|
|
|
// `compiler-builtins` crate is enabled and it's configured to learn where
|
|
|
|
// `compiler-rt` is located.
|
|
|
|
let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
|
|
|
|
let compiler_builtins_c_feature = if compiler_builtins_root.exists() {
|
2020-04-10 22:42:19 +02:00
|
|
|
// Note that `libprofiler_builtins/build.rs` also computes this so if
|
|
|
|
// you're changing something here please also change that.
|
2019-05-20 20:00:34 +02:00
|
|
|
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
|
|
|
|
" compiler-builtins-c".to_string()
|
|
|
|
} else {
|
|
|
|
String::new()
|
|
|
|
};
|
|
|
|
|
2018-04-15 01:27:57 +02:00
|
|
|
if builder.no_std(target) == Some(true) {
|
2019-05-20 20:00:34 +02:00
|
|
|
let mut features = "compiler-builtins-mem".to_string();
|
|
|
|
features.push_str(&compiler_builtins_c_feature);
|
|
|
|
|
2018-04-04 22:42:56 +02:00
|
|
|
// for no-std targets we only compile a few no_std crates
|
std: Depend directly on crates.io crates
Ever since we added a Cargo-based build system for the compiler the
standard library has always been a little special, it's never been able
to depend on crates.io crates for runtime dependencies. This has been a
result of various limitations, namely that Cargo doesn't understand that
crates from crates.io depend on libcore, so Cargo tries to build crates
before libcore is finished.
I had an idea this afternoon, however, which lifts the strategy
from #52919 to directly depend on crates.io crates from the standard
library. After all is said and done this removes a whopping three
submodules that we need to manage!
The basic idea here is that for any crate `std` depends on it adds an
*optional* dependency on an empty crate on crates.io, in this case named
`rustc-std-workspace-core`. This crate is overridden via `[patch]` in
this repository to point to a local crate we write, and *that* has a
`path` dependency on libcore.
Note that all `no_std` crates also depend on `compiler_builtins`, but if
we're not using submodules we can publish `compiler_builtins` to
crates.io and all crates can depend on it anyway! The basic strategy
then looks like:
* The standard library (or some transitive dep) decides to depend on a
crate `foo`.
* The standard library adds
```toml
[dependencies]
foo = { version = "0.1", features = ['rustc-dep-of-std'] }
```
* The crate `foo` has an optional dependency on `rustc-std-workspace-core`
* The crate `foo` has an optional dependency on `compiler_builtins`
* The crate `foo` has a feature `rustc-dep-of-std` which activates these
crates and any other necessary infrastructure in the crate.
A sample commit for `dlmalloc` [turns out to be quite simple][commit].
After that all `no_std` crates should largely build "as is" and still be
publishable on crates.io! Notably they should be able to continue to use
stable Rust if necessary, since the `rename-dependency` feature of Cargo
is soon stabilizing.
As a proof of concept, this commit removes the `dlmalloc`,
`libcompiler_builtins`, and `libc` submodules from this repository. Long
thorns in our side these are now gone for good and we can directly
depend on crates.io! It's hoped that in the long term we can bring in
other crates as necessary, but for now this is largely intended to
simply make it easier to manage these crates and remove submodules.
This should be a transparent non-breaking change for all users, but one
possible stickler is that this almost for sure breaks out-of-tree
`std`-building tools like `xargo` and `cargo-xbuild`. I think it should
be relatively easy to get them working, however, as all that's needed is
an entry in the `[patch]` section used to build the standard library.
Hopefully we can work with these tools to solve this problem!
[commit]: https://github.com/alexcrichton/dlmalloc-rs/commit/28ee12db813a3b650a7c25d1c36d2c17dcb88ae3
2018-11-20 06:52:50 +01:00
|
|
|
cargo
|
2018-04-04 22:42:56 +02:00
|
|
|
.args(&["-p", "alloc"])
|
2018-04-04 22:23:33 +02:00
|
|
|
.arg("--manifest-path")
|
2018-12-14 18:05:31 +01:00
|
|
|
.arg(builder.src.join("src/liballoc/Cargo.toml"))
|
|
|
|
.arg("--features")
|
2019-05-14 23:43:43 +02:00
|
|
|
.arg("compiler-builtins-mem compiler-builtins-c");
|
2018-04-01 18:50:21 +02:00
|
|
|
} else {
|
2019-05-20 20:00:34 +02:00
|
|
|
let mut features = builder.std_features();
|
|
|
|
features.push_str(&compiler_builtins_c_feature);
|
2017-07-17 18:32:08 +02:00
|
|
|
|
2019-12-22 23:42:04 +01:00
|
|
|
cargo
|
|
|
|
.arg("--features")
|
|
|
|
.arg(features)
|
2018-04-01 18:50:21 +02:00
|
|
|
.arg("--manifest-path")
|
bootstrap: Merge the libtest build step with libstd
Since its inception rustbuild has always worked in three stages: one for
libstd, one for libtest, and one for rustc. These three stages were
architected around crates.io dependencies, where rustc wants to depend
on crates.io crates but said crates don't explicitly depend on libstd,
requiring a sysroot assembly step in the middle. This same logic was
applied for libtest where libtest wants to depend on crates.io crates
(`getopts`) but `getopts` didn't say that it depended on std, so it
needed `std` built ahead of time.
Lots of time has passed since the inception of rustbuild, however,
and we've since gotten to the point where even `std` itself is depending
on crates.io crates (albeit with some wonky configuration). This
commit applies the same logic to the two dependencies that the `test`
crate pulls in from crates.io, `getopts` and `unicode-width`. Over the
many years since rustbuild's inception `unicode-width` was the only
dependency picked up by the `test` crate, so the extra configuration
necessary to get crates building in this crate graph is unlikely to be
too much of a burden on developers.
After this patch it means that there are now only two build phasese of
rustbuild, one for libstd and one for rustc. The libtest/libproc_macro
build phase is all lumped into one now with `std`.
This was originally motivated by rust-lang/cargo#7216 where Cargo was
having to deal with synthesizing dependency edges but this commit makes
them explicit in this repository.
2019-08-16 17:29:08 +02:00
|
|
|
.arg(builder.src.join("src/libtest/Cargo.toml"));
|
2017-07-17 18:32:08 +02:00
|
|
|
|
2019-09-09 19:21:15 +02:00
|
|
|
// Help the libc crate compile by assisting it in finding various
|
|
|
|
// sysroot native libraries.
|
2018-04-01 18:50:21 +02:00
|
|
|
if target.contains("musl") {
|
2018-04-15 01:27:57 +02:00
|
|
|
if let Some(p) = builder.musl_root(target) {
|
2019-09-09 19:21:15 +02:00
|
|
|
let root = format!("native={}/lib", p.to_str().unwrap());
|
|
|
|
cargo.rustflag("-L").rustflag(&root);
|
2018-04-01 18:50:21 +02:00
|
|
|
}
|
2017-07-17 18:32:08 +02:00
|
|
|
}
|
Add a new wasm32-unknown-wasi target
This commit adds a new wasm32-based target distributed through rustup,
supported in the standard library, and implemented in the compiler. The
`wasm32-unknown-wasi` target is intended to be a WebAssembly target
which matches the [WASI proposal recently announced.][LINK]. In summary
the WASI target is an effort to define a standard set of syscalls for
WebAssembly modules, allowing WebAssembly modules to not only be
portable across architectures but also be portable across environments
implementing this standard set of system calls.
The wasi target in libstd is still somewhat bare bones. This PR does not
fill out the filesystem, networking, threads, etc. Instead it only
provides the most basic of integration with the wasi syscalls, enabling
features like:
* `Instant::now` and `SystemTime::now` work
* `env::args` is hooked up
* `env::vars` will look up environment variables
* `println!` will print to standard out
* `process::{exit, abort}` should be hooked up appropriately
None of these APIs can work natively on the `wasm32-unknown-unknown`
target, but with the assumption of the WASI set of syscalls we're able
to provide implementations of these syscalls that engines can implement.
Currently the primary engine implementing wasi is [wasmtime], but more
will surely emerge!
In terms of future development of libstd, I think this is something
we'll probably want to discuss. The purpose of the WASI target is to
provide a standardized set of syscalls, but it's *also* to provide a
standard C sysroot for compiling C/C++ programs. This means it's
intended that functions like `read` and `write` are implemented for this
target with a relatively standard definition and implementation. It's
unclear, therefore, how we want to expose file descriptors and how we'll
want to implement system primitives. For example should `std::fs::File`
have a libc-based file descriptor underneath it? The raw wasi file
descriptor? We'll see! Currently these details are all intentionally
hidden and things we can change over time.
A `WasiFd` sample struct was added to the standard library as part of
this commit, but it's not currently used. It shows how all the wasi
syscalls could be ergonomically bound in Rust, and they offer a possible
implementation of primitives like `std::fs::File` if we bind wasi file
descriptors exactly.
Apart from the standard library, there's also the matter of how this
target is integrated with respect to its C standard library. The
reference sysroot, for example, provides managment of standard unix file
descriptors and also standard APIs like `open` (as opposed to the
relative `openat` inspiration for the wasi ssycalls). Currently the
standard library relies on the C sysroot symbols for operations such as
environment management, process exit, and `read`/`write` of stdio fds.
We want these operations in Rust to be interoperable with C if they're
used in the same process. Put another way, if Rust and C are linked into
the same WebAssembly binary they should work together, but that requires
that the same C standard library is used.
We also, however, want the `wasm32-unknown-wasi` target to be
usable-by-default with the Rust compiler without requiring a separate
toolchain to get downloaded and configured. With that in mind, there's
two modes of operation for the `wasm32-unknown-wasi` target:
1. By default the C standard library is statically provided inside of
`liblibc.rlib` distributed as part of the sysroot. This means that
you can `rustc foo.wasm --target wasm32-unknown-unknown` and you're
good to go, a fully workable wasi binary pops out. This is
incompatible with linking in C code, however, which may be compiled
against a different sysroot than the Rust code was previously
compiled against. In this mode the default of `rust-lld` is used to
link binaries.
2. For linking with C code, the `-C target-feature=-crt-static` flag
needs to be passed. This takes inspiration from the musl target for
this flag, but the idea is that you're no longer using the provided
static C runtime, but rather one will be provided externally. This
flag is intended to also get coupled with an external `clang`
compiler configured with its own sysroot. Therefore you'll typically
use this flag with `-C linker=/path/to/clang-script-wrapper`. Using
this mode the Rust code will continue to reference standard C
symbols, but the definition will be pulled in by the linker configured.
Alright so that's all the current state of this PR. I suspect we'll
definitely want to discuss this before landing of course! This PR is
coupled with libc changes as well which I'll be posting shortly.
[LINK]:
[wasmtime]:
2019-02-13 19:02:22 +01:00
|
|
|
|
|
|
|
if target.ends_with("-wasi") {
|
|
|
|
if let Some(p) = builder.wasi_root(target) {
|
2019-09-09 19:21:15 +02:00
|
|
|
let root = format!("native={}/lib/wasm32-wasi", p.to_str().unwrap());
|
|
|
|
cargo.rustflag("-L").rustflag(&root);
|
Add a new wasm32-unknown-wasi target
This commit adds a new wasm32-based target distributed through rustup,
supported in the standard library, and implemented in the compiler. The
`wasm32-unknown-wasi` target is intended to be a WebAssembly target
which matches the [WASI proposal recently announced.][LINK]. In summary
the WASI target is an effort to define a standard set of syscalls for
WebAssembly modules, allowing WebAssembly modules to not only be
portable across architectures but also be portable across environments
implementing this standard set of system calls.
The wasi target in libstd is still somewhat bare bones. This PR does not
fill out the filesystem, networking, threads, etc. Instead it only
provides the most basic of integration with the wasi syscalls, enabling
features like:
* `Instant::now` and `SystemTime::now` work
* `env::args` is hooked up
* `env::vars` will look up environment variables
* `println!` will print to standard out
* `process::{exit, abort}` should be hooked up appropriately
None of these APIs can work natively on the `wasm32-unknown-unknown`
target, but with the assumption of the WASI set of syscalls we're able
to provide implementations of these syscalls that engines can implement.
Currently the primary engine implementing wasi is [wasmtime], but more
will surely emerge!
In terms of future development of libstd, I think this is something
we'll probably want to discuss. The purpose of the WASI target is to
provide a standardized set of syscalls, but it's *also* to provide a
standard C sysroot for compiling C/C++ programs. This means it's
intended that functions like `read` and `write` are implemented for this
target with a relatively standard definition and implementation. It's
unclear, therefore, how we want to expose file descriptors and how we'll
want to implement system primitives. For example should `std::fs::File`
have a libc-based file descriptor underneath it? The raw wasi file
descriptor? We'll see! Currently these details are all intentionally
hidden and things we can change over time.
A `WasiFd` sample struct was added to the standard library as part of
this commit, but it's not currently used. It shows how all the wasi
syscalls could be ergonomically bound in Rust, and they offer a possible
implementation of primitives like `std::fs::File` if we bind wasi file
descriptors exactly.
Apart from the standard library, there's also the matter of how this
target is integrated with respect to its C standard library. The
reference sysroot, for example, provides managment of standard unix file
descriptors and also standard APIs like `open` (as opposed to the
relative `openat` inspiration for the wasi ssycalls). Currently the
standard library relies on the C sysroot symbols for operations such as
environment management, process exit, and `read`/`write` of stdio fds.
We want these operations in Rust to be interoperable with C if they're
used in the same process. Put another way, if Rust and C are linked into
the same WebAssembly binary they should work together, but that requires
that the same C standard library is used.
We also, however, want the `wasm32-unknown-wasi` target to be
usable-by-default with the Rust compiler without requiring a separate
toolchain to get downloaded and configured. With that in mind, there's
two modes of operation for the `wasm32-unknown-wasi` target:
1. By default the C standard library is statically provided inside of
`liblibc.rlib` distributed as part of the sysroot. This means that
you can `rustc foo.wasm --target wasm32-unknown-unknown` and you're
good to go, a fully workable wasi binary pops out. This is
incompatible with linking in C code, however, which may be compiled
against a different sysroot than the Rust code was previously
compiled against. In this mode the default of `rust-lld` is used to
link binaries.
2. For linking with C code, the `-C target-feature=-crt-static` flag
needs to be passed. This takes inspiration from the musl target for
this flag, but the idea is that you're no longer using the provided
static C runtime, but rather one will be provided externally. This
flag is intended to also get coupled with an external `clang`
compiler configured with its own sysroot. Therefore you'll typically
use this flag with `-C linker=/path/to/clang-script-wrapper`. Using
this mode the Rust code will continue to reference standard C
symbols, but the definition will be pulled in by the linker configured.
Alright so that's all the current state of this PR. I suspect we'll
definitely want to discuss this before landing of course! This PR is
coupled with libc changes as well which I'll be posting shortly.
[LINK]:
[wasmtime]:
2019-02-13 19:02:22 +01:00
|
|
|
}
|
|
|
|
}
|
2017-07-17 18:32:08 +02:00
|
|
|
}
|
2020-04-19 13:17:38 +02:00
|
|
|
|
2020-04-30 19:53:16 +02:00
|
|
|
// By default, rustc uses `-Cembed-bitcode=yes`, and Cargo overrides that
|
|
|
|
// with `-Cembed-bitcode=no` for non-LTO builds. However, libstd must be
|
2020-04-19 13:17:38 +02:00
|
|
|
// built with bitcode so that the produced rlibs can be used for both LTO
|
|
|
|
// builds (which use bitcode) and non-LTO builds (which use object code).
|
|
|
|
// So we override the override here!
|
|
|
|
//
|
|
|
|
// But we don't bother for the stage 0 compiler because it's never used
|
|
|
|
// with LTO.
|
|
|
|
if stage >= 1 {
|
2020-04-30 19:53:16 +02:00
|
|
|
cargo.rustflag("-Cembed-bitcode=yes");
|
2020-04-19 13:17:38 +02:00
|
|
|
}
|
2017-07-17 18:32:08 +02:00
|
|
|
}
|
2017-07-05 01:53:53 +02:00
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
struct StdLink {
|
|
|
|
pub compiler: Compiler,
|
|
|
|
pub target_compiler: Compiler,
|
|
|
|
pub target: Interned<String>,
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
impl Step for StdLink {
|
2017-07-05 03:41:43 +02:00
|
|
|
type Output = ();
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
2017-07-19 02:03:38 +02:00
|
|
|
run.never()
|
2017-07-14 14:30:16 +02:00
|
|
|
}
|
|
|
|
|
2017-07-05 03:41:43 +02:00
|
|
|
/// Link all libstd rlibs/dylibs into the sysroot location.
|
|
|
|
///
|
2018-11-11 14:52:36 +01:00
|
|
|
/// Links those artifacts generated by `compiler` to the `stage` compiler's
|
2017-07-05 03:41:43 +02:00
|
|
|
/// sysroot for the specified `host` and `target`.
|
|
|
|
///
|
|
|
|
/// Note that this assumes that `compiler` has already generated the libstd
|
|
|
|
/// libraries for `target`, and this method will find them in the relevant
|
|
|
|
/// output directory.
|
2019-02-25 11:30:32 +01:00
|
|
|
fn run(self, builder: &Builder<'_>) {
|
2017-07-05 03:41:43 +02:00
|
|
|
let compiler = self.compiler;
|
|
|
|
let target_compiler = self.target_compiler;
|
|
|
|
let target = self.target;
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.info(&format!(
|
|
|
|
"Copying stage{} std from stage{} ({} -> {} / {})",
|
|
|
|
target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target
|
|
|
|
));
|
2017-07-05 18:46:41 +02:00
|
|
|
let libdir = builder.sysroot_libdir(target_compiler, target);
|
2018-12-02 21:47:41 +01:00
|
|
|
let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
|
|
|
|
add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
|
2017-04-17 22:22:16 +02:00
|
|
|
}
|
2016-03-06 14:19:51 +01:00
|
|
|
}
|
|
|
|
|
2019-11-07 01:00:00 +01:00
|
|
|
/// Copies sanitizer runtime libraries into target libdir.
|
|
|
|
fn copy_sanitizers(
|
2019-02-25 11:30:32 +01:00
|
|
|
builder: &Builder<'_>,
|
2019-11-07 01:00:00 +01:00
|
|
|
compiler: &Compiler,
|
|
|
|
target: Interned<String>,
|
|
|
|
) -> Vec<PathBuf> {
|
|
|
|
let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
|
|
|
|
|
|
|
|
if builder.config.dry_run {
|
|
|
|
return Vec::new();
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut target_deps = Vec::new();
|
|
|
|
let libdir = builder.sysroot_libdir(*compiler, target);
|
|
|
|
|
|
|
|
for runtime in &runtimes {
|
|
|
|
let dst = libdir.join(&runtime.name);
|
|
|
|
builder.copy(&runtime.path, &dst);
|
|
|
|
|
|
|
|
if target == "x86_64-apple-darwin" {
|
|
|
|
// Update the library install name reflect the fact it has been renamed.
|
|
|
|
let status = Command::new("install_name_tool")
|
|
|
|
.arg("-id")
|
|
|
|
.arg(format!("@rpath/{}", runtime.name))
|
|
|
|
.arg(&dst)
|
|
|
|
.status()
|
|
|
|
.expect("failed to execute `install_name_tool`");
|
|
|
|
assert!(status.success());
|
|
|
|
}
|
|
|
|
|
|
|
|
target_deps.push(dst);
|
2017-04-17 22:22:16 +02:00
|
|
|
}
|
2019-11-07 01:00:00 +01:00
|
|
|
|
|
|
|
target_deps
|
2017-04-17 22:22:16 +02:00
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub struct StartupObjects {
|
|
|
|
pub compiler: Compiler,
|
|
|
|
pub target: Interned<String>,
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
2016-12-30 03:17:31 +01:00
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
impl Step for StartupObjects {
|
2019-10-12 16:01:59 +02:00
|
|
|
type Output = Vec<PathBuf>;
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
2017-07-19 02:03:38 +02:00
|
|
|
run.path("src/rtstartup")
|
2017-07-05 14:41:27 +02:00
|
|
|
}
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn make_run(run: RunConfig<'_>) {
|
2017-07-21 01:51:07 +02:00
|
|
|
run.builder.ensure(StartupObjects {
|
|
|
|
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
|
|
|
target: run.target,
|
2017-07-14 02:48:44 +02:00
|
|
|
});
|
2017-07-05 14:41:27 +02:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Builds and prepare startup objects like rsbegin.o and rsend.o
|
2017-07-05 03:41:43 +02:00
|
|
|
///
|
|
|
|
/// These are primarily used on Windows right now for linking executables/dlls.
|
|
|
|
/// They don't require any library support as they're just plain old object
|
|
|
|
/// files, so we just use the nightly snapshot compiler to always build them (as
|
|
|
|
/// no other compilers are guaranteed to be available).
|
2019-10-12 16:01:59 +02:00
|
|
|
fn run(self, builder: &Builder<'_>) -> Vec<PathBuf> {
|
2017-07-05 18:46:41 +02:00
|
|
|
let for_compiler = self.compiler;
|
2017-07-05 03:41:43 +02:00
|
|
|
let target = self.target;
|
2019-05-27 16:32:00 +02:00
|
|
|
if !target.contains("windows-gnu") {
|
2019-12-22 23:42:04 +01:00
|
|
|
return vec![];
|
2017-02-18 18:10:01 +01:00
|
|
|
}
|
|
|
|
|
2019-10-12 16:01:59 +02:00
|
|
|
let mut target_deps = vec![];
|
|
|
|
|
2018-04-15 01:27:57 +02:00
|
|
|
let src_dir = &builder.src.join("src/rtstartup");
|
|
|
|
let dst_dir = &builder.native_dir(target).join("rtstartup");
|
2017-07-05 18:46:41 +02:00
|
|
|
let sysroot_dir = &builder.sysroot_libdir(for_compiler, target);
|
2017-07-05 03:41:43 +02:00
|
|
|
t!(fs::create_dir_all(dst_dir));
|
|
|
|
|
|
|
|
for file in &["rsbegin", "rsend"] {
|
|
|
|
let src_file = &src_dir.join(file.to_string() + ".rs");
|
|
|
|
let dst_file = &dst_dir.join(file.to_string() + ".o");
|
|
|
|
if !up_to_date(src_file, dst_file) {
|
2018-04-15 01:27:57 +02:00
|
|
|
let mut cmd = Command::new(&builder.initial_rustc);
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.run(
|
|
|
|
cmd.env("RUSTC_BOOTSTRAP", "1")
|
|
|
|
.arg("--cfg")
|
|
|
|
.arg("bootstrap")
|
|
|
|
.arg("--target")
|
|
|
|
.arg(target)
|
|
|
|
.arg("--emit=obj")
|
|
|
|
.arg("-o")
|
|
|
|
.arg(dst_file)
|
|
|
|
.arg(src_file),
|
|
|
|
);
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
2015-11-20 00:20:12 +01:00
|
|
|
|
2020-02-03 20:13:30 +01:00
|
|
|
let target = sysroot_dir.join((*file).to_string() + ".o");
|
2019-10-12 16:01:59 +02:00
|
|
|
builder.copy(dst_file, &target);
|
|
|
|
target_deps.push(target);
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
|
|
|
|
2019-10-12 16:01:59 +02:00
|
|
|
target_deps
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-10 15:01:06 +01:00
|
|
|
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
|
2017-07-14 02:48:44 +02:00
|
|
|
pub struct Rustc {
|
|
|
|
pub target: Interned<String>,
|
2018-03-10 15:01:06 +01:00
|
|
|
pub compiler: Compiler,
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
impl Step for Rustc {
|
2017-07-05 03:41:43 +02:00
|
|
|
type Output = ();
|
2017-07-05 14:41:27 +02:00
|
|
|
const ONLY_HOSTS: bool = true;
|
|
|
|
const DEFAULT: bool = true;
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
Change Step to be invoked with a path when in default mode.
Previously, a Step would be able to tell on its own when it was invoked
"by-default" (that is, `./x.py test` was called instead of `./x.py test
some/path`). This commit replaces that functionality, invoking each Step
with each of the paths it has specified as "should be invoked by."
For example, if a step calls `path("src/tools/cargo")` and
`path("src/doc/cargo")` then it's make_run will be called twice, with
"src/tools/cargo" and "src/doc/cargo." This makes it so that default
handling logic is in builder, instead of spread across various Steps.
However, this meant that some Step specifications needed to be updated,
since for example `rustdoc` can be built by `./x.py build
src/librustdoc` or `./x.py build src/tools/rustdoc`. A `PathSet`
abstraction is added that handles this: now, each Step can not only list
`path(...)` but also `paths(&[a, b, ...])` which will make it so that we
don't invoke it with each of the individual paths, instead invoking it
with the first path in the list (though this shouldn't be depended on).
Future work likely consists of implementing a better/easier way for a
given Step to work with "any" crate in-tree, especially those that want
to run tests, build, or check crates in the std, test, or rustc crate
trees. Currently this is rather painful to do as most of the logic is
duplicated across should_run and make_run. It seems likely this can be
abstracted away into builder somehow.
2018-02-11 17:51:58 +01:00
|
|
|
run.all_krates("rustc-main")
|
2017-07-05 14:41:27 +02:00
|
|
|
}
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn make_run(run: RunConfig<'_>) {
|
2017-07-21 01:51:07 +02:00
|
|
|
run.builder.ensure(Rustc {
|
|
|
|
compiler: run.builder.compiler(run.builder.top_stage, run.host),
|
|
|
|
target: run.target,
|
2017-07-14 02:48:44 +02:00
|
|
|
});
|
2017-07-05 14:41:27 +02:00
|
|
|
}
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Builds the compiler.
|
2017-07-05 03:41:43 +02:00
|
|
|
///
|
|
|
|
/// This will build the compiler for a particular stage of the build using
|
|
|
|
/// the `compiler` targeting the `target` architecture. The artifacts
|
|
|
|
/// created will also be linked into the sysroot directory.
|
2019-02-25 11:30:32 +01:00
|
|
|
fn run(self, builder: &Builder<'_>) {
|
2017-07-05 03:41:43 +02:00
|
|
|
let compiler = self.compiler;
|
|
|
|
let target = self.target;
|
2017-07-05 14:41:27 +02:00
|
|
|
|
bootstrap: Merge the libtest build step with libstd
Since its inception rustbuild has always worked in three stages: one for
libstd, one for libtest, and one for rustc. These three stages were
architected around crates.io dependencies, where rustc wants to depend
on crates.io crates but said crates don't explicitly depend on libstd,
requiring a sysroot assembly step in the middle. This same logic was
applied for libtest where libtest wants to depend on crates.io crates
(`getopts`) but `getopts` didn't say that it depended on std, so it
needed `std` built ahead of time.
Lots of time has passed since the inception of rustbuild, however,
and we've since gotten to the point where even `std` itself is depending
on crates.io crates (albeit with some wonky configuration). This
commit applies the same logic to the two dependencies that the `test`
crate pulls in from crates.io, `getopts` and `unicode-width`. Over the
many years since rustbuild's inception `unicode-width` was the only
dependency picked up by the `test` crate, so the extra configuration
necessary to get crates building in this crate graph is unlikely to be
too much of a burden on developers.
After this patch it means that there are now only two build phasese of
rustbuild, one for libstd and one for rustc. The libtest/libproc_macro
build phase is all lumped into one now with `std`.
This was originally motivated by rust-lang/cargo#7216 where Cargo was
having to deal with synthesizing dependency edges but this commit makes
them explicit in this repository.
2019-08-16 17:29:08 +02:00
|
|
|
builder.ensure(Std { compiler, target });
|
2017-07-05 14:41:27 +02:00
|
|
|
|
2018-07-14 18:58:10 +02:00
|
|
|
if builder.config.keep_stage.contains(&compiler.stage) {
|
|
|
|
builder.info("Warning: Using a potentially old librustc. This may not behave well.");
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.ensure(RustcLink { compiler, target_compiler: compiler, target });
|
2018-07-14 18:58:10 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-28 19:00:53 +02:00
|
|
|
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
|
|
|
|
if compiler_to_use != compiler {
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.ensure(Rustc { compiler: compiler_to_use, target });
|
|
|
|
builder
|
|
|
|
.info(&format!("Uplifting stage1 rustc ({} -> {})", builder.config.build, target));
|
2017-07-05 14:41:27 +02:00
|
|
|
builder.ensure(RustcLink {
|
2019-05-28 19:00:53 +02:00
|
|
|
compiler: compiler_to_use,
|
2017-07-05 14:41:27 +02:00
|
|
|
target_compiler: compiler,
|
|
|
|
target,
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-12-02 21:47:41 +01:00
|
|
|
// Ensure that build scripts and proc macros have a std / libproc_macro to link against.
|
bootstrap: Merge the libtest build step with libstd
Since its inception rustbuild has always worked in three stages: one for
libstd, one for libtest, and one for rustc. These three stages were
architected around crates.io dependencies, where rustc wants to depend
on crates.io crates but said crates don't explicitly depend on libstd,
requiring a sysroot assembly step in the middle. This same logic was
applied for libtest where libtest wants to depend on crates.io crates
(`getopts`) but `getopts` didn't say that it depended on std, so it
needed `std` built ahead of time.
Lots of time has passed since the inception of rustbuild, however,
and we've since gotten to the point where even `std` itself is depending
on crates.io crates (albeit with some wonky configuration). This
commit applies the same logic to the two dependencies that the `test`
crate pulls in from crates.io, `getopts` and `unicode-width`. Over the
many years since rustbuild's inception `unicode-width` was the only
dependency picked up by the `test` crate, so the extra configuration
necessary to get crates building in this crate graph is unlikely to be
too much of a burden on developers.
After this patch it means that there are now only two build phasese of
rustbuild, one for libstd and one for rustc. The libtest/libproc_macro
build phase is all lumped into one now with `std`.
This was originally motivated by rust-lang/cargo#7216 where Cargo was
having to deal with synthesizing dependency edges but this commit makes
them explicit in this repository.
2019-08-16 17:29:08 +02:00
|
|
|
builder.ensure(Std {
|
2018-04-15 01:27:57 +02:00
|
|
|
compiler: builder.compiler(self.compiler.stage, builder.config.build),
|
|
|
|
target: builder.config.build,
|
2017-07-05 14:41:27 +02:00
|
|
|
});
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2018-05-19 22:04:41 +02:00
|
|
|
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build");
|
2019-10-22 17:51:35 +02:00
|
|
|
rustc_cargo(builder, &mut cargo, target);
|
2018-03-16 16:35:03 +01:00
|
|
|
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.info(&format!(
|
|
|
|
"Building stage{} compiler artifacts ({} -> {})",
|
|
|
|
compiler.stage, &compiler.host, target
|
|
|
|
));
|
|
|
|
run_cargo(
|
|
|
|
builder,
|
|
|
|
cargo,
|
|
|
|
vec![],
|
|
|
|
&librustc_stamp(builder, compiler, target),
|
|
|
|
vec![],
|
|
|
|
false,
|
|
|
|
);
|
2017-07-05 14:41:27 +02:00
|
|
|
|
|
|
|
builder.ensure(RustcLink {
|
2018-04-15 01:27:57 +02:00
|
|
|
compiler: builder.compiler(compiler.stage, builder.config.build),
|
2017-07-05 14:41:27 +02:00
|
|
|
target_compiler: compiler,
|
|
|
|
target,
|
|
|
|
});
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
2016-02-25 08:50:32 +01:00
|
|
|
}
|
|
|
|
|
2019-10-22 17:51:35 +02:00
|
|
|
pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
|
2019-12-22 23:42:04 +01:00
|
|
|
cargo
|
|
|
|
.arg("--features")
|
|
|
|
.arg(builder.rustc_features())
|
|
|
|
.arg("--manifest-path")
|
|
|
|
.arg(builder.src.join("src/rustc/Cargo.toml"));
|
2019-10-22 17:51:35 +02:00
|
|
|
rustc_cargo_env(builder, cargo, target);
|
2018-01-22 16:29:24 +01:00
|
|
|
}
|
2017-07-17 18:32:08 +02:00
|
|
|
|
2019-10-22 17:51:35 +02:00
|
|
|
pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
|
2017-07-17 18:32:08 +02:00
|
|
|
// Set some configuration variables picked up by build scripts and
|
|
|
|
// the compiler alike
|
2019-12-22 23:42:04 +01:00
|
|
|
cargo
|
|
|
|
.env("CFG_RELEASE", builder.rust_release())
|
|
|
|
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
|
|
|
|
.env("CFG_VERSION", builder.rust_version())
|
|
|
|
.env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default());
|
2017-07-17 18:32:08 +02:00
|
|
|
|
2020-02-03 20:13:30 +01:00
|
|
|
let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
|
2017-12-07 10:27:12 +01:00
|
|
|
cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
|
2017-07-17 18:32:08 +02:00
|
|
|
|
2018-04-15 01:27:57 +02:00
|
|
|
if let Some(ref ver_date) = builder.rust_info.commit_date() {
|
2017-07-17 18:32:08 +02:00
|
|
|
cargo.env("CFG_VER_DATE", ver_date);
|
|
|
|
}
|
2018-04-15 01:27:57 +02:00
|
|
|
if let Some(ref ver_hash) = builder.rust_info.sha() {
|
2017-07-17 18:32:08 +02:00
|
|
|
cargo.env("CFG_VER_HASH", ver_hash);
|
|
|
|
}
|
2018-04-15 01:27:57 +02:00
|
|
|
if !builder.unstable_features() {
|
2017-07-17 18:32:08 +02:00
|
|
|
cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
|
|
|
|
}
|
2018-04-15 01:27:57 +02:00
|
|
|
if let Some(ref s) = builder.config.rustc_default_linker {
|
2017-07-17 18:32:08 +02:00
|
|
|
cargo.env("CFG_DEFAULT_LINKER", s);
|
|
|
|
}
|
2019-01-28 15:51:47 +01:00
|
|
|
if builder.config.rustc_parallel {
|
2019-09-09 19:22:24 +02:00
|
|
|
cargo.rustflag("--cfg=parallel_compiler");
|
2017-12-03 13:49:01 +01:00
|
|
|
}
|
2018-10-13 10:52:18 +02:00
|
|
|
if builder.config.rust_verify_llvm_ir {
|
|
|
|
cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
|
|
|
|
}
|
2019-10-22 17:51:35 +02:00
|
|
|
|
|
|
|
// Pass down configuration from the LLVM build into the build of
|
|
|
|
// librustc_llvm and librustc_codegen_llvm.
|
|
|
|
//
|
|
|
|
// Note that this is disabled if LLVM itself is disabled or we're in a check
|
2020-05-03 00:39:33 +02:00
|
|
|
// build. If we are in a check build we still go ahead here presuming we've
|
|
|
|
// detected that LLVM is alreay built and good to go which helps prevent
|
|
|
|
// busting caches (e.g. like #71152).
|
|
|
|
if builder.config.llvm_enabled()
|
|
|
|
&& (builder.kind != Kind::Check
|
|
|
|
|| crate::native::prebuilt_llvm_config(builder, target).is_ok())
|
|
|
|
{
|
2019-10-22 17:51:35 +02:00
|
|
|
if builder.is_rust_llvm(target) {
|
|
|
|
cargo.env("LLVM_RUSTLLVM", "1");
|
|
|
|
}
|
|
|
|
let llvm_config = builder.ensure(native::Llvm { target });
|
|
|
|
cargo.env("LLVM_CONFIG", &llvm_config);
|
|
|
|
let target_config = builder.config.target_config.get(&target);
|
|
|
|
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
|
|
|
|
cargo.env("CFG_LLVM_ROOT", s);
|
|
|
|
}
|
|
|
|
// Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm.
|
|
|
|
if let Some(ref s) = builder.config.llvm_ldflags {
|
|
|
|
cargo.env("LLVM_LINKER_FLAGS", s);
|
|
|
|
}
|
|
|
|
// Building with a static libstdc++ is only supported on linux right now,
|
|
|
|
// not for MSVC or macOS
|
2019-12-22 23:42:04 +01:00
|
|
|
if builder.config.llvm_static_stdcpp
|
|
|
|
&& !target.contains("freebsd")
|
|
|
|
&& !target.contains("msvc")
|
|
|
|
&& !target.contains("apple")
|
|
|
|
{
|
|
|
|
let file = compiler_file(builder, builder.cxx(target).unwrap(), target, "libstdc++.a");
|
2019-10-22 17:51:35 +02:00
|
|
|
cargo.env("LLVM_STATIC_STDCPP", file);
|
|
|
|
}
|
|
|
|
if builder.config.llvm_link_shared || builder.config.llvm_thin_lto {
|
|
|
|
cargo.env("LLVM_LINK_SHARED", "1");
|
|
|
|
}
|
|
|
|
if builder.config.llvm_use_libcxx {
|
|
|
|
cargo.env("LLVM_USE_LIBCXX", "1");
|
|
|
|
}
|
|
|
|
if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo {
|
|
|
|
cargo.env("LLVM_NDEBUG", "1");
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 18:32:08 +02:00
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
struct RustcLink {
|
|
|
|
pub compiler: Compiler,
|
|
|
|
pub target_compiler: Compiler,
|
|
|
|
pub target: Interned<String>,
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
impl Step for RustcLink {
|
2017-07-05 03:41:43 +02:00
|
|
|
type Output = ();
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
2017-07-19 02:03:38 +02:00
|
|
|
run.never()
|
2017-07-14 14:30:16 +02:00
|
|
|
}
|
|
|
|
|
2017-07-05 03:41:43 +02:00
|
|
|
/// Same as `std_link`, only for librustc
|
2019-02-25 11:30:32 +01:00
|
|
|
fn run(self, builder: &Builder<'_>) {
|
2017-07-05 03:41:43 +02:00
|
|
|
let compiler = self.compiler;
|
|
|
|
let target_compiler = self.target_compiler;
|
|
|
|
let target = self.target;
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.info(&format!(
|
|
|
|
"Copying stage{} rustc from stage{} ({} -> {} / {})",
|
|
|
|
target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target
|
|
|
|
));
|
2018-12-02 21:47:41 +01:00
|
|
|
add_to_sysroot(
|
|
|
|
builder,
|
|
|
|
&builder.sysroot_libdir(target_compiler, target),
|
|
|
|
&builder.sysroot_libdir(target_compiler, compiler.host),
|
2019-12-22 23:42:04 +01:00
|
|
|
&librustc_stamp(builder, compiler, target),
|
2018-12-02 21:47:41 +01:00
|
|
|
);
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Cargo's output path for the standard library in a given stage, compiled
|
|
|
|
/// by a particular compiler for the specified target.
|
2019-02-25 11:30:32 +01:00
|
|
|
pub fn libstd_stamp(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
compiler: Compiler,
|
|
|
|
target: Interned<String>,
|
|
|
|
) -> PathBuf {
|
2018-05-19 22:04:41 +02:00
|
|
|
builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp")
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
|
2017-04-11 20:58:25 +02:00
|
|
|
/// Cargo's output path for librustc in a given stage, compiled by a particular
|
|
|
|
/// compiler for the specified target.
|
2019-02-25 11:30:32 +01:00
|
|
|
pub fn librustc_stamp(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
compiler: Compiler,
|
|
|
|
target: Interned<String>,
|
|
|
|
) -> PathBuf {
|
2018-05-19 22:04:41 +02:00
|
|
|
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp")
|
2017-04-11 20:58:25 +02:00
|
|
|
}
|
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
pub fn compiler_file(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
compiler: &Path,
|
|
|
|
target: Interned<String>,
|
|
|
|
file: &str,
|
|
|
|
) -> PathBuf {
|
2018-01-22 16:29:24 +01:00
|
|
|
let mut cmd = Command::new(compiler);
|
2018-08-30 19:25:07 +02:00
|
|
|
cmd.args(builder.cflags(target, GitRepo::Rustc));
|
2018-01-22 16:29:24 +01:00
|
|
|
cmd.arg(format!("-print-file-name={}", file));
|
|
|
|
let out = output(&mut cmd);
|
2016-04-05 19:00:25 +02:00
|
|
|
PathBuf::from(out.trim())
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Sysroot {
|
|
|
|
pub compiler: Compiler,
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
impl Step for Sysroot {
|
|
|
|
type Output = Interned<PathBuf>;
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
2017-07-19 02:03:38 +02:00
|
|
|
run.never()
|
2017-07-14 14:30:16 +02:00
|
|
|
}
|
|
|
|
|
2017-07-05 03:41:43 +02:00
|
|
|
/// Returns the sysroot for the `compiler` specified that *this build system
|
|
|
|
/// generates*.
|
|
|
|
///
|
|
|
|
/// That is, the sysroot for the stage0 compiler is not what the compiler
|
|
|
|
/// thinks it is by default, but it's the same as the default for stages
|
|
|
|
/// 1-3.
|
2019-02-25 11:30:32 +01:00
|
|
|
fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
|
2017-07-05 03:41:43 +02:00
|
|
|
let compiler = self.compiler;
|
2017-07-05 14:41:27 +02:00
|
|
|
let sysroot = if compiler.stage == 0 {
|
2018-04-15 01:27:57 +02:00
|
|
|
builder.out.join(&compiler.host).join("stage0-sysroot")
|
2017-07-05 14:41:27 +02:00
|
|
|
} else {
|
2018-04-15 01:27:57 +02:00
|
|
|
builder.out.join(&compiler.host).join(format!("stage{}", compiler.stage))
|
2017-07-05 14:41:27 +02:00
|
|
|
};
|
2017-07-05 03:41:43 +02:00
|
|
|
let _ = fs::remove_dir_all(&sysroot);
|
|
|
|
t!(fs::create_dir_all(&sysroot));
|
2020-04-01 03:00:52 +02:00
|
|
|
|
|
|
|
// Symlink the source root into the same location inside the sysroot,
|
|
|
|
// where `rust-src` component would go (`$sysroot/lib/rustlib/src/rust`),
|
|
|
|
// so that any tools relying on `rust-src` also work for local builds,
|
|
|
|
// and also for translating the virtual `/rustc/$hash` back to the real
|
|
|
|
// directory (for running tests with `rust.remap-debuginfo = true`).
|
|
|
|
let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
|
|
|
|
t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
|
|
|
|
let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
|
|
|
|
if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
|
|
|
|
eprintln!(
|
|
|
|
"warning: creating symbolic link `{}` to `{}` failed with {}",
|
|
|
|
sysroot_lib_rustlib_src_rust.display(),
|
|
|
|
builder.src.display(),
|
|
|
|
e,
|
|
|
|
);
|
|
|
|
if builder.config.rust_remap_debuginfo {
|
|
|
|
eprintln!(
|
|
|
|
"warning: some `src/test/ui` tests will fail when lacking `{}`",
|
|
|
|
sysroot_lib_rustlib_src_rust.display(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
INTERNER.intern_path(sysroot)
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
rustbuild: Compile rustc twice, not thrice
This commit switches the rustbuild build system to compiling the
compiler twice for a normal bootstrap rather than the historical three
times.
Rust is a bootstrapped language which means that a previous version of
the compiler is used to build the next version of the compiler. Over
time, however, we change many parts of compiler artifacts such as the
metadata format, symbol names, etc. These changes make artifacts from
one compiler incompatible from another compiler. Consequently if a
compiler wants to be able to use some artifacts then it itself must have
compiled the artifacts.
Historically the rustc build system has achieved this by compiling the
compiler three times:
* An older compiler (stage0) is downloaded to kick off the chain.
* This compiler now compiles a new compiler (stage1)
* The stage1 compiler then compiles another compiler (stage2)
* Finally, the stage2 compiler needs libraries to link against, so it
compiles all the libraries again.
This entire process amounts in compiling the compiler three times.
Additionally, this process always guarantees that the Rust source tree
can compile itself because the stage2 compiler (created by a freshly
created compiler) would successfully compile itself again. This
property, ensuring Rust can compile itself, is quite important!
In general, though, this third compilation is not required for general
purpose development on the compiler. The third compiler (stage2) can
reuse the libraries that were created during the second compile. In
other words, the second compilation can produce both a compiler and the
libraries that compiler will use. These artifacts *must* be compatible
due to the way plugins work today anyway, and they were created by the
same source code so they *should* be compatible as well.
So given all that, this commit switches the default build process to
only compile the compiler three times, avoiding this third compilation
by copying artifacts from the previous one. Along the way a new entry in
the Travis matrix was also added to ensure that our full bootstrap can
succeed. This entry does not run tests, though, as it should not be
necessary.
To restore the old behavior of a full bootstrap (three compiles) you can
either pass:
./configure --enable-full-bootstrap
or if you're using config.toml:
[build]
full-bootstrap = true
Overall this will hopefully be an easy 33% win in build times of the
compiler. If we do 33% less work we should be 33% faster! This in turn
should affect cycle times and such on Travis and AppVeyor positively as
well as making it easier to work on the compiler itself.
2016-12-26 00:20:33 +01:00
|
|
|
}
|
|
|
|
|
2018-03-10 15:01:06 +01:00
|
|
|
#[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
|
2017-07-14 02:48:44 +02:00
|
|
|
pub struct Assemble {
|
2017-07-05 14:41:27 +02:00
|
|
|
/// The compiler which we will produce in this step. Assemble itself will
|
|
|
|
/// take care of ensuring that the necessary prerequisites to do so exist,
|
|
|
|
/// that is, this target can be a stage2 compiler and Assemble will build
|
|
|
|
/// previous stages for you.
|
2017-07-14 02:48:44 +02:00
|
|
|
pub target_compiler: Compiler,
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
rustbuild: Compile rustc twice, not thrice
This commit switches the rustbuild build system to compiling the
compiler twice for a normal bootstrap rather than the historical three
times.
Rust is a bootstrapped language which means that a previous version of
the compiler is used to build the next version of the compiler. Over
time, however, we change many parts of compiler artifacts such as the
metadata format, symbol names, etc. These changes make artifacts from
one compiler incompatible from another compiler. Consequently if a
compiler wants to be able to use some artifacts then it itself must have
compiled the artifacts.
Historically the rustc build system has achieved this by compiling the
compiler three times:
* An older compiler (stage0) is downloaded to kick off the chain.
* This compiler now compiles a new compiler (stage1)
* The stage1 compiler then compiles another compiler (stage2)
* Finally, the stage2 compiler needs libraries to link against, so it
compiles all the libraries again.
This entire process amounts in compiling the compiler three times.
Additionally, this process always guarantees that the Rust source tree
can compile itself because the stage2 compiler (created by a freshly
created compiler) would successfully compile itself again. This
property, ensuring Rust can compile itself, is quite important!
In general, though, this third compilation is not required for general
purpose development on the compiler. The third compiler (stage2) can
reuse the libraries that were created during the second compile. In
other words, the second compilation can produce both a compiler and the
libraries that compiler will use. These artifacts *must* be compatible
due to the way plugins work today anyway, and they were created by the
same source code so they *should* be compatible as well.
So given all that, this commit switches the default build process to
only compile the compiler three times, avoiding this third compilation
by copying artifacts from the previous one. Along the way a new entry in
the Travis matrix was also added to ensure that our full bootstrap can
succeed. This entry does not run tests, though, as it should not be
necessary.
To restore the old behavior of a full bootstrap (three compiles) you can
either pass:
./configure --enable-full-bootstrap
or if you're using config.toml:
[build]
full-bootstrap = true
Overall this will hopefully be an easy 33% win in build times of the
compiler. If we do 33% less work we should be 33% faster! This in turn
should affect cycle times and such on Travis and AppVeyor positively as
well as making it easier to work on the compiler itself.
2016-12-26 00:20:33 +01:00
|
|
|
|
2017-07-14 02:48:44 +02:00
|
|
|
impl Step for Assemble {
|
|
|
|
type Output = Compiler;
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2019-02-25 11:30:32 +01:00
|
|
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
2018-07-02 22:46:40 +02:00
|
|
|
run.never()
|
2017-07-14 14:30:16 +02:00
|
|
|
}
|
|
|
|
|
2017-07-05 03:41:43 +02:00
|
|
|
/// Prepare a new compiler from the artifacts in `stage`
|
|
|
|
///
|
|
|
|
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
|
2018-04-15 01:27:57 +02:00
|
|
|
/// must have been previously produced by the `stage - 1` builder.build
|
2017-07-05 03:41:43 +02:00
|
|
|
/// compiler.
|
2019-02-25 11:30:32 +01:00
|
|
|
fn run(self, builder: &Builder<'_>) -> Compiler {
|
2017-07-05 14:41:27 +02:00
|
|
|
let target_compiler = self.target_compiler;
|
2016-03-12 02:30:16 +01:00
|
|
|
|
2017-07-05 14:41:27 +02:00
|
|
|
if target_compiler.stage == 0 {
|
2019-12-22 23:42:04 +01:00
|
|
|
assert_eq!(
|
|
|
|
builder.config.build, target_compiler.host,
|
|
|
|
"Cannot obtain compiler for non-native build triple at stage 0"
|
|
|
|
);
|
2017-07-05 14:41:27 +02:00
|
|
|
// The stage 0 compiler for the build triple is always pre-built.
|
|
|
|
return target_compiler;
|
|
|
|
}
|
2016-02-25 04:03:48 +01:00
|
|
|
|
2017-07-05 14:41:27 +02:00
|
|
|
// Get the compiler that we'll use to bootstrap ourselves.
|
2018-01-22 16:29:24 +01:00
|
|
|
//
|
|
|
|
// Note that this is where the recursive nature of the bootstrap
|
|
|
|
// happens, as this will request the previous stage's compiler on
|
|
|
|
// downwards to stage 0.
|
|
|
|
//
|
|
|
|
// Also note that we're building a compiler for the host platform. We
|
|
|
|
// only assume that we can run `build` artifacts, which means that to
|
|
|
|
// produce some other architecture compiler we need to start from
|
|
|
|
// `build` to get there.
|
|
|
|
//
|
|
|
|
// FIXME: Perhaps we should download those libraries?
|
|
|
|
// It would make builds faster...
|
|
|
|
//
|
|
|
|
// FIXME: It may be faster if we build just a stage 1 compiler and then
|
|
|
|
// use that to bootstrap this compiler forward.
|
2019-12-22 23:42:04 +01:00
|
|
|
let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
|
2017-07-05 14:41:27 +02:00
|
|
|
|
|
|
|
// Build the libraries for this compiler to link to (i.e., the libraries
|
|
|
|
// it uses at runtime). NOTE: Crates the target compiler compiles don't
|
|
|
|
// link to these. (FIXME: Is that correct? It seems to be correct most
|
|
|
|
// of the time but I think we do link to these for stage2/bin compilers
|
|
|
|
// when not performing a full bootstrap).
|
2019-12-22 23:42:04 +01:00
|
|
|
builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host });
|
2017-07-05 14:41:27 +02:00
|
|
|
|
2018-04-15 01:27:57 +02:00
|
|
|
let lld_install = if builder.config.lld_enabled {
|
2019-12-22 23:42:04 +01:00
|
|
|
Some(builder.ensure(native::Lld { target: target_compiler.host }))
|
rust: Import LLD for linking wasm objects
This commit imports the LLD project from LLVM to serve as the default linker for
the `wasm32-unknown-unknown` target. The `binaryen` submoule is consequently
removed along with "binaryen linker" support in rustc.
Moving to LLD brings with it a number of benefits for wasm code:
* LLD is itself an actual linker, so there's no need to compile all wasm code
with LTO any more. As a result builds should be *much* speedier as LTO is no
longer forcibly enabled for all builds of the wasm target.
* LLD is quickly becoming an "official solution" for linking wasm code together.
This, I believe at least, is intended to be the main supported linker for
native code and wasm moving forward. Picking up support early on should help
ensure that we can help LLD identify bugs and otherwise prove that it works
great for all our use cases!
* Improvements to the wasm toolchain are currently primarily focused around LLVM
and LLD (from what I can tell at least), so it's in general much better to be
on this bandwagon for bugfixes and new features.
* Historical "hacks" like `wasm-gc` will soon no longer be necessary, LLD
will [natively implement][gc] `--gc-sections` (better than `wasm-gc`!) which
means a postprocessor is no longer needed to show off Rust's "small wasm
binary size".
LLD is added in a pretty standard way to rustc right now. A new rustbuild target
was defined for building LLD, and this is executed when a compiler's sysroot is
being assembled. LLD is compiled against the LLVM that we've got in tree, which
means we're currently on the `release_60` branch, but this may get upgraded in
the near future!
LLD is placed into rustc's sysroot in a `bin` directory. This is similar to
where `gcc.exe` can be found on Windows. This directory is automatically added
to `PATH` whenever rustc executes the linker, allowing us to define a `WasmLd`
linker which implements the interface that `wasm-ld`, LLD's frontend, expects.
Like Emscripten the LLD target is currently only enabled for Tier 1 platforms,
notably OSX/Windows/Linux, and will need to be installed manually for compiling
to wasm on other platforms. LLD is by default turned off in rustbuild, and
requires a `config.toml` option to be enabled to turn it on.
Finally the unstable `#![wasm_import_memory]` attribute was also removed as LLD
has a native option for controlling this.
[gc]: https://reviews.llvm.org/D42511
2017-08-27 03:30:12 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2017-07-05 14:41:27 +02:00
|
|
|
let stage = target_compiler.stage;
|
|
|
|
let host = target_compiler.host;
|
2018-04-15 01:27:57 +02:00
|
|
|
builder.info(&format!("Assembling stage{} compiler ({})", stage, host));
|
2017-07-05 03:41:43 +02:00
|
|
|
|
|
|
|
// Link in all dylibs to the libdir
|
2017-07-05 18:46:41 +02:00
|
|
|
let sysroot = builder.sysroot(target_compiler);
|
2019-03-31 21:28:12 +02:00
|
|
|
let rustc_libdir = builder.rustc_libdir(target_compiler);
|
|
|
|
t!(fs::create_dir_all(&rustc_libdir));
|
2017-07-05 18:46:41 +02:00
|
|
|
let src_libdir = builder.sysroot_libdir(build_compiler, host);
|
2018-03-27 16:06:47 +02:00
|
|
|
for f in builder.read_dir(&src_libdir) {
|
2017-07-05 03:41:43 +02:00
|
|
|
let filename = f.file_name().into_string().unwrap();
|
|
|
|
if is_dylib(&filename) {
|
2019-03-31 21:28:12 +02:00
|
|
|
builder.copy(&f.path(), &rustc_libdir.join(&filename));
|
2017-07-05 03:41:43 +02:00
|
|
|
}
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
|
2019-11-04 20:16:30 +01:00
|
|
|
let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host);
|
rust: Import LLD for linking wasm objects
This commit imports the LLD project from LLVM to serve as the default linker for
the `wasm32-unknown-unknown` target. The `binaryen` submoule is consequently
removed along with "binaryen linker" support in rustc.
Moving to LLD brings with it a number of benefits for wasm code:
* LLD is itself an actual linker, so there's no need to compile all wasm code
with LTO any more. As a result builds should be *much* speedier as LTO is no
longer forcibly enabled for all builds of the wasm target.
* LLD is quickly becoming an "official solution" for linking wasm code together.
This, I believe at least, is intended to be the main supported linker for
native code and wasm moving forward. Picking up support early on should help
ensure that we can help LLD identify bugs and otherwise prove that it works
great for all our use cases!
* Improvements to the wasm toolchain are currently primarily focused around LLVM
and LLD (from what I can tell at least), so it's in general much better to be
on this bandwagon for bugfixes and new features.
* Historical "hacks" like `wasm-gc` will soon no longer be necessary, LLD
will [natively implement][gc] `--gc-sections` (better than `wasm-gc`!) which
means a postprocessor is no longer needed to show off Rust's "small wasm
binary size".
LLD is added in a pretty standard way to rustc right now. A new rustbuild target
was defined for building LLD, and this is executed when a compiler's sysroot is
being assembled. LLD is compiled against the LLVM that we've got in tree, which
means we're currently on the `release_60` branch, but this may get upgraded in
the near future!
LLD is placed into rustc's sysroot in a `bin` directory. This is similar to
where `gcc.exe` can be found on Windows. This directory is automatically added
to `PATH` whenever rustc executes the linker, allowing us to define a `WasmLd`
linker which implements the interface that `wasm-ld`, LLD's frontend, expects.
Like Emscripten the LLD target is currently only enabled for Tier 1 platforms,
notably OSX/Windows/Linux, and will need to be installed manually for compiling
to wasm on other platforms. LLD is by default turned off in rustbuild, and
requires a `config.toml` option to be enabled to turn it on.
Finally the unstable `#![wasm_import_memory]` attribute was also removed as LLD
has a native option for controlling this.
[gc]: https://reviews.llvm.org/D42511
2017-08-27 03:30:12 +02:00
|
|
|
if let Some(lld_install) = lld_install {
|
2019-11-04 20:16:30 +01:00
|
|
|
let src_exe = exe("lld", &target_compiler.host);
|
|
|
|
let dst_exe = exe("rust-lld", &target_compiler.host);
|
|
|
|
// we prepend this bin directory to the user PATH when linking Rust binaries. To
|
|
|
|
// avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
|
|
|
|
let dst = libdir.parent().unwrap().join("bin");
|
|
|
|
t!(fs::create_dir_all(&dst));
|
|
|
|
builder.copy(&lld_install.join("bin").join(&src_exe), &dst.join(&dst_exe));
|
rust: Import LLD for linking wasm objects
This commit imports the LLD project from LLVM to serve as the default linker for
the `wasm32-unknown-unknown` target. The `binaryen` submoule is consequently
removed along with "binaryen linker" support in rustc.
Moving to LLD brings with it a number of benefits for wasm code:
* LLD is itself an actual linker, so there's no need to compile all wasm code
with LTO any more. As a result builds should be *much* speedier as LTO is no
longer forcibly enabled for all builds of the wasm target.
* LLD is quickly becoming an "official solution" for linking wasm code together.
This, I believe at least, is intended to be the main supported linker for
native code and wasm moving forward. Picking up support early on should help
ensure that we can help LLD identify bugs and otherwise prove that it works
great for all our use cases!
* Improvements to the wasm toolchain are currently primarily focused around LLVM
and LLD (from what I can tell at least), so it's in general much better to be
on this bandwagon for bugfixes and new features.
* Historical "hacks" like `wasm-gc` will soon no longer be necessary, LLD
will [natively implement][gc] `--gc-sections` (better than `wasm-gc`!) which
means a postprocessor is no longer needed to show off Rust's "small wasm
binary size".
LLD is added in a pretty standard way to rustc right now. A new rustbuild target
was defined for building LLD, and this is executed when a compiler's sysroot is
being assembled. LLD is compiled against the LLVM that we've got in tree, which
means we're currently on the `release_60` branch, but this may get upgraded in
the near future!
LLD is placed into rustc's sysroot in a `bin` directory. This is similar to
where `gcc.exe` can be found on Windows. This directory is automatically added
to `PATH` whenever rustc executes the linker, allowing us to define a `WasmLd`
linker which implements the interface that `wasm-ld`, LLD's frontend, expects.
Like Emscripten the LLD target is currently only enabled for Tier 1 platforms,
notably OSX/Windows/Linux, and will need to be installed manually for compiling
to wasm on other platforms. LLD is by default turned off in rustbuild, and
requires a `config.toml` option to be enabled to turn it on.
Finally the unstable `#![wasm_import_memory]` attribute was also removed as LLD
has a native option for controlling this.
[gc]: https://reviews.llvm.org/D42511
2017-08-27 03:30:12 +02:00
|
|
|
}
|
2019-12-09 19:25:04 +01:00
|
|
|
|
|
|
|
// Ensure that `libLLVM.so` ends up in the newly build compiler directory,
|
|
|
|
// so that it can be found when the newly built `rustc` is run.
|
2020-05-08 02:27:08 +02:00
|
|
|
dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
|
|
|
|
dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
|
2018-12-18 06:10:59 +01:00
|
|
|
|
2017-07-05 03:41:43 +02:00
|
|
|
// Link the compiler binary itself into place
|
2018-05-19 22:04:41 +02:00
|
|
|
let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
|
2018-05-12 05:30:02 +02:00
|
|
|
let rustc = out_dir.join(exe("rustc_binary", &*host));
|
2017-07-05 03:41:43 +02:00
|
|
|
let bindir = sysroot.join("bin");
|
|
|
|
t!(fs::create_dir_all(&bindir));
|
2017-07-05 19:21:33 +02:00
|
|
|
let compiler = builder.rustc(target_compiler);
|
2018-03-27 16:06:47 +02:00
|
|
|
builder.copy(&rustc, &compiler);
|
2017-07-05 03:41:43 +02:00
|
|
|
|
2017-07-05 18:46:41 +02:00
|
|
|
target_compiler
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Link some files into a rustc sysroot.
|
|
|
|
///
|
2017-05-27 19:19:43 +02:00
|
|
|
/// For a particular stage this will link the file listed in `stamp` into the
|
|
|
|
/// `sysroot_dst` provided.
|
2018-12-02 21:47:41 +01:00
|
|
|
pub fn add_to_sysroot(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
sysroot_dst: &Path,
|
|
|
|
sysroot_host_dst: &Path,
|
2019-12-22 23:42:04 +01:00
|
|
|
stamp: &Path,
|
2018-12-02 21:47:41 +01:00
|
|
|
) {
|
2017-05-27 19:19:43 +02:00
|
|
|
t!(fs::create_dir_all(&sysroot_dst));
|
2018-12-02 21:47:41 +01:00
|
|
|
t!(fs::create_dir_all(&sysroot_host_dst));
|
|
|
|
for (path, host) in builder.read_stamp_file(stamp) {
|
|
|
|
if host {
|
|
|
|
builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap()));
|
|
|
|
} else {
|
|
|
|
builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
|
|
|
|
}
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-08 07:32:37 +01:00
|
|
|
|
2019-12-22 23:42:04 +01:00
|
|
|
pub fn run_cargo(
|
|
|
|
builder: &Builder<'_>,
|
|
|
|
cargo: Cargo,
|
|
|
|
tail_args: Vec<String>,
|
|
|
|
stamp: &Path,
|
|
|
|
additional_target_deps: Vec<PathBuf>,
|
|
|
|
is_check: bool,
|
|
|
|
) -> Vec<PathBuf> {
|
2018-04-15 01:27:57 +02:00
|
|
|
if builder.config.dry_run {
|
2018-03-27 16:06:47 +02:00
|
|
|
return Vec::new();
|
|
|
|
}
|
|
|
|
|
2017-05-27 19:19:43 +02:00
|
|
|
// `target_root_dir` looks like $dir/$target/release
|
|
|
|
let target_root_dir = stamp.parent().unwrap();
|
|
|
|
// `target_deps_dir` looks like $dir/$target/release/deps
|
|
|
|
let target_deps_dir = target_root_dir.join("deps");
|
|
|
|
// `host_root_dir` looks like $dir/release
|
2019-12-22 23:42:04 +01:00
|
|
|
let host_root_dir = target_root_dir
|
|
|
|
.parent()
|
|
|
|
.unwrap() // chop off `release`
|
|
|
|
.parent()
|
|
|
|
.unwrap() // chop off `$target`
|
|
|
|
.join(target_root_dir.file_name().unwrap());
|
2017-05-27 19:19:43 +02:00
|
|
|
|
|
|
|
// Spawn Cargo slurping up its JSON output. We'll start building up the
|
|
|
|
// `deps` array of all files it generated along with a `toplevel` array of
|
|
|
|
// files we need to probe for later.
|
|
|
|
let mut deps = Vec::new();
|
|
|
|
let mut toplevel = Vec::new();
|
2018-12-04 19:26:54 +01:00
|
|
|
let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
|
2018-12-02 21:47:41 +01:00
|
|
|
let (filenames, crate_types) = match msg {
|
|
|
|
CargoMessage::CompilerArtifact {
|
|
|
|
filenames,
|
2019-12-22 23:42:04 +01:00
|
|
|
target: CargoTarget { crate_types },
|
2018-12-02 21:47:41 +01:00
|
|
|
..
|
|
|
|
} => (filenames, crate_types),
|
2018-03-15 18:58:02 +01:00
|
|
|
_ => return,
|
2017-05-27 19:19:43 +02:00
|
|
|
};
|
2018-03-15 18:58:02 +01:00
|
|
|
for filename in filenames {
|
2017-05-27 19:19:43 +02:00
|
|
|
// Skip files like executables
|
2020-02-03 20:13:30 +01:00
|
|
|
if !(filename.ends_with(".rlib")
|
|
|
|
|| filename.ends_with(".lib")
|
|
|
|
|| filename.ends_with(".a")
|
|
|
|
|| is_dylib(&filename)
|
|
|
|
|| (is_check && filename.ends_with(".rmeta")))
|
2019-12-22 23:42:04 +01:00
|
|
|
{
|
2018-06-28 18:06:42 +02:00
|
|
|
continue;
|
2017-05-27 19:19:43 +02:00
|
|
|
}
|
|
|
|
|
2018-03-15 18:58:02 +01:00
|
|
|
let filename = Path::new(&*filename);
|
2017-05-27 19:19:43 +02:00
|
|
|
|
|
|
|
// If this was an output file in the "host dir" we don't actually
|
2018-12-02 21:47:41 +01:00
|
|
|
// worry about it, it's not relevant for us
|
2017-05-27 19:19:43 +02:00
|
|
|
if filename.starts_with(&host_root_dir) {
|
2018-12-02 21:47:41 +01:00
|
|
|
// Unless it's a proc macro used in the compiler
|
|
|
|
if crate_types.iter().any(|t| t == "proc-macro") {
|
|
|
|
deps.push((filename.to_path_buf(), true));
|
|
|
|
}
|
2018-06-28 18:06:42 +02:00
|
|
|
continue;
|
2017-06-27 17:51:26 +02:00
|
|
|
}
|
2017-05-27 19:19:43 +02:00
|
|
|
|
|
|
|
// If this was output in the `deps` dir then this is a precise file
|
|
|
|
// name (hash included) so we start tracking it.
|
2017-06-27 17:51:26 +02:00
|
|
|
if filename.starts_with(&target_deps_dir) {
|
2018-12-02 21:47:41 +01:00
|
|
|
deps.push((filename.to_path_buf(), false));
|
2018-06-28 18:06:42 +02:00
|
|
|
continue;
|
2017-06-27 17:51:26 +02:00
|
|
|
}
|
2017-05-27 19:19:43 +02:00
|
|
|
|
|
|
|
// Otherwise this was a "top level artifact" which right now doesn't
|
|
|
|
// have a hash in the name, but there's a version of this file in
|
|
|
|
// the `deps` folder which *does* have a hash in the name. That's
|
|
|
|
// the one we'll want to we'll probe for it later.
|
2017-10-24 18:32:28 +02:00
|
|
|
//
|
|
|
|
// We do not use `Path::file_stem` or `Path::extension` here,
|
|
|
|
// because some generated files may have multiple extensions e.g.
|
|
|
|
// `std-<hash>.dll.lib` on Windows. The aforementioned methods only
|
|
|
|
// split the file name by the last extension (`.lib`) while we need
|
|
|
|
// to split by all extensions (`.dll.lib`).
|
2017-11-01 20:32:13 +01:00
|
|
|
let expected_len = t!(filename.metadata()).len();
|
2017-10-24 18:32:28 +02:00
|
|
|
let filename = filename.file_name().unwrap().to_str().unwrap();
|
|
|
|
let mut parts = filename.splitn(2, '.');
|
|
|
|
let file_stem = parts.next().unwrap().to_owned();
|
|
|
|
let extension = parts.next().unwrap().to_owned();
|
|
|
|
|
2017-11-01 20:32:13 +01:00
|
|
|
toplevel.push((file_stem, extension, expected_len));
|
2017-05-27 19:19:43 +02:00
|
|
|
}
|
2018-03-15 18:58:02 +01:00
|
|
|
});
|
2017-05-27 19:19:43 +02:00
|
|
|
|
2018-03-15 18:58:02 +01:00
|
|
|
if !ok {
|
2018-11-11 10:43:33 +01:00
|
|
|
exit(1);
|
2017-05-27 19:19:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Ok now we need to actually find all the files listed in `toplevel`. We've
|
|
|
|
// got a list of prefix/extensions and we basically just need to find the
|
|
|
|
// most recent file in the `deps` folder corresponding to each one.
|
|
|
|
let contents = t!(target_deps_dir.read_dir())
|
|
|
|
.map(|e| t!(e))
|
|
|
|
.map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
|
|
|
|
.collect::<Vec<_>>();
|
2017-11-01 20:32:13 +01:00
|
|
|
for (prefix, extension, expected_len) in toplevel {
|
|
|
|
let candidates = contents.iter().filter(|&&(_, ref filename, ref meta)| {
|
2019-12-22 23:42:04 +01:00
|
|
|
filename.starts_with(&prefix[..])
|
2020-02-03 20:13:30 +01:00
|
|
|
&& filename[prefix.len()..].starts_with('-')
|
2019-12-22 23:42:04 +01:00
|
|
|
&& filename.ends_with(&extension[..])
|
|
|
|
&& meta.len() == expected_len
|
2017-05-27 19:19:43 +02:00
|
|
|
});
|
2019-12-22 23:42:04 +01:00
|
|
|
let max = candidates
|
|
|
|
.max_by_key(|&&(_, _, ref metadata)| FileTime::from_last_modification_time(metadata));
|
2017-05-27 19:19:43 +02:00
|
|
|
let path_to_add = match max {
|
|
|
|
Some(triple) => triple.0.to_str().unwrap(),
|
|
|
|
None => panic!("no output generated for {:?} {:?}", prefix, extension),
|
|
|
|
};
|
|
|
|
if is_dylib(path_to_add) {
|
|
|
|
let candidate = format!("{}.lib", path_to_add);
|
|
|
|
let candidate = PathBuf::from(candidate);
|
|
|
|
if candidate.exists() {
|
2018-12-02 21:47:41 +01:00
|
|
|
deps.push((candidate, false));
|
2017-05-27 19:19:43 +02:00
|
|
|
}
|
|
|
|
}
|
2018-12-02 21:47:41 +01:00
|
|
|
deps.push((path_to_add.into(), false));
|
2017-05-27 19:19:43 +02:00
|
|
|
}
|
|
|
|
|
2019-10-12 16:01:59 +02:00
|
|
|
deps.extend(additional_target_deps.into_iter().map(|d| (d, false)));
|
2017-05-27 19:19:43 +02:00
|
|
|
deps.sort();
|
|
|
|
let mut new_contents = Vec::new();
|
2018-12-02 21:47:41 +01:00
|
|
|
for (dep, proc_macro) in deps.iter() {
|
|
|
|
new_contents.extend(if *proc_macro { b"h" } else { b"t" });
|
2017-05-27 19:19:43 +02:00
|
|
|
new_contents.extend(dep.to_str().unwrap().as_bytes());
|
|
|
|
new_contents.extend(b"\0");
|
|
|
|
}
|
2018-11-16 22:22:06 +01:00
|
|
|
t!(fs::write(&stamp, &new_contents));
|
2018-12-02 21:47:41 +01:00
|
|
|
deps.into_iter().map(|(d, _)| d).collect()
|
2016-09-13 06:46:35 +02:00
|
|
|
}
|
2018-03-15 18:58:02 +01:00
|
|
|
|
|
|
|
pub fn stream_cargo(
|
2019-02-25 11:30:32 +01:00
|
|
|
builder: &Builder<'_>,
|
2019-09-09 19:17:38 +02:00
|
|
|
cargo: Cargo,
|
2018-12-04 19:26:54 +01:00
|
|
|
tail_args: Vec<String>,
|
2019-02-25 11:30:32 +01:00
|
|
|
cb: &mut dyn FnMut(CargoMessage<'_>),
|
2018-03-15 18:58:02 +01:00
|
|
|
) -> bool {
|
2019-09-09 19:17:38 +02:00
|
|
|
let mut cargo = Command::from(cargo);
|
2018-04-15 01:27:57 +02:00
|
|
|
if builder.config.dry_run {
|
2018-03-27 16:06:47 +02:00
|
|
|
return true;
|
|
|
|
}
|
2018-03-15 18:58:02 +01:00
|
|
|
// Instruct Cargo to give us json messages on stdout, critically leaving
|
|
|
|
// stderr as piped so we can get those pretty colors.
|
2020-03-31 03:21:35 +02:00
|
|
|
let mut message_format = if builder.config.json_output {
|
|
|
|
String::from("json")
|
|
|
|
} else {
|
|
|
|
String::from("json-render-diagnostics")
|
|
|
|
};
|
2019-12-22 23:42:04 +01:00
|
|
|
if let Some(s) = &builder.config.rustc_error_format {
|
2019-08-12 20:49:12 +02:00
|
|
|
message_format.push_str(",json-diagnostic-");
|
|
|
|
message_format.push_str(s);
|
|
|
|
}
|
|
|
|
cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
|
2018-03-15 18:58:02 +01:00
|
|
|
|
2018-12-04 19:26:54 +01:00
|
|
|
for arg in tail_args {
|
|
|
|
cargo.arg(arg);
|
|
|
|
}
|
|
|
|
|
2018-04-15 01:27:57 +02:00
|
|
|
builder.verbose(&format!("running: {:?}", cargo));
|
2018-03-15 18:58:02 +01:00
|
|
|
let mut child = match cargo.spawn() {
|
|
|
|
Ok(child) => child,
|
|
|
|
Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cargo, e),
|
|
|
|
};
|
|
|
|
|
|
|
|
// Spawn Cargo slurping up its JSON output. We'll start building up the
|
|
|
|
// `deps` array of all files it generated along with a `toplevel` array of
|
|
|
|
// files we need to probe for later.
|
|
|
|
let stdout = BufReader::new(child.stdout.take().unwrap());
|
|
|
|
for line in stdout.lines() {
|
|
|
|
let line = t!(line);
|
2019-02-25 11:30:32 +01:00
|
|
|
match serde_json::from_str::<CargoMessage<'_>>(&line) {
|
2020-06-10 18:59:48 +02:00
|
|
|
Ok(msg) => {
|
|
|
|
if builder.config.json_output {
|
|
|
|
// Forward JSON to stdout.
|
|
|
|
println!("{}", line);
|
|
|
|
}
|
|
|
|
cb(msg)
|
|
|
|
}
|
2018-03-15 18:58:02 +01:00
|
|
|
// If this was informational, just print it out and continue
|
2019-12-22 23:42:04 +01:00
|
|
|
Err(_) => println!("{}", line),
|
2018-03-15 18:58:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure Cargo actually succeeded after we read all of its stdout.
|
|
|
|
let status = t!(child.wait());
|
|
|
|
if !status.success() {
|
2019-12-22 23:42:04 +01:00
|
|
|
eprintln!(
|
|
|
|
"command did not execute successfully: {:?}\n\
|
2018-03-15 18:58:02 +01:00
|
|
|
expected success, got: {}",
|
2019-12-22 23:42:04 +01:00
|
|
|
cargo, status
|
|
|
|
);
|
2018-03-15 18:58:02 +01:00
|
|
|
}
|
|
|
|
status.success()
|
|
|
|
}
|
|
|
|
|
2018-12-02 21:47:41 +01:00
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct CargoTarget<'a> {
|
|
|
|
crate_types: Vec<Cow<'a, str>>,
|
|
|
|
}
|
|
|
|
|
2018-03-15 18:58:02 +01:00
|
|
|
#[derive(Deserialize)]
|
|
|
|
#[serde(tag = "reason", rename_all = "kebab-case")]
|
|
|
|
pub enum CargoMessage<'a> {
|
|
|
|
CompilerArtifact {
|
|
|
|
package_id: Cow<'a, str>,
|
|
|
|
features: Vec<Cow<'a, str>>,
|
|
|
|
filenames: Vec<Cow<'a, str>>,
|
2018-12-02 21:47:41 +01:00
|
|
|
target: CargoTarget<'a>,
|
2018-03-15 18:58:02 +01:00
|
|
|
},
|
|
|
|
BuildScriptExecuted {
|
|
|
|
package_id: Cow<'a, str>,
|
2018-12-04 19:26:54 +01:00
|
|
|
},
|
2020-04-26 01:14:58 +02:00
|
|
|
BuildFinished {
|
|
|
|
success: bool,
|
|
|
|
},
|
2018-12-04 19:26:54 +01:00
|
|
|
}
|