mirror of
https://git.proxmox.com/git/rustc
synced 2026-02-01 17:36:27 +00:00
New upstream version 1.25.0+dfsg1
This commit is contained in:
parent
ff7c6d114e
commit
2c00a5a8d9
@ -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.
|
||||
|
||||
31
RELEASES.md
31
RELEASES.md
@ -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`,
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
d3ae9a9e08edf12de0ed82af57ba2a56c26496ea
|
||||
84203cac67e65ca8640b8392348411098c856985
|
||||
1072
src/Cargo.lock
generated
1072
src/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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" }
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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"],
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
1646
src/bootstrap/test.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -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)]
|
||||
|
||||
@ -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"\??\";
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
};
|
||||
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
clang \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
49
src/ci/docker/dist-various-2/build-cloudabi-toolchain.sh
Executable file
49
src/ci/docker/dist-various-2/build-cloudabi-toolchain.sh
Executable 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
|
||||
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
clang \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
74
src/ci/docker/scripts/musl.sh
Normal file
74
src/ci/docker/scripts/musl.sh
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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'..."
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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!
|
||||
|
||||
[](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/
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
[book]
|
||||
title = "The Rust Programming Language"
|
||||
author = "The Rust Project Developers"
|
||||
|
||||
@ -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 “wrapper type” 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.
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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 that’s 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`. It’s pretty
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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 Rust’s 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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, you’ll need to include // on each line.
|
||||
|
||||
* [Related page in the second edition of The Rust Programming Language][2]
|
||||
```rust
|
||||
// So we’re doing something complicated here, long enough that we need
|
||||
// multiple lines of comments to do it! Whew! Hopefully, this comment will
|
||||
// explain what’s 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 that’s 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 you’d 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 we’ve 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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 they’re 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
Loading…
Reference in New Issue
Block a user