summaryrefslogtreecommitdiffstats
path: root/third_party/rust/autocfg
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /third_party/rust/autocfg
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/autocfg')
-rw-r--r--third_party/rust/autocfg/.cargo-checksum.json1
-rw-r--r--third_party/rust/autocfg/Cargo.lock7
-rw-r--r--third_party/rust/autocfg/Cargo.toml24
-rw-r--r--third_party/rust/autocfg/LICENSE-APACHE201
-rw-r--r--third_party/rust/autocfg/LICENSE-MIT25
-rw-r--r--third_party/rust/autocfg/README.md95
-rw-r--r--third_party/rust/autocfg/examples/integers.rs9
-rw-r--r--third_party/rust/autocfg/examples/paths.rs22
-rw-r--r--third_party/rust/autocfg/examples/traits.rs26
-rw-r--r--third_party/rust/autocfg/examples/versions.rs9
-rw-r--r--third_party/rust/autocfg/src/error.rs69
-rw-r--r--third_party/rust/autocfg/src/lib.rs464
-rw-r--r--third_party/rust/autocfg/src/tests.rs174
-rw-r--r--third_party/rust/autocfg/src/version.rs60
-rw-r--r--third_party/rust/autocfg/tests/rustflags.rs33
15 files changed, 1219 insertions, 0 deletions
diff --git a/third_party/rust/autocfg/.cargo-checksum.json b/third_party/rust/autocfg/.cargo-checksum.json
new file mode 100644
index 0000000000..e4cc3fc45a
--- /dev/null
+++ b/third_party/rust/autocfg/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"3d91565ed13de572a9ebde408a0c98e33f931d6ab52f212b0830a60b4ab26b77","Cargo.toml":"39f627122dceaad42146634719fde802fca3baa1b3908753af723074ae2a6d69","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"4c8f9b5016f2a0c3dbeca5bc41241f57db5568f803e58c1fa480ae2b3638d0a9","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"6fa01458e8f9258d84f83ead24fdb0cdf9aec10838b0262f1dfbdf79c530c537","src/tests.rs":"f0e6dc1ad9223c0336c02e215ea3940acb2af6c3bc8fd791e16cd4e786e6a608","src/version.rs":"175727d5f02f2fe2271ddc9b041db2a5b9c6fe0f95afd17c73a4d982612764a3","tests/rustflags.rs":"5c8169b88216055019db61b5d7baf4abdf675e3b14b54f5037bb1e3acd0a5d3f"},"package":"d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"} \ No newline at end of file
diff --git a/third_party/rust/autocfg/Cargo.lock b/third_party/rust/autocfg/Cargo.lock
new file mode 100644
index 0000000000..2b148536f4
--- /dev/null
+++ b/third_party/rust/autocfg/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
diff --git a/third_party/rust/autocfg/Cargo.toml b/third_party/rust/autocfg/Cargo.toml
new file mode 100644
index 0000000000..f8bd64c08b
--- /dev/null
+++ b/third_party/rust/autocfg/Cargo.toml
@@ -0,0 +1,24 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+name = "autocfg"
+version = "1.1.0"
+authors = ["Josh Stone <cuviper@gmail.com>"]
+exclude = ["/.github/**", "/bors.toml"]
+description = "Automatic cfg for Rust compiler features"
+readme = "README.md"
+keywords = ["rustc", "build", "autoconf"]
+categories = ["development-tools::build-utils"]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/cuviper/autocfg"
+
+[dependencies]
diff --git a/third_party/rust/autocfg/LICENSE-APACHE b/third_party/rust/autocfg/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/autocfg/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/autocfg/LICENSE-MIT b/third_party/rust/autocfg/LICENSE-MIT
new file mode 100644
index 0000000000..44fbc4d8b9
--- /dev/null
+++ b/third_party/rust/autocfg/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2018 Josh Stone
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/autocfg/README.md b/third_party/rust/autocfg/README.md
new file mode 100644
index 0000000000..8c95696cd5
--- /dev/null
+++ b/third_party/rust/autocfg/README.md
@@ -0,0 +1,95 @@
+autocfg
+=======
+
+[![autocfg crate](https://img.shields.io/crates/v/autocfg.svg)](https://crates.io/crates/autocfg)
+[![autocfg documentation](https://docs.rs/autocfg/badge.svg)](https://docs.rs/autocfg)
+![minimum rustc 1.0](https://img.shields.io/badge/rustc-1.0+-red.svg)
+![build status](https://github.com/cuviper/autocfg/workflows/master/badge.svg)
+
+A Rust library for build scripts to automatically configure code based on
+compiler support. Code snippets are dynamically tested to see if the `rustc`
+will accept them, rather than hard-coding specific version support.
+
+
+## Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[build-dependencies]
+autocfg = "1"
+```
+
+Then use it in your `build.rs` script to detect compiler features. For
+example, to test for 128-bit integer support, it might look like:
+
+```rust
+extern crate autocfg;
+
+fn main() {
+ let ac = autocfg::new();
+ ac.emit_has_type("i128");
+
+ // (optional) We don't need to rerun for anything external.
+ autocfg::rerun_path("build.rs");
+}
+```
+
+If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
+for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the
+rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
+should only be used when the compiler supports it.
+
+
+## Release Notes
+
+- 1.1.0 (2022-02-07)
+ - Use `CARGO_ENCODED_RUSTFLAGS` when it is set.
+
+- 1.0.1 (2020-08-20)
+ - Apply `RUSTFLAGS` for more `--target` scenarios, by @adamreichold.
+
+- 1.0.0 (2020-01-08)
+ - 🎉 Release 1.0! 🎉 (no breaking changes)
+ - Add `probe_expression` and `emit_expression_cfg` to test arbitrary expressions.
+ - Add `probe_constant` and `emit_constant_cfg` to test arbitrary constant expressions.
+
+- 0.1.7 (2019-10-20)
+ - Apply `RUSTFLAGS` when probing `$TARGET != $HOST`, mainly for sysroot, by @roblabla.
+
+- 0.1.6 (2019-08-19)
+ - Add `probe`/`emit_sysroot_crate`, by @leo60228.
+
+- 0.1.5 (2019-07-16)
+ - Mask some warnings from newer rustc.
+
+- 0.1.4 (2019-05-22)
+ - Relax `std`/`no_std` probing to a warning instead of an error.
+ - Improve `rustc` bootstrap compatibility.
+
+- 0.1.3 (2019-05-21)
+ - Auto-detects if `#![no_std]` is needed for the `$TARGET`.
+
+- 0.1.2 (2019-01-16)
+ - Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`.
+ - Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`.
+
+
+## Minimum Rust version policy
+
+This crate's minimum supported `rustc` version is `1.0.0`. Compatibility is
+its entire reason for existence, so this crate will be extremely conservative
+about raising this requirement. If this is ever deemed necessary, it will be
+treated as a major breaking change for semver purposes.
+
+
+## License
+
+This project is licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
+ http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or
+ http://opensource.org/licenses/MIT)
+
+at your option.
diff --git a/third_party/rust/autocfg/examples/integers.rs b/third_party/rust/autocfg/examples/integers.rs
new file mode 100644
index 0000000000..23d4cba6ee
--- /dev/null
+++ b/third_party/rust/autocfg/examples/integers.rs
@@ -0,0 +1,9 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+ for i in 3..8 {
+ ac.emit_has_type(&format!("i{}", 1 << i));
+ }
+}
diff --git a/third_party/rust/autocfg/examples/paths.rs b/third_party/rust/autocfg/examples/paths.rs
new file mode 100644
index 0000000000..b7a6ca7a25
--- /dev/null
+++ b/third_party/rust/autocfg/examples/paths.rs
@@ -0,0 +1,22 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+
+ // since ancient times...
+ ac.emit_has_path("std::vec::Vec");
+ ac.emit_path_cfg("std::vec::Vec", "has_vec");
+
+ // rustc 1.10.0
+ ac.emit_has_path("std::panic::PanicInfo");
+ ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info");
+
+ // rustc 1.20.0
+ ac.emit_has_path("std::mem::ManuallyDrop");
+ ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop");
+
+ // rustc 1.25.0
+ ac.emit_has_path("std::ptr::NonNull");
+ ac.emit_path_cfg("std::ptr::NonNull", "has_non_null");
+}
diff --git a/third_party/rust/autocfg/examples/traits.rs b/third_party/rust/autocfg/examples/traits.rs
new file mode 100644
index 0000000000..c1ca00385c
--- /dev/null
+++ b/third_party/rust/autocfg/examples/traits.rs
@@ -0,0 +1,26 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+
+ // since ancient times...
+ ac.emit_has_trait("std::ops::Add");
+ ac.emit_trait_cfg("std::ops::Add", "has_ops");
+
+ // trait parameters have to be provided
+ ac.emit_has_trait("std::borrow::Borrow<str>");
+ ac.emit_trait_cfg("std::borrow::Borrow<str>", "has_borrow");
+
+ // rustc 1.8.0
+ ac.emit_has_trait("std::ops::AddAssign");
+ ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops");
+
+ // rustc 1.12.0
+ ac.emit_has_trait("std::iter::Sum");
+ ac.emit_trait_cfg("std::iter::Sum", "has_sum");
+
+ // rustc 1.28.0
+ ac.emit_has_trait("std::alloc::GlobalAlloc");
+ ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc");
+}
diff --git a/third_party/rust/autocfg/examples/versions.rs b/third_party/rust/autocfg/examples/versions.rs
new file mode 100644
index 0000000000..992919b7c6
--- /dev/null
+++ b/third_party/rust/autocfg/examples/versions.rs
@@ -0,0 +1,9 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+ for i in 0..100 {
+ ac.emit_rustc_version(1, i);
+ }
+}
diff --git a/third_party/rust/autocfg/src/error.rs b/third_party/rust/autocfg/src/error.rs
new file mode 100644
index 0000000000..4624835451
--- /dev/null
+++ b/third_party/rust/autocfg/src/error.rs
@@ -0,0 +1,69 @@
+use std::error;
+use std::fmt;
+use std::io;
+use std::num;
+use std::str;
+
+/// A common error type for the `autocfg` crate.
+#[derive(Debug)]
+pub struct Error {
+ kind: ErrorKind,
+}
+
+impl error::Error for Error {
+ fn description(&self) -> &str {
+ "AutoCfg error"
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ match self.kind {
+ ErrorKind::Io(ref e) => Some(e),
+ ErrorKind::Num(ref e) => Some(e),
+ ErrorKind::Utf8(ref e) => Some(e),
+ ErrorKind::Other(_) => None,
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ match self.kind {
+ ErrorKind::Io(ref e) => e.fmt(f),
+ ErrorKind::Num(ref e) => e.fmt(f),
+ ErrorKind::Utf8(ref e) => e.fmt(f),
+ ErrorKind::Other(s) => s.fmt(f),
+ }
+ }
+}
+
+#[derive(Debug)]
+enum ErrorKind {
+ Io(io::Error),
+ Num(num::ParseIntError),
+ Utf8(str::Utf8Error),
+ Other(&'static str),
+}
+
+pub fn from_io(e: io::Error) -> Error {
+ Error {
+ kind: ErrorKind::Io(e),
+ }
+}
+
+pub fn from_num(e: num::ParseIntError) -> Error {
+ Error {
+ kind: ErrorKind::Num(e),
+ }
+}
+
+pub fn from_utf8(e: str::Utf8Error) -> Error {
+ Error {
+ kind: ErrorKind::Utf8(e),
+ }
+}
+
+pub fn from_str(s: &'static str) -> Error {
+ Error {
+ kind: ErrorKind::Other(s),
+ }
+}
diff --git a/third_party/rust/autocfg/src/lib.rs b/third_party/rust/autocfg/src/lib.rs
new file mode 100644
index 0000000000..0596403a2a
--- /dev/null
+++ b/third_party/rust/autocfg/src/lib.rs
@@ -0,0 +1,464 @@
+//! A Rust library for build scripts to automatically configure code based on
+//! compiler support. Code snippets are dynamically tested to see if the `rustc`
+//! will accept them, rather than hard-coding specific version support.
+//!
+//!
+//! ## Usage
+//!
+//! Add this to your `Cargo.toml`:
+//!
+//! ```toml
+//! [build-dependencies]
+//! autocfg = "1"
+//! ```
+//!
+//! Then use it in your `build.rs` script to detect compiler features. For
+//! example, to test for 128-bit integer support, it might look like:
+//!
+//! ```rust
+//! extern crate autocfg;
+//!
+//! fn main() {
+//! # // Normally, cargo will set `OUT_DIR` for build scripts.
+//! # std::env::set_var("OUT_DIR", "target");
+//! let ac = autocfg::new();
+//! ac.emit_has_type("i128");
+//!
+//! // (optional) We don't need to rerun for anything external.
+//! autocfg::rerun_path("build.rs");
+//! }
+//! ```
+//!
+//! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
+//! for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the
+//! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
+//! should only be used when the compiler supports it.
+//!
+//! ## Caution
+//!
+//! Many of the probing methods of `AutoCfg` document the particular template they
+//! use, **subject to change**. The inputs are not validated to make sure they are
+//! semantically correct for their expected use, so it's _possible_ to escape and
+//! inject something unintended. However, such abuse is unsupported and will not
+//! be considered when making changes to the templates.
+
+#![deny(missing_debug_implementations)]
+#![deny(missing_docs)]
+// allow future warnings that can't be fixed while keeping 1.0 compatibility
+#![allow(unknown_lints)]
+#![allow(bare_trait_objects)]
+#![allow(ellipsis_inclusive_range_patterns)]
+
+/// Local macro to avoid `std::try!`, deprecated in Rust 1.39.
+macro_rules! try {
+ ($result:expr) => {
+ match $result {
+ Ok(value) => value,
+ Err(error) => return Err(error),
+ }
+ };
+}
+
+use std::env;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{stderr, Write};
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+#[allow(deprecated)]
+use std::sync::atomic::ATOMIC_USIZE_INIT;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+mod error;
+pub use error::Error;
+
+mod version;
+use version::Version;
+
+#[cfg(test)]
+mod tests;
+
+/// Helper to detect compiler features for `cfg` output in build scripts.
+#[derive(Clone, Debug)]
+pub struct AutoCfg {
+ out_dir: PathBuf,
+ rustc: PathBuf,
+ rustc_version: Version,
+ target: Option<OsString>,
+ no_std: bool,
+ rustflags: Vec<String>,
+}
+
+/// Writes a config flag for rustc on standard out.
+///
+/// This looks like: `cargo:rustc-cfg=CFG`
+///
+/// Cargo will use this in arguments to rustc, like `--cfg CFG`.
+pub fn emit(cfg: &str) {
+ println!("cargo:rustc-cfg={}", cfg);
+}
+
+/// Writes a line telling Cargo to rerun the build script if `path` changes.
+///
+/// This looks like: `cargo:rerun-if-changed=PATH`
+///
+/// This requires at least cargo 0.7.0, corresponding to rustc 1.6.0. Earlier
+/// versions of cargo will simply ignore the directive.
+pub fn rerun_path(path: &str) {
+ println!("cargo:rerun-if-changed={}", path);
+}
+
+/// Writes a line telling Cargo to rerun the build script if the environment
+/// variable `var` changes.
+///
+/// This looks like: `cargo:rerun-if-env-changed=VAR`
+///
+/// This requires at least cargo 0.21.0, corresponding to rustc 1.20.0. Earlier
+/// versions of cargo will simply ignore the directive.
+pub fn rerun_env(var: &str) {
+ println!("cargo:rerun-if-env-changed={}", var);
+}
+
+/// Create a new `AutoCfg` instance.
+///
+/// # Panics
+///
+/// Panics if `AutoCfg::new()` returns an error.
+pub fn new() -> AutoCfg {
+ AutoCfg::new().unwrap()
+}
+
+impl AutoCfg {
+ /// Create a new `AutoCfg` instance.
+ ///
+ /// # Common errors
+ ///
+ /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
+ /// - The version output from `rustc` can't be parsed.
+ /// - `OUT_DIR` is not set in the environment, or is not a writable directory.
+ ///
+ pub fn new() -> Result<Self, Error> {
+ match env::var_os("OUT_DIR") {
+ Some(d) => Self::with_dir(d),
+ None => Err(error::from_str("no OUT_DIR specified!")),
+ }
+ }
+
+ /// Create a new `AutoCfg` instance with the specified output directory.
+ ///
+ /// # Common errors
+ ///
+ /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
+ /// - The version output from `rustc` can't be parsed.
+ /// - `dir` is not a writable directory.
+ ///
+ pub fn with_dir<T: Into<PathBuf>>(dir: T) -> Result<Self, Error> {
+ let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
+ let rustc: PathBuf = rustc.into();
+ let rustc_version = try!(Version::from_rustc(&rustc));
+
+ let target = env::var_os("TARGET");
+
+ // Sanity check the output directory
+ let dir = dir.into();
+ let meta = try!(fs::metadata(&dir).map_err(error::from_io));
+ if !meta.is_dir() || meta.permissions().readonly() {
+ return Err(error::from_str("output path is not a writable directory"));
+ }
+
+ let mut ac = AutoCfg {
+ rustflags: rustflags(&target, &dir),
+ out_dir: dir,
+ rustc: rustc,
+ rustc_version: rustc_version,
+ target: target,
+ no_std: false,
+ };
+
+ // Sanity check with and without `std`.
+ if !ac.probe("").unwrap_or(false) {
+ ac.no_std = true;
+ if !ac.probe("").unwrap_or(false) {
+ // Neither worked, so assume nothing...
+ ac.no_std = false;
+ let warning = b"warning: autocfg could not probe for `std`\n";
+ stderr().write_all(warning).ok();
+ }
+ }
+ Ok(ac)
+ }
+
+ /// Test whether the current `rustc` reports a version greater than
+ /// or equal to "`major`.`minor`".
+ pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool {
+ self.rustc_version >= Version::new(major, minor, 0)
+ }
+
+ /// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`,
+ /// if the current `rustc` is at least that version.
+ pub fn emit_rustc_version(&self, major: usize, minor: usize) {
+ if self.probe_rustc_version(major, minor) {
+ emit(&format!("rustc_{}_{}", major, minor));
+ }
+ }
+
+ fn probe<T: AsRef<[u8]>>(&self, code: T) -> Result<bool, Error> {
+ #[allow(deprecated)]
+ static ID: AtomicUsize = ATOMIC_USIZE_INIT;
+
+ let id = ID.fetch_add(1, Ordering::Relaxed);
+ let mut command = Command::new(&self.rustc);
+ command
+ .arg("--crate-name")
+ .arg(format!("probe{}", id))
+ .arg("--crate-type=lib")
+ .arg("--out-dir")
+ .arg(&self.out_dir)
+ .arg("--emit=llvm-ir");
+
+ if let Some(target) = self.target.as_ref() {
+ command.arg("--target").arg(target);
+ }
+
+ command.args(&self.rustflags);
+
+ // Mozilla-local change: throw away stderr output.
+ //
+ // Mozilla's build system runs cargo with `-v -v` to help diagnose rustc
+ // selection problems. Without the change below, that causes error
+ // messages from autocfg compiler invocations (which simply indicate
+ // that the feature autocfg was checking for isn't available, and are
+ // not actual build errors) to show up in the build output stream, where
+ // they confuse other parts of Mozilla's build system that try to
+ // highlight and track errors.
+ //
+ // See: https://github.com/cuviper/autocfg/issues/30
+ command.arg("-").stdin(Stdio::piped()).stderr(Stdio::null());
+ let mut child = try!(command.spawn().map_err(error::from_io));
+ let mut stdin = child.stdin.take().expect("rustc stdin");
+
+ if self.no_std {
+ try!(stdin.write_all(b"#![no_std]\n").map_err(error::from_io));
+ }
+ try!(stdin.write_all(code.as_ref()).map_err(error::from_io));
+ drop(stdin);
+
+ let status = try!(child.wait().map_err(error::from_io));
+ Ok(status.success())
+ }
+
+ /// Tests whether the given sysroot crate can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// extern crate CRATE as probe;
+ /// ```
+ pub fn probe_sysroot_crate(&self, name: &str) -> bool {
+ self.probe(format!("extern crate {} as probe;", name)) // `as _` wasn't stabilized until Rust 1.33
+ .unwrap_or(false)
+ }
+
+ /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true.
+ pub fn emit_sysroot_crate(&self, name: &str) {
+ if self.probe_sysroot_crate(name) {
+ emit(&format!("has_{}", mangle(name)));
+ }
+ }
+
+ /// Tests whether the given path can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub use PATH;
+ /// ```
+ pub fn probe_path(&self, path: &str) -> bool {
+ self.probe(format!("pub use {};", path)).unwrap_or(false)
+ }
+
+ /// Emits a config value `has_PATH` if `probe_path` returns true.
+ ///
+ /// Any non-identifier characters in the `path` will be replaced with
+ /// `_` in the generated config value.
+ pub fn emit_has_path(&self, path: &str) {
+ if self.probe_path(path) {
+ emit(&format!("has_{}", mangle(path)));
+ }
+ }
+
+ /// Emits the given `cfg` value if `probe_path` returns true.
+ pub fn emit_path_cfg(&self, path: &str, cfg: &str) {
+ if self.probe_path(path) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given trait can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub trait Probe: TRAIT + Sized {}
+ /// ```
+ pub fn probe_trait(&self, name: &str) -> bool {
+ self.probe(format!("pub trait Probe: {} + Sized {{}}", name))
+ .unwrap_or(false)
+ }
+
+ /// Emits a config value `has_TRAIT` if `probe_trait` returns true.
+ ///
+ /// Any non-identifier characters in the trait `name` will be replaced with
+ /// `_` in the generated config value.
+ pub fn emit_has_trait(&self, name: &str) {
+ if self.probe_trait(name) {
+ emit(&format!("has_{}", mangle(name)));
+ }
+ }
+
+ /// Emits the given `cfg` value if `probe_trait` returns true.
+ pub fn emit_trait_cfg(&self, name: &str, cfg: &str) {
+ if self.probe_trait(name) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given type can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub type Probe = TYPE;
+ /// ```
+ pub fn probe_type(&self, name: &str) -> bool {
+ self.probe(format!("pub type Probe = {};", name))
+ .unwrap_or(false)
+ }
+
+ /// Emits a config value `has_TYPE` if `probe_type` returns true.
+ ///
+ /// Any non-identifier characters in the type `name` will be replaced with
+ /// `_` in the generated config value.
+ pub fn emit_has_type(&self, name: &str) {
+ if self.probe_type(name) {
+ emit(&format!("has_{}", mangle(name)));
+ }
+ }
+
+ /// Emits the given `cfg` value if `probe_type` returns true.
+ pub fn emit_type_cfg(&self, name: &str, cfg: &str) {
+ if self.probe_type(name) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given expression can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub fn probe() { let _ = EXPR; }
+ /// ```
+ pub fn probe_expression(&self, expr: &str) -> bool {
+ self.probe(format!("pub fn probe() {{ let _ = {}; }}", expr))
+ .unwrap_or(false)
+ }
+
+ /// Emits the given `cfg` value if `probe_expression` returns true.
+ pub fn emit_expression_cfg(&self, expr: &str, cfg: &str) {
+ if self.probe_expression(expr) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given constant expression can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub const PROBE: () = ((), EXPR).0;
+ /// ```
+ pub fn probe_constant(&self, expr: &str) -> bool {
+ self.probe(format!("pub const PROBE: () = ((), {}).0;", expr))
+ .unwrap_or(false)
+ }
+
+ /// Emits the given `cfg` value if `probe_constant` returns true.
+ pub fn emit_constant_cfg(&self, expr: &str, cfg: &str) {
+ if self.probe_constant(expr) {
+ emit(cfg);
+ }
+ }
+}
+
+fn mangle(s: &str) -> String {
+ s.chars()
+ .map(|c| match c {
+ 'A'...'Z' | 'a'...'z' | '0'...'9' => c,
+ _ => '_',
+ })
+ .collect()
+}
+
+fn dir_contains_target(
+ target: &Option<OsString>,
+ dir: &Path,
+ cargo_target_dir: Option<OsString>,
+) -> bool {
+ target
+ .as_ref()
+ .and_then(|target| {
+ dir.to_str().and_then(|dir| {
+ let mut cargo_target_dir = cargo_target_dir
+ .map(PathBuf::from)
+ .unwrap_or_else(|| PathBuf::from("target"));
+ cargo_target_dir.push(target);
+
+ cargo_target_dir
+ .to_str()
+ .map(|cargo_target_dir| dir.contains(&cargo_target_dir))
+ })
+ })
+ .unwrap_or(false)
+}
+
+fn rustflags(target: &Option<OsString>, dir: &Path) -> Vec<String> {
+ // Starting with rust-lang/cargo#9601, shipped in Rust 1.55, Cargo always sets
+ // CARGO_ENCODED_RUSTFLAGS for any host/target build script invocation. This
+ // includes any source of flags, whether from the environment, toml config, or
+ // whatever may come in the future. The value is either an empty string, or a
+ // list of arguments separated by the ASCII unit separator (US), 0x1f.
+ if let Ok(a) = env::var("CARGO_ENCODED_RUSTFLAGS") {
+ return if a.is_empty() {
+ Vec::new()
+ } else {
+ a.split('\x1f').map(str::to_string).collect()
+ };
+ }
+
+ // Otherwise, we have to take a more heuristic approach, and we don't
+ // support values from toml config at all.
+ //
+ // Cargo only applies RUSTFLAGS for building TARGET artifact in
+ // cross-compilation environment. Sadly, we don't have a way to detect
+ // when we're building HOST artifact in a cross-compilation environment,
+ // so for now we only apply RUSTFLAGS when cross-compiling an artifact.
+ //
+ // See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030.
+ if *target != env::var_os("HOST")
+ || dir_contains_target(target, dir, env::var_os("CARGO_TARGET_DIR"))
+ {
+ if let Ok(rustflags) = env::var("RUSTFLAGS") {
+ // This is meant to match how cargo handles the RUSTFLAGS environment variable.
+ // See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441
+ return rustflags
+ .split(' ')
+ .map(str::trim)
+ .filter(|s| !s.is_empty())
+ .map(str::to_string)
+ .collect();
+ }
+ }
+
+ Vec::new()
+}
diff --git a/third_party/rust/autocfg/src/tests.rs b/third_party/rust/autocfg/src/tests.rs
new file mode 100644
index 0000000000..d3b1fbb9e9
--- /dev/null
+++ b/third_party/rust/autocfg/src/tests.rs
@@ -0,0 +1,174 @@
+use super::AutoCfg;
+use std::env;
+use std::path::Path;
+
+impl AutoCfg {
+ fn core_std(&self, path: &str) -> String {
+ let krate = if self.no_std { "core" } else { "std" };
+ format!("{}::{}", krate, path)
+ }
+
+ fn assert_std(&self, probe_result: bool) {
+ assert_eq!(!self.no_std, probe_result);
+ }
+
+ fn assert_min(&self, major: usize, minor: usize, probe_result: bool) {
+ assert_eq!(self.probe_rustc_version(major, minor), probe_result);
+ }
+
+ fn for_test() -> Result<Self, super::error::Error> {
+ match env::var_os("TESTS_TARGET_DIR") {
+ Some(d) => Self::with_dir(d),
+ None => Self::with_dir("target"),
+ }
+ }
+}
+
+#[test]
+fn autocfg_version() {
+ let ac = AutoCfg::for_test().unwrap();
+ println!("version: {:?}", ac.rustc_version);
+ assert!(ac.probe_rustc_version(1, 0));
+}
+
+#[test]
+fn version_cmp() {
+ use super::version::Version;
+ let v123 = Version::new(1, 2, 3);
+
+ assert!(Version::new(1, 0, 0) < v123);
+ assert!(Version::new(1, 2, 2) < v123);
+ assert!(Version::new(1, 2, 3) == v123);
+ assert!(Version::new(1, 2, 4) > v123);
+ assert!(Version::new(1, 10, 0) > v123);
+ assert!(Version::new(2, 0, 0) > v123);
+}
+
+#[test]
+fn probe_add() {
+ let ac = AutoCfg::for_test().unwrap();
+ let add = ac.core_std("ops::Add");
+ let add_rhs = add.clone() + "<i32>";
+ let add_rhs_output = add.clone() + "<i32, Output = i32>";
+ let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output;
+ assert!(ac.probe_path(&add));
+ assert!(ac.probe_trait(&add));
+ assert!(ac.probe_trait(&add_rhs));
+ assert!(ac.probe_trait(&add_rhs_output));
+ ac.assert_min(1, 27, ac.probe_type(&dyn_add_rhs_output));
+}
+
+#[test]
+fn probe_as_ref() {
+ let ac = AutoCfg::for_test().unwrap();
+ let as_ref = ac.core_std("convert::AsRef");
+ let as_ref_str = as_ref.clone() + "<str>";
+ let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str;
+ assert!(ac.probe_path(&as_ref));
+ assert!(ac.probe_trait(&as_ref_str));
+ assert!(ac.probe_type(&as_ref_str));
+ ac.assert_min(1, 27, ac.probe_type(&dyn_as_ref_str));
+}
+
+#[test]
+fn probe_i128() {
+ let ac = AutoCfg::for_test().unwrap();
+ let i128_path = ac.core_std("i128");
+ ac.assert_min(1, 26, ac.probe_path(&i128_path));
+ ac.assert_min(1, 26, ac.probe_type("i128"));
+}
+
+#[test]
+fn probe_sum() {
+ let ac = AutoCfg::for_test().unwrap();
+ let sum = ac.core_std("iter::Sum");
+ let sum_i32 = sum.clone() + "<i32>";
+ let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32;
+ ac.assert_min(1, 12, ac.probe_path(&sum));
+ ac.assert_min(1, 12, ac.probe_trait(&sum));
+ ac.assert_min(1, 12, ac.probe_trait(&sum_i32));
+ ac.assert_min(1, 12, ac.probe_type(&sum_i32));
+ ac.assert_min(1, 27, ac.probe_type(&dyn_sum_i32));
+}
+
+#[test]
+fn probe_std() {
+ let ac = AutoCfg::for_test().unwrap();
+ ac.assert_std(ac.probe_sysroot_crate("std"));
+}
+
+#[test]
+fn probe_alloc() {
+ let ac = AutoCfg::for_test().unwrap();
+ ac.assert_min(1, 36, ac.probe_sysroot_crate("alloc"));
+}
+
+#[test]
+fn probe_bad_sysroot_crate() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(!ac.probe_sysroot_crate("doesnt_exist"));
+}
+
+#[test]
+fn probe_no_std() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(ac.probe_type("i32"));
+ assert!(ac.probe_type("[i32]"));
+ ac.assert_std(ac.probe_type("Vec<i32>"));
+}
+
+#[test]
+fn probe_expression() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(ac.probe_expression(r#""test".trim_left()"#));
+ ac.assert_min(1, 30, ac.probe_expression(r#""test".trim_start()"#));
+ ac.assert_std(ac.probe_expression("[1, 2, 3].to_vec()"));
+}
+
+#[test]
+fn probe_constant() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(ac.probe_constant("1 + 2 + 3"));
+ ac.assert_min(1, 33, ac.probe_constant("{ let x = 1 + 2 + 3; x * x }"));
+ ac.assert_min(1, 39, ac.probe_constant(r#""test".len()"#));
+}
+
+#[test]
+fn dir_does_not_contain_target() {
+ assert!(!super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new("/project/target/debug/build/project-ea75983148559682/out"),
+ None,
+ ));
+}
+
+#[test]
+fn dir_does_contain_target() {
+ assert!(super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new(
+ "/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
+ ),
+ None,
+ ));
+}
+
+#[test]
+fn dir_does_not_contain_target_with_custom_target_dir() {
+ assert!(!super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new("/project/custom/debug/build/project-ea75983148559682/out"),
+ Some("custom".into()),
+ ));
+}
+
+#[test]
+fn dir_does_contain_target_with_custom_target_dir() {
+ assert!(super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new(
+ "/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
+ ),
+ Some("custom".into()),
+ ));
+}
diff --git a/third_party/rust/autocfg/src/version.rs b/third_party/rust/autocfg/src/version.rs
new file mode 100644
index 0000000000..378c21e61e
--- /dev/null
+++ b/third_party/rust/autocfg/src/version.rs
@@ -0,0 +1,60 @@
+use std::path::Path;
+use std::process::Command;
+use std::str;
+
+use super::{error, Error};
+
+/// A version structure for making relative comparisons.
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Version {
+ major: usize,
+ minor: usize,
+ patch: usize,
+}
+
+impl Version {
+ /// Creates a `Version` instance for a specific `major.minor.patch` version.
+ pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+ Version {
+ major: major,
+ minor: minor,
+ patch: patch,
+ }
+ }
+
+ pub fn from_rustc(rustc: &Path) -> Result<Self, Error> {
+ // Get rustc's verbose version
+ let output = try!(Command::new(rustc)
+ .args(&["--version", "--verbose"])
+ .output()
+ .map_err(error::from_io));
+ if !output.status.success() {
+ return Err(error::from_str("could not execute rustc"));
+ }
+ let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8));
+
+ // Find the release line in the verbose version output.
+ let release = match output.lines().find(|line| line.starts_with("release: ")) {
+ Some(line) => &line["release: ".len()..],
+ None => return Err(error::from_str("could not find rustc release")),
+ };
+
+ // Strip off any extra channel info, e.g. "-beta.N", "-nightly"
+ let version = match release.find('-') {
+ Some(i) => &release[..i],
+ None => release,
+ };
+
+ // Split the version into semver components.
+ let mut iter = version.splitn(3, '.');
+ let major = try!(iter.next().ok_or(error::from_str("missing major version")));
+ let minor = try!(iter.next().ok_or(error::from_str("missing minor version")));
+ let patch = try!(iter.next().ok_or(error::from_str("missing patch version")));
+
+ Ok(Version::new(
+ try!(major.parse().map_err(error::from_num)),
+ try!(minor.parse().map_err(error::from_num)),
+ try!(patch.parse().map_err(error::from_num)),
+ ))
+ }
+}
diff --git a/third_party/rust/autocfg/tests/rustflags.rs b/third_party/rust/autocfg/tests/rustflags.rs
new file mode 100644
index 0000000000..f054546681
--- /dev/null
+++ b/third_party/rust/autocfg/tests/rustflags.rs
@@ -0,0 +1,33 @@
+extern crate autocfg;
+
+use std::env;
+
+/// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS
+/// environment variables when running rustc.
+#[test]
+fn test_with_sysroot() {
+ // Use the same path as this test binary.
+ let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
+ env::set_var("OUT_DIR", &format!("{}", dir.display()));
+
+ // If we have encoded rustflags, they take precedence, even if empty.
+ env::set_var("CARGO_ENCODED_RUSTFLAGS", "");
+ env::set_var("RUSTFLAGS", &format!("-L {}", dir.display()));
+ let ac = autocfg::AutoCfg::new().unwrap();
+ assert!(ac.probe_sysroot_crate("std"));
+ assert!(!ac.probe_sysroot_crate("autocfg"));
+
+ // Now try again with useful encoded args.
+ env::set_var(
+ "CARGO_ENCODED_RUSTFLAGS",
+ &format!("-L\x1f{}", dir.display()),
+ );
+ let ac = autocfg::AutoCfg::new().unwrap();
+ assert!(ac.probe_sysroot_crate("autocfg"));
+
+ // Try the old-style RUSTFLAGS, ensuring HOST != TARGET.
+ env::remove_var("CARGO_ENCODED_RUSTFLAGS");
+ env::set_var("HOST", "lol");
+ let ac = autocfg::AutoCfg::new().unwrap();
+ assert!(ac.probe_sysroot_crate("autocfg"));
+}