From 7aca34b8963fd9ac8681485a44417e537e617245 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Fri, 16 Feb 2018 16:47:00 -0600 Subject: [PATCH 01/21] add readme for librustdoc --- src/librustdoc/README.md | 170 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 src/librustdoc/README.md diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md new file mode 100644 index 000000000000..844c54c7aa88 --- /dev/null +++ b/src/librustdoc/README.md @@ -0,0 +1,170 @@ +# The walking tour of rustdoc + +Rustdoc is implemented entirely within the crate `librustdoc`. After partially compiling a crate to +get its AST (technically the HIR map) from rustc, librustdoc performs two major steps past that to +render a set of documentation: + +* "Clean" the AST into a form that's more suited to creating documentation (and slightly more + resistant to churn in the compiler). +* Use this cleaned AST to render a crate's documentation, one page at a time. + +Naturally, there's more than just this, and those descriptions simplify out lots of details, but +that's the high-level overview. + +(Side note: this is a library crate! The `rustdoc` binary is crated using the project in +`src/tools/rustdoc`. Note that literally all that does is call the `main()` that's in this crate's +`lib.rs`, though.) + +## Cheat sheet + +* Use `x.py build --stage 1 src/libstd src/tools/rustdoc` to make a useable rustdoc you can run on + other projects. + * Add `src/libtest` to be able to use `rustdoc --test`. + * If you've used `rustup toolchain link local /path/to/build/$TARGET/stage1` previously, then + after the previous build command, `cargo +local doc` will Just Work. +* Use `x.py doc --stage 1 src/libstd` to use this rustdoc to generate the standard library docs. + * The completed docs will be available in `build/$TARGET/doc/std`, though the bundle is meant to + be used as though you would copy out the `doc` folder to a web server, since that's where the + CSS/JS and landing page are. +* Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. It's in a bunch of + `fmt::Display` implementations and supplementary functions. +* The types that operates on are defined in `clean/mod.rs`, right next to the custom `Clean` trait + used to process them out of the rustc HIR. +* The bits specific to using rustdoc as a test harness are in `test.rs`. +* The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting + doctests from a given block of Markdown. +* The tests on rustdoc *output* are located in `src/test/rustdoc`, where they're handled by the test + runner of rustbuild and the supplementary script `src/etc/htmldocck.py`. +* Tests on search index generation are located in `src/test/rustdoc-js`, as a series of JavaScript + files that encode queries on the standard library search index and expected results. + +## From crate to clean + +In `core.rs` are two central items: the `DocContext` struct, and the `run_core` function. The latter +is where rustdoc calls out to rustc to compile a crate to the point where rustdoc can take over. The +former is a state container used when crawling through a crate to gather its documentation. + +The main process of crate crawling is done in `clean/mod.rs` through several implementations of the +`Clean` trait defined within. This is a conversion trait, which defines one method: + +```rust +pub trait Clean { + fn clean(&self, cx: &DocContext) -> T; +} +``` + +`clean/mod.rs` also defines the types for the "cleaned" AST used later on to render documentation +pages. Each usually accompanies an implementation of `Clean` that takes some AST or HIR type from +rustc and converts it into the appropriate "cleaned" type. "Big" items like modules or associated +items may have some extra processing in its `Clean` implementation, but for the most part these +impls are straightforward conversions. The "entry point" to this module is the `impl Clean +for visit_ast::RustdocVisitor`, which is called by `run_core` above. + +You see, I actually lied a little earlier: There's another AST transformation that happens before +the events in `clean/mod.rs`. In `visit_ast.rs` is the type `RustdocVisitor`, which *actually* +crawls a `hir::Crate` to get the first intermediate representation, defined in `doctree.rs`. This +pass is mainly to get a few intermediate wrappers around the HIR types and to process visibility +and inlining. This is where `#[doc(inline)]`, `#[doc(no_inline)]`, and `#[doc(hidden)]` are +processed, as well as the logic for whether a `pub use` should get the full page or a "Reexport" +line in the module page. + +Back in `clean/mod.rs`, the other major thing that happens here is the special collection of doc +comments (and basic `#[doc=""]` attributes) into a separate field in the `Attributes` struct from +the other attributes. The primary output of this process is a `clean::Crate` with a tree of `Item`s +which describe the publicly-documentable items in the target crate. + +### Hot potato + +Before moving on to the next major step, a few important "passes" occur over the documentation. +These do things like combine the separate "attributes" into a single string and strip leading +whitespace to make the document easier on the markdown parser, or drop items that are not public or +deliberately hidden with `#[doc(hidden)]`. These are all implemented in the `passes/` directory, one +file per pass. By default, all of these passes are run on a crate, but the ones regarding dropping +private/hidden items can be bypassed by passing `--document-private-items` to rustdoc. + +(Strictly speaking, you can fine-tune the passes run and even add your own, but [we're trying to +deprecate that][44136]. If you need finer-grain control over these passes, please let us know!) + +[44136]: https://github.com/rust-lang/rust/issues/44136 + +## From clean to crate + +This is where the "second phase" in rustdoc begins. This phase primarily lives in the `html/` +folder, and it all starts with `run()` in `html/render.rs`. This code is responsible for setting up +the `Context`, `SharedContext`, and `Cache` which are used during rendering, copying out the static +files which live in every rendered set of documentation (things like the fonts, CSS, and JavaScript +that live in `html/static/`), creating the search index, and printing out the source code rendering, +before beginning the process of rendering all the documentation for the crate. + +Several functions implemented directly on `Context` take the `clean::Crate` and set up some state +between rendering items or recursing on a module's child items. From here the "page rendering" +begins, via an enormous `write!()` call in `html/layout.rs`. The parts that actually generate HTML +from the items and documentation occurs within a series of `std::fmt::Display` implementations and +functions that pass around a `&mut std::fmt::Formatter`. The top-level implementation that writes +out the page body is the `impl<'a> fmt::Display for Item<'a>` in `html/render.rs`, which switches +out to one of several `item_*` functions based on the kind of `Item` being rendered. + +Depending on what kind of rendering code you're looking for, you'll probably find it either in +`html/render.rs` for major items like "what sections should I print for a struct page" or +`html/format.rs` for smaller component pieces like "how should I print a where clause as part of +some other item". + +Whenever rustdoc comes across an item that should print hand-written documentation alongside, it +calls out to `html/markdown.rs` which interfaces with the Markdown parser. This is exposed as a +series of types that wrap a string of Markdown, and implement `fmt::Display` to emit HTML text. It +takes special care to enable certain features like footnotes and tables and add syntax highlighting +to Rust code blocks (via `html/highlight.rs`) before running the Markdown parser. There's also a +function in here (`find_testable_code`) that specifically scans for Rust code blocks so the +test-runner code can find all the doctests in the crate. + +### From soup to nuts + +(alternate title: ["An unbroken thread that stretches from those first `Cell`s to us"][video]) + +[video]: https://www.youtube.com/watch?v=hOLAGYmUQV0 + +It's important to note that the AST cleaning can ask the compiler for information (crucially, +`DocContext` contains a `TyCtxt`), but page rendering cannot. The `clean::Crate` created within +`run_core` is passed outside the compiler context before being handed to `html::render::run`. This +means that a lot of the "supplementary data" that isn't immediately available inside an item's +definition, like which trait is the `Deref` trait used by the language, needs to be collected during +cleaning, stored in the `DocContext`, and passed along to the `SharedContext` during HTML rendering. +This manifests as a bunch of shared state, context variables, and `RefCell`s. + +Also of note is that some items that come from "asking the compiler" don't go directly into the +`DocContext` - for example, when loading items from a foreign crate, rustdoc will ask about trait +implementations and generate new `Item`s for the impls based on that information. This goes directly +into the returned `Crate` rather than roundabout through the `DocContext`. This way, these +implementations can be collected alongside the others, right before rendering the HTML. + +## Other tricks up its sleeve + +All this describes the process for generating HTML documentation from a Rust crate, but there are +couple other major modes that rustdoc runs in. It can also be run on a standalone Markdown file, or +it can run doctests on Rust code or standalone Markdown files. For the former, it shortcuts straight +to `html/markdown.rs`, optionally including a mode which inserts a Table of Contents to the output +HTML. + +For the latter, rustdoc runs a similar partial-compilation to get relevant documentation in +`test.rs`, but instead of going through the full clean and render process, it runs a much simpler +crate walk to grab *just* the hand-written documentation. Combined with the aforementioned +"`find_testable_code`" in `html/markdown.rs`, it builds up a collection of tests to run before +handing them off to the libtest test runner. One notable location in `test.rs` is the function +`make_test`, which is where hand-written doctests get transformed into something that can be +executed. + +## Dotting i's and crossing t's + +So that's rustdoc's code in a nutshell, but there's more things in the repo that deal with it. Since +we have the full `compiletest` suite at hand, there's a set of tests in `src/test/rustdoc` that make +sure the final HTML is what we expect in various situations. These tests also use a supplementary +script, `src/etc/htmldocck.py`, that allows it to look through the final HTML using XPath notation +to get a precise look at the output. The full description of all the commands available to rustdoc +tests is in `htmldocck.py`. + +In addition, there are separate tests for the search index and rustdoc's ability to query it. The +files in `src/test/rustdoc-js` each contain a different search query and the expected results, +broken out by search tab. These files are processed by a script in `src/tools/rustdoc-js` and the +Node.js runtime. These tests don't have as thorough of a writeup, but a broad example that features +results in all tabs can be found in `basic.js`. The basic idea is that you match a given `QUERY` +with a set of `EXPECTED` results, complete with the full item path of each item. From 8d893c1e9e136302a1640035b29e23023f87866e Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 20 Feb 2018 09:26:44 -0600 Subject: [PATCH 02/21] review nits --- src/librustdoc/README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md index 844c54c7aa88..b0a5ae3718df 100644 --- a/src/librustdoc/README.md +++ b/src/librustdoc/README.md @@ -28,8 +28,8 @@ that's the high-level overview. CSS/JS and landing page are. * Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. It's in a bunch of `fmt::Display` implementations and supplementary functions. -* The types that operates on are defined in `clean/mod.rs`, right next to the custom `Clean` trait - used to process them out of the rustc HIR. +* The types that got `Display` impls above are defined in `clean/mod.rs`, right next to the custom + `Clean` trait used to process them out of the rustc HIR. * The bits specific to using rustdoc as a test harness are in `test.rs`. * The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting doctests from a given block of Markdown. @@ -68,10 +68,12 @@ and inlining. This is where `#[doc(inline)]`, `#[doc(no_inline)]`, and `#[doc(hi processed, as well as the logic for whether a `pub use` should get the full page or a "Reexport" line in the module page. -Back in `clean/mod.rs`, the other major thing that happens here is the special collection of doc -comments (and basic `#[doc=""]` attributes) into a separate field in the `Attributes` struct from -the other attributes. The primary output of this process is a `clean::Crate` with a tree of `Item`s -which describe the publicly-documentable items in the target crate. +The other major thing that happens in `clean/mod.rs` is the collection of doc comments and +`#[doc=""]` attributes into a separate field of the Attributes struct, present on anything that gets +hand-written documentation. This makes it easier to collect this documentation later in the process. + +The primary output of this process is a clean::Crate with a tree of Items which describe the +publicly-documentable items in the target crate. ### Hot potato From 8e4ad29cb9cc74bf44486f4507f36df70d495187 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 23 Feb 2018 21:48:41 +0900 Subject: [PATCH 03/21] Disable NEON on musl ARMv7 --- .../target/armv7_unknown_linux_musleabihf.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs index a36e26c0b7d5..88f2b5967518 100644 --- a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs +++ b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs @@ -12,13 +12,7 @@ use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let mut base = super::linux_musl_base::opts(); - - // Most of these settings are copied from the armv7_unknown_linux_gnueabihf - // target. - base.features = "+v7,+vfp3,+neon".to_string(); - base.cpu = "cortex-a8".to_string(); - base.max_atomic_width = Some(64); + let base = super::linux_musl_base::opts(); Ok(Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and LLVM @@ -33,9 +27,15 @@ pub fn target() -> TargetResult { target_env: "musl".to_string(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, + + // Most of these settings are copied from the armv7_unknown_linux_gnueabihf + // target. options: TargetOptions { + features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(), + cpu: "generic".to_string(), + max_atomic_width: Some(64), abi_blacklist: super::arm_base::abi_blacklist(), .. base - }, + } }) } From ffb6291cd032e3b0577bf67a2b6d932d6ba0787c Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Mon, 26 Feb 2018 20:45:52 -0500 Subject: [PATCH 04/21] Improve --help performance for x.py Since compiling the bootstrap command doesn't require any submodules, we can skip updating submodules when a --help command is passed in. On my machine, this saves 1 minute if the submodules are already downloaded, and 10 minutes if run on a clean repo. This commit also adds a message before compiling/downloading anything when a --help command is passed in, to tell the user WHY --help takes so long to complete. It also points the user to the bootstrap README.md for faster help. Finally, this fixes one warning message that still referenced using make instead of x.py, even though x.py is now the standard way of building rust. --- src/bootstrap/bootstrap.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 603a97ddfd41..f5fcf4ba0f56 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -670,7 +670,7 @@ class RustBuild(object): self._download_url = 'https://dev-static.rust-lang.org' -def bootstrap(): +def bootstrap(help_triggered): """Configure, fetch, build and run the initial bootstrap""" parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') @@ -708,7 +708,7 @@ def bootstrap(): print(' and so in order to preserve your $HOME this will now') print(' use vendored sources by default. Note that if this') print(' does not work you should run a normal build first') - print(' before running a command like `sudo make install`') + print(' before running a command like `sudo ./x.py install`') if build.use_vendored_sources: if not os.path.exists('.cargo'): @@ -734,7 +734,10 @@ def bootstrap(): if 'dev' in data: build.set_dev_environment() - build.update_submodules() + # No help text depends on submodules. This check saves ~1 minute of git commands, even if + # all the submodules are present and downloaded! + if not help_triggered: + build.update_submodules() # Fetch/build the bootstrap build.build = args.build or build.build_triple() @@ -760,7 +763,13 @@ def main(): help_triggered = ( '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) try: - bootstrap() + # If the user is asking for help, let them know that the whole download-and-build + # process has to happen before anything is printed out. + if help_triggered: + print("NOTE: Downloading and compiling bootstrap requirements before processing") + print(" --help command. See src/bootstrap/README.md for help with common") + print(" commands.") + bootstrap(help_triggered) if not help_triggered: print("Build completed successfully in {}".format( format_build_time(time() - start_time))) From 89e55d108c5c6d5f29c4eb0cb829e47bccb8598b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 3 Dec 2017 14:24:14 +0100 Subject: [PATCH 05/21] Make TransitiveRelation thread safe. Avoid locking by using get_mut in some cases. --- .../transitive_relation.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index ba7ab0c07c66..6d63bc4436fe 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -10,16 +10,16 @@ use bitvec::BitMatrix; use fx::FxHashMap; +use sync::Lock; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use stable_hasher::{HashStable, StableHasher, StableHasherResult}; -use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::mem; #[derive(Clone, Debug)] -pub struct TransitiveRelation { +pub struct TransitiveRelation { // List of elements. This is used to map from a T to a usize. elements: Vec, @@ -32,14 +32,14 @@ pub struct TransitiveRelation { // This is a cached transitive closure derived from the edges. // Currently, we build it lazilly and just throw out any existing - // copy whenever a new edge is added. (The RefCell is to permit + // copy whenever a new edge is added. (The Lock is to permit // the lazy computation.) This is kind of silly, except for the // fact its size is tied to `self.elements.len()`, so I wanted to // wait before building it up to avoid reallocating as new edges // are added with new elements. Perhaps better would be to ask the // user for a batch of edges to minimize this effect, but I // already wrote the code this way. :P -nmatsakis - closure: RefCell>, + closure: Lock>, } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] @@ -51,13 +51,13 @@ struct Edge { target: Index, } -impl TransitiveRelation { +impl TransitiveRelation { pub fn new() -> TransitiveRelation { TransitiveRelation { elements: vec![], map: FxHashMap(), edges: vec![], - closure: RefCell::new(None), + closure: Lock::new(None), } } @@ -72,7 +72,7 @@ impl TransitiveRelation { fn add_index(&mut self, a: T) -> Index { let &mut TransitiveRelation { ref mut elements, - ref closure, + ref mut closure, ref mut map, .. } = self; @@ -82,7 +82,7 @@ impl TransitiveRelation { elements.push(a); // if we changed the dimensions, clear the cache - *closure.borrow_mut() = None; + *closure.get_mut() = None; Index(elements.len() - 1) }) @@ -122,7 +122,7 @@ impl TransitiveRelation { self.edges.push(edge); // added an edge, clear the cache - *self.closure.borrow_mut() = None; + *self.closure.get_mut() = None; } } @@ -443,7 +443,7 @@ impl Decodable for TransitiveRelation .enumerate() .map(|(index, elem)| (elem.clone(), Index(index))) .collect(); - Ok(TransitiveRelation { elements, edges, map, closure: RefCell::new(None) }) + Ok(TransitiveRelation { elements, edges, map, closure: Lock::new(None) }) }) } } From 5ac4f62f3832f2a4ed26ab95567c96a38a9f4f15 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Wed, 28 Feb 2018 20:57:56 -0800 Subject: [PATCH 06/21] impl Clone for ::std_unicode::char::{ToLowercase, ToUppercase} --- src/libstd_unicode/char.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 844ff7a3c125..5dd9c6277509 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -59,7 +59,7 @@ pub use version::UnicodeVersion; /// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase /// [`char`]: ../../std/primitive.char.html #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ToLowercase(CaseMappingIter); #[stable(feature = "rust1", since = "1.0.0")] @@ -81,7 +81,7 @@ impl FusedIterator for ToLowercase {} /// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase /// [`char`]: ../../std/primitive.char.html #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ToUppercase(CaseMappingIter); #[stable(feature = "rust1", since = "1.0.0")] @@ -95,7 +95,7 @@ impl Iterator for ToUppercase { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for ToUppercase {} -#[derive(Debug)] +#[derive(Debug, Clone)] enum CaseMappingIter { Three(char, char, char), Two(char, char), From 39d0b054cea73614a0c1dd06cd98d3d22eea6b10 Mon Sep 17 00:00:00 2001 From: Segev Finer Date: Thu, 1 Mar 2018 14:47:20 +0200 Subject: [PATCH 07/21] Restore the download of rust-mingw The build might otherwise break due to mixing MinGW object files from rust-std and the local MinGW which might be newer/older than the version used to build rust-std. Fixes #48272 --- src/bootstrap/bootstrap.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5966bb65df9c..761cc94c8c66 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -351,6 +351,11 @@ 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())): From 5332d9a8e8a66e22b8c81f3f302ce72734ba137f Mon Sep 17 00:00:00 2001 From: Segev Finer Date: Thu, 1 Mar 2018 18:33:14 +0200 Subject: [PATCH 08/21] Document why we download rust-mingw --- src/bootstrap/bootstrap.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 761cc94c8c66..5d297570bc12 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -351,6 +351,9 @@ class RustBuild(object): with open(self.rustc_stamp(), 'w') as rust_stamp: rust_stamp.write(self.date) + # This is required so that we don't mix incompatible MinGW + # libraries/binaries that are included in rust-std with + # the system MinGW ones. if "pc-windows-gnu" in self.build: filename = "rust-mingw-{}-{}.tar.gz".format( rustc_channel, self.build) From fdef6a881e784c505fc28ee85d54f72a77921410 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 28 Feb 2018 21:25:12 -0800 Subject: [PATCH 09/21] rustbuild: Pass `ccache` to build scripts This is a re-attempt at #48192 hopefully this time with 100% less randomly [blocking builds for 20 minutes][block]. To work around #48192 the sccache server is started in the `run.sh` script very early on in the compilation process. [block]: https://github.com/rust-lang/rust/issues/48192 --- src/bootstrap/builder.rs | 27 ++++++++++++++++++++++----- src/ci/run.sh | 6 ++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b5946b44e05e..c88aa462a954 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -686,9 +686,25 @@ impl<'a> Builder<'a> { // // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { - let cc = self.cc(target); - cargo.env(format!("CC_{}", target), cc) - .env("CC", cc); + let ccache = self.config.ccache.as_ref(); + let ccacheify = |s: &Path| { + let ccache = match ccache { + Some(ref s) => s, + None => return s.display().to_string(), + }; + // FIXME: the cc-rs crate only recognizes the literal strings + // `ccache` and `sccache` when doing caching compilations, so we + // mirror that here. It should probably be fixed upstream to + // accept a new env var or otherwise work with custom ccache + // vars. + match &ccache[..] { + "ccache" | "sccache" => format!("{} {}", ccache, s.display()), + _ => s.display().to_string(), + } + }; + let cc = ccacheify(&self.cc(target)); + cargo.env(format!("CC_{}", target), &cc) + .env("CC", &cc); let cflags = self.cflags(target).join(" "); cargo.env(format!("CFLAGS_{}", target), cflags.clone()) @@ -703,8 +719,9 @@ impl<'a> Builder<'a> { } if let Ok(cxx) = self.cxx(target) { - cargo.env(format!("CXX_{}", target), cxx) - .env("CXX", cxx) + let cxx = ccacheify(&cxx); + cargo.env(format!("CXX_{}", target), &cxx) + .env("CXX", &cxx) .env(format!("CXXFLAGS_{}", target), cflags.clone()) .env("CXXFLAGS", cflags); } diff --git a/src/ci/run.sh b/src/ci/run.sh index 02480c6937de..3be1c255c164 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -67,6 +67,12 @@ else fi fi +# We've had problems in the past of shell scripts leaking fds into the sccache +# server (#48192) which causes Cargo to erroneously think that a build script +# hasn't finished yet. Try to solve that problem by starting a very long-lived +# sccache server at the start of the build, but no need to worry if this fails. +SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true + travis_fold start configure travis_time_start $SRC/configure $RUST_CONFIGURE_ARGS From 2269ff521fe2a945e462d5156799011c5fce2966 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Fri, 2 Mar 2018 03:29:35 -0500 Subject: [PATCH 10/21] Remove print_what_bootstrap_means It was an existing solution to tell the user why a --help command takes a long time to process. However, it would only print if the stage0 rust compiler needed to be downloaded, it came after update_submodules (which took a long time), and it was immediately followed by download messages and loading bars, meaning users could easily gloss over the message. This commit also moves the help message out of main(), and instead puts it at the top of bootstrap(). main() is intended to be minimal, only handling error messages. --- src/bootstrap/bootstrap.py | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index f5fcf4ba0f56..327ae0cb65c8 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -314,7 +314,6 @@ class RustBuild(object): self.build_dir = os.path.join(os.getcwd(), "build") self.clean = False self.config_toml = '' - self.printed = False self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) self.use_locked_deps = '' self.use_vendored_sources = '' @@ -336,7 +335,6 @@ class RustBuild(object): if self.rustc().startswith(self.bin_root()) and \ (not os.path.exists(self.rustc()) or self.program_out_of_date(self.rustc_stamp())): - self.print_what_bootstrap_means() if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) filename = "rust-std-{}-{}.tar.gz".format( @@ -354,7 +352,6 @@ class RustBuild(object): if self.cargo().startswith(self.bin_root()) and \ (not os.path.exists(self.cargo()) or self.program_out_of_date(self.cargo_stamp())): - self.print_what_bootstrap_means() filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build) self._download_stage0_helper(filename, "cargo") self.fix_executable("{}/bin/cargo".format(self.bin_root())) @@ -555,23 +552,6 @@ class RustBuild(object): return '.exe' return '' - def print_what_bootstrap_means(self): - """Prints more information about the build system""" - if hasattr(self, 'printed'): - return - self.printed = True - if os.path.exists(self.bootstrap_binary()): - return - if '--help' not in sys.argv or len(sys.argv) == 1: - return - - print('info: the build system for Rust is written in Rust, so this') - print(' script is now going to download a stage0 rust compiler') - print(' and then compile the build system itself') - print('') - print('info: in the meantime you can read more about rustbuild at') - print(' src/bootstrap/README.md before the download finishes') - def bootstrap_binary(self): """Return the path of the boostrap binary @@ -585,7 +565,6 @@ class RustBuild(object): def build_bootstrap(self): """Build bootstrap""" - self.print_what_bootstrap_means() build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -672,6 +651,14 @@ class RustBuild(object): def bootstrap(help_triggered): """Configure, fetch, build and run the initial bootstrap""" + + # If the user is asking for help, let them know that the whole download-and-build + # process has to happen before anything is printed out. + if help_triggered: + print("info: Downloading and building bootstrap before processing --help") + print(" command. See src/bootstrap/README.md for help with common") + print(" commands.") + parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') parser.add_argument('--build') @@ -763,12 +750,6 @@ def main(): help_triggered = ( '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) try: - # If the user is asking for help, let them know that the whole download-and-build - # process has to happen before anything is printed out. - if help_triggered: - print("NOTE: Downloading and compiling bootstrap requirements before processing") - print(" --help command. See src/bootstrap/README.md for help with common") - print(" commands.") bootstrap(help_triggered) if not help_triggered: print("Build completed successfully in {}".format( From 6250a47ea6147a60e11e59aded80ebb62c8e3ab1 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Fri, 2 Mar 2018 09:19:50 +0100 Subject: [PATCH 11/21] make codegen-backends directory name configurable This allows to parallel-install several versions of rust system-wide Fixes #48263 Signed-off-by: Marc-Antoine Perennou --- config.toml.example | 3 +++ src/bootstrap/builder.rs | 2 +- src/bootstrap/compile.rs | 3 ++- src/bootstrap/config.rs | 5 +++++ src/bootstrap/dist.rs | 3 ++- src/librustc_driver/lib.rs | 4 +++- 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/config.toml.example b/config.toml.example index 8d1fa3eec5cf..3dfd25aade1e 100644 --- a/config.toml.example +++ b/config.toml.example @@ -321,6 +321,9 @@ # bootstrap) #codegen-backends = ["llvm"] +# This is the name of the directory in which codegen backends will get installed +#codegen-backends-dir = "codegen-backends" + # 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. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b5946b44e05e..2eec6c69739b 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -462,7 +462,7 @@ impl<'a> Builder<'a> { pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf { self.sysroot_libdir(compiler, compiler.host) - .with_file_name("codegen-backends") + .with_file_name(self.build.config.rust_codegen_backends_dir.clone()) } /// Returns the compiler's libdir where it stores the dynamic libraries that diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 2c9f0ddb6c33..f8e0a1f5a923 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -514,7 +514,8 @@ fn rustc_cargo_env(build: &Build, cargo: &mut Command) { cargo.env("CFG_RELEASE", build.rust_release()) .env("CFG_RELEASE_CHANNEL", &build.config.channel) .env("CFG_VERSION", build.rust_version()) - .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default()); + .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default()) + .env("CFG_CODEGEN_BACKENDS_DIR", &build.config.rust_codegen_backends_dir); let libdir_relative = build.config.libdir_relative().unwrap_or(Path::new("lib")); cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 6bc20181a033..361fc704bc07 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -96,6 +96,7 @@ pub struct Config { pub rust_debuginfo_tests: bool, pub rust_dist_src: bool, pub rust_codegen_backends: Vec>, + pub rust_codegen_backends_dir: String, pub build: Interned, pub hosts: Vec>, @@ -289,6 +290,7 @@ struct Rust { test_miri: Option, save_toolstates: Option, codegen_backends: Option>, + codegen_backends_dir: Option, wasm_syscall: Option, } @@ -330,6 +332,7 @@ impl Config { config.rust_dist_src = true; config.test_miri = false; config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")]; + config.rust_codegen_backends_dir = "codegen-backends".to_owned(); config.rustc_error_format = flags.rustc_error_format; config.on_fail = flags.on_fail; @@ -488,6 +491,8 @@ impl Config { .collect(); } + set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone()); + match rust.codegen_units { Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32), Some(n) => config.rust_codegen_units = Some(n), diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e7aed7eb4fea..05630b8431fb 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -590,7 +590,8 @@ impl Step for Std { let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); src.pop(); // Remove the trailing /lib folder from the sysroot_libdir cp_filtered(&src, &dst, &|path| { - path.file_name().and_then(|s| s.to_str()) != Some("codegen-backends") + path.file_name().and_then(|s| s.to_str()) != + Some(build.config.rust_codegen_backends_dir.as_str()) }); let mut cmd = rust_installer(builder); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 22c26b064305..0f7a04e391bf 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -303,7 +303,9 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box { let sysroot = sysroot_candidates.iter() .map(|sysroot| { let libdir = filesearch::relative_target_lib_path(&sysroot, &target); - sysroot.join(libdir).with_file_name("codegen-backends") + sysroot.join(libdir) + .with_file_name(option_env!("CFG_CODEGEN_BACKENDS_DIR") + .unwrap_or("codegen-backends")) }) .filter(|f| { info!("codegen backend candidate: {}", f.display()); From ab7ce1c3c48d4f1be6c16928704e2eec0aed9ae2 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sun, 11 Feb 2018 15:52:44 -0700 Subject: [PATCH 12/21] Remove --host and --target arguments to configure These arguments are passed to the relevant x.py invocation in all cases anyway. As such, there is no need to separately configure them. x.py will ignore the configuration when they are passed on the command line anyway. --- src/ci/docker/arm-android/Dockerfile | 4 +--- src/ci/docker/armhf-gnu/Dockerfile | 4 +--- src/ci/docker/asmjs/Dockerfile | 2 +- src/ci/docker/disabled/aarch64-gnu/Dockerfile | 1 - src/ci/docker/disabled/dist-aarch64-android/Dockerfile | 2 -- src/ci/docker/disabled/dist-armv7-android/Dockerfile | 2 -- src/ci/docker/disabled/dist-i686-android/Dockerfile | 2 -- src/ci/docker/disabled/dist-x86_64-android/Dockerfile | 2 -- src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile | 2 +- src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile | 4 ++-- src/ci/docker/disabled/dist-x86_64-redox/Dockerfile | 2 +- src/ci/docker/disabled/wasm32-exp/Dockerfile | 2 +- src/ci/docker/disabled/wasm32/Dockerfile | 3 --- src/ci/docker/dist-aarch64-linux/Dockerfile | 2 +- src/ci/docker/dist-android/Dockerfile | 1 - src/ci/docker/dist-arm-linux/Dockerfile | 2 +- src/ci/docker/dist-armhf-linux/Dockerfile | 2 +- src/ci/docker/dist-armv7-linux/Dockerfile | 2 +- src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile | 4 +--- src/ci/docker/dist-i686-freebsd/Dockerfile | 2 +- src/ci/docker/dist-i686-linux/Dockerfile | 6 ++---- src/ci/docker/dist-mips-linux/Dockerfile | 2 +- src/ci/docker/dist-mips64-linux/Dockerfile | 2 +- src/ci/docker/dist-mips64el-linux/Dockerfile | 2 +- src/ci/docker/dist-mipsel-linux/Dockerfile | 2 +- src/ci/docker/dist-powerpc-linux/Dockerfile | 2 +- src/ci/docker/dist-powerpc64-linux/Dockerfile | 2 +- src/ci/docker/dist-powerpc64le-linux/Dockerfile | 2 +- src/ci/docker/dist-s390x-linux/Dockerfile | 2 +- src/ci/docker/dist-various-1/Dockerfile | 1 - src/ci/docker/dist-various-2/Dockerfile | 2 +- src/ci/docker/dist-x86_64-freebsd/Dockerfile | 2 +- src/ci/docker/dist-x86_64-linux/Dockerfile | 1 - src/ci/docker/dist-x86_64-musl/Dockerfile | 1 - src/ci/docker/dist-x86_64-netbsd/Dockerfile | 2 +- src/ci/docker/wasm32-unknown/Dockerfile | 1 - 36 files changed, 27 insertions(+), 52 deletions(-) diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index f2773a720cfb..e10ccd56a4a5 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -31,9 +31,7 @@ ENV PATH=$PATH:/android/sdk/platform-tools ENV TARGETS=arm-linux-androideabi -ENV RUST_CONFIGURE_ARGS \ - --target=$TARGETS \ - --arm-linux-androideabi-ndk=/android/ndk/arm-14 +ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14 ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index 191f8e3a2895..2b7624d53ee0 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -76,9 +76,7 @@ RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/cu COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENV RUST_CONFIGURE_ARGS \ - --target=arm-unknown-linux-gnueabihf \ - --qemu-armhf-rootfs=/tmp/rootfs +ENV RUST_CONFIGURE_ARGS --qemu-armhf-rootfs=/tmp/rootfs ENV SCRIPT python2.7 ../x.py test --target arm-unknown-linux-gnueabihf ENV NO_CHANGE_USER=1 diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index ff0708459bc8..2a0901691a55 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -29,6 +29,6 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=asmjs-unknown-emscripten -ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-emscripten +ENV RUST_CONFIGURE_ARGS --enable-emscripten ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/disabled/aarch64-gnu/Dockerfile b/src/ci/docker/disabled/aarch64-gnu/Dockerfile index fedb4094c8aa..b2a3ba3ec260 100644 --- a/src/ci/docker/disabled/aarch64-gnu/Dockerfile +++ b/src/ci/docker/disabled/aarch64-gnu/Dockerfile @@ -74,7 +74,6 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ - --target=aarch64-unknown-linux-gnu \ --qemu-aarch64-rootfs=/tmp/rootfs ENV SCRIPT python2.7 ../x.py test --target aarch64-unknown-linux-gnu ENV NO_CHANGE_USER=1 diff --git a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile index ce5e8cfaf095..a7903b6f4250 100644 --- a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile @@ -14,8 +14,6 @@ ENV DEP_Z_ROOT=/android/ndk/arm64-21/sysroot/usr/ ENV HOSTS=aarch64-linux-android ENV RUST_CONFIGURE_ARGS \ - --host=$HOSTS \ - --target=$HOSTS \ --aarch64-linux-android-ndk=/android/ndk/arm64-21 \ --disable-rpath \ --enable-extended \ diff --git a/src/ci/docker/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/disabled/dist-armv7-android/Dockerfile index 3177fa2147fa..c02a5e5a0954 100644 --- a/src/ci/docker/disabled/dist-armv7-android/Dockerfile +++ b/src/ci/docker/disabled/dist-armv7-android/Dockerfile @@ -20,8 +20,6 @@ ENV DEP_Z_ROOT=/android/ndk/arm-14/sysroot/usr/ ENV HOSTS=armv7-linux-androideabi ENV RUST_CONFIGURE_ARGS \ - --host=$HOSTS \ - --target=$HOSTS \ --armv7-linux-androideabi-ndk=/android/ndk/arm \ --disable-rpath \ --enable-extended \ diff --git a/src/ci/docker/disabled/dist-i686-android/Dockerfile b/src/ci/docker/disabled/dist-i686-android/Dockerfile index ace9c4feb4f3..04e83a431c45 100644 --- a/src/ci/docker/disabled/dist-i686-android/Dockerfile +++ b/src/ci/docker/disabled/dist-i686-android/Dockerfile @@ -20,8 +20,6 @@ ENV DEP_Z_ROOT=/android/ndk/x86-14/sysroot/usr/ ENV HOSTS=i686-linux-android ENV RUST_CONFIGURE_ARGS \ - --host=$HOSTS \ - --target=$HOSTS \ --i686-linux-android-ndk=/android/ndk/x86 \ --disable-rpath \ --enable-extended \ diff --git a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile index 322d26f0adc4..937301864cd0 100644 --- a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile @@ -14,8 +14,6 @@ ENV DEP_Z_ROOT=/android/ndk/x86_64-21/sysroot/usr/ ENV HOSTS=x86_64-linux-android ENV RUST_CONFIGURE_ARGS \ - --host=$HOSTS \ - --target=$HOSTS \ --x86_64-linux-android-ndk=/android/ndk/x86_64-21 \ --disable-rpath \ --enable-extended \ diff --git a/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile b/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile index f3509efdb988..dbff9e32e131 100644 --- a/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile +++ b/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile @@ -32,5 +32,5 @@ ENV \ ENV HOSTS=x86_64-unknown-dragonfly -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile b/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile index 621976b5cbe3..440afd7c97f5 100644 --- a/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile +++ b/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile @@ -42,8 +42,8 @@ RUN sh /scripts/sccache.sh ENV HOST=x86_64-unknown-haiku ENV TARGET=target.$HOST -ENV RUST_CONFIGURE_ARGS --host=$HOST --target=$HOST --disable-jemalloc \ +ENV RUST_CONFIGURE_ARGS --disable-jemalloc \ --set=$TARGET.cc=x86_64-unknown-haiku-gcc \ --set=$TARGET.cxx=x86_64-unknown-haiku-g++ \ --set=$TARGET.llvm-config=/bin/llvm-config-haiku -ENV SCRIPT python2.7 ../x.py dist +ENV SCRIPT python2.7 ../x.py dist --host=$HOST --target=$HOST diff --git a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile index ed19939545f6..f4c25f791bc3 100644 --- a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile +++ b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile @@ -18,5 +18,5 @@ ENV \ CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ CXX_x86_64_unknown_redox=x86_64-unknown-redox-g++ -ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-redox --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --target x86_64-unknown-redox diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile index 8653b0e8b465..420d47b314c0 100644 --- a/src/ci/docker/disabled/wasm32-exp/Dockerfile +++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile @@ -30,6 +30,6 @@ ENV EM_CONFIG=/root/.emscripten ENV TARGETS=wasm32-experimental-emscripten -ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly +ENV RUST_CONFIGURE_ARGS --experimental-targets=WebAssembly ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile index 7f6f8ae08827..6ac90d17450a 100644 --- a/src/ci/docker/disabled/wasm32/Dockerfile +++ b/src/ci/docker/disabled/wasm32/Dockerfile @@ -29,7 +29,4 @@ ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=wasm32-unknown-emscripten - -ENV RUST_CONFIGURE_ARGS --target=$TARGETS - ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index 841d3012125f..dbc319312aa9 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-gcc \ ENV HOSTS=aarch64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile index 5d7545a3c2a9..aa5da136758a 100644 --- a/src/ci/docker/dist-android/Dockerfile +++ b/src/ci/docker/dist-android/Dockerfile @@ -21,7 +21,6 @@ ENV TARGETS=$TARGETS,aarch64-linux-android ENV TARGETS=$TARGETS,x86_64-linux-android ENV RUST_CONFIGURE_ARGS \ - --target=$TARGETS \ --enable-extended \ --arm-linux-androideabi-ndk=/android/ndk/arm-14 \ --armv7-linux-androideabi-ndk=/android/ndk/arm-14 \ diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile index ecd5090ea05f..89f7f85cb3b1 100644 --- a/src/ci/docker/dist-arm-linux/Dockerfile +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \ ENV HOSTS=arm-unknown-linux-gnueabi -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-armhf-linux/Dockerfile b/src/ci/docker/dist-armhf-linux/Dockerfile index 5bbd17bd4142..e0c1b9a9e858 100644 --- a/src/ci/docker/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/dist-armhf-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \ ENV HOSTS=arm-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index ea9034d71788..e7d4f464ffcd 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \ ENV HOSTS=armv7-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile index 035846b4f643..7bcc649f4aa5 100644 --- a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile +++ b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile @@ -30,7 +30,6 @@ 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 @@ -46,8 +45,7 @@ ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no # 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 TARGETS=i586-unknown-linux-gnu,i686-unknown-linux-musl ENV SCRIPT \ python2.7 ../x.py test --target $TARGETS && \ diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile index 673fa4c0c4bc..1f595ba7a290 100644 --- a/src/ci/docker/dist-i686-freebsd/Dockerfile +++ b/src/ci/docker/dist-i686-freebsd/Dockerfile @@ -29,5 +29,5 @@ ENV \ ENV HOSTS=i686-unknown-freebsd -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index 5e405aa72e83..da7c6233fc86 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -82,13 +82,11 @@ RUN sh /scripts/sccache.sh ENV HOSTS=i686-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ - --host=$HOSTS \ --enable-extended \ --enable-sanitizers \ --enable-profiler \ - --enable-emscripten \ - --build=i686-unknown-linux-gnu -ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS + --enable-emscripten +ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs ENV DIST_SRC 1 diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile index 94a3cf8a3820..37ab5bdcce55 100644 --- a/src/ci/docker/dist-mips-linux/Dockerfile +++ b/src/ci/docker/dist-mips-linux/Dockerfile @@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mips-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile index 0b0dfff1fe36..a5180780b225 100644 --- a/src/ci/docker/dist-mips64-linux/Dockerfile +++ b/src/ci/docker/dist-mips64-linux/Dockerfile @@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mips64-unknown-linux-gnuabi64 -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mips64el-linux/Dockerfile b/src/ci/docker/dist-mips64el-linux/Dockerfile index 1810b1cdc5ab..d38ed24f6255 100644 --- a/src/ci/docker/dist-mips64el-linux/Dockerfile +++ b/src/ci/docker/dist-mips64el-linux/Dockerfile @@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mips64el-unknown-linux-gnuabi64 -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mipsel-linux/Dockerfile b/src/ci/docker/dist-mipsel-linux/Dockerfile index f5be07484758..491c57ba6773 100644 --- a/src/ci/docker/dist-mipsel-linux/Dockerfile +++ b/src/ci/docker/dist-mipsel-linux/Dockerfile @@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mipsel-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile index 14ce3654fce7..c503f2af9cda 100644 --- a/src/ci/docker/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -34,7 +34,7 @@ ENV \ ENV HOSTS=powerpc-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # FIXME(#36150) this will fail the bootstrap. Probably means something bad is diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile index 1f6e83e2f49e..4a3691777360 100644 --- a/src/ci/docker/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile @@ -35,5 +35,5 @@ ENV \ ENV HOSTS=powerpc64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/dist-powerpc64le-linux/Dockerfile index d4677e180609..bf6c8b4b7121 100644 --- a/src/ci/docker/dist-powerpc64le-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64le-linux/Dockerfile @@ -32,5 +32,5 @@ ENV \ ENV HOSTS=powerpc64le-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-s390x-linux/Dockerfile b/src/ci/docker/dist-s390x-linux/Dockerfile index 39478e92f7c9..a2ebf590bab7 100644 --- a/src/ci/docker/dist-s390x-linux/Dockerfile +++ b/src/ci/docker/dist-s390x-linux/Dockerfile @@ -34,5 +34,5 @@ ENV \ ENV HOSTS=s390x-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index c83f101d0ac4..a23153645cde 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -89,7 +89,6 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft" ENV RUST_CONFIGURE_ARGS \ - --target=$TARGETS \ --musl-root-arm=/musl-arm \ --musl-root-armhf=/musl-armhf \ --musl-root-armv7=/musl-armv7 \ diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index 5f342eb57050..4505a60e4639 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -55,5 +55,5 @@ 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 RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile index f9f5b7062f8a..dd595a192051 100644 --- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile @@ -29,5 +29,5 @@ ENV \ ENV HOSTS=x86_64-unknown-freebsd -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index d368a00b55bd..86b3beeb4e59 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -82,7 +82,6 @@ RUN sh /scripts/sccache.sh ENV HOSTS=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ - --host=$HOSTS \ --enable-extended \ --enable-sanitizers \ --enable-profiler \ diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile index c1061309c30f..3a9ad178c639 100644 --- a/src/ci/docker/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/dist-x86_64-musl/Dockerfile @@ -30,7 +30,6 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ - --target=x86_64-unknown-linux-musl \ --musl-root-x86_64=/musl-x86_64 \ --enable-extended diff --git a/src/ci/docker/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/dist-x86_64-netbsd/Dockerfile index 4fd2503c31bb..06298a12fc70 100644 --- a/src/ci/docker/dist-x86_64-netbsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-netbsd/Dockerfile @@ -33,5 +33,5 @@ ENV \ ENV HOSTS=x86_64-unknown-netbsd -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile index dc1727b7014c..106f907bab9e 100644 --- a/src/ci/docker/wasm32-unknown/Dockerfile +++ b/src/ci/docker/wasm32-unknown/Dockerfile @@ -22,7 +22,6 @@ RUN sh /scripts/sccache.sh ENV TARGETS=wasm32-unknown-unknown ENV RUST_CONFIGURE_ARGS \ - --target=$TARGETS \ --set build.nodejs=/node-v9.2.0-linux-x64/bin/node ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \ From 900d511fdca20998e42634d5351f7033bbde1aed Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 2 Mar 2018 13:52:13 -0500 Subject: [PATCH 13/21] Don't produce TOCs for doc markdown files Currently, we are producing headers for markdown files, which is generally not what we want. As such, passing this flag causes them to render normally. --- src/bootstrap/doc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 55d9723527e6..a791dd13f0f4 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -312,6 +312,7 @@ fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned Date: Sat, 17 Feb 2018 17:23:19 -0800 Subject: [PATCH 14/21] std: Add `arch` and `simd` modules This commit imports the `stdsimd` crate into the standard library, creating an `arch` and `simd` module inside of both libcore and libstd. Both of these modules are **unstable** and will continue to be so until RFC 2335 is stabilized. As a brief recap, the modules are organized as so: * `arch` contains all current architectures with intrinsics, for example `std::arch::x86`, `std::arch::x86_64`, `std::arch::arm`, etc. These modules contain all of the intrinsics defined for the platform, like `_mm_set1_epi8`. * In the standard library, the `arch` module also exports a `is_target_feature_detected` macro which performs runtime detection to determine whether a target feature is available at runtime. * The `simd` module contains experimental versions of strongly-typed lane-aware SIMD primitives, to be fully fleshed out in a future RFC. The main purpose of this commit is to start pulling in all these intrinsics and such into the standard library on nightly and allow testing and such. This'll help allow users to easily kick the tires and see if intrinsics work as well as allow us to test out all the infrastructure for moving the intrinsics into the standard library. --- .gitmodules | 3 +++ src/libcore/lib.rs | 33 +++++++++++++++++++++++++++++---- src/libstd/lib.rs | 30 ++++++++++++++++++++++++++++++ src/stdsimd | 1 + src/tools/tidy/src/lib.rs | 1 + 5 files changed, 64 insertions(+), 4 deletions(-) create mode 160000 src/stdsimd diff --git a/.gitmodules b/.gitmodules index fc2f8bbc8a35..5b7fd4812992 100644 --- a/.gitmodules +++ b/.gitmodules @@ -50,3 +50,6 @@ [submodule "src/llvm-emscripten"] path = src/llvm-emscripten url = https://github.com/rust-lang/llvm +[submodule "src/stdsimd"] + path = src/stdsimd + url = https://github.com/rust-lang-nursery/stdsimd diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 3dd30ee1c69e..1efd605112dc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -68,16 +68,21 @@ #![feature(allow_internal_unstable)] #![feature(asm)] #![feature(associated_type_defaults)] +#![feature(attr_literals)] #![feature(cfg_target_feature)] #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] #![feature(const_fn)] #![feature(custom_attribute)] +#![feature(doc_spotlight)] #![feature(fundamental)] #![feature(i128_type)] #![feature(inclusive_range_syntax)] #![feature(intrinsics)] +#![feature(iterator_flatten)] +#![feature(iterator_repeat_with)] #![feature(lang_items)] +#![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(no_core)] #![feature(on_unimplemented)] @@ -85,15 +90,17 @@ #![feature(prelude_import)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] +#![feature(rustc_const_unstable)] +#![feature(simd_ffi)] #![feature(specialization)] #![feature(staged_api)] +#![feature(stmt_expr_attributes)] +#![feature(target_feature)] #![feature(unboxed_closures)] #![feature(untagged_unions)] #![feature(unwind_attributes)] -#![feature(doc_spotlight)] -#![feature(rustc_const_unstable)] -#![feature(iterator_repeat_with)] -#![feature(iterator_flatten)] + +#![cfg_attr(stage0, allow(unused_attributes))] #[prelude_import] #[allow(unused)] @@ -179,3 +186,21 @@ mod char_private; mod iter_private; mod tuple; mod unit; + +// Pull in the the `coresimd` crate directly into libcore. This is where all the +// architecture-specific (and vendor-specific) intrinsics are defined. AKA +// things like SIMD and such. Note that the actual source for all this lies in a +// different repository, rust-lang-nursery/stdsimd. That's why the setup here is +// a bit wonky. +#[path = "../stdsimd/coresimd/mod.rs"] +#[allow(missing_docs, missing_debug_implementations, dead_code)] +#[unstable(feature = "stdsimd", issue = "48556")] +#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0 +mod coresimd; + +#[unstable(feature = "stdsimd", issue = "48556")] +#[cfg(not(stage0))] +pub use coresimd::simd; +#[unstable(feature = "stdsimd", issue = "48556")] +#[cfg(not(stage0))] +pub use coresimd::arch; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d7d856fe3ad0..a7e1c0ce732e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -299,6 +299,7 @@ #![feature(rand)] #![feature(raw)] #![feature(rustc_attrs)] +#![feature(stdsimd)] #![feature(sip_hash_13)] #![feature(slice_bytes)] #![feature(slice_concat_ext)] @@ -501,6 +502,35 @@ mod memchr; // compiler pub mod rt; +// Pull in the the `stdsimd` crate directly into libstd. This is the same as +// libcore's arch/simd modules where the source of truth here is in a different +// repository, but we pull things in here manually to get it into libstd. +// +// Note that the #[cfg] here is intended to do two things. First it allows us to +// change the rustc implementation of intrinsics in stage0 by not compiling simd +// intrinsics in stage0. Next it doesn't compile anything in test mode as +// stdsimd has tons of its own tests which we don't want to run. +#[path = "../stdsimd/stdsimd/mod.rs"] +#[allow(missing_debug_implementations, missing_docs, dead_code)] +#[unstable(feature = "stdsimd", issue = "48556")] +#[cfg(all(not(stage0), not(test)))] +mod stdsimd; + +// A "fake" module needed by the `stdsimd` module to compile, not actually +// exported though. +#[cfg(not(stage0))] +mod coresimd { + pub use core::arch; + pub use core::simd; +} + +#[unstable(feature = "stdsimd", issue = "48556")] +#[cfg(all(not(stage0), not(test)))] +pub use stdsimd::simd; +#[unstable(feature = "stdsimd", issue = "48556")] +#[cfg(all(not(stage0), not(test)))] +pub use stdsimd::arch; + // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` // because rustdoc only looks for these modules at the crate level. diff --git a/src/stdsimd b/src/stdsimd new file mode 160000 index 000000000000..678cbd325c84 --- /dev/null +++ b/src/stdsimd @@ -0,0 +1 @@ +Subproject commit 678cbd325c84070c9dbe4303969fbd2734c0b4ee diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 4d89008d5ca5..1def3048ce07 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -71,6 +71,7 @@ fn filter_dirs(path: &Path) -> bool { "src/librustc/mir/interpret", "src/librustc_mir/interpret", "src/target", + "src/stdsimd", ]; skip.iter().any(|p| path.ends_with(p)) } From 46fef766b0dc3717937911f0f67c9f1ee2a7f21e Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sun, 28 Jan 2018 14:24:19 -0500 Subject: [PATCH 15/21] Have Vec use slice's implementations of Index and IndexMut --- src/liballoc/vec.rs | 130 ++------------------------------------------ 1 file changed, 5 insertions(+), 125 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 3c9b6b94b440..9c6b10c32f1e 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1527,11 +1527,11 @@ impl Hash for Vec { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl Index for Vec { - type Output = T; +impl Index for Vec where [T]: Index { + type Output = <[T] as Index>::Output; #[inline] - fn index(&self, index: usize) -> &T { + fn index(&self, index: I) -> &Self::Output { // NB built-in indexing via `&[T]` &(**self)[index] } @@ -1539,134 +1539,14 @@ impl Index for Vec { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl IndexMut for Vec { +impl IndexMut for Vec where [T]: IndexMut { #[inline] - fn index_mut(&mut self, index: usize) -> &mut T { + fn index_mut(&mut self, index: I) -> &mut Self::Output { // NB built-in indexing via `&mut [T]` &mut (**self)[index] } } -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::Index> for Vec { - type Output = [T]; - - #[inline] - fn index(&self, index: ops::Range) -> &[T] { - Index::index(&**self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::Index> for Vec { - type Output = [T]; - - #[inline] - fn index(&self, index: ops::RangeTo) -> &[T] { - Index::index(&**self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::Index> for Vec { - type Output = [T]; - - #[inline] - fn index(&self, index: ops::RangeFrom) -> &[T] { - Index::index(&**self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::Index for Vec { - type Output = [T]; - - #[inline] - fn index(&self, _index: ops::RangeFull) -> &[T] { - self - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::Index> for Vec { - type Output = [T]; - - #[inline] - fn index(&self, index: ops::RangeInclusive) -> &[T] { - Index::index(&**self, index) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::Index> for Vec { - type Output = [T]; - - #[inline] - fn index(&self, index: ops::RangeToInclusive) -> &[T] { - Index::index(&**self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::IndexMut> for Vec { - #[inline] - fn index_mut(&mut self, index: ops::Range) -> &mut [T] { - IndexMut::index_mut(&mut **self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::IndexMut> for Vec { - #[inline] - fn index_mut(&mut self, index: ops::RangeTo) -> &mut [T] { - IndexMut::index_mut(&mut **self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::IndexMut> for Vec { - #[inline] - fn index_mut(&mut self, index: ops::RangeFrom) -> &mut [T] { - IndexMut::index_mut(&mut **self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::IndexMut for Vec { - #[inline] - fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] { - self - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::IndexMut> for Vec { - #[inline] - fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut [T] { - IndexMut::index_mut(&mut **self, index) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl ops::IndexMut> for Vec { - #[inline] - fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut [T] { - IndexMut::index_mut(&mut **self, index) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for Vec { type Target = [T]; From 2db05f04bebd8a8cfbdb323fbd6d3341aee551d9 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Mon, 29 Jan 2018 15:01:52 -0500 Subject: [PATCH 16/21] Update UI test --- src/test/ui/index-help.stderr | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr index f4dde95b1046..1b5d28d5bb1b 100644 --- a/src/test/ui/index-help.stderr +++ b/src/test/ui/index-help.stderr @@ -1,10 +1,11 @@ -error[E0277]: the trait bound `std::vec::Vec<{integer}>: std::ops::Index` is not satisfied +error[E0277]: the trait bound `i32: std::slice::SliceIndex<[{integer}]>` is not satisfied --> $DIR/index-help.rs:13:5 | LL | x[0i32]; //~ ERROR E0277 - | ^^^^^^^ vector indices are of type `usize` or ranges of `usize` + | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `std::ops::Index` is not implemented for `std::vec::Vec<{integer}>` + = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `i32` + = note: required because of the requirements on the impl of `std::ops::Index` for `[{integer}]` error: aborting due to previous error From 45bdf9cbeec3788c29d8958dc661dd449bb7247c Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Mon, 29 Jan 2018 15:02:44 -0500 Subject: [PATCH 17/21] Update comments --- src/liballoc/vec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 9c6b10c32f1e..83538e5acd4c 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1532,7 +1532,7 @@ impl Index for Vec where [T]: Index { #[inline] fn index(&self, index: I) -> &Self::Output { - // NB built-in indexing via `&[T]` + // NB indexing via implementation on slice &(**self)[index] } } @@ -1542,7 +1542,7 @@ impl Index for Vec where [T]: Index { impl IndexMut for Vec where [T]: IndexMut { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { - // NB built-in indexing via `&mut [T]` + // NB indexing via implementation on slice &mut (**self)[index] } } From ae73a210814bdf50d72a95568eb8c9c96772c641 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Wed, 31 Jan 2018 20:14:17 -0500 Subject: [PATCH 18/21] Update compile fail test error messages --- src/test/compile-fail/integral-indexing.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs index 659b08b55a00..4b01afb8131b 100644 --- a/src/test/compile-fail/integral-indexing.rs +++ b/src/test/compile-fail/integral-indexing.rs @@ -13,10 +13,10 @@ pub fn main() { let s: String = "abcdef".to_string(); v[3_usize]; v[3]; - v[3u8]; //~ERROR : std::ops::Index` is not satisfied - v[3i8]; //~ERROR : std::ops::Index` is not satisfied - v[3u32]; //~ERROR : std::ops::Index` is not satisfied - v[3i32]; //~ERROR : std::ops::Index` is not satisfied + v[3u8]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied + v[3i8]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied + v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied + v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied s.as_bytes()[3_usize]; s.as_bytes()[3]; s.as_bytes()[3u8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied From 370df40dab8df9f3c0b10bb7396225b8d24869b3 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Fri, 2 Mar 2018 23:23:00 -0500 Subject: [PATCH 19/21] Don't have Vec delegate to [T]'s bounds for indexing --- src/liballoc/vec.rs | 18 +++++++++++------- src/test/ui/index-help.stderr | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 83538e5acd4c..feed7c8699a3 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1527,23 +1527,27 @@ impl Hash for Vec { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl Index for Vec where [T]: Index { - type Output = <[T] as Index>::Output; +impl Index for Vec +where + I: ::core::slice::SliceIndex<[T]>, +{ + type Output = I::Output; #[inline] fn index(&self, index: I) -> &Self::Output { - // NB indexing via implementation on slice - &(**self)[index] + Index::index(&**self, index) } } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] -impl IndexMut for Vec where [T]: IndexMut { +impl IndexMut for Vec +where + I: ::core::slice::SliceIndex<[T]>, +{ #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { - // NB indexing via implementation on slice - &mut (**self)[index] + IndexMut::index_mut(&mut **self, index) } } diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr index 1b5d28d5bb1b..ae3cd529ac42 100644 --- a/src/test/ui/index-help.stderr +++ b/src/test/ui/index-help.stderr @@ -5,7 +5,7 @@ LL | x[0i32]; //~ ERROR E0277 | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `i32` - = note: required because of the requirements on the impl of `std::ops::Index` for `[{integer}]` + = note: required because of the requirements on the impl of `std::ops::Index` for `std::vec::Vec<{integer}>` error: aborting due to previous error From d69b24805b5071e5ec9e62d2777a761723644144 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Aug 2017 18:30:12 -0700 Subject: [PATCH 20/21] rust: Import LLD for linking wasm objects This commit imports the LLD project from LLVM to serve as the default linker for the `wasm32-unknown-unknown` target. The `binaryen` submoule is consequently removed along with "binaryen linker" support in rustc. Moving to LLD brings with it a number of benefits for wasm code: * LLD is itself an actual linker, so there's no need to compile all wasm code with LTO any more. As a result builds should be *much* speedier as LTO is no longer forcibly enabled for all builds of the wasm target. * LLD is quickly becoming an "official solution" for linking wasm code together. This, I believe at least, is intended to be the main supported linker for native code and wasm moving forward. Picking up support early on should help ensure that we can help LLD identify bugs and otherwise prove that it works great for all our use cases! * Improvements to the wasm toolchain are currently primarily focused around LLVM and LLD (from what I can tell at least), so it's in general much better to be on this bandwagon for bugfixes and new features. * Historical "hacks" like `wasm-gc` will soon no longer be necessary, LLD will [natively implement][gc] `--gc-sections` (better than `wasm-gc`!) which means a postprocessor is no longer needed to show off Rust's "small wasm binary size". LLD is added in a pretty standard way to rustc right now. A new rustbuild target was defined for building LLD, and this is executed when a compiler's sysroot is being assembled. LLD is compiled against the LLVM that we've got in tree, which means we're currently on the `release_60` branch, but this may get upgraded in the near future! LLD is placed into rustc's sysroot in a `bin` directory. This is similar to where `gcc.exe` can be found on Windows. This directory is automatically added to `PATH` whenever rustc executes the linker, allowing us to define a `WasmLd` linker which implements the interface that `wasm-ld`, LLD's frontend, expects. Like Emscripten the LLD target is currently only enabled for Tier 1 platforms, notably OSX/Windows/Linux, and will need to be installed manually for compiling to wasm on other platforms. LLD is by default turned off in rustbuild, and requires a `config.toml` option to be enabled to turn it on. Finally the unstable `#![wasm_import_memory]` attribute was also removed as LLD has a native option for controlling this. [gc]: https://reviews.llvm.org/D42511 --- .gitmodules | 6 +- .travis.yml | 4 +- README.md | 3 - appveyor.yml | 10 +- config.toml.example | 4 + src/Cargo.lock | 10 - src/binaryen | 1 - src/bootstrap/bin/rustc.rs | 2 +- src/bootstrap/bootstrap.py | 4 + src/bootstrap/builder.rs | 2 +- src/bootstrap/cc_detect.rs | 3 + src/bootstrap/compile.rs | 26 +++ src/bootstrap/config.rs | 4 + src/bootstrap/configure.py | 5 + src/bootstrap/dist.rs | 18 +- src/bootstrap/lib.rs | 8 +- src/bootstrap/native.rs | 198 ++++++++++++------ src/bootstrap/test.rs | 2 +- src/ci/docker/dist-i686-linux/Dockerfile | 5 +- src/ci/docker/dist-x86_64-linux/Dockerfile | 5 +- src/ci/docker/wasm32-unknown/Dockerfile | 3 +- src/etc/wasm32-shim.js | 2 + src/librustc_back/lib.rs | 54 +++-- .../target/wasm32_unknown_unknown.rs | 55 +---- src/librustc_binaryen/BinaryenWrapper.cpp | 160 -------------- src/librustc_binaryen/Cargo.toml | 16 -- src/librustc_binaryen/build.rs | 60 ------ src/librustc_binaryen/lib.rs | 172 --------------- src/librustc_trans/Cargo.toml | 1 - src/librustc_trans/back/command.rs | 14 ++ src/librustc_trans/back/link.rs | 39 +--- src/librustc_trans/back/linker.rs | 117 ++++++++++- src/librustc_trans/back/symbol_export.rs | 17 +- src/librustc_trans/back/write.rs | 85 +------- src/librustc_trans/lib.rs | 1 - src/libsyntax/feature_gate.rs | 8 - src/test/run-pass/issue-15487.rs | 1 + .../ui/feature-gate-wasm_import_memory.rs | 14 -- .../ui/feature-gate-wasm_import_memory.stderr | 11 - src/tools/lld | 1 + src/tools/tidy/src/lib.rs | 2 +- 41 files changed, 408 insertions(+), 745 deletions(-) delete mode 160000 src/binaryen delete mode 100644 src/librustc_binaryen/BinaryenWrapper.cpp delete mode 100644 src/librustc_binaryen/Cargo.toml delete mode 100644 src/librustc_binaryen/build.rs delete mode 100644 src/librustc_binaryen/lib.rs delete mode 100644 src/test/ui/feature-gate-wasm_import_memory.rs delete mode 100644 src/test/ui/feature-gate-wasm_import_memory.stderr create mode 160000 src/tools/lld diff --git a/.gitmodules b/.gitmodules index 5b7fd4812992..55f586389b11 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,9 +41,6 @@ [submodule "src/dlmalloc"] path = src/dlmalloc url = https://github.com/alexcrichton/dlmalloc-rs.git -[submodule "src/binaryen"] - path = src/binaryen - url = https://github.com/alexcrichton/binaryen.git [submodule "src/doc/rust-by-example"] path = src/doc/rust-by-example url = https://github.com/rust-lang/rust-by-example @@ -53,3 +50,6 @@ [submodule "src/stdsimd"] path = src/stdsimd url = https://github.com/rust-lang-nursery/stdsimd +[submodule "src/tools/lld"] + path = src/tools/lld + url = https://github.com/rust-lang/lld.git diff --git a/.travis.yml b/.travis.yml index 0d8641e45ed1..4738f91665db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,7 +81,7 @@ matrix: # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7. - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended --enable-profiler --enable-emscripten" + RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -95,7 +95,7 @@ matrix: - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers --enable-profiler --enable-emscripten" + RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 diff --git a/README.md b/README.md index e78bbb82711a..19ef96fae015 100644 --- a/README.md +++ b/README.md @@ -129,9 +129,6 @@ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64. python x.py build ``` -If you are seeing build failure when compiling `rustc_binaryen`, make sure the path -length of the rust folder is not longer than 22 characters. - #### Specifying an ABI [specifying-an-abi]: #specifying-an-abi diff --git a/appveyor.yml b/appveyor.yml index 0ea15dd671c8..0735ead8923c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -67,21 +67,19 @@ environment: # 32/64 bit MSVC and GNU deployment - RUST_CONFIGURE_ARGS: > --build=x86_64-pc-windows-msvc - --enable-extended + --enable-full-tools --enable-profiler - --enable-emscripten SCRIPT: python x.py dist DEPLOY: 1 - RUST_CONFIGURE_ARGS: > --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc - --enable-extended + --enable-full-tools --enable-profiler - --enable-emscripten SCRIPT: python x.py dist DEPLOY: 1 - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-emscripten + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools SCRIPT: python x.py dist MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z @@ -89,7 +87,7 @@ environment: DEPLOY: 1 - MSYS_BITS: 64 SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-emscripten + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z MINGW_DIR: mingw64 diff --git a/config.toml.example b/config.toml.example index 3dfd25aade1e..b47f9163c0da 100644 --- a/config.toml.example +++ b/config.toml.example @@ -329,6 +329,10 @@ # target, as without this option the test output will not be captured. #wasm-syscall = false +# Indicates whether LLD will be compiled and made available in the sysroot for +# rustc to execute. +#lld = false + # ============================================================================= # Options for specific targets # diff --git a/src/Cargo.lock b/src/Cargo.lock index 7b4bfecea3fa..7620fe8ddb3c 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1818,15 +1818,6 @@ dependencies = [ "syntax 0.0.0", ] -[[package]] -name = "rustc_binaryen" -version = "0.0.0" -dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc_borrowck" version = "0.0.0" @@ -2107,7 +2098,6 @@ dependencies = [ "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", "rustc_back 0.0.0", - "rustc_binaryen 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", diff --git a/src/binaryen b/src/binaryen deleted file mode 160000 index 17841e155edf..000000000000 --- a/src/binaryen +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 17841e155edf858c8ea7802dd5f5ecbef54b989f diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index ca35a896e08c..6c3c48aba72f 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -224,7 +224,7 @@ fn main() { // flesh out rpath support more fully in the future. cmd.arg("-Z").arg("osx-rpath-install-name"); Some("-Wl,-rpath,@loader_path/../lib") - } else if !target.contains("windows") { + } else if !target.contains("windows") && !target.contains("wasm32") { Some("-Wl,-rpath,$ORIGIN/../lib") } else { None diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 77df372d4fa3..d8f7cd7ed922 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -641,6 +641,10 @@ class RustBuild(object): continue if self.get_toml('jemalloc'): continue + if module.endswith("lld"): + config = self.get_toml('lld') + if config is None or config == 'false': + continue filtered_submodules.append(module) run(["git", "submodule", "update", "--init", "--recursive"] + filtered_submodules, diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index bc75d31e06e4..8cbb1f3d0e9c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -316,7 +316,7 @@ impl<'a> Builder<'a> { tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy, - native::Llvm, tool::Rustfmt, tool::Miri), + native::Llvm, tool::Rustfmt, tool::Miri, native::Lld), 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, diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index e531fdaf2923..9e1b1f7db2f9 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -79,6 +79,9 @@ pub fn find(build: &mut Build) { let mut cfg = cc::Build::new(); cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false) .target(&target).host(&build.build); + if target.contains("msvc") { + cfg.static_crt(true); + } let config = build.config.target_config.get(&target); if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 30ca9dffc198..695cf04a82c1 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -747,6 +747,21 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder, } } +fn copy_lld_to_sysroot(builder: &Builder, + target_compiler: Compiler, + lld_install_root: &Path) { + let target = target_compiler.host; + + let dst = builder.sysroot_libdir(target_compiler, target) + .parent() + .unwrap() + .join("bin"); + t!(fs::create_dir_all(&dst)); + + let exe = exe("lld", &target); + copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe)); +} + /// 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) -> PathBuf { @@ -896,6 +911,14 @@ impl Step for Assemble { } } + let lld_install = if build.config.lld_enabled && target_compiler.stage > 0 { + Some(builder.ensure(native::Lld { + target: target_compiler.host, + })) + } else { + None + }; + let stage = target_compiler.stage; let host = target_compiler.host; println!("Assembling stage{} compiler ({})", stage, host); @@ -915,6 +938,9 @@ impl Step for Assemble { copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler); + if let Some(lld_install) = lld_install { + copy_lld_to_sysroot(builder, target_compiler, &lld_install); + } // Link the compiler binary itself into place let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 361fc704bc07..f15d4d358583 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -81,6 +81,8 @@ pub struct Config { pub llvm_experimental_targets: String, pub llvm_link_jobs: Option, + pub lld_enabled: bool, + // rust codegen options pub rust_optimize: bool, pub rust_codegen_units: Option, @@ -292,6 +294,7 @@ struct Rust { codegen_backends: Option>, codegen_backends_dir: Option, wasm_syscall: Option, + lld: Option, } /// TOML representation of how each build target is configured. @@ -480,6 +483,7 @@ impl Config { set(&mut config.quiet_tests, rust.quiet_tests); set(&mut config.test_miri, rust.test_miri); set(&mut config.wasm_syscall, rust.wasm_syscall); + set(&mut config.lld_enabled, rust.lld); 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); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 99a3ee4e4c36..e9b4a233d0af 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -66,6 +66,7 @@ o("dist-src", "rust.dist-src", "when building tarballs enables building a source 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") +o("full-tools", None, "enable all tools") # Optimization and debugging options. These may be overridden by the release # channel, etc. @@ -326,6 +327,10 @@ for key in known_args: set('build.target', value.split(',')) elif option.name == 'emscripten': set('rust.codegen-backends', ['llvm', 'emscripten']) + elif option.name == 'full-tools': + set('rust.codegen-backends', ['llvm', 'emscripten']) + set('rust.lld', True) + set('build.extended', True) elif option.name == 'option-checking': # this was handled above pass diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 05630b8431fb..02ef7c0e1ff6 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -28,7 +28,7 @@ use build_helper::output; use {Build, Compiler, Mode}; use channel; -use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file}; +use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file, exe}; use builder::{Builder, RunConfig, ShouldRun, Step}; use compile; use native; @@ -443,6 +443,22 @@ impl Step for Rustc { t!(fs::create_dir_all(&backends_dst)); cp_r(&backends_src, &backends_dst); + // Copy over lld if it's there + if builder.config.lld_enabled { + let exe = exe("lld", &compiler.host); + let src = builder.sysroot_libdir(compiler, host) + .parent() + .unwrap() + .join("bin") + .join(&exe); + let dst = image.join("lib/rustlib") + .join(&*host) + .join("bin") + .join(&exe); + t!(fs::create_dir_all(&dst.parent().unwrap())); + copy(&src, &dst); + } + // Man pages t!(fs::create_dir_all(image.join("share/man/man1"))); let man_src = build.src.join("src/doc/man"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 90f50275b6bb..f3d9246c6fc6 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -501,6 +501,10 @@ impl Build { self.out.join(&*target).join("llvm-emscripten") } + fn lld_out(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("lld") + } + /// Output directory for all documentation for a target fn doc_out(&self, target: Interned) -> PathBuf { self.out.join(&*target).join("doc") @@ -685,7 +689,9 @@ impl Build { .and_then(|c| c.linker.as_ref()) { Some(linker) } else if target != self.config.build && - !target.contains("msvc") && !target.contains("emscripten") { + !target.contains("msvc") && + !target.contains("emscripten") && + !target.contains("wasm32") { Some(self.cc(target)) } else { None diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 653606e5d24b..987d70fd047f 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -81,11 +81,11 @@ impl Step for Llvm { let (out_dir, llvm_config_ret_dir) = if emscripten { let dir = build.emscripten_llvm_out(target); - let config_dir = dir.join("bin"); + let config_dir = dir.join("build/bin"); (dir, config_dir) } else { (build.llvm_out(target), - build.llvm_out(build.config.build).join("bin")) + build.llvm_out(build.config.build).join("build/bin")) }; let done_stamp = out_dir.join("llvm-finished-building"); let build_llvm_config = llvm_config_ret_dir @@ -110,9 +110,6 @@ impl Step for Llvm { // http://llvm.org/docs/CMake.html 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"); - } let profile = match (build.config.llvm_optimize, build.config.llvm_release_debuginfo) { (false, _) => "Debug", @@ -139,9 +136,7 @@ impl Step for Llvm { let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; - cfg.target(&target) - .host(&build.build) - .out_dir(&out_dir) + cfg.out_dir(&out_dir) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) .define("LLVM_TARGETS_TO_BUILD", llvm_targets) @@ -213,67 +208,7 @@ impl Step for Llvm { cfg.define("LLVM_NATIVE_BUILD", build.llvm_out(build.build).join("build")); } - let sanitize_cc = |cc: &Path| { - if target.contains("msvc") { - OsString::from(cc.to_str().unwrap().replace("\\", "/")) - } else { - cc.as_os_str().to_owned() - } - }; - - let configure_compilers = |cfg: &mut cmake::Config| { - // MSVC with CMake uses msbuild by default which doesn't respect these - // vars that we'd otherwise configure. In that case we just skip this - // entirely. - if target.contains("msvc") && !build.config.ninja { - return - } - - let cc = build.cc(target); - let cxx = build.cxx(target).unwrap(); - - // Handle msvc + ninja + ccache specially (this is what the bots use) - if target.contains("msvc") && - build.config.ninja && - build.config.ccache.is_some() { - let mut cc = env::current_exe().expect("failed to get cwd"); - cc.set_file_name("sccache-plus-cl.exe"); - - cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc)) - .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc)); - cfg.env("SCCACHE_PATH", - build.config.ccache.as_ref().unwrap()) - .env("SCCACHE_TARGET", target); - - // If ccache is configured we inform the build a little differently hwo - // to invoke ccache while also invoking our compilers. - } else if let Some(ref ccache) = build.config.ccache { - cfg.define("CMAKE_C_COMPILER", ccache) - .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc)) - .define("CMAKE_CXX_COMPILER", ccache) - .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx)); - } else { - cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc)) - .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx)); - } - - cfg.build_arg("-j").build_arg(build.jobs().to_string()); - cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); - cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" ")); - if let Some(ar) = build.ar(target) { - if ar.is_absolute() { - // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it - // tries to resolve this path in the LLVM build directory. - cfg.define("CMAKE_AR", sanitize_cc(ar)); - } - } - }; - - configure_compilers(&mut cfg); - - if env::var_os("SCCACHE_ERROR_LOG").is_some() { - cfg.env("RUST_LOG", "sccache=warn"); - } + configure_cmake(build, target, &mut cfg); // FIXME: we don't actually need to build all LLVM tools and all LLVM // libraries here, e.g. we just want a few components and a few @@ -304,6 +239,131 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version) } +fn configure_cmake(build: &Build, + target: Interned, + cfg: &mut cmake::Config) { + if build.config.ninja { + cfg.generator("Ninja"); + } + cfg.target(&target) + .host(&build.config.build); + + let sanitize_cc = |cc: &Path| { + if target.contains("msvc") { + OsString::from(cc.to_str().unwrap().replace("\\", "/")) + } else { + cc.as_os_str().to_owned() + } + }; + + // MSVC with CMake uses msbuild by default which doesn't respect these + // vars that we'd otherwise configure. In that case we just skip this + // entirely. + if target.contains("msvc") && !build.config.ninja { + return + } + + let cc = build.cc(target); + let cxx = build.cxx(target).unwrap(); + + // Handle msvc + ninja + ccache specially (this is what the bots use) + if target.contains("msvc") && + build.config.ninja && + build.config.ccache.is_some() { + let mut cc = env::current_exe().expect("failed to get cwd"); + cc.set_file_name("sccache-plus-cl.exe"); + + cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc)) + .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc)); + cfg.env("SCCACHE_PATH", + build.config.ccache.as_ref().unwrap()) + .env("SCCACHE_TARGET", target); + + // If ccache is configured we inform the build a little differently hwo + // to invoke ccache while also invoking our compilers. + } else if let Some(ref ccache) = build.config.ccache { + cfg.define("CMAKE_C_COMPILER", ccache) + .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc)) + .define("CMAKE_CXX_COMPILER", ccache) + .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx)); + } else { + cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc)) + .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx)); + } + + cfg.build_arg("-j").build_arg(build.jobs().to_string()); + cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); + let mut cxxflags = build.cflags(target).join(" "); + if build.config.llvm_static_stdcpp && !target.contains("windows") { + cxxflags.push_str(" -static-libstdc++"); + } + cfg.define("CMAKE_CXX_FLAGS", cxxflags); + if let Some(ar) = build.ar(target) { + if ar.is_absolute() { + // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it + // tries to resolve this path in the LLVM build directory. + cfg.define("CMAKE_AR", sanitize_cc(ar)); + } + } + + if env::var_os("SCCACHE_ERROR_LOG").is_some() { + cfg.env("RUST_LOG", "sccache=warn"); + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Lld { + pub target: Interned, +} + +impl Step for Lld { + type Output = PathBuf; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/lld") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Lld { target: run.target }); + } + + /// Compile LLVM for `target`. + fn run(self, builder: &Builder) -> PathBuf { + let target = self.target; + let build = builder.build; + + let llvm_config = builder.ensure(Llvm { + target: self.target, + emscripten: false, + }); + + let out_dir = build.lld_out(target); + let done_stamp = out_dir.join("lld-finished-building"); + if done_stamp.exists() { + return out_dir + } + + let _folder = build.fold_output(|| "lld"); + println!("Building LLD for {}", target); + let _time = util::timeit(); + t!(fs::create_dir_all(&out_dir)); + + let mut cfg = cmake::Config::new(build.src.join("src/tools/lld")); + configure_cmake(build, target, &mut cfg); + + cfg.out_dir(&out_dir) + .profile("Release") + .define("LLVM_CONFIG_PATH", llvm_config) + .define("LLVM_INCLUDE_TESTS", "OFF"); + + cfg.build(); + + t!(File::create(&done_stamp)); + out_dir + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct TestHelpers { pub target: Interned, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index b27ddfdbc5e5..c0998c1e42c9 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -914,7 +914,7 @@ impl Step for Compiletest { } if build.config.llvm_enabled { - let llvm_config = build.llvm_config(target); + let llvm_config = build.llvm_config(build.config.build); let llvm_version = output(Command::new(&llvm_config).arg("--version")); cmd.arg("--llvm-version").arg(llvm_version); if !build.is_rust_llvm(target) { diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index da7c6233fc86..0ec57ee08868 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -82,10 +82,9 @@ RUN sh /scripts/sccache.sh ENV HOSTS=i686-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ - --enable-extended \ + --enable-full-tools \ --enable-sanitizers \ - --enable-profiler \ - --enable-emscripten + --enable-profiler ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index 86b3beeb4e59..3b98b0aa926b 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -82,10 +82,9 @@ RUN sh /scripts/sccache.sh ENV HOSTS=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ - --enable-extended \ + --enable-full-tools \ --enable-sanitizers \ - --enable-profiler \ - --enable-emscripten + --enable-profiler ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile index 106f907bab9e..0972eb85191a 100644 --- a/src/ci/docker/wasm32-unknown/Dockerfile +++ b/src/ci/docker/wasm32-unknown/Dockerfile @@ -22,7 +22,8 @@ RUN sh /scripts/sccache.sh ENV TARGETS=wasm32-unknown-unknown ENV RUST_CONFIGURE_ARGS \ - --set build.nodejs=/node-v9.2.0-linux-x64/bin/node + --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \ + --set rust.lld ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \ src/test/ui \ diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js index 69647f37eecc..98d6202a63fb 100644 --- a/src/etc/wasm32-shim.js +++ b/src/etc/wasm32-shim.js @@ -107,6 +107,8 @@ imports.env = { exp2f: function(x) { return Math.pow(2, x); }, ldexp: function(x, y) { return x * Math.pow(2, y); }, ldexpf: function(x, y) { return x * Math.pow(2, y); }, + log: Math.log, + log2: Math.log2, log10: Math.log10, log10f: Math.log10, diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 8bf60b091a7a..141c8954a330 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -43,14 +43,29 @@ use std::str::FromStr; use serialize::json::{Json, ToJson}; -macro_rules! linker_flavor { - ($(($variant:ident, $string:expr),)+) => { - #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, - RustcEncodable, RustcDecodable)] - pub enum LinkerFlavor { - $($variant,)+ - } +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, + RustcEncodable, RustcDecodable)] +pub enum LinkerFlavor { + Em, + Gcc, + Ld, + Msvc, + Lld(LldFlavor), +} +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, + RustcEncodable, RustcDecodable)] +pub enum LldFlavor { + Wasm, +} + +impl ToJson for LinkerFlavor { + fn to_json(&self) -> Json { + self.desc().to_json() + } +} +macro_rules! flavor_mappings { + ($((($($flavor:tt)*), $string:expr),)*) => ( impl LinkerFlavor { pub const fn one_of() -> &'static str { concat!("one of: ", $($string, " ",)+) @@ -58,32 +73,27 @@ macro_rules! linker_flavor { pub fn from_str(s: &str) -> Option { Some(match s { - $($string => LinkerFlavor::$variant,)+ + $($string => $($flavor)*,)+ _ => return None, }) } pub fn desc(&self) -> &str { match *self { - $(LinkerFlavor::$variant => $string,)+ + $($($flavor)* => $string,)+ } } } - - impl ToJson for LinkerFlavor { - fn to_json(&self) -> Json { - self.desc().to_json() - } - } - } + ) } -linker_flavor! { - (Em, "em"), - (Binaryen, "binaryen"), - (Gcc, "gcc"), - (Ld, "ld"), - (Msvc, "msvc"), + +flavor_mappings! { + ((LinkerFlavor::Em), "em"), + ((LinkerFlavor::Gcc), "gcc"), + ((LinkerFlavor::Ld), "ld"), + ((LinkerFlavor::Msvc), "msvc"), + ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"), } #[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_back/target/wasm32_unknown_unknown.rs index 242860e5c6e9..c771762cfc89 100644 --- a/src/librustc_back/target/wasm32_unknown_unknown.rs +++ b/src/librustc_back/target/wasm32_unknown_unknown.rs @@ -8,40 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// The wasm32-unknown-unknown target is currently a highly experimental version -// of a wasm-based target which does *not* use the Emscripten toolchain. Instead -// this is a pretty flavorful (aka hacked up) target right now. The definition -// and semantics of this target are likely to change and so this shouldn't be -// relied on just yet. +// The wasm32-unknown-unknown target is currently an experimental version of a +// wasm-based target which does *not* use the Emscripten toolchain. Instead +// this toolchain is based purely on LLVM's own toolchain, using LLVM's native +// WebAssembly backend as well as LLD for a native linker. // -// In general everyone is currently waiting on a linker for wasm code. In the -// meantime we have no means of actually making use of the traditional separate -// compilation model. At a high level this means that assembling Rust programs -// into a WebAssembly program looks like: -// -// 1. All intermediate artifacts are LLVM bytecode. We'll be using LLVM as -// a linker later on. -// 2. For the final artifact we emit one giant assembly file (WebAssembly -// doesn't have an object file format). To do this we force LTO to be turned -// on (`requires_lto` below) to ensure all Rust code is in one module. Any -// "linked" C library is basically just ignored. -// 3. Using LLVM we emit a `foo.s` file (assembly) with some... what I can only -// describe as arcane syntax. From there we need to actually change this -// into a wasm module. For this step we use the `binaryen` project. This -// project is mostly intended as a WebAssembly code generator, but for now -// we're just using its LLVM-assembly-to-wasm-module conversion utilities. -// -// And voila, out comes a web assembly module! There's some various tweaks here -// and there, but that's the high level at least. Note that this will be -// rethought from the ground up once a linker (lld) is available, so this is all -// temporary and should improve in the future. +// There's some trickery below on crate types supported and various defaults +// (aka panic=abort by default), but otherwise this is in general a relatively +// standard target. -use LinkerFlavor; +use {LinkerFlavor, LldFlavor}; use super::{Target, TargetOptions, PanicStrategy}; pub fn target() -> Result { let opts = TargetOptions { - linker: "not-used".to_string(), + linker: "lld".to_string(), // we allow dynamic linking, but only cdylibs. Basically we allow a // final library artifact that exports some symbols (a wasm module) but @@ -58,9 +39,6 @@ pub fn target() -> Result { dll_suffix: ".wasm".to_string(), linker_is_gnu: false, - // We're storing bitcode for now in all the rlibs - obj_is_bitcode: true, - // A bit of a lie, but "eh" max_atomic_width: Some(32), @@ -69,27 +47,17 @@ pub fn target() -> Result { // the future once unwinding is implemented. Don't rely on this. panic_strategy: PanicStrategy::Abort, - // There's no linker yet so we're forced to use LLVM as a linker. This - // means that we must always enable LTO for final artifacts. - requires_lto: true, - // Wasm doesn't have atomics yet, so tell LLVM that we're in a single // threaded model which will legalize atomics to normal operations. singlethread: true, - // Because we're always enabling LTO we can't enable builtin lowering as - // otherwise we'll lower the definition of the `memcpy` function to - // memcpy itself. Note that this is specifically because we're - // performing LTO with compiler-builtins. - no_builtins: true, - // no dynamic linking, no need for default visibility! default_hidden_visibility: true, .. Default::default() }; Ok(Target { - llvm_target: "wasm32-unknown-unknown".to_string(), + llvm_target: "wasm32-unknown-unknown-wasm".to_string(), target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), @@ -100,8 +68,7 @@ pub fn target() -> Result { target_vendor: "unknown".to_string(), data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), arch: "wasm32".to_string(), - // A bit of a lie, but it gets the job done - linker_flavor: LinkerFlavor::Binaryen, + linker_flavor: LinkerFlavor::Lld(LldFlavor::Wasm), options: opts, }) } diff --git a/src/librustc_binaryen/BinaryenWrapper.cpp b/src/librustc_binaryen/BinaryenWrapper.cpp deleted file mode 100644 index 55f11665f6d0..000000000000 --- a/src/librustc_binaryen/BinaryenWrapper.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This is a small C API inserted on top of the Binaryen C++ API which we use -// from Rust. Once we have a real linker for we'll be able to remove all this, -// and otherwise this is just all on a "as we need it" basis for now. - -#include -#include -#include -#include - -#include "s2wasm.h" -#include "wasm-binary.h" -#include "wasm-linker.h" - -using namespace wasm; - -struct BinaryenRustModule { - BufferWithRandomAccess buffer; - std::string sourceMapJSON; -}; - -struct BinaryenRustModuleOptions { - uint64_t globalBase; - bool debug; - uint64_t stackAllocation; - uint64_t initialMem; - uint64_t maxMem; - bool importMemory; - bool ignoreUnknownSymbols; - bool debugInfo; - std::string startFunction; - std::string sourceMapUrl; - - BinaryenRustModuleOptions() : - globalBase(0), - debug(false), - stackAllocation(0), - initialMem(0), - maxMem(0), - importMemory(false), - ignoreUnknownSymbols(false), - debugInfo(false), - startFunction(""), - sourceMapUrl("") - {} - -}; - -extern "C" BinaryenRustModuleOptions* -BinaryenRustModuleOptionsCreate() { - return new BinaryenRustModuleOptions; -} - -extern "C" void -BinaryenRustModuleOptionsFree(BinaryenRustModuleOptions *options) { - delete options; -} - -extern "C" void -BinaryenRustModuleOptionsSetDebugInfo(BinaryenRustModuleOptions *options, - bool debugInfo) { - options->debugInfo = debugInfo; -} - -extern "C" void -BinaryenRustModuleOptionsSetStart(BinaryenRustModuleOptions *options, - char *start) { - options->startFunction = start; -} - -extern "C" void -BinaryenRustModuleOptionsSetSourceMapUrl(BinaryenRustModuleOptions *options, - char *sourceMapUrl) { - options->sourceMapUrl = sourceMapUrl; -} - -extern "C" void -BinaryenRustModuleOptionsSetStackAllocation(BinaryenRustModuleOptions *options, - uint64_t stack) { - options->stackAllocation = stack; -} - -extern "C" void -BinaryenRustModuleOptionsSetImportMemory(BinaryenRustModuleOptions *options, - bool import) { - options->importMemory = import; -} - -extern "C" BinaryenRustModule* -BinaryenRustModuleCreate(const BinaryenRustModuleOptions *options, - const char *assembly) { - Linker linker( - options->globalBase, - options->stackAllocation, - options->initialMem, - options->maxMem, - options->importMemory, - options->ignoreUnknownSymbols, - options->startFunction, - options->debug); - - S2WasmBuilder mainbuilder(assembly, options->debug); - linker.linkObject(mainbuilder); - linker.layout(); - - auto ret = make_unique(); - { - WasmBinaryWriter writer(&linker.getOutput().wasm, ret->buffer, options->debug); - writer.setNamesSection(options->debugInfo); - - std::unique_ptr sourceMapStream = nullptr; - { - sourceMapStream = make_unique(); - writer.setSourceMap(sourceMapStream.get(), options->sourceMapUrl); - } - - // FIXME: support symbol maps? - // writer.setSymbolMap(symbolMap); - writer.write(); - - if (sourceMapStream) { - ret->sourceMapJSON = sourceMapStream->str(); - } - } - return ret.release(); -} - -extern "C" const uint8_t* -BinaryenRustModulePtr(const BinaryenRustModule *M) { - return M->buffer.data(); -} - -extern "C" size_t -BinaryenRustModuleLen(const BinaryenRustModule *M) { - return M->buffer.size(); -} - -extern "C" const char* -BinaryenRustModuleSourceMapPtr(const BinaryenRustModule *M) { - return M->sourceMapJSON.data(); -} - -extern "C" size_t -BinaryenRustModuleSourceMapLen(const BinaryenRustModule *M) { - return M->sourceMapJSON.length(); -} - -extern "C" void -BinaryenRustModuleFree(BinaryenRustModule *M) { - delete M; -} diff --git a/src/librustc_binaryen/Cargo.toml b/src/librustc_binaryen/Cargo.toml deleted file mode 100644 index 9573c8947140..000000000000 --- a/src/librustc_binaryen/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -# Wondering what this crate is? Take a look at the `lib.rs`! - -[package] -name = "rustc_binaryen" -version = "0.0.0" -authors = ["The Rust Project Developers"] - -[lib] -path = "lib.rs" - -[dependencies] -libc = "0.2" - -[build-dependencies] -cmake = "0.1" -cc = "1.0" diff --git a/src/librustc_binaryen/build.rs b/src/librustc_binaryen/build.rs deleted file mode 100644 index f23ff3cee555..000000000000 --- a/src/librustc_binaryen/build.rs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate cc; -extern crate cmake; - -use std::env; - -use cmake::Config; - -fn main() { - let target = env::var("TARGET").unwrap(); - - // Bring in `__emutls_get_address` which is apparently needed for now - if target.contains("pc-windows-gnu") { - println!("cargo:rustc-link-lib=gcc_eh"); - println!("cargo:rustc-link-lib=pthread"); - } - - Config::new("../binaryen") - .define("BUILD_STATIC_LIB", "ON") - .build_target("binaryen") - .build(); - - // I couldn't figure out how to link just one of these, so link everything. - println!("cargo:rustc-link-lib=static=asmjs"); - println!("cargo:rustc-link-lib=static=binaryen"); - println!("cargo:rustc-link-lib=static=cfg"); - println!("cargo:rustc-link-lib=static=emscripten-optimizer"); - println!("cargo:rustc-link-lib=static=ir"); - println!("cargo:rustc-link-lib=static=passes"); - println!("cargo:rustc-link-lib=static=support"); - println!("cargo:rustc-link-lib=static=wasm"); - - let out_dir = env::var("OUT_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}/build/lib", out_dir); - - // Add in our own little shim along with some extra files that weren't - // included in the main build. - let mut cfg = cc::Build::new(); - cfg.file("BinaryenWrapper.cpp") - .file("../binaryen/src/wasm-linker.cpp") - .file("../binaryen/src/wasm-emscripten.cpp") - .include("../binaryen/src") - .cpp_link_stdlib(None) - .warnings(false) - .cpp(true); - - if !target.contains("msvc") { - cfg.flag("-std=c++11"); - } - cfg.compile("binaryen_wrapper"); -} diff --git a/src/librustc_binaryen/lib.rs b/src/librustc_binaryen/lib.rs deleted file mode 100644 index 36174e11ba04..000000000000 --- a/src/librustc_binaryen/lib.rs +++ /dev/null @@ -1,172 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Rustc bindings to the binaryen project. -//! -//! This crate is a small shim around the binaryen project which provides us the -//! ability to take LLVM's output and generate a wasm module. Specifically this -//! only supports one operation, creating a module from LLVM's assembly format -//! and then serializing that module to a wasm module. - -extern crate libc; - -use std::slice; -use std::ffi::{CString, CStr}; - -/// In-memory representation of a serialized wasm module. -pub struct Module { - ptr: *mut BinaryenRustModule, -} - -impl Module { - /// Creates a new wasm module from the LLVM-assembly provided (in a C string - /// format). - /// - /// The actual module creation can be tweaked through the various options in - /// `ModuleOptions` as well. Any errors are just returned as a bland string. - pub fn new(assembly: &CStr, opts: &ModuleOptions) -> Result { - unsafe { - let ptr = BinaryenRustModuleCreate(opts.ptr, assembly.as_ptr()); - if ptr.is_null() { - Err(format!("failed to create binaryen module")) - } else { - Ok(Module { ptr }) - } - } - } - - /// Returns the data of the serialized wasm module. This is a `foo.wasm` - /// file contents. - pub fn data(&self) -> &[u8] { - unsafe { - let ptr = BinaryenRustModulePtr(self.ptr); - let len = BinaryenRustModuleLen(self.ptr); - slice::from_raw_parts(ptr, len) - } - } - - /// Returns the data of the source map JSON. - pub fn source_map(&self) -> &[u8] { - unsafe { - let ptr = BinaryenRustModuleSourceMapPtr(self.ptr); - let len = BinaryenRustModuleSourceMapLen(self.ptr); - slice::from_raw_parts(ptr, len) - } - } -} - -impl Drop for Module { - fn drop(&mut self) { - unsafe { - BinaryenRustModuleFree(self.ptr); - } - } -} - -pub struct ModuleOptions { - ptr: *mut BinaryenRustModuleOptions, -} - -impl ModuleOptions { - pub fn new() -> ModuleOptions { - unsafe { - let ptr = BinaryenRustModuleOptionsCreate(); - ModuleOptions { ptr } - } - } - - /// Turns on or off debug info. - /// - /// From what I can tell this just creates a "names" section of the wasm - /// module which contains a table of the original function names. - pub fn debuginfo(&mut self, debug: bool) -> &mut Self { - unsafe { - BinaryenRustModuleOptionsSetDebugInfo(self.ptr, debug); - } - self - } - - /// Configures a `start` function for the module, to be executed when it's - /// loaded. - pub fn start(&mut self, func: &str) -> &mut Self { - let func = CString::new(func).unwrap(); - unsafe { - BinaryenRustModuleOptionsSetStart(self.ptr, func.as_ptr()); - } - self - } - - /// Configures a `sourceMappingURL` custom section value for the module. - pub fn source_map_url(&mut self, url: &str) -> &mut Self { - let url = CString::new(url).unwrap(); - unsafe { - BinaryenRustModuleOptionsSetSourceMapUrl(self.ptr, url.as_ptr()); - } - self - } - - /// Configures how much stack is initially allocated for the module. 1MB is - /// probably good enough for now. - pub fn stack(&mut self, amt: u64) -> &mut Self { - unsafe { - BinaryenRustModuleOptionsSetStackAllocation(self.ptr, amt); - } - self - } - - /// Flags whether the initial memory should be imported or exported. So far - /// we export it by default. - pub fn import_memory(&mut self, import: bool) -> &mut Self { - unsafe { - BinaryenRustModuleOptionsSetImportMemory(self.ptr, import); - } - self - } -} - -impl Drop for ModuleOptions { - fn drop(&mut self) { - unsafe { - BinaryenRustModuleOptionsFree(self.ptr); - } - } -} - -enum BinaryenRustModule {} -enum BinaryenRustModuleOptions {} - -extern { - fn BinaryenRustModuleCreate(opts: *const BinaryenRustModuleOptions, - assembly: *const libc::c_char) - -> *mut BinaryenRustModule; - fn BinaryenRustModulePtr(module: *const BinaryenRustModule) -> *const u8; - fn BinaryenRustModuleLen(module: *const BinaryenRustModule) -> usize; - fn BinaryenRustModuleSourceMapPtr(module: *const BinaryenRustModule) -> *const u8; - fn BinaryenRustModuleSourceMapLen(module: *const BinaryenRustModule) -> usize; - fn BinaryenRustModuleFree(module: *mut BinaryenRustModule); - - fn BinaryenRustModuleOptionsCreate() - -> *mut BinaryenRustModuleOptions; - fn BinaryenRustModuleOptionsSetDebugInfo(module: *mut BinaryenRustModuleOptions, - debuginfo: bool); - fn BinaryenRustModuleOptionsSetStart(module: *mut BinaryenRustModuleOptions, - start: *const libc::c_char); - fn BinaryenRustModuleOptionsSetSourceMapUrl(module: *mut BinaryenRustModuleOptions, - sourceMapUrl: *const libc::c_char); - fn BinaryenRustModuleOptionsSetStackAllocation( - module: *mut BinaryenRustModuleOptions, - stack: u64, - ); - fn BinaryenRustModuleOptionsSetImportMemory( - module: *mut BinaryenRustModuleOptions, - import: bool, - ); - fn BinaryenRustModuleOptionsFree(module: *mut BinaryenRustModuleOptions); -} diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 500c4fdf4e8d..4b9c93088a51 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -21,7 +21,6 @@ rustc-demangle = "0.1.4" rustc_allocator = { path = "../librustc_allocator" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_back = { path = "../librustc_back" } -rustc_binaryen = { path = "../librustc_binaryen" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs index 0bccef1e62a8..e5e0a4e3ba0e 100644 --- a/src/librustc_trans/back/command.rs +++ b/src/librustc_trans/back/command.rs @@ -17,6 +17,8 @@ use std::io; use std::mem; use std::process::{self, Output}; +use rustc_back::LldFlavor; + #[derive(Clone)] pub struct Command { program: Program, @@ -28,6 +30,7 @@ pub struct Command { enum Program { Normal(OsString), CmdBatScript(OsString), + Lld(OsString, LldFlavor) } impl Command { @@ -39,6 +42,10 @@ impl Command { Command::_new(Program::CmdBatScript(program.as_ref().to_owned())) } + pub fn lld>(program: P, flavor: LldFlavor) -> Command { + Command::_new(Program::Lld(program.as_ref().to_owned(), flavor)) + } + fn _new(program: Program) -> Command { Command { program, @@ -101,6 +108,13 @@ impl Command { c.arg("/c").arg(p); c } + Program::Lld(ref p, flavor) => { + let mut c = process::Command::new(p); + c.arg("-flavor").arg(match flavor { + LldFlavor::Wasm => "wasm", + }); + c + } }; ret.args(&self.args); ret.envs(self.env.clone()); diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 8f308e726865..c134203a773f 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -15,6 +15,7 @@ use super::command::Command; use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; +use rustc_back::LinkerFlavor; use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest}; use rustc::session::config::{RUST_CGU_EXT, Lto}; use rustc::session::filesearch; @@ -27,7 +28,7 @@ use rustc::util::common::time; use rustc::util::fs::fix_windows_verbatim_for_gcc; use rustc::hir::def_id::CrateNum; use tempdir::TempDir; -use rustc_back::{PanicStrategy, RelroLevel, LinkerFlavor}; +use rustc_back::{PanicStrategy, RelroLevel}; use context::get_reloc_model; use llvm; @@ -82,6 +83,10 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString) } else if sess.target.target.options.is_like_msvc { let (cmd, envs) = msvc_link_exe_cmd(sess); (PathBuf::from("link.exe"), cmd, envs) + } else if let LinkerFlavor::Lld(f) = sess.linker_flavor() { + let linker = PathBuf::from(&sess.target.target.options.linker); + let cmd = Command::lld(&linker, f); + (linker, cmd, envs) } else { let linker = PathBuf::from(&sess.target.target.options.linker); let cmd = cmd(&linker); @@ -612,11 +617,6 @@ fn link_natively(sess: &Session, info!("preparing {:?} to {:?}", crate_type, out_filename); let flavor = sess.linker_flavor(); - // The "binaryen linker" is massively special, so skip everything below. - if flavor == LinkerFlavor::Binaryen { - return link_binaryen(sess, crate_type, out_filename, trans, tmpdir); - } - // The invocations of cc share some flags across platforms let (pname, mut cmd, envs) = get_linker(sess); // This will set PATH on windows @@ -1485,33 +1485,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { } } -/// For now "linking with binaryen" is just "move the one module we generated in -/// the backend to the final output" -/// -/// That is, all the heavy lifting happens during the `back::write` phase. Here -/// we just clean up after that. -/// -/// Note that this is super temporary and "will not survive the night", this is -/// guaranteed to get removed as soon as a linker for wasm exists. This should -/// not be used for anything other than wasm. -fn link_binaryen(sess: &Session, - _crate_type: config::CrateType, - out_filename: &Path, - trans: &CrateTranslation, - _tmpdir: &Path) { - assert!(trans.allocator_module.is_none()); - assert_eq!(trans.modules.len(), 1); - - let object = trans.modules[0].object.as_ref().expect("object must exist"); - let res = fs::hard_link(object, out_filename) - .or_else(|_| fs::copy(object, out_filename).map(|_| ())); - if let Err(e) = res { - sess.fatal(&format!("failed to create `{}`: {}", - out_filename.display(), - e)); - } -} - fn is_full_lto_enabled(sess: &Session) -> bool { match sess.lto() { Lto::Yes | diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 7e7811c56c74..a82270c5272b 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -23,7 +23,7 @@ use rustc::middle::dependency_format::Linkage; use rustc::session::Session; use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel}; use rustc::ty::TyCtxt; -use rustc_back::LinkerFlavor; +use rustc_back::{LinkerFlavor, LldFlavor}; use serialize::{json, Encoder}; /// For all the linkers we support, and information they might @@ -77,8 +77,11 @@ impl LinkerInfo { is_ld: true, }) as Box } - LinkerFlavor::Binaryen => { - panic!("can't instantiate binaryen linker") + + LinkerFlavor::Lld(LldFlavor::Wasm) => { + Box::new(WasmLd { + cmd, + }) as Box } } } @@ -785,3 +788,111 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { symbols } + +pub struct WasmLd { + cmd: Command, +} + +impl Linker for WasmLd { + fn link_dylib(&mut self, lib: &str) { + self.cmd.arg("-l").arg(lib); + } + + fn link_staticlib(&mut self, lib: &str) { + self.cmd.arg("-l").arg(lib); + } + + fn link_rlib(&mut self, lib: &Path) { + self.cmd.arg(lib); + } + + fn include_path(&mut self, path: &Path) { + self.cmd.arg("-L").arg(path); + } + + fn framework_path(&mut self, _path: &Path) { + panic!("frameworks not supported") + } + + fn output_filename(&mut self, path: &Path) { + self.cmd.arg("-o").arg(path); + } + + fn add_object(&mut self, path: &Path) { + self.cmd.arg(path); + } + + fn position_independent_executable(&mut self) { + } + + fn partial_relro(&mut self) { + } + + fn full_relro(&mut self) { + } + + fn build_static_executable(&mut self) { + } + + fn args(&mut self, args: &[String]) { + self.cmd.args(args); + } + + fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { + self.cmd.arg("-l").arg(lib); + } + + fn link_framework(&mut self, _framework: &str) { + panic!("frameworks not supported") + } + + fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) { + self.cmd.arg("-l").arg(lib); + } + + fn link_whole_rlib(&mut self, lib: &Path) { + self.cmd.arg(lib); + } + + fn gc_sections(&mut self, _keep_metadata: bool) { + } + + fn optimize(&mut self) { + } + + fn debuginfo(&mut self) { + } + + fn no_default_libraries(&mut self) { + } + + fn build_dylib(&mut self, _out_filename: &Path) { + } + + fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) { + } + + fn subsystem(&mut self, _subsystem: &str) { + } + + fn no_position_independent_executable(&mut self) { + } + + fn finalize(&mut self) -> Command { + self.cmd.arg("--threads"); + + // FIXME we probably shouldn't pass this but instead pass an explicit + // whitelist of symbols we'll allow to be undefined. Unfortunately + // though we can't handle symbols like `log10` that LLVM injects at a + // super late date without actually parsing object files. For now let's + // stick to this and hopefully fix it before stabilization happens. + self.cmd.arg("--allow-undefined"); + + // For now we just never have an entry symbol + self.cmd.arg("--no-entry"); + + let mut cmd = Command::new(""); + ::std::mem::swap(&mut cmd, &mut self.cmd); + cmd + } +} diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 68c0ba026500..55ef4e7ed3ae 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -21,7 +21,6 @@ use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; use rustc::util::nodemap::FxHashMap; use rustc_allocator::ALLOCATOR_METHODS; -use rustc_back::LinkerFlavor; use syntax::attr; pub type ExportedSymbols = FxHashMap< @@ -156,26 +155,12 @@ pub fn provide_extern(providers: &mut Providers) { let special_runtime_crate = tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); - // Dealing with compiler-builtins and wasm right now is super janky. - // There's no linker! As a result we need all of the compiler-builtins - // exported symbols to make their way through all the way to the end of - // compilation. We want to make sure that LLVM doesn't remove them as - // well because we may or may not need them in the final output - // artifact. For now just force them to always get exported at the C - // layer, and we'll worry about gc'ing them later. - let compiler_builtins_and_binaryen = - tcx.is_compiler_builtins(cnum) && - tcx.sess.linker_flavor() == LinkerFlavor::Binaryen; - let mut crate_exports: Vec<_> = tcx .exported_symbol_ids(cnum) .iter() .map(|&def_id| { let name = tcx.symbol_name(Instance::mono(tcx, def_id)); - let export_level = if compiler_builtins_and_binaryen && - tcx.contains_extern_indicator(def_id) { - SymbolExportLevel::C - } else if special_runtime_crate { + let export_level = if special_runtime_crate { // We can probably do better here by just ensuring that // it has hidden visibility rather than public // visibility, as this is primarily here to ensure it's diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index af5178eb565d..1664aa9d0b3a 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -23,7 +23,6 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePass AllPasses, Sanitizer, Lto}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; -use rustc_back::LinkerFlavor; use time_graph::{self, TimeGraph, Timeline}; use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; @@ -344,9 +343,7 @@ pub struct CodegenContext { pub tm_factory: Arc Result + Send + Sync>, pub msvc_imps_needed: bool, pub target_pointer_width: String, - binaryen_linker: bool, debuginfo: config::DebugInfoLevel, - wasm_import_memory: bool, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -639,13 +636,6 @@ unsafe fn codegen(cgcx: &CodegenContext, f(cpm) } - // If we're going to generate wasm code from the assembly that llvm - // generates then we'll be transitively affecting a ton of options below. - // This only happens on the wasm target now. - let asm2wasm = cgcx.binaryen_linker && - !cgcx.crate_types.contains(&config::CrateTypeRlib) && - mtrans.kind == ModuleKind::Regular; - // If we don't have the integrated assembler, then we need to emit asm // from LLVM and use `gcc` to create the object file. let asm_to_obj = config.emit_obj && config.no_integrated_as; @@ -654,10 +644,10 @@ unsafe fn codegen(cgcx: &CodegenContext, // just llvm bitcode. In that case write bitcode, and possibly // delete the bitcode if it wasn't requested. Don't generate the // machine code, instead copy the .o file from the .bc - let write_bc = config.emit_bc || (config.obj_is_bitcode && !asm2wasm); - let rm_bc = !config.emit_bc && config.obj_is_bitcode && !asm2wasm; - let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm2wasm && !asm_to_obj; - let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode && !asm2wasm; + let write_bc = config.emit_bc || config.obj_is_bitcode; + let rm_bc = !config.emit_bc && config.obj_is_bitcode; + let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; + let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); @@ -736,13 +726,13 @@ unsafe fn codegen(cgcx: &CodegenContext, timeline.record("ir"); } - if config.emit_asm || (asm2wasm && config.emit_obj) || asm_to_obj { + if config.emit_asm || asm_to_obj { let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); // We can't use the same module for asm and binary output, because that triggers // various errors like invalid IR or broken binaries, so we might have to clone the // module to produce the asm output - let llmod = if config.emit_obj && !asm2wasm { + let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod @@ -751,24 +741,13 @@ unsafe fn codegen(cgcx: &CodegenContext, write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile) })?; - if config.emit_obj && !asm2wasm { + if config.emit_obj { llvm::LLVMDisposeModule(llmod); } timeline.record("asm"); } - if asm2wasm && config.emit_obj { - let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - let suffix = ".wasm.map"; // FIXME use target suffix - let map = cgcx.output_filenames.path(OutputType::Exe) - .with_extension(&suffix[1..]); - binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out, &map); - timeline.record("binaryen"); - - if !config.emit_asm { - drop(fs::remove_file(&assembly)); - } - } else if write_obj { + if write_obj { with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(diag_handler, tm, cpm, llmod, &obj_out, llvm::FileType::ObjectFile) @@ -808,49 +787,6 @@ unsafe fn codegen(cgcx: &CodegenContext, &cgcx.output_filenames)) } -/// Translates the LLVM-generated `assembly` on the filesystem into a wasm -/// module using binaryen, placing the output at `object`. -/// -/// In this case the "object" is actually a full and complete wasm module. We -/// won't actually be doing anything else to the output for now. This is all -/// pretty janky and will get removed as soon as a linker for wasm exists. -fn binaryen_assemble(cgcx: &CodegenContext, - handler: &Handler, - assembly: &Path, - object: &Path, - map: &Path) { - use rustc_binaryen::{Module, ModuleOptions}; - - let input = fs::read(&assembly).and_then(|contents| { - Ok(CString::new(contents)?) - }); - let mut options = ModuleOptions::new(); - if cgcx.debuginfo != config::NoDebugInfo { - options.debuginfo(true); - let map_file_name = map.file_name().unwrap(); - options.source_map_url(map_file_name.to_str().unwrap()); - } - - options.stack(1024 * 1024); - options.import_memory(cgcx.wasm_import_memory); - let assembled = input.and_then(|input| { - Module::new(&input, &options) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) - }); - let err = assembled.and_then(|binary| { - fs::write(&object, binary.data()).and_then(|()| { - if cgcx.debuginfo != config::NoDebugInfo { - fs::write(map, binary.source_map()) - } else { - Ok(()) - } - }) - }); - if let Err(e) = err { - handler.err(&format!("failed to run binaryen assembler: {}", e)); - } -} - pub(crate) struct CompiledModules { pub modules: Vec, pub metadata_module: CompiledModule, @@ -1431,9 +1367,6 @@ fn start_executing_work(tcx: TyCtxt, each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); })); - let wasm_import_memory = - attr::contains_name(&tcx.hir.krate().attrs, "wasm_import_memory"); - let assembler_cmd = if modules_config.no_integrated_as { // HACK: currently we use linker (gcc) as our assembler let (name, mut cmd, _) = get_linker(sess); @@ -1471,9 +1404,7 @@ fn start_executing_work(tcx: TyCtxt, total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), - binaryen_linker: tcx.sess.linker_flavor() == LinkerFlavor::Binaryen, debuginfo: tcx.sess.opts.debuginfo, - wasm_import_memory, assembler_cmd, }; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 6cb9d2027c74..51ad17fe2051 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -49,7 +49,6 @@ extern crate rustc_mir; extern crate rustc_allocator; extern crate rustc_apfloat; extern crate rustc_back; -extern crate rustc_binaryen; extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_demangle; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 70ea015de4e3..058df1d51690 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -414,9 +414,6 @@ declare_features! ( // Allow trait methods with arbitrary self types (active, arbitrary_self_types, "1.23.0", Some(44874)), - // #![wasm_import_memory] attribute - (active, wasm_import_memory, "1.22.0", None), - // `crate` in paths (active, crate_in_paths, "1.23.0", Some(45477)), @@ -985,11 +982,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG never be stable", cfg_fn!(rustc_attrs))), - ("wasm_import_memory", Whitelisted, Gated(Stability::Unstable, - "wasm_import_memory", - "wasm_import_memory attribute is currently unstable", - cfg_fn!(wasm_import_memory))), - ("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "never will be stable", diff --git a/src/test/run-pass/issue-15487.rs b/src/test/run-pass/issue-15487.rs index cc5db0af88be..3616ab9e6c73 100644 --- a/src/test/run-pass/issue-15487.rs +++ b/src/test/run-pass/issue-15487.rs @@ -9,6 +9,7 @@ // except according to those terms. // ignore-windows +// ignore-wasm32-bare no libs to link #![feature(link_args)] diff --git a/src/test/ui/feature-gate-wasm_import_memory.rs b/src/test/ui/feature-gate-wasm_import_memory.rs deleted file mode 100644 index a010ebb3551d..000000000000 --- a/src/test/ui/feature-gate-wasm_import_memory.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![wasm_import_memory] //~ ERROR: currently unstable - -fn main() {} - diff --git a/src/test/ui/feature-gate-wasm_import_memory.stderr b/src/test/ui/feature-gate-wasm_import_memory.stderr deleted file mode 100644 index 0ec502724672..000000000000 --- a/src/test/ui/feature-gate-wasm_import_memory.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: wasm_import_memory attribute is currently unstable - --> $DIR/feature-gate-wasm_import_memory.rs:11:1 - | -LL | #![wasm_import_memory] //~ ERROR: currently unstable - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(wasm_import_memory)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/tools/lld b/src/tools/lld new file mode 160000 index 000000000000..b87873eaceb7 --- /dev/null +++ b/src/tools/lld @@ -0,0 +1 @@ +Subproject commit b87873eaceb75cf9342d5273f01ba2c020f61ca8 diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 1def3048ce07..5134c8699126 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -50,7 +50,6 @@ pub mod unstable_book; fn filter_dirs(path: &Path) -> bool { let skip = [ - "src/binaryen", "src/dlmalloc", "src/jemalloc", "src/llvm", @@ -68,6 +67,7 @@ fn filter_dirs(path: &Path) -> bool { "src/tools/rust-installer", "src/tools/rustfmt", "src/tools/miri", + "src/tools/lld", "src/librustc/mir/interpret", "src/librustc_mir/interpret", "src/target", From 0129b01a41a062f82909cecdfd0cc7f0093c71f8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 10 Feb 2018 12:09:25 -0800 Subject: [PATCH 21/21] rustc: Tweak default linker selection This commit refactors how the path to the linker that we're going to invoke is selected. Previously all targets listed *both* a `LinkerFlavor` and a `linker` (path) option, but this meant that whenever you changed one you had to change the other. The purpose of this commit is to avoid coupling these where possible. Target specifications now only unconditionally define the *flavor* of the linker that they're using by default. If not otherwise specified each flavor now implies a particular default linker to run. As a result, this means that if you'd like to test out `ld` for example you should be able to do: rustc -Z linker-flavor=ld foo.rs whereas previously you had to do rustc -Z linker-flavor=ld -C linker=ld foo.rs This will hopefully make it a bit easier to tinker around with variants that should otherwise be well known to work, for example with LLD, `ld` on OSX, etc. --- src/bootstrap/dist.rs | 6 +- src/bootstrap/native.rs | 13 ++- src/librustc_back/lib.rs | 6 ++ .../target/aarch64_unknown_cloudabi.rs | 2 +- .../target/armv7_unknown_cloudabi_eabihf.rs | 2 +- .../target/asmjs_unknown_emscripten.rs | 3 - src/librustc_back/target/emscripten_base.rs | 17 ---- src/librustc_back/target/haiku_base.rs | 1 - .../target/i686_unknown_cloudabi.rs | 2 +- src/librustc_back/target/l4re_base.rs | 1 - src/librustc_back/target/mod.rs | 9 +- src/librustc_back/target/msp430_none_elf.rs | 2 +- src/librustc_back/target/thumb_base.rs | 2 +- .../target/wasm32_experimental_emscripten.rs | 3 - .../target/wasm32_unknown_emscripten.rs | 3 - .../target/wasm32_unknown_unknown.rs | 2 - src/librustc_back/target/windows_base.rs | 2 +- src/librustc_back/target/windows_msvc_base.rs | 1 - .../target/x86_64_rumprun_netbsd.rs | 2 +- .../target/x86_64_unknown_cloudabi.rs | 2 +- src/librustc_trans/Cargo.toml | 4 +- src/librustc_trans/back/command.rs | 14 +-- src/librustc_trans/back/link.rs | 95 +++++++++---------- src/librustc_trans/back/linker.rs | 4 + src/librustc_trans/back/write.rs | 2 +- src/librustc_trans/lib.rs | 1 - 26 files changed, 83 insertions(+), 118 deletions(-) delete mode 100644 src/librustc_back/target/emscripten_base.rs diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 02ef7c0e1ff6..576e50782474 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -606,8 +606,10 @@ impl Step for Std { let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); src.pop(); // Remove the trailing /lib folder from the sysroot_libdir cp_filtered(&src, &dst, &|path| { - path.file_name().and_then(|s| s.to_str()) != - Some(build.config.rust_codegen_backends_dir.as_str()) + let name = path.file_name().and_then(|s| s.to_str()); + name != Some(build.config.rust_codegen_backends_dir.as_str()) && + name != Some("bin") + }); let mut cmd = rust_installer(builder); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 987d70fd047f..7888f0b938d9 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -208,7 +208,7 @@ impl Step for Llvm { cfg.define("LLVM_NATIVE_BUILD", build.llvm_out(build.build).join("build")); } - configure_cmake(build, target, &mut cfg); + configure_cmake(build, target, &mut cfg, false); // FIXME: we don't actually need to build all LLVM tools and all LLVM // libraries here, e.g. we just want a few components and a few @@ -241,7 +241,8 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { fn configure_cmake(build: &Build, target: Interned, - cfg: &mut cmake::Config) { + cfg: &mut cmake::Config, + building_dist_binaries: bool) { if build.config.ninja { cfg.generator("Ninja"); } @@ -294,8 +295,10 @@ fn configure_cmake(build: &Build, cfg.build_arg("-j").build_arg(build.jobs().to_string()); cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); let mut cxxflags = build.cflags(target).join(" "); - if build.config.llvm_static_stdcpp && !target.contains("windows") { - cxxflags.push_str(" -static-libstdc++"); + if building_dist_binaries { + if build.config.llvm_static_stdcpp && !target.contains("windows") { + cxxflags.push_str(" -static-libstdc++"); + } } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = build.ar(target) { @@ -350,7 +353,7 @@ impl Step for Lld { t!(fs::create_dir_all(&out_dir)); let mut cfg = cmake::Config::new(build.src.join("src/tools/lld")); - configure_cmake(build, target, &mut cfg); + configure_cmake(build, target, &mut cfg, true); cfg.out_dir(&out_dir) .profile("Release") diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 141c8954a330..9de56cca3394 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -57,6 +57,9 @@ pub enum LinkerFlavor { RustcEncodable, RustcDecodable)] pub enum LldFlavor { Wasm, + Ld64, + Ld, + Link, } impl ToJson for LinkerFlavor { @@ -94,6 +97,9 @@ flavor_mappings! { ((LinkerFlavor::Ld), "ld"), ((LinkerFlavor::Msvc), "msvc"), ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"), + ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"), + ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"), + ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"), } #[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_back/target/aarch64_unknown_cloudabi.rs b/src/librustc_back/target/aarch64_unknown_cloudabi.rs index 59c82e06a679..a5d0e5bf166d 100644 --- a/src/librustc_back/target/aarch64_unknown_cloudabi.rs +++ b/src/librustc_back/target/aarch64_unknown_cloudabi.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::cloudabi_base::opts(); base.max_atomic_width = Some(128); base.abi_blacklist = super::arm_base::abi_blacklist(); - base.linker = "aarch64-unknown-cloudabi-cc".to_string(); + base.linker = Some("aarch64-unknown-cloudabi-cc".to_string()); Ok(Target { llvm_target: "aarch64-unknown-cloudabi".to_string(), diff --git a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs index faa2c4fdceb9..fa66a35abbf3 100644 --- a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs +++ b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs @@ -17,7 +17,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(64); base.features = "+v7,+vfp3,+neon".to_string(); base.abi_blacklist = super::arm_base::abi_blacklist(); - base.linker = "armv7-unknown-cloudabi-eabihf-cc".to_string(); + base.linker = Some("armv7-unknown-cloudabi-eabihf-cc".to_string()); Ok(Target { llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(), diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index 5d9f0f6012bf..f114926740a5 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -10,7 +10,6 @@ use LinkerFlavor; use super::{LinkArgs, Target, TargetOptions}; -use super::emscripten_base::{cmd}; pub fn target() -> Result { let mut args = LinkArgs::new(); @@ -19,8 +18,6 @@ pub fn target() -> Result { "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); let opts = TargetOptions { - linker: cmd("emcc"), - dynamic_linking: false, executables: true, exe_suffix: ".js".to_string(), diff --git a/src/librustc_back/target/emscripten_base.rs b/src/librustc_back/target/emscripten_base.rs deleted file mode 100644 index bacada3f5ab0..000000000000 --- a/src/librustc_back/target/emscripten_base.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn cmd(name: &str) -> String { - if cfg!(windows) { - format!("{}.bat", name) - } else { - name.to_string() - } -} diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs index 112f424f7a8b..a1ccb632cab7 100644 --- a/src/librustc_back/target/haiku_base.rs +++ b/src/librustc_back/target/haiku_base.rs @@ -13,7 +13,6 @@ use std::default::Default; pub fn opts() -> TargetOptions { TargetOptions { - linker: "cc".to_string(), dynamic_linking: true, executables: true, has_rpath: false, diff --git a/src/librustc_back/target/i686_unknown_cloudabi.rs b/src/librustc_back/target/i686_unknown_cloudabi.rs index e244f443d3e3..69c3b298caba 100644 --- a/src/librustc_back/target/i686_unknown_cloudabi.rs +++ b/src/librustc_back/target/i686_unknown_cloudabi.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::cloudabi_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.linker = "i686-unknown-cloudabi-cc".to_string(); + base.linker = Some("i686-unknown-cloudabi-cc".to_string()); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); base.stack_probes = true; diff --git a/src/librustc_back/target/l4re_base.rs b/src/librustc_back/target/l4re_base.rs index 31d428d26683..7cb7f8d613de 100644 --- a/src/librustc_back/target/l4re_base.rs +++ b/src/librustc_back/target/l4re_base.rs @@ -73,7 +73,6 @@ pub fn opts() -> Result { has_elf_tls: false, exe_allocation_crate: None, panic_strategy: PanicStrategy::Abort, - linker: "ld".to_string(), pre_link_args, post_link_args, target_family: Some("unix".to_string()), diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index be69127d8f2a..0a3e1826f3a1 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -58,7 +58,6 @@ mod arm_base; mod bitrig_base; mod cloudabi_base; mod dragonfly_base; -mod emscripten_base; mod freebsd_base; mod haiku_base; mod linux_base; @@ -279,8 +278,8 @@ pub struct TargetOptions { /// Whether the target is built-in or loaded from a custom target specification. pub is_builtin: bool, - /// Linker to invoke. Defaults to "cc". - pub linker: String, + /// Linker to invoke + pub linker: Option, /// Linker arguments that are unconditionally passed *before* any /// user-defined libraries. @@ -482,7 +481,7 @@ impl Default for TargetOptions { fn default() -> TargetOptions { TargetOptions { is_builtin: false, - linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(), + linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()), pre_link_args: LinkArgs::new(), post_link_args: LinkArgs::new(), asm_args: Vec::new(), @@ -732,7 +731,7 @@ impl Target { } key!(is_builtin, bool); - key!(linker); + key!(linker, optional); key!(pre_link_args, link_args); key!(pre_link_objects_exe, list); key!(pre_link_objects_dll, list); diff --git a/src/librustc_back/target/msp430_none_elf.rs b/src/librustc_back/target/msp430_none_elf.rs index 966df897f01f..d0f512ae47cd 100644 --- a/src/librustc_back/target/msp430_none_elf.rs +++ b/src/librustc_back/target/msp430_none_elf.rs @@ -32,7 +32,7 @@ pub fn target() -> TargetResult { // to gcc to get object files. For this reason we have a hard // dependency on this specific gcc. asm_args: vec!["-mcpu=msp430".to_string()], - linker: "msp430-elf-gcc".to_string(), + linker: Some("msp430-elf-gcc".to_string()), no_integrated_as: true, // There are no atomic instructions available in the MSP430 diff --git a/src/librustc_back/target/thumb_base.rs b/src/librustc_back/target/thumb_base.rs index 6bb496649a85..6a8f52f50931 100644 --- a/src/librustc_back/target/thumb_base.rs +++ b/src/librustc_back/target/thumb_base.rs @@ -45,7 +45,7 @@ pub fn opts() -> TargetOptions { executables: true, // In 99%+ of cases, we want to use the `arm-none-eabi-gcc` compiler (there aren't many // options around) - linker: "arm-none-eabi-gcc".to_string(), + linker: Some("arm-none-eabi-gcc".to_string()), // Because these devices have very little resources having an unwinder is too onerous so we // default to "abort" because the "unwind" strategy is very rare. panic_strategy: PanicStrategy::Abort, diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs index a261c982b3f2..13dee3a57686 100644 --- a/src/librustc_back/target/wasm32_experimental_emscripten.rs +++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs @@ -10,7 +10,6 @@ use LinkerFlavor; use super::{LinkArgs, Target, TargetOptions}; -use super::emscripten_base::{cmd}; pub fn target() -> Result { let mut post_link_args = LinkArgs::new(); @@ -24,8 +23,6 @@ pub fn target() -> Result { "-g3".to_string()]); let opts = TargetOptions { - linker: cmd("emcc"), - dynamic_linking: false, executables: true, // Today emcc emits two files - a .js file to bootstrap and diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index 4823541f2262..2770e67e30a5 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -10,7 +10,6 @@ use LinkerFlavor; use super::{LinkArgs, Target, TargetOptions}; -use super::emscripten_base::{cmd}; pub fn target() -> Result { let mut post_link_args = LinkArgs::new(); @@ -21,8 +20,6 @@ pub fn target() -> Result { "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); let opts = TargetOptions { - linker: cmd("emcc"), - dynamic_linking: false, executables: true, // Today emcc emits two files - a .js file to bootstrap and diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_back/target/wasm32_unknown_unknown.rs index c771762cfc89..1d84e1375174 100644 --- a/src/librustc_back/target/wasm32_unknown_unknown.rs +++ b/src/librustc_back/target/wasm32_unknown_unknown.rs @@ -22,8 +22,6 @@ use super::{Target, TargetOptions, PanicStrategy}; pub fn target() -> Result { let opts = TargetOptions { - linker: "lld".to_string(), - // we allow dynamic linking, but only cdylibs. Basically we allow a // final library artifact that exports some symbols (a wasm module) but // we don't allow intermediate `dylib` crate types diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index 30038400f6c8..05b6247c9518 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -75,7 +75,7 @@ pub fn opts() -> TargetOptions { TargetOptions { // FIXME(#13846) this should be enabled for windows function_sections: false, - linker: "gcc".to_string(), + linker: Some("gcc".to_string()), dynamic_linking: true, executables: true, dll_prefix: "".to_string(), diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index e0bf36ee4077..34aa17267f8b 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions { TargetOptions { function_sections: true, - linker: "link.exe".to_string(), dynamic_linking: true, executables: true, dll_prefix: "".to_string(), diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs index 18f6380b6eed..3158665a2e28 100644 --- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs +++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); - base.linker = "x86_64-rumprun-netbsd-gcc".to_string(); + base.linker = Some("x86_64-rumprun-netbsd-gcc".to_string()); base.max_atomic_width = Some(64); base.dynamic_linking = false; diff --git a/src/librustc_back/target/x86_64_unknown_cloudabi.rs b/src/librustc_back/target/x86_64_unknown_cloudabi.rs index 1ce3c6444f1e..d1a9cb1cd7e7 100644 --- a/src/librustc_back/target/x86_64_unknown_cloudabi.rs +++ b/src/librustc_back/target/x86_64_unknown_cloudabi.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::cloudabi_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.linker = "x86_64-unknown-cloudabi-cc".to_string(); + base.linker = Some("x86_64-unknown-cloudabi-cc".to_string()); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.stack_probes = true; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 4b9c93088a51..805d2086ee4f 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -11,6 +11,7 @@ test = false [dependencies] bitflags = "1.0" +cc = "1.0.1" flate2 = "1.0" jobserver = "0.1.5" libc = "0.2" @@ -34,9 +35,6 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } tempdir = "0.3" -[target."cfg(windows)".dependencies] -cc = "1.0.1" - [features] # Used to communicate the feature to `rustc_back` in the same manner that the # `rustc` driver script communicate this. diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs index e5e0a4e3ba0e..ecf7bf5036e0 100644 --- a/src/librustc_trans/back/command.rs +++ b/src/librustc_trans/back/command.rs @@ -81,17 +81,6 @@ impl Command { self } - pub fn envs(&mut self, envs: I) -> &mut Command - where I: IntoIterator, - K: AsRef, - V: AsRef - { - for (key, value) in envs { - self._env(key.as_ref(), value.as_ref()); - } - self - } - fn _env(&mut self, key: &OsStr, value: &OsStr) { self.env.push((key.to_owned(), value.to_owned())); } @@ -112,6 +101,9 @@ impl Command { let mut c = process::Command::new(p); c.arg("-flavor").arg(match flavor { LldFlavor::Wasm => "wasm", + LldFlavor::Ld => "gnu", + LldFlavor::Link => "link", + LldFlavor::Ld64 => "darwin", }); c } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index c134203a773f..636b3984117d 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cc::windows_registry; use super::archive::{ArchiveBuilder, ArchiveConfig}; use super::bytecode::RLIB_BYTECODE_EXTENSION; use super::linker::Linker; @@ -35,7 +36,6 @@ use llvm; use std::ascii; use std::char; use std::env; -use std::ffi::OsString; use std::fmt; use std::fs; use std::io; @@ -58,9 +58,7 @@ pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_o // The third parameter is for env vars, used on windows to set up the // path for MSVC to find its DLLs, and gcc to find its bundled // toolchain -pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)>) { - let envs = vec![("PATH".into(), command_path(sess))]; - +pub fn get_linker(sess: &Session) -> (PathBuf, Command) { // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle // emscripten where the linker is `emcc.bat` and needs to be spawned as @@ -75,60 +73,57 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString) return Command::bat_script(linker) } } - Command::new(linker) + match sess.linker_flavor() { + LinkerFlavor::Lld(f) => Command::lld(linker, f), + _ => Command::new(linker), + + } }; - if let Some(ref linker) = sess.opts.cg.linker { - (linker.clone(), cmd(linker), envs) - } else if sess.target.target.options.is_like_msvc { - let (cmd, envs) = msvc_link_exe_cmd(sess); - (PathBuf::from("link.exe"), cmd, envs) - } else if let LinkerFlavor::Lld(f) = sess.linker_flavor() { - let linker = PathBuf::from(&sess.target.target.options.linker); - let cmd = Command::lld(&linker, f); - (linker, cmd, envs) - } else { - let linker = PathBuf::from(&sess.target.target.options.linker); - let cmd = cmd(&linker); - (linker, cmd, envs) - } -} + let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple, "link.exe"); -#[cfg(windows)] -pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) { - use cc::windows_registry; + let linker_path = sess.opts.cg.linker.as_ref().map(|s| &**s) + .or(sess.target.target.options.linker.as_ref().map(|s| s.as_ref())) + .unwrap_or(match sess.linker_flavor() { + LinkerFlavor::Msvc => { + msvc_tool.as_ref().map(|t| t.path()).unwrap_or("link.exe".as_ref()) + } + LinkerFlavor::Em if cfg!(windows) => "emcc.bat".as_ref(), + LinkerFlavor::Em => "emcc".as_ref(), + LinkerFlavor::Gcc => "cc".as_ref(), + LinkerFlavor::Ld => "ld".as_ref(), + LinkerFlavor::Lld(_) => "lld".as_ref(), + }); - let target = &sess.opts.target_triple; - let tool = windows_registry::find_tool(target, "link.exe"); + let mut cmd = cmd(linker_path); - if let Some(tool) = tool { - let mut cmd = Command::new(tool.path()); - cmd.args(tool.args()); - for &(ref k, ref v) in tool.env() { - cmd.env(k, v); - } - let envs = tool.env().to_vec(); - (cmd, envs) - } else { - debug!("Failed to locate linker."); - (Command::new("link.exe"), vec![]) - } -} - -#[cfg(not(windows))] -pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)>) { - (Command::new("link.exe"), vec![]) -} - -fn command_path(sess: &Session) -> OsString { // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All) .get_tools_search_paths(); - if let Some(path) = env::var_os("PATH") { - new_path.extend(env::split_paths(&path)); + let mut msvc_changed_path = false; + if sess.target.target.options.is_like_msvc { + if let Some(ref tool) = msvc_tool { + cmd.args(tool.args()); + for &(ref k, ref v) in tool.env() { + if k == "PATH" { + new_path.extend(env::split_paths(v)); + msvc_changed_path = true; + } else { + cmd.env(k, v); + } + } + } } - env::join_paths(new_path).unwrap() + + if !msvc_changed_path { + if let Some(path) = env::var_os("PATH") { + new_path.extend(env::split_paths(&path)); + } + } + cmd.env("PATH", env::join_paths(new_path).unwrap()); + + (linker_path.to_path_buf(), cmd) } pub fn remove(sess: &Session, path: &Path) { @@ -618,9 +613,7 @@ fn link_natively(sess: &Session, let flavor = sess.linker_flavor(); // The invocations of cc share some flags across platforms - let (pname, mut cmd, envs) = get_linker(sess); - // This will set PATH on windows - cmd.envs(envs); + let (pname, mut cmd) = get_linker(sess); let root = sess.target_filesearch(PathKind::Native).get_lib_path(); if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a82270c5272b..a3ff39a47a29 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -45,6 +45,7 @@ impl LinkerInfo { cmd: Command, sess: &'a Session) -> Box { match sess.linker_flavor() { + LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { Box::new(MsvcLinker { cmd, @@ -68,6 +69,9 @@ impl LinkerInfo { is_ld: false, }) as Box } + + LinkerFlavor::Lld(LldFlavor::Ld) | + LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Ld => { Box::new(GccLinker { cmd, diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 1664aa9d0b3a..78b26a37485e 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1369,7 +1369,7 @@ fn start_executing_work(tcx: TyCtxt, let assembler_cmd = if modules_config.no_integrated_as { // HACK: currently we use linker (gcc) as our assembler - let (name, mut cmd, _) = get_linker(sess); + let (name, mut cmd) = get_linker(sess); cmd.args(&sess.target.target.options.asm_args); Some(Arc::new(AssemblerCommand { name, diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 51ad17fe2051..0b8da10b78e7 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -62,7 +62,6 @@ extern crate rustc_trans_utils; extern crate syntax_pos; extern crate rustc_errors as errors; extern crate serialize; -#[cfg(windows)] extern crate cc; // Used to locate MSVC extern crate tempdir;