New upstream version 1.25.0+dfsg1

This commit is contained in:
Ximin Luo 2018-03-31 14:59:52 +02:00
parent ff7c6d114e
commit 2c00a5a8d9
4967 changed files with 236301 additions and 52557 deletions

View File

@ -301,12 +301,12 @@ It's absolutely fine to have multiple build directories with different
[pull-requests]: #pull-requests
Pull requests are the primary mechanism we use to change Rust. GitHub itself
has some [great documentation][pull-requests] on using the Pull Request feature.
has some [great documentation][about-pull-requests] on using the Pull Request feature.
We use the "fork and pull" model [described here][development-models], where
contributors push changes to their personal fork and create pull requests to
bring those changes into the source repository.
[pull-requests]: https://help.github.com/articles/about-pull-requests/
[about-pull-requests]: https://help.github.com/articles/about-pull-requests/
[development-models]: https://help.github.com/articles/about-collaborative-development-models/
Please make pull requests against the `master` branch.

View File

@ -1,16 +1,3 @@
Version 1.24.1 (2018-03-01)
==========================
- [Do not abort when unwinding through FFI][48251]
- [Emit UTF-16 files for linker arguments on Windows][48318]
- [Make the error index generator work again][48308]
- [Cargo will warn on Windows 7 if an update is needed][cargo/5069].
[48251]: https://github.com/rust-lang/rust/issues/48251
[48308]: https://github.com/rust-lang/rust/issues/48308
[48318]: https://github.com/rust-lang/rust/issues/48318
[cargo/5069]: https://github.com/rust-lang/cargo/pull/5069
Version 1.24.0 (2018-02-15)
==========================
@ -165,7 +152,6 @@ Stabilized APIs
Cargo
-----
- [Cargo now supports alternative registries][cargo/4506]
- [Cargo now supports uninstallation of multiple packages][cargo/4561]
eg. `cargo uninstall foo bar` uninstalls `foo` and `bar`.
- [Added unit test checking to `cargo check`][cargo/4592]
@ -176,7 +162,6 @@ Misc
----
- [Releases now ship with the Cargo book documentation.][45692]
- [rustdoc now prints rendering warnings on every run.][45324]
- [Release tarballs now come with rustfmt][45903]
Compatibility Notes
-------------------
@ -210,9 +195,7 @@ Compatibility Notes
[45852]: https://github.com/rust-lang/rust/issues/45852
[45853]: https://github.com/rust-lang/rust/pull/45853
[45887]: https://github.com/rust-lang/rust/pull/45887
[45903]: https://github.com/rust-lang/rust/pull/45903
[45920]: https://github.com/rust-lang/rust/pull/45920
[cargo/4506]: https://github.com/rust-lang/cargo/pull/4506
[cargo/4561]: https://github.com/rust-lang/cargo/pull/4561
[cargo/4592]: https://github.com/rust-lang/cargo/pull/4592
[cargo/4637]: https://github.com/rust-lang/cargo/pull/4637
@ -708,7 +691,7 @@ Compatibility Notes
a warning.
- [From the pound escape, lines consisting of multiple `#`s are
now visible][41785]
- [It is an error to reexport private enum variants][42460]. This is
- [It is an error to re-export private enum variants][42460]. This is
known to break a number of crates that depend on an older version of
mustache.
- [On Windows, if `VCINSTALLDIR` is set incorrectly, `rustc` will try
@ -2382,10 +2365,10 @@ Rustdoc
-------
* [Fix empty implementation section on some module pages](https://github.com/rust-lang/rust/pull/34536)
* [Fix inlined renamed reexports in import lists](https://github.com/rust-lang/rust/pull/34479)
* [Fix inlined renamed re-exports in import lists](https://github.com/rust-lang/rust/pull/34479)
* [Fix search result layout for enum variants and struct fields](https://github.com/rust-lang/rust/pull/34477)
* [Fix issues with source links to external crates](https://github.com/rust-lang/rust/pull/34387)
* [Fix redirect pages for renamed reexports](https://github.com/rust-lang/rust/pull/34245)
* [Fix redirect pages for renamed re-exports](https://github.com/rust-lang/rust/pull/34245)
Tooling
-------
@ -5119,7 +5102,7 @@ Version 0.10 (2014-04-03)
* std: The `vec` module has been renamed to `slice`.
* std: A new vector type, `Vec<T>`, has been added in preparation for DST.
This will become the only growable vector in the future.
* std: `std::io` now has more public-reexports. Types such as `BufferedReader`
* std: `std::io` now has more public re-exports. Types such as `BufferedReader`
are now found at `std::io::BufferedReader` instead of
`std::io::buffered::BufferedReader`.
* std: `print` and `println` are no longer in the prelude, the `print!` and
@ -5210,8 +5193,8 @@ Version 0.10 (2014-04-03)
* render standalone markdown files.
* the --test flag tests all code blocks by default.
* exported macros are displayed.
* reexported types have their documentation inlined at the location of the
first reexport.
* re-exported types have their documentation inlined at the location of the
first re-export.
* search works across crates that have been rendered to the same output
directory.
@ -5598,7 +5581,7 @@ Version 0.7 (2013-07-03)
incl. `any`, `all`. removed.
* std: The `finalize` method of `Drop` renamed to `drop`.
* std: The `drop` method now takes `&mut self` instead of `&self`.
* std: The prelude no longer reexports any modules, only types and traits.
* std: The prelude no longer re-exports any modules, only types and traits.
* std: Prelude additions: `print`, `println`, `FromStr`, `ApproxEq`, `Equiv`,
`Iterator`, `IteratorUtil`, many numeric traits, many tuple traits.
* std: New numeric traits: `Fractional`, `Real`, `RealExt`, `Integer`, `Ratio`,

View File

@ -151,6 +151,10 @@
# default.
#extended = false
# Installs choosen set of extended tools if enables. By default builds all.
# If choosen tool failed to build the installation fails.
#tools = ["cargo", "rls", "rustfmt", "analysis", "src"]
# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
#verbose = 0
@ -235,6 +239,11 @@
# compiler.
#codegen-units = 1
# Whether to enable ThinLTO (and increase the codegen units to either a default
# or the configured value). On by default. If we want the fastest possible
# compiler, we should disable this.
#thinlto = true
# Whether or not debug assertions are enabled for the compiler and standard
# library. Also enables compilation of debug! and trace! logging macros.
#debug-assertions = false
@ -290,7 +299,7 @@
# Flag indicating whether git info will be retrieved from .git automatically.
# Having the git information can cause a lot of rebuilds during development.
# Note: If this attribute is not explicity set (e.g. if left commented out) it
# Note: If this attribute is not explicitly set (e.g. if left commented out) it
# will default to true if channel = "dev", but will default to false otherwise.
#ignore-git = true
@ -305,6 +314,18 @@
# result (broken, compiling, testing) into this JSON file.
#save-toolstates = "/path/to/toolstates.json"
# This is an array of the codegen backends that will be compiled for the rustc
# that's being compiled. The default is to only build the LLVM codegen backend,
# but you can also optionally enable the "emscripten" backend for asm.js or
# make this an empty array (but that probably won't get too far in the
# bootstrap)
#codegen-backends = ["llvm"]
# Flag indicating whether `libstd` calls an imported function to handle basic IO
# when targeting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown`
# target, as without this option the test output will not be captured.
#wasm-syscall = false
# =============================================================================
# Options for specific targets
#
@ -332,7 +353,7 @@
#linker = "cc"
# Path to the `llvm-config` binary of the installation of a custom LLVM to link
# against. Note that if this is specifed we don't compile LLVM at all for this
# against. Note that if this is specified we don't compile LLVM at all for this
# target.
#llvm-config = "../path/to/llvm/root/bin/llvm-config"

View File

@ -1 +1 @@
d3ae9a9e08edf12de0ed82af57ba2a56c26496ea
84203cac67e65ca8640b8392348411098c856985

1072
src/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@ members = [
"rustc",
"libstd",
"libtest",
"librustc_trans",
"tools/cargotest",
"tools/clippy",
"tools/compiletest",
@ -21,6 +22,7 @@ members = [
"tools/rls",
"tools/rustfmt",
"tools/miri",
"tools/rustdoc-themes",
# FIXME(https://github.com/rust-lang/cargo/issues/4089): move these to exclude
"tools/rls/test_data/bin_lib",
"tools/rls/test_data/borrow_error",
@ -55,8 +57,18 @@ debug-assertions = false
debug = false
debug-assertions = false
# We want the RLS to use the version of Cargo that we've got vendored in this
# repository to ensure that the same exact version of Cargo is used by both the
# RLS and the Cargo binary itself. The RLS depends on Cargo as a git repository
# so we use a `[patch]` here to override the github repository with our local
# vendored copy.
[patch."https://github.com/rust-lang/cargo"]
cargo = { path = "tools/cargo" }
[patch.crates-io]
# Similar to Cargo above we want the RLS to use a vendored version of `rustfmt`
# that we're shipping as well (to ensure that the rustfmt in RLS and the
# `rustfmt` executable are the same exact vesion). Unlike Cargo, however, the
# RLS depends on `rustfmt` from crates.io, so we put this in a `[patch]` section
# for crates.io
rustfmt-nightly = { path = "tools/rustfmt" }

View File

@ -87,7 +87,7 @@ int main(int argc, const char *argv[]) {
[&trapMode](Options *o, const std::string &argument) {
try {
trapMode = trapModeFromString(argument);
} catch (std::invalid_argument e) {
} catch (std::invalid_argument& e) {
std::cerr << "Error: " << e.what() << "\n";
exit(EXIT_FAILURE);
}

View File

@ -92,7 +92,7 @@ int main(int argc, const char *argv[]) {
[&trapMode](Options *o, const std::string &argument) {
try {
trapMode = trapModeFromString(argument);
} catch (std::invalid_argument e) {
} catch (std::invalid_argument& e) {
std::cerr << "Error: " << e.what() << "\n";
exit(EXIT_FAILURE);
}

View File

@ -1408,9 +1408,9 @@ Name SExpressionWasmBuilder::getLabel(Element& s) {
uint64_t offset;
try {
offset = std::stoll(s.c_str(), nullptr, 0);
} catch (std::invalid_argument) {
} catch (std::invalid_argument&) {
throw ParseException("invalid break offset");
} catch (std::out_of_range) {
} catch (std::out_of_range&) {
throw ParseException("out of range break offset");
}
if (offset > nameMapper.labelStack.size()) throw ParseException("invalid label", s.line, s.col);

View File

@ -125,11 +125,6 @@ fn main() {
cmd.arg(format!("-Clinker={}", target_linker));
}
// Pass down incremental directory, if any.
if let Ok(dir) = env::var("RUSTC_INCREMENTAL") {
cmd.arg(format!("-Zincremental={}", dir));
}
let crate_name = args.windows(2)
.find(|a| &*a[0] == "--crate-name")
.unwrap();

View File

@ -23,10 +23,17 @@ use std::path::PathBuf;
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set");
let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set");
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
use std::str::FromStr;
let verbose = match env::var("RUSTC_VERBOSE") {
Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
Err(_) => 0,
};
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
@ -63,6 +70,10 @@ fn main() {
cmd.arg("--deny-render-differences");
}
if verbose > 1 {
eprintln!("rustdoc command: {:?}", cmd);
}
std::process::exit(match cmd.status() {
Ok(s) => s.code().unwrap_or(1),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),

View File

@ -351,11 +351,6 @@ class RustBuild(object):
with open(self.rustc_stamp(), 'w') as rust_stamp:
rust_stamp.write(self.date)
if "pc-windows-gnu" in self.build:
filename = "rust-mingw-{}-{}.tar.gz".format(
rustc_channel, self.build)
self._download_stage0_helper(filename, "rust-mingw")
if self.cargo().startswith(self.bin_root()) and \
(not os.path.exists(self.cargo()) or
self.program_out_of_date(self.cargo_stamp())):
@ -607,6 +602,7 @@ class RustBuild(object):
env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
(os.pathsep + env["LIBRARY_PATH"]) \
if "LIBRARY_PATH" in env else ""
env["RUSTFLAGS"] = "-Cdebuginfo=2"
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
os.pathsep + env["PATH"]
if not os.path.isfile(self.cargo()):
@ -644,14 +640,23 @@ class RustBuild(object):
os.path.join(self.rust_root, ".gitmodules"),
"--get-regexp", "path"]
).decode(default_encoding).splitlines()]
submodules = [module for module in submodules
if not ((module.endswith("llvm") and
self.get_toml('llvm-config')) or
(module.endswith("jemalloc") and
(self.get_toml('use-jemalloc') == "false" or
self.get_toml('jemalloc'))))]
filtered_submodules = []
for module in submodules:
if module.endswith("llvm"):
if self.get_toml('llvm-config'):
continue
if module.endswith("llvm-emscripten"):
backends = self.get_toml('codegen-backends')
if backends is None or not 'emscripten' in backends:
continue
if module.endswith("jemalloc"):
if self.get_toml('use-jemalloc') == 'false':
continue
if self.get_toml('jemalloc'):
continue
filtered_submodules.append(module)
run(["git", "submodule", "update",
"--init", "--recursive"] + submodules,
"--init", "--recursive"] + filtered_submodules,
cwd=self.rust_root, verbose=self.verbose)
run(["git", "submodule", "-q", "foreach", "git",
"reset", "-q", "--hard"],

View File

@ -26,6 +26,7 @@ use util::{exe, libdir, add_lib_path};
use {Build, Mode};
use cache::{INTERNER, Interned, Cache};
use check;
use test;
use flags::Subcommand;
use doc;
use tool;
@ -94,7 +95,7 @@ pub struct RunConfig<'a> {
pub builder: &'a Builder<'a>,
pub host: Interned<String>,
pub target: Interned<String>,
pub path: Option<&'a Path>,
pub path: PathBuf,
}
struct StepDescription {
@ -104,6 +105,32 @@ struct StepDescription {
only_build: bool,
should_run: fn(ShouldRun) -> ShouldRun,
make_run: fn(RunConfig),
name: &'static str,
}
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
struct PathSet {
set: BTreeSet<PathBuf>,
}
impl PathSet {
fn empty() -> PathSet {
PathSet { set: BTreeSet::new() }
}
fn one<P: Into<PathBuf>>(path: P) -> PathSet {
let mut set = BTreeSet::new();
set.insert(path.into());
PathSet { set }
}
fn has(&self, needle: &Path) -> bool {
self.set.iter().any(|p| p.ends_with(needle))
}
fn path(&self, builder: &Builder) -> PathBuf {
self.set.iter().next().unwrap_or(&builder.build.src).to_path_buf()
}
}
impl StepDescription {
@ -115,10 +142,18 @@ impl StepDescription {
only_build: S::ONLY_BUILD,
should_run: S::should_run,
make_run: S::make_run,
name: unsafe { ::std::intrinsics::type_name::<S>() },
}
}
fn maybe_run(&self, builder: &Builder, path: Option<&Path>) {
fn maybe_run(&self, builder: &Builder, pathset: &PathSet) {
if builder.config.exclude.iter().any(|e| pathset.has(e)) {
eprintln!("Skipping {:?} because it is excluded", pathset);
return;
} else if !builder.config.exclude.is_empty() {
eprintln!("{:?} not skipped for {:?} -- not in {:?}", pathset,
self.name, builder.config.exclude);
}
let build = builder.build;
let hosts = if self.only_build_targets || self.only_build {
build.build_triple()
@ -143,7 +178,7 @@ impl StepDescription {
for target in targets {
let run = RunConfig {
builder,
path,
path: pathset.path(builder),
host: *host,
target: *target,
};
@ -156,24 +191,33 @@ impl StepDescription {
let should_runs = v.iter().map(|desc| {
(desc.should_run)(ShouldRun::new(builder))
}).collect::<Vec<_>>();
// sanity checks on rules
for (desc, should_run) in v.iter().zip(&should_runs) {
assert!(!should_run.paths.is_empty(),
"{:?} should have at least one pathset", desc.name);
}
if paths.is_empty() {
for (desc, should_run) in v.iter().zip(should_runs) {
if desc.default && should_run.is_really_default {
desc.maybe_run(builder, None);
for pathset in &should_run.paths {
desc.maybe_run(builder, pathset);
}
}
}
} else {
for path in paths {
let mut attempted_run = false;
for (desc, should_run) in v.iter().zip(&should_runs) {
if should_run.run(path) {
if let Some(pathset) = should_run.pathset_for_path(path) {
attempted_run = true;
desc.maybe_run(builder, Some(path));
desc.maybe_run(builder, pathset);
}
}
if !attempted_run {
eprintln!("Warning: no rules matched {}.", path.display());
panic!("Error: no rules matched {}.", path.display());
}
}
}
@ -184,7 +228,7 @@ impl StepDescription {
pub struct ShouldRun<'a> {
pub builder: &'a Builder<'a>,
// use a BTreeSet to maintain sort order
paths: BTreeSet<PathBuf>,
paths: BTreeSet<PathSet>,
// If this is a default rule, this is an additional constraint placed on
// it's run. Generally something like compiler docs being enabled.
@ -205,31 +249,53 @@ impl<'a> ShouldRun<'a> {
self
}
// Unlike `krate` this will create just one pathset. As such, it probably shouldn't actually
// ever be used, but as we transition to having all rules properly handle passing krate(...) by
// actually doing something different for every crate passed.
pub fn all_krates(mut self, name: &str) -> Self {
let mut set = BTreeSet::new();
for krate in self.builder.in_tree_crates(name) {
set.insert(PathBuf::from(&krate.path));
}
self.paths.insert(PathSet { set });
self
}
pub fn krate(mut self, name: &str) -> Self {
for (_, krate_path) in self.builder.crates(name) {
self.paths.insert(PathBuf::from(krate_path));
for krate in self.builder.in_tree_crates(name) {
self.paths.insert(PathSet::one(&krate.path));
}
self
}
pub fn path(mut self, path: &str) -> Self {
self.paths.insert(PathBuf::from(path));
// single, non-aliased path
pub fn path(self, path: &str) -> Self {
self.paths(&[path])
}
// multiple aliases for the same job
pub fn paths(mut self, paths: &[&str]) -> Self {
self.paths.insert(PathSet {
set: paths.iter().map(PathBuf::from).collect(),
});
self
}
// allows being more explicit about why should_run in Step returns the value passed to it
pub fn never(self) -> ShouldRun<'a> {
pub fn never(mut self) -> ShouldRun<'a> {
self.paths.insert(PathSet::empty());
self
}
fn run(&self, path: &Path) -> bool {
self.paths.iter().any(|p| path.ends_with(p))
fn pathset_for_path(&self, path: &Path) -> Option<&PathSet> {
self.paths.iter().find(|pathset| pathset.has(path))
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Kind {
Build,
Check,
Test,
Bench,
Dist,
@ -251,18 +317,24 @@ impl<'a> Builder<'a> {
tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient,
tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy,
native::Llvm, tool::Rustfmt, tool::Miri),
Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest,
check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Rustdoc,
check::Linkcheck, check::Cargotest, check::Cargo, check::Rls, check::Docs,
check::ErrorIndex, check::Distcheck, check::Rustfmt, check::Miri, check::Clippy),
Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
Kind::Check => describe!(check::Std, check::Test, check::Rustc),
Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass,
test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind,
test::MirOpt, test::Codegen, test::CodegenUnits, test::Incremental, test::Debuginfo,
test::UiFullDeps, test::RunPassFullDeps, test::RunFailFullDeps,
test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty,
test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty,
test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake,
test::Crate, test::CrateLibrustc, test::Rustdoc, test::Linkcheck, test::Cargotest,
test::Cargo, test::Rls, test::Docs, test::ErrorIndex, test::Distcheck,
test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme),
Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
doc::Reference, doc::Rustdoc, doc::CargoBook),
doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook),
Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign,
dist::DontDistWithMiriEnabled),
dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign),
Kind::Install => describe!(install::Docs, install::Std, install::Cargo, install::Rls,
install::Rustfmt, install::Analysis, install::Src, install::Rustc),
}
@ -293,8 +365,10 @@ impl<'a> Builder<'a> {
should_run = (desc.should_run)(should_run);
}
let mut help = String::from("Available paths:\n");
for path in should_run.paths {
help.push_str(format!(" ./x.py {} {}\n", subcommand, path.display()).as_str());
for pathset in should_run.paths {
for path in pathset.set {
help.push_str(format!(" ./x.py {} {}\n", subcommand, path.display()).as_str());
}
}
Some(help)
}
@ -302,6 +376,7 @@ impl<'a> Builder<'a> {
pub fn run(build: &Build) {
let (kind, paths) = match build.config.cmd {
Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
@ -310,6 +385,12 @@ impl<'a> Builder<'a> {
Subcommand::Clean { .. } => panic!(),
};
if let Some(path) = paths.get(0) {
if path == Path::new("nonexistent/path/to/trigger/cargo/metadata") {
return;
}
}
let builder = Builder {
build,
top_stage: build.config.stage.unwrap_or(2),
@ -318,6 +399,12 @@ impl<'a> Builder<'a> {
stack: RefCell::new(Vec::new()),
};
if kind == Kind::Dist {
assert!(!build.config.test_miri, "Do not distribute with miri enabled.\n\
The distributed libraries would include all MIR (increasing binary size).
The distributed MIR would include validation statements.");
}
StepDescription::run(&Builder::get_step_descriptions(builder.kind), &builder, paths);
}
@ -357,10 +444,11 @@ impl<'a> Builder<'a> {
fn run(self, builder: &Builder) -> Interned<PathBuf> {
let compiler = self.compiler;
let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() {
builder.build.config.libdir_relative.clone().unwrap()
let config = &builder.build.config;
let lib = if compiler.stage >= 1 && config.libdir_relative().is_some() {
builder.build.config.libdir_relative().unwrap()
} else {
PathBuf::from("lib")
Path::new("lib")
};
let sysroot = builder.sysroot(self.compiler).join(lib)
.join("rustlib").join(self.target).join("lib");
@ -372,6 +460,11 @@ impl<'a> Builder<'a> {
self.ensure(Libdir { compiler, target })
}
pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
self.sysroot_libdir(compiler, compiler.host)
.with_file_name("codegen-backends")
}
/// Returns the compiler's libdir where it stores the dynamic libraries that
/// it itself links against.
///
@ -416,7 +509,7 @@ impl<'a> Builder<'a> {
let compiler = self.compiler(self.top_stage, host);
cmd.env("RUSTC_STAGE", compiler.stage.to_string())
.env("RUSTC_SYSROOT", self.sysroot(compiler))
.env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
.env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
.env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
.env("RUSTDOC_REAL", self.rustdoc(host))
.env("RUSTDOC_CRATE_VERSION", self.build.rust_version())
@ -443,7 +536,8 @@ impl<'a> Builder<'a> {
let out_dir = self.stage_out(compiler, mode);
cargo.env("CARGO_TARGET_DIR", out_dir)
.arg(cmd)
.arg("--target").arg(target);
.arg("--target")
.arg(target);
// If we were invoked from `make` then that's already got a jobserver
// set up for us so no need to tell Cargo about jobs all over again.
@ -463,6 +557,18 @@ impl<'a> Builder<'a> {
stage = compiler.stage;
}
let mut extra_args = env::var(&format!("RUSTFLAGS_STAGE_{}", stage)).unwrap_or_default();
if stage != 0 {
let s = env::var("RUSTFLAGS_STAGE_NOT_0").unwrap_or_default();
extra_args.push_str(" ");
extra_args.push_str(&s);
}
if !extra_args.is_empty() {
cargo.env("RUSTFLAGS",
format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args));
}
// Customize the compiler we're running. Specify the compiler to cargo
// as our shim and then pass it some various options used to configure
// how the actual compiler itself is called.
@ -486,9 +592,6 @@ impl<'a> Builder<'a> {
})
.env("TEST_MIRI", self.config.test_miri.to_string())
.env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir());
if let Some(n) = self.config.rust_codegen_units {
cargo.env("RUSTC_CODEGEN_UNITS", n.to_string());
}
if let Some(host_linker) = self.build.linker(compiler.host) {
cargo.env("RUSTC_HOST_LINKER", host_linker);
@ -496,6 +599,9 @@ impl<'a> Builder<'a> {
if let Some(target_linker) = self.build.linker(target) {
cargo.env("RUSTC_TARGET_LINKER", target_linker);
}
if cmd != "build" && cmd != "check" {
cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.build.build)));
}
if mode != Mode::Tool {
// Tools don't get debuginfo right now, e.g. cargo and rls don't
@ -547,7 +653,7 @@ impl<'a> Builder<'a> {
// build scripts in that situation.
//
// If LLVM support is disabled we need to use the snapshot compiler to compile
// build scripts, as the new compiler doesnt support executables.
// build scripts, as the new compiler doesn't support executables.
if mode == Mode::Libstd || !self.build.config.llvm_enabled {
cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc)
.env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
@ -560,8 +666,7 @@ impl<'a> Builder<'a> {
// not guaranteeing correctness across builds if the compiler
// is changing under your feet.`
if self.config.incremental && compiler.stage == 0 {
let incr_dir = self.incremental_dir(compiler);
cargo.env("RUSTC_INCREMENTAL", incr_dir);
cargo.env("CARGO_INCREMENTAL", "1");
}
if let Some(ref on_fail) = self.config.on_fail {
@ -617,9 +722,49 @@ impl<'a> Builder<'a> {
// Set this for all builds to make sure doc builds also get it.
cargo.env("CFG_RELEASE_CHANNEL", &self.build.config.channel);
// This one's a bit tricky. As of the time of this writing the compiler
// links to the `winapi` crate on crates.io. This crate provides raw
// bindings to Windows system functions, sort of like libc does for
// Unix. This crate also, however, provides "import libraries" for the
// MinGW targets. There's an import library per dll in the windows
// distribution which is what's linked to. These custom import libraries
// are used because the winapi crate can reference Windows functions not
// present in the MinGW import libraries.
//
// For example MinGW may ship libdbghelp.a, but it may not have
// references to all the functions in the dbghelp dll. Instead the
// custom import library for dbghelp in the winapi crates has all this
// information.
//
// Unfortunately for us though the import libraries are linked by
// default via `-ldylib=winapi_foo`. That is, they're linked with the
// `dylib` type with a `winapi_` prefix (so the winapi ones don't
// conflict with the system MinGW ones). This consequently means that
// the binaries we ship of things like rustc_trans (aka the rustc_trans
// DLL) when linked against *again*, for example with procedural macros
// or plugins, will trigger the propagation logic of `-ldylib`, passing
// `-lwinapi_foo` to the linker again. This isn't actually available in
// our distribution, however, so the link fails.
//
// To solve this problem we tell winapi to not use its bundled import
// libraries. This means that it will link to the system MinGW import
// libraries by default, and the `-ldylib=foo` directives will still get
// passed to the final linker, but they'll look like `-lfoo` which can
// be resolved because MinGW has the import library. The downside is we
// don't get newer functions from Windows, but we don't use any of them
// anyway.
cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
if self.is_very_verbose() {
cargo.arg("-v");
}
// This must be kept before the thinlto check, as we set codegen units
// to 1 forcibly there.
if let Some(n) = self.config.rust_codegen_units {
cargo.env("RUSTC_CODEGEN_UNITS", n.to_string());
}
if self.config.rust_optimize {
// FIXME: cargo bench does not accept `--release`
if cmd != "bench" {
@ -627,11 +772,17 @@ impl<'a> Builder<'a> {
}
if self.config.rust_codegen_units.is_none() &&
self.build.is_rust_llvm(compiler.host)
{
self.build.is_rust_llvm(compiler.host) &&
self.config.rust_thinlto {
cargo.env("RUSTC_THINLTO", "1");
} else if self.config.rust_codegen_units.is_none() {
// Generally, if ThinLTO has been disabled for some reason, we
// want to set the codegen units to 1. However, we shouldn't do
// this if the option was specifically set by the user.
cargo.env("RUSTC_CODEGEN_UNITS", "1");
}
}
if self.config.locked_deps {
cargo.arg("--locked");
}

View File

@ -24,7 +24,7 @@ use Build;
use config::Config;
// The version number
pub const CFG_RELEASE_NUM: &str = "1.24.1";
pub const CFG_RELEASE_NUM: &str = "1.25.0";
pub struct GitInfo {
inner: Option<Info>,

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@ impl Step for Std {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path("src/libstd").krate("std")
run.all_krates("std")
}
fn make_run(run: RunConfig) {
@ -80,7 +80,7 @@ impl Step for Std {
// Even if we're not building std this stage, the new sysroot must
// still contain the musl startup objects.
if target.contains("musl") && !target.contains("mips") {
if target.contains("musl") {
let libdir = builder.sysroot_libdir(compiler, target);
copy_musl_third_party_objects(build, target, &libdir);
}
@ -97,7 +97,7 @@ impl Step for Std {
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
&compiler.host, target);
if target.contains("musl") && !target.contains("mips") {
if target.contains("musl") {
let libdir = builder.sysroot_libdir(compiler, target);
copy_musl_third_party_objects(build, target, &libdir);
}
@ -108,7 +108,8 @@ impl Step for Std {
std_cargo(build, &compiler, target, &mut cargo);
run_cargo(build,
&mut cargo,
&libstd_stamp(build, compiler, target));
&libstd_stamp(build, compiler, target),
false);
builder.ensure(StdLink {
compiler: builder.compiler(compiler.stage, build.build),
@ -299,7 +300,11 @@ impl Step for StartupObjects {
}
for obj in ["crt2.o", "dllcrt2.o"].iter() {
copy(&compiler_file(build.cc(target), obj), &sysroot_dir.join(obj));
let src = compiler_file(build,
build.cc(target),
target,
obj);
copy(&src, &sysroot_dir.join(obj));
}
}
}
@ -315,7 +320,7 @@ impl Step for Test {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path("src/libtest").krate("test")
run.all_krates("test")
}
fn make_run(run: RunConfig) {
@ -360,7 +365,8 @@ impl Step for Test {
test_cargo(build, &compiler, target, &mut cargo);
run_cargo(build,
&mut cargo,
&libtest_stamp(build, compiler, target));
&libtest_stamp(build, compiler, target),
false);
builder.ensure(TestLink {
compiler: builder.compiler(compiler.stage, build.build),
@ -430,7 +436,7 @@ impl Step for Rustc {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path("src/librustc").krate("rustc-main")
run.all_krates("rustc-main")
}
fn make_run(run: RunConfig) {
@ -452,10 +458,6 @@ impl Step for Rustc {
builder.ensure(Test { compiler, target });
// Build LLVM for our target. This will implicitly build the host LLVM
// if necessary.
builder.ensure(native::Llvm { target });
if build.force_use_stage1(compiler, target) {
builder.ensure(Rustc {
compiler: builder.compiler(1, build.build),
@ -485,10 +487,11 @@ impl Step for Rustc {
build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
rustc_cargo(build, &compiler, target, &mut cargo);
rustc_cargo(build, &mut cargo);
run_cargo(build,
&mut cargo,
&librustc_stamp(build, compiler, target));
&librustc_stamp(build, compiler, target),
false);
builder.ensure(RustcLink {
compiler: builder.compiler(compiler.stage, build.build),
@ -498,15 +501,14 @@ impl Step for Rustc {
}
}
/// Same as `std_cargo`, but for libtest
pub fn rustc_cargo(build: &Build,
compiler: &Compiler,
target: Interned<String>,
cargo: &mut Command) {
pub fn rustc_cargo(build: &Build, cargo: &mut Command) {
cargo.arg("--features").arg(build.rustc_features())
.arg("--manifest-path")
.arg(build.src.join("src/rustc/Cargo.toml"));
rustc_cargo_env(build, cargo);
}
fn rustc_cargo_env(build: &Build, cargo: &mut Command) {
// Set some configuration variables picked up by build scripts and
// the compiler alike
cargo.env("CFG_RELEASE", build.rust_release())
@ -514,13 +516,8 @@ pub fn rustc_cargo(build: &Build,
.env("CFG_VERSION", build.rust_version())
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
if compiler.stage == 0 {
cargo.env("CFG_LIBDIR_RELATIVE", "lib");
} else {
let libdir_relative =
build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib"));
cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
}
let libdir_relative = build.config.libdir_relative().unwrap_or(Path::new("lib"));
cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
// If we're not building a compiler with debugging information then remove
// these two env vars which would be set otherwise.
@ -538,27 +535,6 @@ pub fn rustc_cargo(build: &Build,
if !build.unstable_features() {
cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
}
// Flag that rust llvm is in use
if build.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
cargo.env("LLVM_CONFIG", build.llvm_config(target));
let target_config = build.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);
}
// Building with a static libstdc++ is only supported on linux right now,
// not for MSVC or macOS
if build.config.llvm_static_stdcpp &&
!target.contains("freebsd") &&
!target.contains("windows") &&
!target.contains("apple") {
cargo.env("LLVM_STATIC_STDCPP",
compiler_file(build.cxx(target).unwrap(), "libstdc++.a"));
}
if build.config.llvm_link_shared {
cargo.env("LLVM_LINK_SHARED", "1");
}
if let Some(ref s) = build.config.rustc_default_linker {
cargo.env("CFG_DEFAULT_LINKER", s);
}
@ -603,6 +579,172 @@ impl Step for RustcLink {
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CodegenBackend {
pub compiler: Compiler,
pub target: Interned<String>,
pub backend: Interned<String>,
}
impl Step for CodegenBackend {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.all_krates("rustc_trans")
}
fn make_run(run: RunConfig) {
let backend = run.builder.config.rust_codegen_backends.get(0);
let backend = backend.cloned().unwrap_or_else(|| {
INTERNER.intern_str("llvm")
});
run.builder.ensure(CodegenBackend {
compiler: run.builder.compiler(run.builder.top_stage, run.host),
target: run.target,
backend
});
}
fn run(self, builder: &Builder) {
let build = builder.build;
let compiler = self.compiler;
let target = self.target;
builder.ensure(Rustc { compiler, target });
if build.force_use_stage1(compiler, target) {
builder.ensure(CodegenBackend {
compiler: builder.compiler(1, build.build),
target,
backend: self.backend,
});
return;
}
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
let mut features = build.rustc_features().to_string();
cargo.arg("--manifest-path")
.arg(build.src.join("src/librustc_trans/Cargo.toml"));
rustc_cargo_env(build, &mut cargo);
match &*self.backend {
"llvm" | "emscripten" => {
// Build LLVM for our target. This will implicitly build the
// host LLVM if necessary.
let llvm_config = builder.ensure(native::Llvm {
target,
emscripten: self.backend == "emscripten",
});
if self.backend == "emscripten" {
features.push_str(" emscripten");
}
let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
println!("Building stage{} codegen artifacts ({} -> {}, {})",
compiler.stage, &compiler.host, target, self.backend);
// Pass down configuration from the LLVM build into the build of
// librustc_llvm and librustc_trans.
if build.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
cargo.env("LLVM_CONFIG", &llvm_config);
if self.backend != "emscripten" {
let target_config = build.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);
}
}
// Building with a static libstdc++ is only supported on linux right now,
// not for MSVC or macOS
if build.config.llvm_static_stdcpp &&
!target.contains("freebsd") &&
!target.contains("windows") &&
!target.contains("apple") {
let file = compiler_file(build,
build.cxx(target).unwrap(),
target,
"libstdc++.a");
cargo.env("LLVM_STATIC_STDCPP", file);
}
if build.config.llvm_link_shared {
cargo.env("LLVM_LINK_SHARED", "1");
}
}
_ => panic!("unknown backend: {}", self.backend),
}
let tmp_stamp = build.cargo_out(compiler, Mode::Librustc, target)
.join(".tmp.stamp");
let files = run_cargo(build,
cargo.arg("--features").arg(features),
&tmp_stamp,
false);
let mut files = files.into_iter()
.filter(|f| {
let filename = f.file_name().unwrap().to_str().unwrap();
is_dylib(filename) && filename.contains("rustc_trans-")
});
let codegen_backend = match files.next() {
Some(f) => f,
None => panic!("no dylibs built for codegen backend?"),
};
if let Some(f) = files.next() {
panic!("codegen backend built two dylibs:\n{}\n{}",
codegen_backend.display(),
f.display());
}
let stamp = codegen_backend_stamp(build, compiler, target, self.backend);
let codegen_backend = codegen_backend.to_str().unwrap();
t!(t!(File::create(&stamp)).write_all(codegen_backend.as_bytes()));
}
}
/// Creates the `codegen-backends` folder for a compiler that's about to be
/// assembled as a complete compiler.
///
/// This will take the codegen artifacts produced by `compiler` and link them
/// into an appropriate location for `target_compiler` to be a functional
/// compiler.
fn copy_codegen_backends_to_sysroot(builder: &Builder,
compiler: Compiler,
target_compiler: Compiler) {
let build = builder.build;
let target = target_compiler.host;
// Note that this step is different than all the other `*Link` steps in
// that it's not assembling a bunch of libraries but rather is primarily
// moving the codegen backend into place. The codegen backend of rustc is
// not linked into the main compiler by default but is rather dynamically
// selected at runtime for inclusion.
//
// Here we're looking for the output dylib of the `CodegenBackend` step and
// we're copying that into the `codegen-backends` folder.
let dst = builder.sysroot_codegen_backends(target_compiler);
t!(fs::create_dir_all(&dst));
for backend in builder.config.rust_codegen_backends.iter() {
let stamp = codegen_backend_stamp(build, compiler, target, *backend);
let mut dylib = String::new();
t!(t!(File::open(&stamp)).read_to_string(&mut dylib));
let file = Path::new(&dylib);
let filename = file.file_name().unwrap().to_str().unwrap();
// change `librustc_trans-xxxxxx.so` to `librustc_trans-llvm.so`
let target_filename = {
let dash = filename.find("-").unwrap();
let dot = filename.find(".").unwrap();
format!("{}-{}{}",
&filename[..dash],
backend,
&filename[dot..])
};
copy(&file, &dst.join(target_filename));
}
}
/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
@ -621,9 +763,22 @@ pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned<String
build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
}
fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
let out = output(Command::new(compiler)
.arg(format!("-print-file-name={}", file)));
fn codegen_backend_stamp(build: &Build,
compiler: Compiler,
target: Interned<String>,
backend: Interned<String>) -> PathBuf {
build.cargo_out(compiler, Mode::Librustc, target)
.join(format!(".librustc_trans-{}.stamp", backend))
}
fn compiler_file(build: &Build,
compiler: &Path,
target: Interned<String>,
file: &str) -> PathBuf {
let mut cmd = Command::new(compiler);
cmd.args(build.cflags(target));
cmd.arg(format!("-print-file-name={}", file));
let out = output(&mut cmd);
PathBuf::from(out.trim())
}
@ -672,7 +827,7 @@ impl Step for Assemble {
type Output = Compiler;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path("src/rustc")
run.all_krates("rustc-main")
}
/// Prepare a new compiler from the artifacts in `stage`
@ -692,20 +847,23 @@ impl Step for Assemble {
}
// Get the compiler that we'll use to bootstrap ourselves.
let build_compiler = if target_compiler.host != build.build {
// Build a compiler for the host platform. We cannot use the stage0
// compiler for the host platform for this because it doesn't have
// the libraries we need. 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.
builder.compiler(target_compiler.stage - 1, build.build)
} else {
// Build the compiler we'll use to build the stage requested. This
// may build more than one compiler (going down to stage 0).
builder.compiler(target_compiler.stage - 1, target_compiler.host)
};
//
// 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.
let build_compiler =
builder.compiler(target_compiler.stage - 1, build.build);
// 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
@ -723,7 +881,17 @@ impl Step for Assemble {
builder.ensure(RustcLink { compiler, target_compiler, target });
}
} else {
builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host });
builder.ensure(Rustc {
compiler: build_compiler,
target: target_compiler.host,
});
for &backend in build.config.rust_codegen_backends.iter() {
builder.ensure(CodegenBackend {
compiler: build_compiler,
target: target_compiler.host,
backend,
});
}
}
let stage = target_compiler.stage;
@ -742,9 +910,12 @@ impl Step for Assemble {
}
}
let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
copy_codegen_backends_to_sysroot(builder,
build_compiler,
target_compiler);
// Link the compiler binary itself into place
let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
let rustc = out_dir.join(exe("rustc", &*host));
let bindir = sysroot.join("bin");
t!(fs::create_dir_all(&bindir));
@ -760,7 +931,7 @@ impl Step for Assemble {
///
/// For a particular stage this will link the file listed in `stamp` into the
/// `sysroot_dst` provided.
fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
pub fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
t!(fs::create_dir_all(&sysroot_dst));
for path in read_stamp_file(stamp) {
copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
@ -790,7 +961,9 @@ fn stderr_isatty() -> bool {
}
}
fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: bool)
-> Vec<PathBuf>
{
// Instruct Cargo to give us json messages on stdout, critically leaving
// stderr as piped so we can get those pretty colors.
cargo.arg("--message-format").arg("json")
@ -841,7 +1014,8 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
// Skip files like executables
if !filename.ends_with(".rlib") &&
!filename.ends_with(".lib") &&
!is_dylib(&filename) {
!is_dylib(&filename) &&
!(is_check && filename.ends_with(".rmeta")) {
continue
}
@ -933,8 +1107,8 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
let mut new_contents = Vec::new();
let mut max = None;
let mut max_path = None;
for dep in deps {
let mtime = mtime(&dep);
for dep in deps.iter() {
let mtime = mtime(dep);
if Some(mtime) > max {
max = Some(mtime);
max_path = Some(dep.clone());
@ -947,7 +1121,7 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
if stamp_contents == new_contents && max <= stamp_mtime {
build.verbose(&format!("not updating {:?}; contents equal and {} <= {}",
stamp, max, stamp_mtime));
return
return deps
}
if max > stamp_mtime {
build.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
@ -955,4 +1129,5 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
build.verbose(&format!("updating {:?} as deps changed", stamp));
}
t!(t!(File::create(stamp)).write_all(&new_contents));
deps
}

View File

@ -13,11 +13,11 @@
//! This module implements parsing `config.toml` configuration files to tweak
//! how the build runs.
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process;
use std::cmp;
@ -52,9 +52,11 @@ pub struct Config {
pub target_config: HashMap<Interned<String>, Target>,
pub full_bootstrap: bool,
pub extended: bool,
pub tools: Option<HashSet<String>>,
pub sanitizers: bool,
pub profiler: bool,
pub ignore_git: bool,
pub exclude: Vec<PathBuf>,
pub run_host_only: bool,
@ -81,6 +83,7 @@ pub struct Config {
// rust codegen options
pub rust_optimize: bool,
pub rust_codegen_units: Option<u32>,
pub rust_thinlto: bool,
pub rust_debug_assertions: bool,
pub rust_debuginfo: bool,
pub rust_debuginfo_lines: bool,
@ -91,6 +94,7 @@ pub struct Config {
pub rust_optimize_tests: bool,
pub rust_debuginfo_tests: bool,
pub rust_dist_src: bool,
pub rust_codegen_backends: Vec<Interned<String>>,
pub build: Interned<String>,
pub hosts: Vec<Interned<String>>,
@ -106,6 +110,7 @@ pub struct Config {
pub debug_jemalloc: bool,
pub use_jemalloc: bool,
pub backtrace: bool, // support for RUST_BACKTRACE
pub wasm_syscall: bool,
// misc
pub low_priority: bool,
@ -118,10 +123,10 @@ pub struct Config {
pub musl_root: Option<PathBuf>,
pub prefix: Option<PathBuf>,
pub sysconfdir: Option<PathBuf>,
pub datadir: Option<PathBuf>,
pub docdir: Option<PathBuf>,
pub bindir: Option<PathBuf>,
pub libdir: Option<PathBuf>,
pub libdir_relative: Option<PathBuf>,
pub mandir: Option<PathBuf>,
pub codegen_tests: bool,
pub nodejs: Option<PathBuf>,
@ -189,6 +194,7 @@ struct Build {
python: Option<String>,
full_bootstrap: Option<bool>,
extended: Option<bool>,
tools: Option<HashSet<String>>,
verbose: Option<usize>,
sanitizers: Option<bool>,
profiler: Option<bool>,
@ -203,13 +209,13 @@ struct Build {
struct Install {
prefix: Option<String>,
sysconfdir: Option<String>,
datadir: Option<String>,
docdir: Option<String>,
bindir: Option<String>,
libdir: Option<String>,
mandir: Option<String>,
// standard paths, currently unused
datadir: Option<String>,
infodir: Option<String>,
localstatedir: Option<String>,
}
@ -260,6 +266,7 @@ impl Default for StringOrBool {
struct Rust {
optimize: Option<bool>,
codegen_units: Option<u32>,
thinlto: Option<bool>,
debug_assertions: Option<bool>,
debuginfo: Option<bool>,
debuginfo_lines: Option<bool>,
@ -281,6 +288,8 @@ struct Rust {
quiet_tests: Option<bool>,
test_miri: Option<bool>,
save_toolstates: Option<String>,
codegen_backends: Option<Vec<String>>,
wasm_syscall: Option<bool>,
}
/// TOML representation of how each build target is configured.
@ -304,6 +313,7 @@ impl Config {
let flags = Flags::parse(&args);
let file = flags.config.clone();
let mut config = Config::default();
config.exclude = flags.exclude;
config.llvm_enabled = true;
config.llvm_optimize = true;
config.llvm_version_check = true;
@ -319,6 +329,7 @@ impl Config {
config.ignore_git = false;
config.rust_dist_src = true;
config.test_miri = false;
config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
config.on_fail = flags.on_fail;
config.stage = flags.stage;
@ -389,6 +400,7 @@ impl Config {
set(&mut config.vendor, build.vendor);
set(&mut config.full_bootstrap, build.full_bootstrap);
set(&mut config.extended, build.extended);
config.tools = build.tools;
set(&mut config.verbose, build.verbose);
set(&mut config.sanitizers, build.sanitizers);
set(&mut config.profiler, build.profiler);
@ -400,6 +412,7 @@ impl Config {
if let Some(ref install) = toml.install {
config.prefix = install.prefix.clone().map(PathBuf::from);
config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from);
config.datadir = install.datadir.clone().map(PathBuf::from);
config.docdir = install.docdir.clone().map(PathBuf::from);
config.bindir = install.bindir.clone().map(PathBuf::from);
config.libdir = install.libdir.clone().map(PathBuf::from);
@ -408,6 +421,7 @@ impl Config {
// Store off these values as options because if they're not provided
// we'll infer default values for them later
let mut thinlto = None;
let mut llvm_assertions = None;
let mut debuginfo_lines = None;
let mut debuginfo_only_std = None;
@ -451,6 +465,7 @@ impl Config {
optimize = rust.optimize;
ignore_git = rust.ignore_git;
debug_jemalloc = rust.debug_jemalloc;
thinlto = rust.thinlto;
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
set(&mut config.codegen_tests, rust.codegen_tests);
@ -461,11 +476,18 @@ impl Config {
set(&mut config.rust_dist_src, rust.dist_src);
set(&mut config.quiet_tests, rust.quiet_tests);
set(&mut config.test_miri, rust.test_miri);
set(&mut config.wasm_syscall, rust.wasm_syscall);
config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false);
config.rustc_default_linker = rust.default_linker.clone();
config.musl_root = rust.musl_root.clone().map(PathBuf::from);
config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
if let Some(ref backends) = rust.codegen_backends {
config.rust_codegen_backends = backends.iter()
.map(|s| INTERNER.intern_str(s))
.collect();
}
match rust.codegen_units {
Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32),
Some(n) => config.rust_codegen_units = Some(n),
@ -528,6 +550,7 @@ impl Config {
"stable" | "beta" | "nightly" => true,
_ => false,
};
config.rust_thinlto = thinlto.unwrap_or(true);
config.rust_debuginfo_lines = debuginfo_lines.unwrap_or(default);
config.rust_debuginfo_only_std = debuginfo_only_std.unwrap_or(default);
@ -543,6 +566,17 @@ impl Config {
config
}
/// Try to find the relative path of `libdir`.
pub fn libdir_relative(&self) -> Option<&Path> {
let libdir = self.libdir.as_ref()?;
if libdir.is_relative() {
Some(libdir)
} else {
// Try to make it relative to the prefix.
libdir.strip_prefix(self.prefix.as_ref()?).ok()
}
}
pub fn verbose(&self) -> bool {
self.verbose > 0
}

View File

@ -65,10 +65,12 @@ o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, lsan, m
o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball")
o("cargo-openssl-static", "build.openssl-static", "static openssl in cargo")
o("profiler", "build.profiler", "build the profiler runtime")
o("emscripten", None, "compile the emscripten backend as well as LLVM")
# Optimization and debugging options. These may be overridden by the release
# channel, etc.
o("optimize", "rust.optimize", "build optimized rust code")
o("thinlto", "rust.thinlto", "build Rust with ThinLTO enabled")
o("optimize-llvm", "llvm.optimize", "build optimized LLVM")
o("llvm-assertions", "llvm.assertions", "build LLVM with assertions")
o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
@ -108,6 +110,8 @@ v("musl-root", "target.x86_64-unknown-linux-musl.musl-root",
"MUSL root installation directory (deprecated)")
v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",
"x86_64-unknown-linux-musl install directory")
v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root",
"i586-unknown-linux-musl install directory")
v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root",
"i686-unknown-linux-musl install directory")
v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
@ -118,6 +122,10 @@ v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root",
"armv7-unknown-linux-musleabihf install directory")
v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root",
"aarch64-unknown-linux-musl install directory")
v("musl-root-mips", "target.mips-unknown-linux-musl.musl-root",
"mips-unknown-linux-musl install directory")
v("musl-root-mipsel", "target.mipsel-unknown-linux-musl.musl-root",
"mipsel-unknown-linux-musl install directory")
v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this")
v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
@ -136,6 +144,7 @@ o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc")
o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two")
o("extended", "build.extended", "build an extended rust tool set")
v("tools", "build.tools", "List of extended tools will be installed")
v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
v("host", None, "GNUs ./configure syntax LLVM host triples")
v("target", None, "GNUs ./configure syntax LLVM target triples")
@ -315,6 +324,8 @@ for key in known_args:
set('build.host', value.split(','))
elif option.name == 'target':
set('build.target', value.split(','))
elif option.name == 'emscripten':
set('rust.codegen-backends', ['llvm', 'emscripten'])
elif option.name == 'option-checking':
# this was handled above
pass

View File

@ -31,6 +31,7 @@ use channel;
use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file};
use builder::{Builder, RunConfig, ShouldRun, Step};
use compile;
use native;
use tool::{self, Tool};
use cache::{INTERNER, Interned};
use time;
@ -225,6 +226,8 @@ fn make_win_dist(
"libwinspool.a",
"libws2_32.a",
"libwsock32.a",
"libdbghelp.a",
"libmsimg32.a",
];
//Find mingw artifacts we want to bundle
@ -433,6 +436,13 @@ impl Step for Rustc {
}
}
// Copy over the codegen backends
let backends_src = builder.sysroot_codegen_backends(compiler);
let backends_rel = backends_src.strip_prefix(&src).unwrap();
let backends_dst = image.join(&backends_rel);
t!(fs::create_dir_all(&backends_dst));
cp_r(&backends_src, &backends_dst);
// Man pages
t!(fs::create_dir_all(image.join("share/man/man1")));
let man_src = build.src.join("src/doc/man");
@ -579,7 +589,9 @@ impl Step for Std {
t!(fs::create_dir_all(&dst));
let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
cp_r(&src, &dst);
cp_filtered(&src, &dst, &|path| {
path.file_name().and_then(|s| s.to_str()) != Some("codegen-backends")
});
let mut cmd = rust_installer(builder);
cmd.arg("generate")
@ -887,6 +899,12 @@ impl Step for PlainSourceTarball {
.arg("--vers").arg(CARGO_VENDOR_VERSION)
.arg("cargo-vendor")
.env("RUSTC", &build.initial_rustc);
if let Some(dir) = build.openssl_install_dir(build.config.build) {
builder.ensure(native::Openssl {
target: build.config.build,
});
cmd.env("OPENSSL_DIR", dir);
}
build.run(&mut cmd);
}
@ -1215,31 +1233,6 @@ impl Step for Rustfmt {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct DontDistWithMiriEnabled;
impl Step for DontDistWithMiriEnabled {
type Output = PathBuf;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
let build_miri = run.builder.build.config.test_miri;
run.default_condition(build_miri)
}
fn make_run(run: RunConfig) {
run.builder.ensure(DontDistWithMiriEnabled);
}
fn run(self, _: &Builder) -> PathBuf {
panic!("Do not distribute with miri enabled.\n\
The distributed libraries would include all MIR (increasing binary size).
The distributed MIR would include validation statements.");
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Extended {
stage: u32,

View File

@ -12,7 +12,7 @@
//!
//! This module implements generation for all bits and pieces of documentation
//! for the Rust project. This notably includes suites like the rust book, the
//! nomicon, standalone documentation, etc.
//! nomicon, rust by example, standalone documentation, etc.
//!
//! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`.
@ -69,6 +69,7 @@ book!(
Nomicon, "src/doc/nomicon", "nomicon";
Reference, "src/doc/reference", "reference";
Rustdoc, "src/doc/rustdoc", "rustdoc";
RustByExample, "src/doc/rust-by-example", "rust-by-example";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@ -159,7 +160,7 @@ impl Step for CargoBook {
let target = self.target;
let name = self.name;
let src = build.src.join("src/tools/cargo/src/doc/book");
let src = build.src.join("src/tools/cargo/src/doc");
let out = build.doc_out(target);
t!(fs::create_dir_all(&out));
@ -418,8 +419,8 @@ impl Step for Standalone {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Std {
stage: u32,
target: Interned<String>,
pub stage: u32,
pub target: Interned<String>,
}
impl Step for Std {
@ -428,7 +429,7 @@ impl Step for Std {
fn should_run(run: ShouldRun) -> ShouldRun {
let builder = run.builder;
run.krate("std").default_condition(builder.build.config.docs)
run.all_krates("std").default_condition(builder.build.config.docs)
}
fn make_run(run: RunConfig) {
@ -616,7 +617,7 @@ impl Step for Rustc {
t!(symlink_dir_force(&my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
compile::rustc_cargo(build, &compiler, target, &mut cargo);
compile::rustc_cargo(build, &mut cargo);
if build.config.compiler_docs {
// src/rustc/Cargo.toml contains a bin crate called rustc which

View File

@ -42,18 +42,23 @@ pub struct Flags {
pub jobs: Option<u32>,
pub cmd: Subcommand,
pub incremental: bool,
pub exclude: Vec<PathBuf>,
}
pub enum Subcommand {
Build {
paths: Vec<PathBuf>,
},
Check {
paths: Vec<PathBuf>,
},
Doc {
paths: Vec<PathBuf>,
},
Test {
paths: Vec<PathBuf>,
test_args: Vec<String>,
rustc_args: Vec<String>,
fail_fast: bool,
},
Bench {
@ -87,6 +92,7 @@ Usage: x.py <subcommand> [options] [<paths>...]
Subcommands:
build Compile either the compiler or libraries
check Compile either the compiler or libraries, using cargo check
test Build and run some test suites
bench Build and run some benchmarks
doc Build documentation
@ -104,6 +110,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
opts.optmulti("", "host", "host targets to build", "HOST");
opts.optmulti("", "target", "target targets to build", "TARGET");
opts.optmulti("", "exclude", "build paths to exclude", "PATH");
opts.optopt("", "on-fail", "command to run on failure", "CMD");
opts.optopt("", "stage", "stage to build", "N");
opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
@ -127,6 +134,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
// there on out.
let subcommand = args.iter().find(|&s|
(s == "build")
|| (s == "check")
|| (s == "test")
|| (s == "bench")
|| (s == "doc")
@ -150,6 +158,12 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
"test" => {
opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
opts.optmulti("", "test-args", "extra arguments", "ARGS");
opts.optmulti(
"",
"rustc-args",
"extra options to pass the compiler when running tests",
"ARGS",
);
},
"bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
"clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@ -210,6 +224,21 @@ Arguments:
arguments would), and then use the compiler built in stage 0 to build
src/libtest and its dependencies.
Once this is done, build/$ARCH/stage1 contains a usable compiler.");
}
"check" => {
subcommand_help.push_str("\n
Arguments:
This subcommand accepts a number of paths to directories to the crates
and/or artifacts to compile. For example:
./x.py check src/libcore
./x.py check src/libcore src/libproc_macro
If no arguments are passed then the complete artifacts are compiled: std, test, and rustc. Note
also that since we use `cargo check`, by default this will automatically enable incremental
compilation, so there's no need to pass it separately, though it won't hurt. We also completely
ignore the stage passed, as there's no way to compile in non-stage 0 without actually building
the compiler.");
}
"test" => {
subcommand_help.push_str("\n
@ -246,7 +275,10 @@ Arguments:
};
// Get any optional paths which occur after the subcommand
let cwd = t!(env::current_dir());
let paths = matches.free[1..].iter().map(|p| cwd.join(p)).collect::<Vec<_>>();
let src = matches.opt_str("src").map(PathBuf::from)
.or_else(|| env::var_os("SRC").map(PathBuf::from))
.unwrap_or(cwd.clone());
let paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| {
if fs::metadata("config.toml").is_ok() {
@ -279,10 +311,14 @@ Arguments:
"build" => {
Subcommand::Build { paths: paths }
}
"check" => {
Subcommand::Check { paths: paths }
}
"test" => {
Subcommand::Test {
paths,
test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
}
}
@ -327,11 +363,6 @@ Arguments:
stage = Some(1);
}
let cwd = t!(env::current_dir());
let src = matches.opt_str("src").map(PathBuf::from)
.or_else(|| env::var_os("SRC").map(PathBuf::from))
.unwrap_or(cwd);
Flags {
verbose: matches.opt_count("verbose"),
stage,
@ -343,10 +374,12 @@ Arguments:
target: split(matches.opt_strs("target"))
.into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(),
config: cfg_file,
src,
jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),
cmd,
incremental: matches.opt_present("incremental"),
exclude: split(matches.opt_strs("exclude"))
.into_iter().map(|p| p.into()).collect::<Vec<_>>(),
src,
}
}
}
@ -362,6 +395,15 @@ impl Subcommand {
}
}
pub fn rustc_args(&self) -> Vec<&str> {
match *self {
Subcommand::Test { ref rustc_args, .. } => {
rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
}
_ => Vec::new(),
}
}
pub fn fail_fast(&self) -> bool {
match *self {
Subcommand::Test { fail_fast, .. } => fail_fast,

View File

@ -22,6 +22,7 @@ use dist::{self, pkgname, sanitize_sh, tmpdir};
use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;
use config::Config;
pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "docs", "rust-docs", stage, Some(host));
@ -66,18 +67,21 @@ fn install_sh(
let prefix_default = PathBuf::from("/usr/local");
let sysconfdir_default = PathBuf::from("/etc");
let docdir_default = PathBuf::from("share/doc/rust");
let datadir_default = PathBuf::from("share");
let docdir_default = datadir_default.join("doc/rust");
let bindir_default = PathBuf::from("bin");
let libdir_default = PathBuf::from("lib");
let mandir_default = PathBuf::from("share/man");
let mandir_default = datadir_default.join("man");
let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
let datadir = build.config.datadir.as_ref().unwrap_or(&datadir_default);
let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);
let sysconfdir = prefix.join(sysconfdir);
let datadir = prefix.join(datadir);
let docdir = prefix.join(docdir);
let bindir = prefix.join(bindir);
let libdir = prefix.join(libdir);
@ -87,6 +91,7 @@ fn install_sh(
let prefix = add_destdir(&prefix, &destdir);
let sysconfdir = add_destdir(&sysconfdir, &destdir);
let datadir = add_destdir(&datadir, &destdir);
let docdir = add_destdir(&docdir, &destdir);
let bindir = add_destdir(&bindir, &destdir);
let libdir = add_destdir(&libdir, &destdir);
@ -106,6 +111,7 @@ fn install_sh(
.arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
.arg(format!("--prefix={}", sanitize_sh(&prefix)))
.arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
.arg(format!("--datadir={}", sanitize_sh(&datadir)))
.arg(format!("--docdir={}", sanitize_sh(&docdir)))
.arg(format!("--bindir={}", sanitize_sh(&bindir)))
.arg(format!("--libdir={}", sanitize_sh(&libdir)))
@ -144,6 +150,19 @@ macro_rules! install {
pub host: Interned<String>,
}
impl $name {
#[allow(dead_code)]
fn should_build(config: &Config) -> bool {
config.extended && config.tools.as_ref()
.map_or(true, |t| t.contains($path))
}
#[allow(dead_code)]
fn should_install(builder: &Builder) -> bool {
builder.config.tools.as_ref().map_or(false, |t| t.contains($path))
}
}
impl Step for $name {
type Output = ();
const DEFAULT: bool = true;
@ -185,32 +204,34 @@ install!((self, builder, _config),
install_std(builder, self.stage, *target);
}
};
Cargo, "cargo", _config.extended, only_hosts: true, {
Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
install_cargo(builder, self.stage, self.target);
};
Rls, "rls", _config.extended, only_hosts: true, {
if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() {
Rls, "rls", Self::should_build(_config), only_hosts: true, {
if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() ||
Self::should_install(builder) {
install_rls(builder, self.stage, self.target);
} else {
println!("skipping Install RLS stage{} ({})", self.stage, self.target);
}
};
Rustfmt, "rustfmt", _config.extended, only_hosts: true, {
if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() {
Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() ||
Self::should_install(builder) {
install_rustfmt(builder, self.stage, self.target);
} else {
println!("skipping Install Rustfmt stage{} ({})", self.stage, self.target);
}
};
Analysis, "analysis", _config.extended, only_hosts: false, {
Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
builder.ensure(dist::Analysis {
compiler: builder.compiler(self.stage, self.host),
target: self.target
});
install_analysis(builder, self.stage, self.target);
};
Src, "src", _config.extended, only_hosts: true, {
Src, "src", Self::should_build(_config) , only_hosts: true, {
builder.ensure(dist::Src);
install_src(builder, self.stage);
}, ONLY_BUILD;

View File

@ -113,9 +113,8 @@
//! More documentation can be found in each respective module below, and you can
//! also check out the `src/bootstrap/README.md` file for more information.
#![deny(warnings)]
#![allow(stable_features)]
#![feature(associated_consts)]
//#![deny(warnings)]
#![feature(core_intrinsics)]
#[macro_use]
extern crate build_helper;
@ -151,6 +150,7 @@ use util::{exe, libdir, OutputFolder, CiEnv};
mod cc_detect;
mod channel;
mod check;
mod test;
mod clean;
mod compile;
mod metadata;
@ -266,6 +266,18 @@ struct Crate {
bench_step: String,
}
impl Crate {
fn is_local(&self, build: &Build) -> bool {
self.path.starts_with(&build.config.src) &&
!self.path.to_string_lossy().ends_with("_shim")
}
fn local_path(&self, build: &Build) -> PathBuf {
assert!(self.is_local(build));
self.path.strip_prefix(&build.config.src).unwrap().into()
}
}
/// The various "modes" of invoking Cargo.
///
/// These entries currently correspond to the various output directories of the
@ -423,6 +435,9 @@ impl Build {
if self.config.profiler {
features.push_str(" profiler");
}
if self.config.wasm_syscall {
features.push_str(" wasm_syscall");
}
features
}
@ -432,9 +447,6 @@ impl Build {
if self.config.use_jemalloc {
features.push_str(" jemalloc");
}
if self.config.llvm_enabled {
features.push_str(" llvm");
}
features
}
@ -450,12 +462,6 @@ impl Build {
out
}
/// Get the directory for incremental by-products when using the
/// given compiler.
fn incremental_dir(&self, compiler: Compiler) -> PathBuf {
self.out.join(&*compiler.host).join(format!("stage{}-incremental", compiler.stage))
}
/// Returns the root directory for all output generated in a particular
/// stage when running with a particular host compiler.
///
@ -489,6 +495,10 @@ impl Build {
self.out.join(&*target).join("llvm")
}
fn emscripten_llvm_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(&*target).join("llvm-emscripten")
}
/// Output directory for all documentation for a target
fn doc_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(&*target).join("doc")
@ -667,7 +677,7 @@ impl Build {
}
}
/// Returns the path to the linker for the given target if it needs to be overriden.
/// Returns the path to the linker for the given target if it needs to be overridden.
fn linker(&self, target: Interned<String>) -> Option<&Path> {
if let Some(linker) = self.config.target_config.get(&target)
.and_then(|c| c.linker.as_ref()) {
@ -831,7 +841,7 @@ impl Build {
);
let n = count.trim().parse().unwrap();
self.prerelease_version.set(Some(n));
return n
n
}
/// Returns the value of `release` above for Rust itself.
@ -950,22 +960,18 @@ impl Build {
}
}
/// Get a list of crates from a root crate.
///
/// Returns Vec<(crate, path to crate, is_root_crate)>
fn crates(&self, root: &str) -> Vec<(Interned<String>, &Path)> {
let interned = INTERNER.intern_string(root.to_owned());
fn in_tree_crates(&self, root: &str) -> Vec<&Crate> {
let mut ret = Vec::new();
let mut list = vec![interned];
let mut list = vec![INTERNER.intern_str(root)];
let mut visited = HashSet::new();
while let Some(krate) = list.pop() {
let krate = &self.crates[&krate];
// If we can't strip prefix, then out-of-tree path
let path = krate.path.strip_prefix(&self.src).unwrap_or(&krate.path);
ret.push((krate.name, path));
for dep in &krate.deps {
if visited.insert(dep) && dep != "build_helper" {
list.push(*dep);
if krate.is_local(self) {
ret.push(krate);
for dep in &krate.deps {
if visited.insert(dep) && dep != "build_helper" {
list.push(*dep);
}
}
}
}

View File

@ -22,7 +22,7 @@ use std::env;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::Command;
use build_helper::output;
@ -30,7 +30,7 @@ use cmake;
use cc;
use Build;
use util;
use util::{self, exe};
use build_helper::up_to_date;
use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;
@ -38,35 +38,40 @@ use cache::Interned;
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Llvm {
pub target: Interned<String>,
pub emscripten: bool,
}
impl Step for Llvm {
type Output = ();
type Output = PathBuf; // path to llvm-config
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path("src/llvm")
run.path("src/llvm").path("src/llvm-emscripten")
}
fn make_run(run: RunConfig) {
run.builder.ensure(Llvm { target: run.target })
let emscripten = run.path.ends_with("llvm-emscripten");
run.builder.ensure(Llvm {
target: run.target,
emscripten,
});
}
/// Compile LLVM for `target`.
fn run(self, builder: &Builder) {
fn run(self, builder: &Builder) -> PathBuf {
let build = builder.build;
let target = self.target;
// If we're not compiling for LLVM bail out here.
if !build.config.llvm_enabled {
return;
}
let emscripten = self.emscripten;
// If we're using a custom LLVM bail out here, but we can only use a
// custom LLVM for the build triple.
if let Some(config) = build.config.target_config.get(&target) {
if let Some(ref s) = config.llvm_config {
return check_llvm_version(build, s);
if !self.emscripten {
if let Some(config) = build.config.target_config.get(&target) {
if let Some(ref s) = config.llvm_config {
check_llvm_version(build, s);
return s.to_path_buf()
}
}
}
@ -74,8 +79,17 @@ impl Step for Llvm {
let mut rebuild_trigger_contents = String::new();
t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents));
let out_dir = build.llvm_out(target);
let (out_dir, llvm_config_ret_dir) = if emscripten {
let dir = build.emscripten_llvm_out(target);
let config_dir = dir.join("bin");
(dir, config_dir)
} else {
(build.llvm_out(target),
build.llvm_out(build.config.build).join("bin"))
};
let done_stamp = out_dir.join("llvm-finished-building");
let build_llvm_config = llvm_config_ret_dir
.join(exe("llvm-config", &*build.config.build));
if done_stamp.exists() {
let mut done_contents = String::new();
t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents));
@ -83,17 +97,19 @@ impl Step for Llvm {
// If LLVM was already built previously and contents of the rebuild-trigger file
// didn't change from the previous build, then no action is required.
if done_contents == rebuild_trigger_contents {
return
return build_llvm_config
}
}
let _folder = build.fold_output(|| "llvm");
println!("Building LLVM for {}", target);
let descriptor = if emscripten { "Emscripten " } else { "" };
println!("Building {}LLVM for {}", descriptor, target);
let _time = util::timeit();
t!(fs::create_dir_all(&out_dir));
// http://llvm.org/docs/CMake.html
let mut cfg = cmake::Config::new(build.src.join("src/llvm"));
let root = if self.emscripten { "src/llvm-emscripten" } else { "src/llvm" };
let mut cfg = cmake::Config::new(build.src.join(root));
if build.config.ninja {
cfg.generator("Ninja");
}
@ -104,13 +120,22 @@ impl Step for Llvm {
(true, true) => "RelWithDebInfo",
};
// NOTE: remember to also update `config.toml.example` when changing the defaults!
let llvm_targets = match build.config.llvm_targets {
Some(ref s) => s,
None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon",
// NOTE: remember to also update `config.toml.example` when changing the
// defaults!
let llvm_targets = if self.emscripten {
"JSBackend"
} else {
match build.config.llvm_targets {
Some(ref s) => s,
None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;MSP430;Sparc;NVPTX;Hexagon",
}
};
let llvm_exp_targets = &build.config.llvm_experimental_targets;
let llvm_exp_targets = if self.emscripten {
""
} else {
&build.config.llvm_experimental_targets[..]
};
let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
@ -159,8 +184,11 @@ impl Step for Llvm {
}
// http://llvm.org/docs/HowToCrossCompileLLVM.html
if target != build.build {
builder.ensure(Llvm { target: build.build });
if target != build.build && !emscripten {
builder.ensure(Llvm {
target: build.build,
emscripten: false,
});
// FIXME: if the llvm root for the build triple is overridden then we
// should use llvm-tblgen from there, also should verify that it
// actually exists most of the time in normal installs of LLVM.
@ -246,6 +274,8 @@ impl Step for Llvm {
cfg.build();
t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes()));
build_llvm_config
}
}
@ -429,6 +459,8 @@ impl Step for Openssl {
"arm-unknown-linux-gnueabihf" => "linux-armv4",
"armv7-linux-androideabi" => "android-armv7",
"armv7-unknown-linux-gnueabihf" => "linux-armv4",
"i586-unknown-linux-gnu" => "linux-elf",
"i586-unknown-linux-musl" => "linux-elf",
"i686-apple-darwin" => "darwin-i386-cc",
"i686-linux-android" => "android-x86",
"i686-unknown-freebsd" => "BSD-x86-elf",

View File

@ -21,9 +21,10 @@
use std::collections::HashMap;
use std::env;
use std::ffi::{OsString, OsStr};
use std::fs;
use std::process::Command;
use std::fs::{self, File};
use std::io::Read;
use std::path::PathBuf;
use std::process::Command;
use build_helper::output;
@ -169,7 +170,7 @@ pub fn check(build: &mut Build) {
}
// Make sure musl-root is valid
if target.contains("musl") && !target.contains("mips") {
if target.contains("musl") {
// If this is a native target (host is also musl) and no musl-root is given,
// fall back to the system toolchain in /usr before giving up
if build.musl_root(*target).is_none() && build.config.build == *target {
@ -234,4 +235,14 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
if let Some(ref s) = build.config.ccache {
cmd_finder.must_have(s);
}
if build.config.channel == "stable" {
let mut stage0 = String::new();
t!(t!(File::open(build.src.join("src/stage0.txt")))
.read_to_string(&mut stage0));
if stage0.contains("\ndev:") {
panic!("bootstrapping from a dev compiler in a stable release, but \
should only be bootstrapping from a released compiler!");
}
}
}

1646
src/bootstrap/test.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -260,6 +260,7 @@ tool!(
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
RustInstaller, "src/tools/rust-installer", "fabricate", Mode::Libstd;
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::Libstd;
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]

View File

@ -315,7 +315,7 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
let db = data.as_mut_ptr()
as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
let buf = &mut (*db).ReparseTarget as *mut _;
let buf = &mut (*db).ReparseTarget as *mut u16;
let mut i = 0;
// FIXME: this conversion is very hacky
let v = br"\??\";

View File

@ -29,6 +29,6 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten
ENV TARGETS=asmjs-unknown-emscripten
ENV RUST_CONFIGURE_ARGS --target=$TARGETS
ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-emscripten
ENV SCRIPT python2.7 ../x.py test --target $TARGETS

View File

@ -17,14 +17,21 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config
WORKDIR /build/
COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/
RUN sh /build/build-musl.sh && rm -rf /build
COPY scripts/musl.sh /build/
RUN CC=gcc CFLAGS="-m32 -Wa,-mrelax-relocations=no" \
CXX=g++ CXXFLAGS="-m32 -Wa,-mrelax-relocations=no" \
bash musl.sh i686 --target=i686 && \
CC=gcc CFLAGS="-march=pentium -m32 -Wa,-mrelax-relocations=no" \
CXX=g++ CXXFLAGS="-march=pentium -m32 -Wa,-mrelax-relocations=no" \
bash musl.sh i586 --target=i586 && \
rm -rf /build
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV RUST_CONFIGURE_ARGS \
--target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
--musl-root-i586=/musl-i586 \
--musl-root-i686=/musl-i686 \
--enable-extended
@ -35,12 +42,13 @@ ENV RUST_CONFIGURE_ARGS \
# See: https://github.com/rust-lang/rust/issues/34978
ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
# FIXME remove -Wl,-melf_i386 after cc is updated to include
# https://github.com/alexcrichton/cc-rs/pull/281
ENV CFLAGS_i586_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wl,-melf_i386"
ENV TARGETS=i586-unknown-linux-gnu
ENV TARGETS=$TARGETS,i686-unknown-linux-musl
ENV SCRIPT \
python2.7 ../x.py test \
--target i686-unknown-linux-musl \
--target i586-unknown-linux-gnu \
&& \
python2.7 ../x.py dist \
--target i686-unknown-linux-musl \
--target i586-unknown-linux-gnu
python2.7 ../x.py test --target $TARGETS && \
python2.7 ../x.py dist --target $TARGETS,i586-unknown-linux-musl

View File

@ -1,55 +0,0 @@
#!/bin/sh
# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
export CXXFLAGS="-Wa,-mrelax-relocations=no"
MUSL=musl-1.1.17
curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
cd $MUSL
CC=gcc \
CFLAGS="$CFLAGS -m32" \
./configure --prefix=/musl-i686 --disable-shared \
--target=i686
make AR=ar RANLIB=ranlib -j10
make install
cd ..
# To build MUSL we're going to need a libunwind lying around, so acquire that
# here and build it.
curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf -
curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf -
# Whoa what's this mysterious patch we're applying to libunwind! Why are we
# swapping the values of ESP/EBP in libunwind?!
#
# Discovered in #35599 it turns out that the vanilla build of libunwind is not
# suitable for unwinding 32-bit musl. After some investigation it ended up
# looking like the register values for ESP/EBP were indeed incorrect (swapped)
# in the source. Similar commits in libunwind (r280099 and r282589) have noticed
# this for other platforms, and we just need to realize it for musl linux as
# well.
#
# More technical info can be found at #35599
cd libunwind-release_37
patch -Np1 < /build/musl-libunwind-patch.patch
cd ..
mkdir libunwind-build
cd libunwind-build
CFLAGS="$CFLAGS -m32" CXXFLAGS="$CXXFLAGS -m32" cmake ../libunwind-release_37 \
-DLLVM_PATH=/build/llvm-release_37 \
-DLIBUNWIND_ENABLE_SHARED=0
make -j10
cp lib/libunwind.a /musl-i686/lib

View File

@ -1,15 +0,0 @@
diff --git a/include/libunwind.h b/include/libunwind.h
index c5b9633..1360eb2 100644
--- a/include/libunwind.h
+++ b/include/libunwind.h
@@ -151,8 +151,8 @@ enum {
UNW_X86_ECX = 1,
UNW_X86_EDX = 2,
UNW_X86_EBX = 3,
- UNW_X86_EBP = 4,
- UNW_X86_ESP = 5,
+ UNW_X86_ESP = 4,
+ UNW_X86_EBP = 5,
UNW_X86_ESI = 6,
UNW_X86_EDI = 7
};

View File

@ -1,4 +1,4 @@
FROM ubuntu:16.04
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y --no-install-recommends \
clang \

View File

@ -85,7 +85,9 @@ ENV RUST_CONFIGURE_ARGS \
--host=$HOSTS \
--enable-extended \
--enable-sanitizers \
--enable-profiler
--enable-profiler \
--enable-emscripten \
--build=i686-unknown-linux-gnu
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
# This is the only builder which will create source tarballs

View File

@ -17,6 +17,23 @@ GCC=4.8.5
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
cd gcc-$GCC
# FIXME(#49246): Remove the `sed` below.
#
# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this
# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue:
# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection
# timed out" error, and even when the download completed, the file is usually corrupted. This causes
# nothing to be landed that day.
#
# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability
# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third
# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the
# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
# instead here.
#
sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
./contrib/download_prerequisites
mkdir ../gcc-build
cd ../gcc-build

View File

@ -12,7 +12,7 @@
set -ex
source shared.sh
curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
cd git-2.10.0
make configure

View File

@ -22,22 +22,49 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libssl-dev \
pkg-config
WORKDIR /tmp
WORKDIR /build
COPY dist-various-1/build-rumprun.sh /tmp/
COPY dist-various-1/build-rumprun.sh /build
RUN ./build-rumprun.sh
COPY dist-various-1/build-arm-musl.sh /tmp/
RUN ./build-arm-musl.sh
COPY dist-various-1/install-x86_64-redox.sh /build
RUN ./install-x86_64-redox.sh
COPY dist-various-1/install-mips-musl.sh /tmp/
COPY dist-various-1/install-mips-musl.sh /build
RUN ./install-mips-musl.sh
COPY dist-various-1/install-mipsel-musl.sh /tmp/
COPY dist-various-1/install-mipsel-musl.sh /build
RUN ./install-mipsel-musl.sh
COPY dist-various-1/install-x86_64-redox.sh /tmp/
RUN ./install-x86_64-redox.sh
# Suppress some warnings in the openwrt toolchains we downloaded
ENV STAGING_DIR=/tmp
COPY scripts/musl.sh /build
RUN env \
CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv6 -marm" \
CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv6 -marm" \
bash musl.sh arm && \
env \
CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv6 -marm" \
CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm" \
bash musl.sh armhf && \
env \
CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a" \
CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a" \
bash musl.sh armv7 && \
env \
CC=aarch64-linux-gnu-gcc \
CXX=aarch64-linux-gnu-g++ \
bash musl.sh aarch64 && \
env \
CC=mips-openwrt-linux-gcc \
CXX=mips-openwrt-linux-g++ \
bash musl.sh mips && \
env \
CC=mipsel-openwrt-linux-gcc \
CXX=mipsel-openwrt-linux-g++ \
bash musl.sh mipsel && \
rm -rf /build/*
ENV TARGETS=asmjs-unknown-emscripten
ENV TARGETS=$TARGETS,wasm32-unknown-emscripten
@ -61,16 +88,16 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
CC_armv5te_unknown_linux_gnueabi=arm-linux-gnueabi-gcc \
CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft"
# Suppress some warnings in the openwrt toolchains we downloaded
ENV STAGING_DIR=/tmp
ENV RUST_CONFIGURE_ARGS \
--enable-extended \
--target=$TARGETS \
--musl-root-arm=/usr/local/arm-linux-musleabi \
--musl-root-armhf=/usr/local/arm-linux-musleabihf \
--musl-root-armv7=/usr/local/armv7-linux-musleabihf \
--musl-root-aarch64=/usr/local/aarch64-linux-musl
--musl-root-arm=/musl-arm \
--musl-root-armhf=/musl-armhf \
--musl-root-armv7=/musl-armv7 \
--musl-root-aarch64=/musl-aarch64 \
--musl-root-mips=/musl-mips \
--musl-root-mipsel=/musl-mipsel \
--enable-emscripten
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
# sccache

View File

@ -1,147 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
MUSL=1.1.17
hide_output() {
set +x
on_err="
echo ERROR: An error was encountered with the build.
cat /tmp/build.log
exit 1
"
trap "$on_err" ERR
bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
PING_LOOP_PID=$!
$@ &> /tmp/build.log
trap - ERR
kill $PING_LOOP_PID
rm /tmp/build.log
set -x
}
curl -O https://www.musl-libc.org/releases/musl-$MUSL.tar.gz
tar xf musl-$MUSL.tar.gz
cd musl-$MUSL
CC=arm-linux-gnueabi-gcc \
CFLAGS="-march=armv6 -marm" \
hide_output ./configure \
--prefix=/usr/local/arm-linux-musleabi \
--enable-wrapper=gcc
hide_output make -j$(nproc)
hide_output make install
cd ..
rm -rf musl-$MUSL
tar xf musl-$MUSL.tar.gz
cd musl-$MUSL
CC=arm-linux-gnueabihf-gcc \
CFLAGS="-march=armv6 -marm" \
hide_output ./configure \
--prefix=/usr/local/arm-linux-musleabihf \
--enable-wrapper=gcc
hide_output make -j$(nproc)
hide_output make install
cd ..
rm -rf musl-$MUSL
tar xf musl-$MUSL.tar.gz
cd musl-$MUSL
CC=arm-linux-gnueabihf-gcc \
CFLAGS="-march=armv7-a" \
hide_output ./configure \
--prefix=/usr/local/armv7-linux-musleabihf \
--enable-wrapper=gcc
hide_output make -j$(nproc)
hide_output make install
cd ..
rm -rf musl-$MUSL
tar xf musl-$MUSL.tar.gz
cd musl-$MUSL
CC=aarch64-linux-gnu-gcc \
CFLAGS="" \
hide_output ./configure \
--prefix=/usr/local/aarch64-linux-musl \
--enable-wrapper=gcc
hide_output make -j$(nproc)
hide_output make install
cd ..
rm -rf musl-$MUSL*
ln -nsf ../arm-linux-musleabi/bin/musl-gcc /usr/local/bin/arm-linux-musleabi-gcc
ln -nsf ../arm-linux-musleabihf/bin/musl-gcc /usr/local/bin/arm-linux-musleabihf-gcc
ln -nsf ../armv7-linux-musleabihf/bin/musl-gcc /usr/local/bin/armv7-linux-musleabihf-gcc
ln -nsf ../aarch64-linux-musl/bin/musl-gcc /usr/local/bin/aarch64-unknown-linux-musl-gcc
curl -L https://github.com/llvm-mirror/llvm/archive/release_39.tar.gz | tar xzf -
curl -L https://github.com/llvm-mirror/libunwind/archive/release_39.tar.gz | tar xzf -
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_39 \
-DLLVM_PATH=/tmp/llvm-release_39 \
-DLIBUNWIND_ENABLE_SHARED=0 \
-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \
-DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ \
-DCMAKE_C_FLAGS="-march=armv6 -marm" \
-DCMAKE_CXX_FLAGS="-march=armv6 -marm"
make -j$(nproc)
cp lib/libunwind.a /usr/local/arm-linux-musleabi/lib
cd ..
rm -rf libunwind-build
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_39 \
-DLLVM_PATH=/tmp/llvm-release_39 \
-DLIBUNWIND_ENABLE_SHARED=0 \
-DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \
-DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \
-DCMAKE_C_FLAGS="-march=armv6 -marm" \
-DCMAKE_CXX_FLAGS="-march=armv6 -marm"
make -j$(nproc)
cp lib/libunwind.a /usr/local/arm-linux-musleabihf/lib
cd ..
rm -rf libunwind-build
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_39 \
-DLLVM_PATH=/tmp/llvm-release_39 \
-DLIBUNWIND_ENABLE_SHARED=0 \
-DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \
-DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \
-DCMAKE_C_FLAGS="-march=armv7-a" \
-DCMAKE_CXX_FLAGS="-march=armv7-a"
make -j$(nproc)
cp lib/libunwind.a /usr/local/armv7-linux-musleabihf/lib
cd ..
rm -rf libunwind-build
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_39 \
-DLLVM_PATH=/tmp/llvm-release_39 \
-DLIBUNWIND_ENABLE_SHARED=0 \
-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
-DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
-DCMAKE_C_FLAGS="" \
-DCMAKE_CXX_FLAGS=""
make -j$(nproc)
cp lib/libunwind.a /usr/local/aarch64-linux-musl/lib
cd ..
rm -rf libunwind-build
rm -rf libunwind-release_39
rm -rf llvm-release_39

View File

@ -1,4 +1,4 @@
FROM ubuntu:16.04
FROM ubuntu:17.10
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
@ -21,9 +21,12 @@ RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7
RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main'
WORKDIR /tmp
COPY dist-various-2/shared.sh dist-various-2/build-fuchsia-toolchain.sh /tmp/
COPY dist-various-2/build-solaris-toolchain.sh /tmp/
COPY dist-various-2/shared.sh /tmp/
COPY dist-various-2/build-cloudabi-toolchain.sh /tmp/
RUN /tmp/build-cloudabi-toolchain.sh x86_64-unknown-cloudabi
COPY dist-various-2/build-fuchsia-toolchain.sh /tmp/
RUN /tmp/build-fuchsia-toolchain.sh
COPY dist-various-2/build-solaris-toolchain.sh /tmp/
RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386
RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
@ -50,6 +53,7 @@ ENV TARGETS=$TARGETS,sparcv9-sun-solaris
ENV TARGETS=$TARGETS,wasm32-unknown-unknown
ENV TARGETS=$TARGETS,x86_64-sun-solaris
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi
ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS

View File

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright 2018 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -eux
# Install prerequisites.
apt-get update
apt-get install -y --no-install-recommends \
apt-transport-https \
ca-certificates \
clang-5.0 \
cmake \
curl \
file \
g++ \
gdb \
git \
lld-5.0 \
make \
python \
sudo \
xz-utils
# Set up a Clang-based cross compiler toolchain.
# Based on the steps described at https://nuxi.nl/cloudabi/debian/
target=$1
for tool in ar nm objdump ranlib size; do
ln -s ../lib/llvm-5.0/bin/llvm-${tool} /usr/bin/${target}-${tool}
done
ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-cc
ln -s ../lib/llvm-5.0/bin/clang /usr/bin/${target}-c++
ln -s ../lib/llvm-5.0/bin/lld /usr/bin/${target}-ld
ln -s ../../${target} /usr/lib/llvm-5.0/${target}
# Install the C++ runtime libraries from CloudABI Ports.
echo deb https://nuxi.nl/distfiles/cloudabi-ports/debian/ cloudabi cloudabi > \
/etc/apt/sources.list.d/cloudabi.list
curl 'https://pgp.mit.edu/pks/lookup?op=get&search=0x0DA51B8531344B15' | \
apt-key add -
apt-get update
apt-get install -y $(echo ${target} | sed -e s/_/-/g)-cxx-runtime

View File

@ -1,4 +1,4 @@
FROM ubuntu:16.04
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y --no-install-recommends \
clang \

View File

@ -85,7 +85,8 @@ ENV RUST_CONFIGURE_ARGS \
--host=$HOSTS \
--enable-extended \
--enable-sanitizers \
--enable-profiler
--enable-profiler \
--enable-emscripten
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
# This is the only builder which will create source tarballs

View File

@ -17,6 +17,23 @@ GCC=4.8.5
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
cd gcc-$GCC
# FIXME(#49246): Remove the `sed` below.
#
# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this
# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue:
# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection
# timed out" error, and even when the download completed, the file is usually corrupted. This causes
# nothing to be landed that day.
#
# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability
# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third
# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the
# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
# instead here.
#
sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
./contrib/download_prerequisites
mkdir ../gcc-build
cd ../gcc-build

View File

@ -12,7 +12,7 @@
set -ex
source shared.sh
curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
cd git-2.10.0
make configure

View File

@ -17,8 +17,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config
WORKDIR /build/
COPY dist-x86_64-musl/build-musl.sh /build/
RUN sh /build/build-musl.sh && rm -rf /build
COPY scripts/musl.sh /build/
# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
RUN CC=gcc \
CFLAGS="-Wa,-mrelax-relocations=no" \
CXX=g++ \
CXXFLAGS="-Wa,-mrelax-relocations=no" \
bash musl.sh x86_64 && rm -rf /build
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

View File

@ -1,38 +0,0 @@
#!/bin/sh
# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
export CFLAGS="-fPIC -Wa,-mrelax-relocations=no"
export CXXFLAGS="-Wa,-mrelax-relocations=no"
MUSL=musl-1.1.17
curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
cd $MUSL
./configure --prefix=/musl-x86_64 --disable-shared
make -j10
make install
cd ..
rm -rf $MUSL
# To build MUSL we're going to need a libunwind lying around, so acquire that
# here and build it.
curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf -
curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf -
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_37 -DLLVM_PATH=/build/llvm-release_37 \
-DLIBUNWIND_ENABLE_SHARED=0
make -j10
cp lib/libunwind.a /musl-x86_64/lib

View File

@ -54,7 +54,7 @@ cd usr/src
# The options, in order, do the following
# * this is an unprivileged build
# * output to a predictable location
# * disable various uneeded stuff
# * disable various unneeded stuff
MKUNPRIVED=yes TOOLDIR=/x-tools/x86_64-unknown-netbsd \
MKSHARE=no MKDOC=no MKHTML=no MKINFO=no MKKMOD=no MKLINT=no MKMAN=no MKNLS=no MKPROFILE=no \
hide_output ./build.sh -j10 -m amd64 tools

View File

@ -0,0 +1,74 @@
# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
hide_output() {
set +x
on_err="
echo ERROR: An error was encountered with the build.
cat /tmp/build.log
exit 1
"
trap "$on_err" ERR
bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
PING_LOOP_PID=$!
$@ &> /tmp/build.log
trap - ERR
kill $PING_LOOP_PID
rm /tmp/build.log
set -x
}
TAG=$1
shift
export CFLAGS="-fPIC $CFLAGS"
MUSL=musl-1.1.18
# may have been downloaded in a previous run
if [ ! -d $MUSL ]; then
curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
fi
cd $MUSL
./configure --disable-shared --prefix=/musl-$TAG $@
if [ "$TAG" = "i586" -o "$TAG" = "i686" ]; then
hide_output make -j$(nproc) AR=ar RANLIB=ranlib
else
hide_output make -j$(nproc)
fi
hide_output make install
hide_output make clean
cd ..
LLVM=60
# may have been downloaded in a previous run
if [ ! -d libunwind-release_$LLVM ]; then
curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf -
curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf -
fi
mkdir libunwind-build
cd libunwind-build
cmake ../libunwind-release_$LLVM \
-DLLVM_PATH=/build/llvm-release_$LLVM \
-DLIBUNWIND_ENABLE_SHARED=0 \
-DCMAKE_C_COMPILER=$CC \
-DCMAKE_CXX_COMPILER=$CXX \
-DCMAKE_C_FLAGS="$CFLAGS" \
-DCMAKE_CXX_FLAGS="$CXXFLAGS"
hide_output make -j$(nproc)
cp lib/libunwind.a /musl-$TAG/lib
cd ../ && rm -rf libunwind-build

View File

@ -19,3 +19,4 @@ RUN sh /scripts/sccache.sh
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache
ENV RUST_CHECK_TARGET check
ENV CARGO_INCREMENTAL 0

View File

@ -23,14 +23,15 @@ touch "$TOOLSTATE_FILE"
set +e
python2.7 "$X_PY" test --no-fail-fast \
src/tools/rls \
src/tools/rustfmt
src/tools/rustfmt \
src/tools/clippy
set -e
cat "$TOOLSTATE_FILE"
# If this PR is intended to update one of these tools, do not let the build pass
# when they do not test-pass.
for TOOL in rls rustfmt; do
for TOOL in rls rustfmt clippy; do
echo "Verifying status of $TOOL..."
if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]src/tools/$TOOL$"; then
echo "This PR updated 'src/tools/$TOOL', verifying if status is 'test-pass'..."

View File

@ -48,7 +48,12 @@ travis_time_start
# Update the cache (a pristine copy of the rust source master)
retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \
git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir"
(cd $cache_src_dir && git rm src/llvm)
if [ -d $cache_src_dir/src/llvm ]; then
(cd $cache_src_dir && git rm src/llvm)
fi
if [ -d $cache_src_dir/src/llvm-emscripten ]; then
(cd $cache_src_dir && git rm src/llvm-emscripten)
fi
retry sh -c "cd $cache_src_dir && \
git submodule deinit -f . && git submodule sync && git submodule update --init"
@ -64,14 +69,14 @@ travis_time_start
# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
for module in $modules; do
if [ "$module" = src/llvm ]; then
commit="$(git ls-tree HEAD src/llvm | awk '{print $3}')"
git rm src/llvm
if [ "$module" = src/llvm ] || [ "$module" = src/llvm-emscripten ]; then
commit="$(git ls-tree HEAD $module | awk '{print $3}')"
git rm $module
retry sh -c "rm -f $commit.tar.gz && \
curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz"
tar -C src/ -xf "$commit.tar.gz"
rm "$commit.tar.gz"
mv "src/llvm-$commit" src/llvm
mv "src/llvm-$commit" $module
continue
fi
if [ ! -e "$cache_src_dir/$module/.git" ]; then

View File

@ -46,6 +46,7 @@ export RUST_RELEASE_CHANNEL=stable
if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-thinlto"
if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"

View File

@ -902,7 +902,7 @@ impl Dlmalloc {
}
// If dv is a better fit, then return null so malloc will use it
if v.is_null() || rsize + size >= self.dvsize {
if v.is_null() || (self.dvsize >= size && !(rsize < self.dvsize - size)) {
return ptr::null_mut()
}
@ -1512,7 +1512,7 @@ impl Dlmalloc {
tsize < self.min_size_for_tree_index(idx + 1));
let mut u = t;
let mut head = ptr::null_mut();
let mut head = ptr::null_mut::<TreeChunk>();
loop {
let uc = TreeChunk::chunk(u);
self.check_any_chunk(uc);

View File

@ -1,21 +1,18 @@
use core::ptr;
extern {
#[link_name = "llvm.wasm.current.memory.i32"]
fn current_memory() -> u32;
// TODO: this intrinsic actually returns the previous limit, but LLVM
// doesn't expose that right now. When we upgrade LLVM stop using
// `current_memory` above.
#[link_name = "llvm.wasm.grow.memory.i32"]
fn grow_memory(pages: u32);
fn grow_memory(pages: u32) -> i32;
}
pub unsafe fn alloc(size: usize) -> (*mut u8, usize, u32) {
let pages = size / page_size();
let cur = current_memory() as usize;
grow_memory(pages as u32);
((cur * page_size()) as *mut u8, pages * page_size(), 0)
let prev = grow_memory(pages as u32);
if prev == -1 {
return (ptr::null_mut(), 0, 0);
}
let prev = prev as usize;
((prev * page_size()) as *mut u8, pages * page_size(), 0)
}
pub unsafe fn remap(_ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool)

View File

@ -29,4 +29,4 @@ rustdoc reference.md
An overview of how to use the `rustdoc` command is available [in the docs][1].
Further details are available from the command line by with `rustdoc --help`.
[1]: https://github.com/rust-lang/rust/blob/master/src/doc/book/documentation.md
[1]: https://github.com/rust-lang/rust/blob/master/src/doc/rustdoc/src/what-is-rustdoc.md

View File

@ -13,6 +13,6 @@ addons:
- aspell
- aspell-en
before_script:
- (cargo install mdbook --vers 0.0.26 --force || true)
- (cargo install mdbook --vers 0.1.0 --force || true)
script:
- bash ci/build.sh

View File

@ -1,7 +1,7 @@
# NOTICE ABOUT STATUS
The second edition of The Rust Programming Language is getting ever closer to being printed!
This means we're not able to make large changes to chapters that are in any column to the
This means we're not able to make large changes to chapters that are in any column to the
right of, and including, the "Frozen" column [on our Project board][proj]. Issues or pull
requests submitted for frozen chapters are welcome but will be closed until we start work
on a third edition. Thank you!
@ -12,22 +12,18 @@ on a third edition. Thank you!
[![Build Status](https://travis-ci.org/rust-lang/book.svg?branch=master)](https://travis-ci.org/rust-lang/book)
This repo contains two editions of “The Rust Programming Language”.
This repo contains two editions of “The Rust Programming Language”; we
recommend starting with the second edition.
The second edition is a rewrite that will be printed by NoStarch Press,
available around October 2017.
The second edition is a rewrite that will be printed by No Starch Press,
available around May 2018. Check [the No Starch Page][nostarch] for the latest
information on the release date and how to order.
[You can read the very latest online][html]; the last few chapters aren't completed yet, but
the first half of the book is much improved from the first edition. We recommend
starting with the second edition.
[nostarch]: https://nostarch.com/rust
[html]: http://rust-lang.github.io/book/
Note that links to the standard library won't work in this version; this is intentional
so that links work with the book and API docs shipped with Rust installations for offline
reading. For a version of the book where these links do work, please see the book as shipped
with the latest [stable], [beta], or [nightly] Rust releases. Be aware that issues in those
versions may have been fixed in this repository already.
You can read the book for free online! Please see the book as shipped with the
latest [stable], [beta], or [nightly] Rust releases. Be aware that issues in
those versions may have been fixed in this repository already.
[stable]: https://doc.rust-lang.org/stable/book/second-edition/
[beta]: https://doc.rust-lang.org/beta/book/second-edition/

View File

@ -1,2 +1,3 @@
[book]
title = "The Rust Programming Language"
author = "The Rust Project Developers"

View File

@ -4,8 +4,8 @@ One important feature of Rust is that it lets us control the costs and guarantee
of a program.
There are various &ldquo;wrapper type&rdquo; abstractions in the Rust standard library which embody
a multitude of tradeoffs between cost, ergonomics, and guarantees. Many let one choose between
run time and compile time enforcement. This section will explain a few selected abstractions in
a multitude of trade-offs between cost, ergonomics, and guarantees. Many let one choose between
run-time and compile-time enforcement. This section will explain a few selected abstractions in
detail.
Before proceeding, it is highly recommended that one reads about [ownership][ownership] and
@ -86,7 +86,7 @@ last. It's a viable alternative to `&T` when `&T` is either impossible to static
correctness, or creates extremely unergonomic code where the programmer does not wish to spend the
development cost of working with.
This pointer is _not_ thread safe, and Rust will not let it be sent or shared with other threads.
This pointer is _not_ thread-safe, and Rust will not let it be sent or shared with other threads.
This lets one avoid the cost of atomics in situations where they are unnecessary.
There is a sister smart pointer to this one, `Weak<T>`. This is a non-owning, but also non-borrowed,
@ -243,7 +243,7 @@ At runtime each borrow causes a modification/check of the refcount.
Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc<T>` and
`RefCell<T>`, which both use non-atomic reference counts (_atomic_ reference counts are those which
can be incremented from multiple threads without causing a data race), cannot be used this way. This
makes them cheaper to use, but we need thread safe versions of these too. They exist, in the form of
makes them cheaper to use, but we need thread-safe versions of these too. They exist, in the form of
`Arc<T>` and `Mutex<T>`/`RwLock<T>`
Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile
@ -271,7 +271,7 @@ behavior, so even monotonicity may not be enough to justify `UnsafeCell`.
#### Guarantees
Like `Rc`, this provides the (thread safe) guarantee that the destructor for the internal data will
Like `Rc`, this provides the (thread-safe) guarantee that the destructor for the internal data will
be run when the last `Arc` goes out of scope (barring any cycles).
#### Cost
@ -354,7 +354,7 @@ When reading code that uses these, go in step by step and look at the guarantees
When choosing a composed type, we must do the reverse; figure out which guarantees we want, and at
which point of the composition we need them. For example, if there is a choice between
`Vec<RefCell<T>>` and `RefCell<Vec<T>>`, we should figure out the tradeoffs as done above and pick
`Vec<RefCell<T>>` and `RefCell<Vec<T>>`, we should figure out the trade-offs as done above and pick
one.
[^3]: `&[T]` and `&mut [T]` are _slices_; they consist of a pointer and a length and can refer to a portion of a vector or array. `&mut [T]` can have its elements mutated, however its length cannot be touched.

View File

@ -237,7 +237,7 @@ This won't work, however, and will give us the error:
```
As the error message mentions, `Rc` cannot be sent between threads safely. This
is because the internal reference count is not maintained in a thread safe
is because the internal reference count is not maintained in a thread-safe
manner and can have a data race.
To solve this, we'll use `Arc<T>`, Rust's standard atomic reference count type.
@ -288,7 +288,7 @@ involved—can cause data races!
Usually when we wish to make something in an immutable position mutable, we use
`Cell<T>` or `RefCell<T>` which allow safe mutation via runtime checks or
otherwise (see also: [Choosing Your Guarantees](choosing-your-guarantees.html)).
However, similar to `Rc`, these are not thread safe. If we try using these, we
However, similar to `Rc`, these are not thread-safe. If we try using these, we
will get an error about these types not being `Sync`, and the code will fail to
compile.

View File

@ -38,6 +38,9 @@ reference stored in a static has a [`'static` lifetime][lifetimes]:
static NAME: &'static str = "Steve";
```
The type of a `static` value must be `Sync` unless the `static` value is
mutable.
[lifetimes]: lifetimes.html
## Mutability
@ -64,17 +67,20 @@ unsafe {
[unsafe]: unsafe.html
Furthermore, any type stored in a `static` must be `Sync`, and must not have
a [`Drop`][drop] implementation.
[drop]: drop.html
# Initializing
Both `const` and `static` have requirements for giving them a value. They must
be given a value thats a constant expression. In other words, you cannot use
the result of a function call or anything similarly complex or at runtime.
# Dropping
Types implementing [`Drop`][drop] are allowed in `const` and `static`
definitions. Constants are inlined where they are used and are dropped
accordingly. `static` values are not dropped.
[drop]: drop.html
# Which construct should I use?
Almost always, if you can choose between the two, choose `const`. Its pretty

View File

@ -473,7 +473,7 @@ it also requires us to add a [`Debug`][8] constraint on the `E` type
parameter (which represents our error type). Since the vast majority
of types should satisfy the `Debug` constraint, this tends to work out
in practice. (`Debug` on a type simply means that there's a reasonable
way to print a human readable description of values with that type.)
way to print a human-readable description of values with that type.)
OK, let's move on to an example.
@ -554,7 +554,7 @@ fn main() {
}
```
This is a little better, but now we've written a lot more code! The case
This is a little better, but now we've written much more code! The case
analysis has once again bitten us.
Combinators to the rescue! Just like `Option`, `Result` has lots of combinators
@ -647,9 +647,9 @@ a bit nicer to deal with, since it will show your message instead of
My advice boils down to this: use good judgment. There's a reason why the words
“never do X” or “Y is considered harmful” don't appear in my writing. There are
trade offs to all things, and it is up to you as the programmer to determine
trade-offs to all things, and it is up to you as the programmer to determine
what is acceptable for your use cases. My goal is only to help you evaluate
trade offs as accurately as possible.
trade-offs as accurately as possible.
Now that we've covered the basics of error handling in Rust, and
explained unwrapping, let's start exploring more of the standard
@ -815,7 +815,7 @@ type from `i32` to something else.
The first thing we need to decide: should we use `Option` or `Result`? We
certainly could use `Option` very easily. If any of the three errors occur, we
could simply return `None`. This will work *and it is better than panicking*,
but we can do a lot better. Instead, we should pass some detail about the error
but we can do much better. Instead, we should pass some detail about the error
that occurred. Since we want to express the *possibility of error*, we should
use `Result<i32, E>`. But what should `E` be? Since two *different* types of
errors can occur, we need to convert them to a common type. One such type is
@ -917,7 +917,7 @@ Reasonable people can disagree over whether this code is better than the code
that uses combinators, but if you aren't familiar with the combinator approach,
this code looks simpler to read to me. It uses explicit case analysis with
`match` and `if let`. If an error occurs, it simply stops executing the
function and returns the error (by converting it to a string).
function and returns the error (by converting it to string).
Isn't this a step backwards though? Previously, we said that the key to
ergonomic error handling is reducing explicit case analysis, yet we've reverted
@ -1026,7 +1026,7 @@ use std::io;
use std::num;
// We derive `Debug` because all types should probably derive `Debug`.
// This gives us a reasonable human readable description of `CliError` values.
// This gives us a reasonable human-readable description of `CliError` values.
#[derive(Debug)]
enum CliError {
Io(io::Error),
@ -1127,7 +1127,7 @@ use std::io;
use std::num;
// We derive `Debug` because all types should probably derive `Debug`.
// This gives us a reasonable human readable description of `CliError` values.
// This gives us a reasonable human-readable description of `CliError` values.
#[derive(Debug)]
enum CliError {
Io(io::Error),
@ -1285,7 +1285,7 @@ macro_rules! try {
```
There's one tiny but powerful change: the error value is passed through
`From::from`. This makes the `try!` macro a lot more powerful because it gives
`From::from`. This makes the `try!` macro much more powerful because it gives
you automatic type conversion for free.
Armed with our more powerful `try!` macro, let's take a look at code we wrote
@ -1367,7 +1367,7 @@ use std::num;
use std::path::Path;
// We derive `Debug` because all types should probably derive `Debug`.
// This gives us a reasonable human readable description of `CliError` values.
// This gives us a reasonable human-readable description of `CliError` values.
#[derive(Debug)]
enum CliError {
Io(io::Error),
@ -1643,7 +1643,7 @@ sure to add `extern crate csv;` to the top of your file.)
use std::fs::File;
// This struct represents the data in each row of the CSV file.
// Type based decoding absolves us of a lot of the nitty gritty error
// Type based decoding absolves us of a lot of the nitty-gritty error
// handling, like parsing strings as integers or floats.
#[derive(Debug, RustcDecodable)]
struct Row {

View File

@ -532,10 +532,10 @@ This is currently hidden behind the `abi_vectorcall` gate and is subject to chan
* `win64`
* `sysv64`
Most of the abis in this list are self-explanatory, but the `system` abi may
Most of the ABIs in this list are self-explanatory, but the `system` ABI may
seem a little odd. This constraint selects whatever the appropriate ABI is for
interoperating with the target's libraries. For example, on win32 with a x86
architecture, this means that the abi used would be `stdcall`. On x86_64,
architecture, this means that the ABI used would be `stdcall`. On x86_64,
however, windows uses the `C` calling convention, so `C` would be used. This
means that in our previous example, we could have used `extern "system" { ... }`
to define a block for all windows systems, not only x86 ones.

View File

@ -177,7 +177,7 @@ similar to regular macros work. You should check out the
[docs](https://docs.rs/quote) for a good introduction.
So I think that's it. Oh, well, we do need to add dependencies for `syn` and
`quote` in the `cargo.toml` for `hello-world-derive`.
`quote` in the `Cargo.toml` for `hello-world-derive`.
```toml
[dependencies]

View File

@ -28,7 +28,7 @@ Generally speaking, unless you have a specific reason, you should be using the
stable release channel. These releases are intended for a general audience.
However, depending on your interest in Rust, you may choose to use nightly
instead. The basic tradeoff is this: in the nightly channel, you can use
instead. The basic trade-off is this: in the nightly channel, you can use
unstable, new Rust features. However, unstable features are subject to change,
and so any new nightly release may break your code. If you use the stable
release, you cannot use experimental features, but the next release of Rust

View File

@ -1,12 +1,23 @@
% There is a new edition of the book
% Associated Types
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Associated types are a way of associating a type placeholder with a trait such that the trait method definitions can use these placeholder types in their signatures.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 19.03 — Advanced Traits][2]**
* <small>[In the first edition: Ch 3.30 — Associated Types][1]</small>
[1]: first-edition/associated-types.html
[2]: second-edition/ch19-03-advanced-traits.html#associated-types
[2]: second-edition/ch19-03-advanced-traits.html#associated-types-specify-placeholder-types-in-trait-definitions

View File

@ -1,12 +1,24 @@
% There is a new edition of the book
% Attributes
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Any item declaration may have an attribute applied to it.
* [Index of the second edition of The Rust Programming Language][2]
```rust
// A function marked as a unit test
#[test]
fn test_foo() {
/* ... */
}
```
---
Here are the relevant sections in the new and old books:
* **[In the Rust Reference: Ch 5.3 — Attributes][2]**
* <small>[In the first edition: Ch 3.27 — Attributes][1]</small>
[1]: first-edition/attributes.html
[2]: second-edition/index.html
[2]: ../reference/attributes.html

View File

@ -1,12 +1,14 @@
% There is a new edition of the book
% Bibliography
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
This page does not exist in [the second edition][2].
You might be interested in a similar page in [the Rust Reference][3].
* [Index of the second edition of The Rust Programming Language][2]
* **[In the Rust Reference: Appendix — Influences][3]**
* <small>[In the first edition: Section 7 — Bibliography][1]</small>
[1]: first-edition/bibliography.html
[2]: second-edition/index.html
[3]: ../reference/influences.html

View File

@ -1,12 +1,25 @@
% There is a new edition of the book
% Borrow and AsRef
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> A cheap reference-to-reference conversion.
> Used to convert a value to a reference value within generic code.
* [Index of the second edition of The Rust Programming Language][2]
```rust
fn is_hello<T: AsRef<str>>(s: T) {
assert_eq!("hello", s.as_ref());
}
```
---
This chapter does not exist in [the second edition][2].
The best place to learn more about this is [the Rust documentation][3].
* **[In the Rust documentation: `convert::AsRef`][3]**
* <small>[In the first edition: Ch 4.10 — Borrow and AsRef][1]</small>
[1]: first-edition/borrow-and-asref.html
[2]: second-edition/index.html
[3]: ../std/convert/trait.AsRef.html

View File

@ -1,12 +1,32 @@
% There is a new edition of the book
% Casting between types
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> A type cast expression is denoted with the binary operator `as`.
> Executing an `as` expression casts the value on the left-hand side to the type on the right-hand side.
* [Index of the second edition of The Rust Programming Language][2]
```rust
# fn sum(values: &[f64]) -> f64 { 0.0 }
# fn len(values: &[f64]) -> i32 { 0 }
fn average(values: &[f64]) -> f64 {
let sum: f64 = sum(values);
let size: f64 = len(values) as f64;
sum / size
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Appendix A — Keywords][2]**
* [In the Rust Reference: Type Cast Expressions][3]
* [In the Rust documentation: `mem::transmute`][4]
* <small>[In the first edition: Ch 3.29 — Casting between types][1]</small>
[1]: first-edition/casting-between-types.html
[2]: second-edition/index.html
[2]: second-edition/appendix-01-keywords.html
[3]: ../reference/expressions/operator-expr.html#type-cast-expressions
[4]: ../std/mem/fn.transmute.html

View File

@ -1,11 +1,21 @@
% There is a new edition of the book
% Choosing your Guarantees
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Smart pointers are data structures that act like a pointer, but they also have additional metadata and capabilities.
> The different smart pointers defined in Rusts standard library provide extra functionality beyond what references provide.
* [Related chapter in the second edition of The Rust Programming Language][2]
```rust
let b = Box::new(5);
println!("b = {}", b);
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 15.00 — Smart Pointers][2]**
* <small>[In the first edition: Ch 4.8 — Choosing your Guarantees][1]</small>
[1]: first-edition/choosing-your-guarantees.html

View File

@ -1,11 +1,27 @@
% There is a new edition of the book
% Closures
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Anonymous functions you can save in a variable or pass as arguments to other functions.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
# use std::thread;
# use std::time::Duration;
let expensive_closure = |num| {
println!("calculating slowly...");
thread::sleep(Duration::from_secs(2));
num
};
# expensive_closure(5);
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 13.01 — Closures][2]**
* <small>[In the first edition: Ch 3.23 — Closures][1]</small>
[1]: first-edition/closures.html

View File

@ -1,11 +1,22 @@
% There is a new edition of the book
% Comments
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Comments must start with two slashes and continue until the end of the line.
> For comments that extend beyond a single line, youll need to include // on each line.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
// So were doing something complicated here, long enough that we need
// multiple lines of comments to do it! Whew! Hopefully, this comment will
// explain whats going on.
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 3.04 — Comments][2]**
* <small>[In the first edition: Ch 3.4 — Comments][1]</small>
[1]: first-edition/comments.html

View File

@ -1,6 +1,13 @@
% The Rust Programming Language Has Moved
% Compiler Plugins
This chapter of the book has moved to [a chapter in the Unstable
Book][unstable book plugins]. Please check it out there.
<small>There is a new edition of the book and this is an old link.</small>
[unstable book plugins]: ../unstable-book/language-features/plugin.html
> Compiler plugins are user-provided libraries that extend the compiler's behavior with new syntax extensions, lint checks, etc.
---
This particular chapter has moved to [the Unstable Book][2].
* **[In the Unstable Rust Book: `plugin`][2]**
[2]: ../unstable-book/language-features/plugin.html

View File

@ -1,11 +1,16 @@
% There is a new edition of the book
% Concurrency
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Historically, programming [concurrency] has been difficult and error prone: Rust hopes to change that.
> Fearless concurrency allows you to write code thats free of subtle bugs and is easy to refactor without introducing new bugs.
* [Related chapter in the second edition of The Rust Programming Language][2]
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 16.00 — Fearless Concurrency][2]**
* <small>[In the first edition: Ch 4.6 — Concurrency][1]</small>
[1]: first-edition/concurrency.html

View File

@ -1,12 +1,28 @@
% There is a new edition of the book
% Conditional Compilation
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Sometimes one wants to have different compiler outputs from the same code, depending on build target, such as targeted operating system, or to enable release builds.
> Configuration options are either provided by the compiler or passed in on the command line using.
> Rust code then checks for their presence using the `#[cfg(...)]` attribute
* [Index of the second edition of The Rust Programming Language][2]
```rust
// The function is only included in the build when compiling for macOS
#[cfg(target_os = "macos")]
fn macos_only() {
// ...
}
```
---
This particular chapter does not exist in [the second edition][2].
The best place to learn about it is [the Rust Reference][3].
* **[In the Rust Reference: Ch 5.3 — Attributes, Conditional Compilation section][3]**
* <small>[In the first edition: Ch 4.3 — Conditional Compilation][1]</small>
[1]: first-edition/conditional-compilation.html
[2]: second-edition/index.html
[3]: ../reference/attributes.html#conditional-compilation

View File

@ -1,12 +1,23 @@
% There is a new edition of the book
% `const` and `static`
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Constants are _always_ immutable, and may only be set to a constant expression, not the result of a function call or any other value that could only be computed at runtime.
>
> Global variables are called `static` in Rust.
* [Related section about `const` in the second edition of The Rust Programming Language][2]
* [Related section about `static` in the second edition of The Rust Programming Language][3]
```rust
const MAX_POINTS: u32 = 100_000;
static HELLO_WORLD: &str = "Hello, world!";
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 3.01 — Variables and Mutability, section Constants][2]**
* **[In the second edition: Ch 19.01 — Unsafe Rust, section Static Variables][3]**
* <small>[In the first edition: Ch 3.26 — `const` and `static`][1]</small>
[1]: first-edition/const-and-static.html

View File

@ -1,15 +1,28 @@
% There is a new edition of the book
% Crates and Modules
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Rust has a module system that enables the reuse of code in an organized fashion.
> A module is a namespace that contains definitions of functions or types, and you can choose whether those definitions are visible outside their module (public) or not (private).
>
> A crate is a project that other people can pull into their projects as a dependency.
* [Related chapter about modules in the second edition of The Rust Programming Language][2]
```rust
mod network {
fn connect() {
}
}
```
* [Related chapter about crates in the second edition of The Rust Programming Language][3]
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 7.01 — `mod` and the Filesystem][2]**
* [In the second edition: Ch 14.02 — Publishing a Crate to Crates.io][2]
* <small>[In the first edition: Ch 3.25 — Crates and Modules][1]</small>
[1]: first-edition/crates-and-modules.html
[2]: second-edition/ch07-00-modules.html
[3]: second-edition/ch14-00-more-about-cargo.html
[2]: second-edition/ch07-01-mod-and-the-filesystem.html
[3]: second-edition/ch14-02-publishing-to-crates-io.html

View File

@ -1,12 +1,30 @@
% There is a new edition of the book
% Deref coercions
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Implementing the `Deref` trait allows us to customize the behavior of the _dereference operator_ `*`.
> By implementing `Deref` in such a way that a smart pointer can be treated like a regular reference, we can write code that operates on references and use that code with smart pointers too.
* [Related section in the second edition of The Rust Programming Language][2]
```rust
use std::ops::Deref;
# struct MyBox<T>(T);
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 15.02 — Treating Smart Pointers like Regular References with the `Deref` Trait][2]**
* <small>[In the first edition: Ch 3.33 — Deref coercions][1]</small>
[1]: first-edition/deref-coercions.html
[2]: second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
[2]: second-edition/ch15-02-deref.html

View File

@ -1,11 +1,31 @@
% There is a new edition of the book
% Documentation
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Documentation comments use `///` instead of `//` and support Markdown notation for formatting the text if youd like.
> You place documentation comments just before the item they are documenting.
* [Related section in the second edition of The Rust Programming Language][2]
```rust,no_run
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 14.02 — Publishing to crates.io, section Making useful documentation][2]**
* <small>[In the first edition: Ch 4.4 — Documentation][1]</small>
[1]: first-edition/documentation.html

View File

@ -1,11 +1,33 @@
% There is a new edition of the book
% Drop
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> `Drop` lets us customize what happens when a value is about to go out of scope.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
fn main() {
let c = CustomSmartPointer { data: String::from("my stuff") };
let d = CustomSmartPointer { data: String::from("other stuff") };
println!("CustomSmartPointers created.");
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 15.03 — The `Drop` Trait Runs Code on Cleanup][2]**
* <small>[In the first edition: Ch 3.20 — Drop][1]</small>
[1]: first-edition/drop.html

View File

@ -1,11 +1,13 @@
% There is a new edition of the book
% Effective Rust
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
This section does not exist in [the second edition][2].
However, the second edition encourages writing effective Rust from the start.
It is recommended to start there.
* [Index of the second edition of The Rust Programming Language][2]
* **[The second edition of The Rust Programming Language][2]**
* <small>[In the first edition: Ch 4 — Effective Rust][1]</small>
[1]: first-edition/effective-rust.html

View File

@ -1,11 +1,22 @@
% There is a new edition of the book
% Enums
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Enums allow you to define a type by enumerating its possible values.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
enum IpAddrKind {
V4,
V6,
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 6.01 — Defining an Enum][2]**
* <small>[In the first edition: Ch 3.13 — Enums][1]</small>
[1]: first-edition/enums.html

View File

@ -1,11 +1,15 @@
% There is a new edition of the book
% Error Handling
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Rust groups errors into two major categories: _recoverable_ errors with `Result<T, E>` and _unrecoverable_ errors with `panic!`.
* [Related chapter in the second edition of The Rust Programming Language][2]
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 9.00 — Error Handling][2]**
* <small>[In the first edition: Ch 4.7 — Error Handling][1]</small>
[1]: first-edition/error-handling.html

View File

@ -1,12 +1,29 @@
% There is a new edition of the book
% FFI
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Sometimes, your Rust code may need to interact with code written in another language.
> To do this, Rust has a keyword, `extern`, that facilitates creating and using a _Foreign Function Interface_ (FFI).
* [Related section in the second edition of The Rust Programming Language][2]
```rust
extern "C" {
fn abs(input: i32) -> i32;
}
fn main() {
unsafe {
println!("Absolute value of -3 according to C: {}", abs(-3));
}
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 19.01 — Unsafe Rust, section `extern` functions][2]**
* <small>[In the first edition: Ch 4.9 — FFI][1]</small>
[1]: first-edition/ffi.html
[2]: second-edition/ch19-01-unsafe-rust.html#calling-an-unsafe-function-or-method
[2]: second-edition/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code

View File

@ -1,11 +1,29 @@
% There is a new edition of the book
% Functions
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Function definitions in Rust start with `fn` and have a set of parentheses after the function name.
> The curly brackets tell the compiler where the function body begins and ends.
> We can call any function weve defined by entering its name followed by a set of parentheses.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
fn main() {
println!("Hello, world!");
another_function();
}
fn another_function() {
println!("Another function.");
}
```
---
Here are the relevant sections in the new and old books:
* **[In the first edition: Ch 3.2 — Functions][1]**
* <small>[In the second edition: Ch 3.03 — Functions][2]</small>
[1]: first-edition/functions.html

View File

@ -1,11 +1,28 @@
% There is a new edition of the book
% Generics
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Generics are abstract stand-ins for concrete types or other properties.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
struct Point<T, U> {
x: T,
y: U,
}
fn main() {
let both_integer = Point { x: 5, y: 10 };
let both_float = Point { x: 1.0, y: 4.0 };
let integer_and_float = Point { x: 5, y: 4.0 };
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 10.00 — Generic Types, Traits, and Lifetimes][2]**
* <small>[In the first edition: Ch 3.18 — Generics][1]</small>
[1]: first-edition/generics.html

View File

@ -1,11 +1,12 @@
% There is a new edition of the book
% Getting Started
This is an old link. You can [continue to the exact older page][1].
<small>There is a new edition of the book and this is an old link.</small>
You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
* [This page in the first edition of the The Rust Programming Language][1]
* [Related chapter in the second edition of The Rust Programming Language][2]
* **[In the second edition: Introduction][2]**
* <small>[In the first edition: Getting Started][1]</small>
[1]: first-edition/getting-started.html

View File

@ -1,11 +1,13 @@
% There is a new edition of the book
% Glossary
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
This section does not exist in [the second edition][2].
However, the second edition defines the terms it uses inline, rather than using a glossary.
It is recommended to start there.
* [Index of the second edition of The Rust Programming Language][2]
* **[The second edition of The Rust Programming Language][2]**
* <small>[In the first edition: Glossary][1]</small>
[1]: first-edition/glossary.html

View File

@ -1,11 +1,11 @@
% There is a new edition of the book
% Tutorial: Guessing Game
<small>There is a new edition of the book and this is an old link.</small>
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
* [This page in the first edition of the The Rust Programming Language][1]
* [Related chapter in second edition of The Rust Programming Language][2]
* **[In the first edition: Tutorial — Guessing Game][1]**
* <small>[In the second edition: Ch 2.00 — Guessing Game tutorial][2]</small>
[1]: first-edition/guessing-game.html

View File

@ -1,11 +1,22 @@
% There is a new edition of the book
% if let
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> The `if let` syntax lets you combine `if` and `let` into a less verbose way to handle values that match one pattern and ignore the rest.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
let some_u8_value = Some(3u8);
if let Some(3) = some_u8_value {
println!("three");
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 6.03 — Concise Control Flow with `if let`][2]**
* <small>[In the first edition: Ch 3.21 — if let][1]</small>
[1]: first-edition/if-let.html

View File

@ -1,11 +1,27 @@
% There is a new edition of the book
% if
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> An `if` expression allows us to branch our code depending on conditions.
* [Related section in second edition of The Rust Programming Language][2]
```rust
fn main() {
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 3.05 — Control flow][2]**
* <small>[In the first edition: Ch 3.5 — if][1]</small>
[1]: first-edition/if.html

View File

@ -1,11 +1,26 @@
% There is a new edition of the book
% Iterators
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> The iterator pattern allows you to perform some task on a sequence of items in turn.
> An iterator is responsible for the logic of iterating over each item and determining when the sequence has finished.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
for val in v1_iter {
println!("Got: {}", val);
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 13.02 — Iterators][2]**
* <small>[In the first edition: Ch 4.5 — Iterators][1]</small>
[1]: first-edition/iterators.html

View File

@ -1,13 +1,28 @@
% There is a new edition of the book
% Lifetimes
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Every reference in Rust has a lifetime, which is the scope for which that reference is valid.
> Most of the time lifetimes are implicit and inferred.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
{
let x = 5; // -----+-- 'b
// |
let r = &x; // --+--+-- 'a
// | |
println!("r: {}", r); // | |
// --+ |
} // -----+
```
* [Related page in the second edition of The Rust Programming Language (covering more advanced topics)][3]
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 10.03 — Lifetimes][2]**
* [In the second edition: Ch 19.02 — Advanced Lifetimes][3]
* <small>[In the first edition: Ch 3.10 — Lifetimes][1]</small>
[1]: first-edition/lifetimes.html

View File

@ -1,11 +1,35 @@
% There is a new edition of the book
% Loops
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Rust has three kinds of loops: `loop`, `while`, and `for`.
> The `loop` keyword tells Rust to execute a block of code over and over again forever or until you explicitly tell it to stop.
> `while` loops evaluate a block of code until a condition ceases to be true.
> A `for` loop executes some code for each item in a collection.
* [Related section in the second edition of The Rust Programming Language][2]
```rust,no_run
loop {
println!("again!");
}
let mut number = 3;
while number != 0 {
println!("{}!", number);
number = number - 1;
}
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("the value is: {}", element);
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 3.05 — Control flow][2]**
* <small>[In the first edition: Ch 3.6 — Loops][1]</small>
[1]: first-edition/loops.html

View File

@ -1,12 +1,31 @@
% There is a new edition of the book
% Macros
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> While functions and types abstract over code, macros abstract at a syntactic level.
* [Index of the second edition of The Rust Programming Language][2]
```rust
macro_rules! five_times {
($x:expr) => (5 * $x);
}
fn main() {
assert_eq!(25, five_times!(2 + 3));
}
```
---
This chapter does not exist yet in [the second edition][2].
You can check out other resources that describe macros.
* **[Rust By Example: Macros][3]**
* [In the Rust Reference: Ch 3.1 — Macros by Example][4]
* [In the second edition: (future) Appendix D — Macros][2]
* <small>[In the first edition: Ch 3.34 — Macros][1]</small>
[1]: first-edition/macros.html
[2]: second-edition/index.html
[2]: second-edition/appendix-04-macros.html
[3]: https://rustbyexample.com/macros.html
[4]: ../reference/macros-by-example.html

View File

@ -1,13 +1,35 @@
% There is a new edition of the book
% Match
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> `match` allows us to compare a value against a series of patterns and then execute code based on which pattern matches.
> Patterns can be made up of literal values, variable names, wildcards, and many other things.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
* [Related chapter in the second edition of The Rust Programming Language (covering more advanced topics)][3]
fn value_in_cents(coin: Coin) -> u32 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 6.02 — The `match` Control Flow Operator][2]**
* [In the second edition: Ch 18.00 — Patterns][3]
* <small>[In the first edition: Ch 3.14 — Match][1]</small>
[1]: first-edition/match.html

View File

@ -1,11 +1,28 @@
% There is a new edition of the book
% Method Syntax
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Methods are different from functions in that theyre defined within the context of a struct, and their first parameter is always `self`, which represents the instance of the struct the method is being called on.
* [Related page in the second edition of The Rust Programming Language][2]
```rust
# struct Rectangle {
# width: u32,
# height: u32,
# }
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 5.03 — Method Syntax][2]**
* <small>[In the first edition: Ch 3.16 — Method Syntax][1]</small>
[1]: first-edition/method-syntax.html

View File

@ -1,11 +1,22 @@
% There is a new edition of the book
% Mutability
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Variables are immutable only by default; we can make them mutable by adding mut in front of the variable name.
* [Related page in second edition of The Rust Programming Language][2]
```rust
let mut x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 3.01 — Variables and Mutability][2]**
* <small>[In the first edition: Ch 3.11 — Mutability][1]</small>
[1]: first-edition/mutability.html

View File

@ -1,12 +1,43 @@
% There is a new edition of the book
% Operators and Overloading
This is an old link. You can [continue to the exact older page][1].
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
<small>There is a new edition of the book and this is an old link.</small>
* [This page in the first edition of the The Rust Programming Language][1]
> Rust does not allow you to create your own operators or overload arbitrary operators, but the operations and corresponding traits listed in `std::ops` can be overloaded by implementing the traits associated with the operator.
* [Related section in the second edition of The Rust Programming Language][2]
```rust
use std::ops::Add;
#[derive(Debug,PartialEq)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
fn main() {
assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
Point { x: 3, y: 3 });
}
```
---
Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 19.03 — Advanced Traits, section Operator Overloading][2]**
* [In the Rust documentation: `std::ops`][3]
* <small>[In the first edition: Ch 3.32 — Operators and Overloading][1]</small>
[1]: first-edition/operators-and-overloading.html
[2]: second-edition/ch19-03-advanced-traits.html#operator-overloading-and-default-type-parameters
[2]: second-edition/ch19-03-advanced-traits.html#default-generic-type-parameters-and-operator-overloading
[3]: ../std/ops/index.html

Some files were not shown because too many files have changed in this diff Show More