From 7aca34b8963fd9ac8681485a44417e537e617245 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Fri, 16 Feb 2018 16:47:00 -0600 Subject: 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 00000000000..844c54c7aa8 --- /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. -- cgit 1.4.1-3-g733a5 From 8d893c1e9e136302a1640035b29e23023f87866e Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 20 Feb 2018 09:26:44 -0600 Subject: 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 844c54c7aa8..b0a5ae3718d 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 -- cgit 1.4.1-3-g733a5 From 8e4ad29cb9cc74bf44486f4507f36df70d495187 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 23 Feb 2018 21:48:41 +0900 Subject: 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 a36e26c0b7d..88f2b596751 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 - }, + } }) } -- cgit 1.4.1-3-g733a5 From ffb6291cd032e3b0577bf67a2b6d932d6ba0787c Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Mon, 26 Feb 2018 20:45:52 -0500 Subject: 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 603a97ddfd4..f5fcf4ba0f5 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))) -- cgit 1.4.1-3-g733a5 From 89e55d108c5c6d5f29c4eb0cb829e47bccb8598b Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Sun, 3 Dec 2017 14:24:14 +0100 Subject: Make TransitiveRelation thread safe. Avoid locking by using get_mut in some cases. --- src/librustc_data_structures/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 ba7ab0c07c6..6d63bc4436f 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) }) }) } } -- cgit 1.4.1-3-g733a5 From 5ac4f62f3832f2a4ed26ab95567c96a38a9f4f15 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Wed, 28 Feb 2018 20:57:56 -0800 Subject: 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 844ff7a3c12..5dd9c627750 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), -- cgit 1.4.1-3-g733a5 From 39d0b054cea73614a0c1dd06cd98d3d22eea6b10 Mon Sep 17 00:00:00 2001 From: Segev Finer Date: Thu, 1 Mar 2018 14:47:20 +0200 Subject: 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 5966bb65df9..761cc94c8c6 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())): -- cgit 1.4.1-3-g733a5 From 5332d9a8e8a66e22b8c81f3f302ce72734ba137f Mon Sep 17 00:00:00 2001 From: Segev Finer Date: Thu, 1 Mar 2018 18:33:14 +0200 Subject: 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 761cc94c8c6..5d297570bc1 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) -- cgit 1.4.1-3-g733a5 From fdef6a881e784c505fc28ee85d54f72a77921410 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 28 Feb 2018 21:25:12 -0800 Subject: 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 b5946b44e05..c88aa462a95 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 02480c6937d..3be1c255c16 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 -- cgit 1.4.1-3-g733a5 From 2269ff521fe2a945e462d5156799011c5fce2966 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Fri, 2 Mar 2018 03:29:35 -0500 Subject: 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 f5fcf4ba0f5..327ae0cb65c 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( -- cgit 1.4.1-3-g733a5 From 6250a47ea6147a60e11e59aded80ebb62c8e3ab1 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Fri, 2 Mar 2018 09:19:50 +0100 Subject: 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 8d1fa3eec5c..3dfd25aade1 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 b5946b44e05..2eec6c69739 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 2c9f0ddb6c3..f8e0a1f5a92 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 6bc20181a03..361fc704bc0 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 e7aed7eb4fe..05630b8431f 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 22c26b06430..0f7a04e391b 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()); -- cgit 1.4.1-3-g733a5 From ab7ce1c3c48d4f1be6c16928704e2eec0aed9ae2 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sun, 11 Feb 2018 15:52:44 -0700 Subject: 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 f2773a720cf..e10ccd56a4a 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 191f8e3a289..2b7624d53ee 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 ff0708459bc..2a0901691a5 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 fedb4094c8a..b2a3ba3ec26 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 ce5e8cfaf09..a7903b6f425 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 3177fa2147f..c02a5e5a095 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 ace9c4feb4f..04e83a431c4 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 322d26f0adc..937301864cd 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 f3509efdb98..dbff9e32e13 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 621976b5cbe..440afd7c97f 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 ed19939545f..f4c25f791bc 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 8653b0e8b46..420d47b314c 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 7f6f8ae0882..6ac90d17450 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 841d3012125..dbc319312aa 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 5d7545a3c2a..aa5da136758 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 ecd5090ea05..89f7f85cb3b 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 5bbd17bd414..e0c1b9a9e85 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 ea9034d7178..e7d4f464ffc 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 035846b4f64..7bcc649f4aa 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 673fa4c0c4b..1f595ba7a29 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 5e405aa72e8..da7c6233fc8 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 94a3cf8a382..37ab5bdcce5 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 0b0dfff1fe3..a5180780b22 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 1810b1cdc5a..d38ed24f625 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 f5be0748475..491c57ba677 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 14ce3654fce..c503f2af9cd 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 1f6e83e2f49..4a369177736 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 d4677e18060..bf6c8b4b712 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 39478e92f7c..a2ebf590bab 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 c83f101d0ac..a23153645cd 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 5f342eb5705..4505a60e463 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 f9f5b7062f8..dd595a19205 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 d368a00b55b..86b3beeb4e5 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 c1061309c30..3a9ad178c63 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 4fd2503c31b..06298a12fc7 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 dc1727b7014..106f907bab9 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 \ -- cgit 1.4.1-3-g733a5 From 900d511fdca20998e42634d5351f7033bbde1aed Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 2 Mar 2018 13:52:13 -0500 Subject: 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 55d9723527e..a791dd13f0f 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: 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 fc2f8bbc8a3..5b7fd481299 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 3dd30ee1c69..1efd605112d 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 d7d856fe3ad..a7e1c0ce732 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 00000000000..678cbd325c8 --- /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 4d89008d5ca..1def3048ce0 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)) } -- cgit 1.4.1-3-g733a5 From 46fef766b0dc3717937911f0f67c9f1ee2a7f21e Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sun, 28 Jan 2018 14:24:19 -0500 Subject: 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 3c9b6b94b44..9c6b10c32f1 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]; -- cgit 1.4.1-3-g733a5 From 2db05f04bebd8a8cfbdb323fbd6d3341aee551d9 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Mon, 29 Jan 2018 15:01:52 -0500 Subject: 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 f4dde95b104..1b5d28d5bb1 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 -- cgit 1.4.1-3-g733a5 From 45bdf9cbeec3788c29d8958dc661dd449bb7247c Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Mon, 29 Jan 2018 15:02:44 -0500 Subject: 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 9c6b10c32f1..83538e5acd4 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] } } -- cgit 1.4.1-3-g733a5 From ae73a210814bdf50d72a95568eb8c9c96772c641 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Wed, 31 Jan 2018 20:14:17 -0500 Subject: 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 659b08b55a0..4b01afb8131 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 -- cgit 1.4.1-3-g733a5 From 370df40dab8df9f3c0b10bb7396225b8d24869b3 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Fri, 2 Mar 2018 23:23:00 -0500 Subject: 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 83538e5acd4..feed7c8699a 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 1b5d28d5bb1..ae3cd529ac4 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 -- cgit 1.4.1-3-g733a5 From d69b24805b5071e5ec9e62d2777a761723644144 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Aug 2017 18:30:12 -0700 Subject: 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 +++--- src/librustc_back/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 + src/test/ui/feature-gate-wasm_import_memory.rs | 14 -- src/test/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 5b7fd481299..55f586389b1 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 0d8641e45ed..4738f91665d 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 e78bbb82711..19ef96fae01 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 0ea15dd671c..0735ead8923 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 3dfd25aade1..b47f9163c0d 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 7b4bfecea3f..7620fe8ddb3 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 17841e155ed..00000000000 --- 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 ca35a896e08..6c3c48aba72 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 77df372d4fa..d8f7cd7ed92 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 bc75d31e06e..8cbb1f3d0e9 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 e531fdaf292..9e1b1f7db2f 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 30ca9dffc19..695cf04a82c 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 361fc704bc0..f15d4d35858 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 99a3ee4e4c3..e9b4a233d0a 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 05630b8431f..02ef7c0e1ff 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 90f50275b6b..f3d9246c6fc 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 653606e5d24..987d70fd047 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 b27ddfdbc5e..c0998c1e42c 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 da7c6233fc8..0ec57ee0886 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 86b3beeb4e5..3b98b0aa926 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 106f907bab9..0972eb85191 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 69647f37eec..98d6202a63f 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 8bf60b091a7..141c8954a33 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 242860e5c6e..c771762cfc8 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 55f11665f6d..00000000000 --- 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 9573c894714..00000000000 --- 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 f23ff3cee55..00000000000 --- 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 36174e11ba0..00000000000 --- 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 500c4fdf4e8..4b9c93088a5 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 0bccef1e62a..e5e0a4e3ba0 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 8f308e72686..c134203a773 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 7e7811c56c7..a82270c5272 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 68c0ba02650..55ef4e7ed3a 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 af5178eb565..1664aa9d0b3 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 6cb9d2027c7..51ad17fe205 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 70ea015de4e..058df1d5169 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 cc5db0af88b..3616ab9e6c7 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 a010ebb3551..00000000000 --- 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 0ec50272467..00000000000 --- 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 00000000000..b87873eaceb --- /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 1def3048ce0..5134c869912 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", -- cgit 1.4.1-3-g733a5 From 0129b01a41a062f82909cecdfd0cc7f0093c71f8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 10 Feb 2018 12:09:25 -0800 Subject: 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 - src/librustc_back/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 - src/librustc_back/target/wasm32_unknown_unknown.rs | 2 - src/librustc_back/target/windows_base.rs | 2 +- src/librustc_back/target/windows_msvc_base.rs | 1 - src/librustc_back/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 02ef7c0e1ff..576e5078247 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 987d70fd047..7888f0b938d 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 141c8954a33..9de56cca339 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 59c82e06a67..a5d0e5bf166 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 faa2c4fdceb..fa66a35abbf 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 5d9f0f6012b..f114926740a 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 bacada3f5ab..00000000000 --- 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 112f424f7a8..a1ccb632cab 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 e244f443d3e..69c3b298cab 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 31d428d2668..7cb7f8d613d 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 be69127d8f2..0a3e1826f3a 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 966df897f01..d0f512ae47c 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 6bb496649a8..6a8f52f5093 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 a261c982b3f..13dee3a5768 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 4823541f226..2770e67e30a 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 c771762cfc8..1d84e137517 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 30038400f6c..05b6247c951 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 e0bf36ee407..34aa17267f8 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 18f6380b6ee..3158665a2e2 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 1ce3c6444f1..d1a9cb1cd7e 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 4b9c93088a5..805d2086ee4 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 e5e0a4e3ba0..ecf7bf5036e 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 c134203a773..636b3984117 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) - }; - - 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) - } -} + match sess.linker_flavor() { + LinkerFlavor::Lld(f) => Command::lld(linker, f), + _ => Command::new(linker), -#[cfg(windows)] -pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) { - use cc::windows_registry; + } + }; - let target = &sess.opts.target_triple; - let tool = windows_registry::find_tool(target, "link.exe"); + let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple, "link.exe"); - 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![]) - } -} + 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(), + }); -#[cfg(not(windows))] -pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)>) { - (Command::new("link.exe"), vec![]) -} + let mut cmd = cmd(linker_path); -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 a82270c5272..a3ff39a47a2 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 1664aa9d0b3..78b26a37485 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 51ad17fe205..0b8da10b78e 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; -- cgit 1.4.1-3-g733a5