resolved upstream merge conflicts

This commit is contained in:
Brad Gibson 2018-07-29 20:03:15 -07:00
commit 56016cb1e0
4255 changed files with 114117 additions and 91403 deletions

3
.gitattributes vendored
View File

@ -4,7 +4,8 @@
*.cpp rust
*.h rust
*.rs rust
*.fixed linguist-language=Rust
src/etc/installer/gfx/* binary
*.woff binary
src/vendor/** -text
Cargo.lock -merge
Cargo.lock -merge linguist-generated=false

21
.gitignore vendored
View File

@ -74,27 +74,30 @@ __pycache__/
/obj/
/rt/
/rustllvm/
/src/libstd_unicode/DerivedCoreProperties.txt
/src/libstd_unicode/DerivedNormalizationProps.txt
/src/libstd_unicode/PropList.txt
/src/libstd_unicode/ReadMe.txt
/src/libstd_unicode/Scripts.txt
/src/libstd_unicode/SpecialCasing.txt
/src/libstd_unicode/UnicodeData.txt
/src/libcore/unicode/DerivedCoreProperties.txt
/src/libcore/unicode/DerivedNormalizationProps.txt
/src/libcore/unicode/PropList.txt
/src/libcore/unicode/ReadMe.txt
/src/libcore/unicode/Scripts.txt
/src/libcore/unicode/SpecialCasing.txt
/src/libcore/unicode/UnicodeData.txt
/stage[0-9]+/
/target
target/
/test/
/tmp/
tags
tags.*
TAGS
TAGS.emacs
TAGS.vi
TAGS.*
\#*
\#*\#
config.mk
config.stamp
keywords.md
lexer.ml
mir_dump
Session.vim
src/etc/dl
tmp.*.rs
version.md

3
.gitmodules vendored
View File

@ -53,3 +53,6 @@
[submodule "src/tools/lld"]
path = src/tools/lld
url = https://github.com/rust-lang/lld.git
[submodule "src/libbacktrace"]
path = src/libbacktrace
url = https://github.com/rust-lang-nursery/libbacktrace

View File

@ -51,6 +51,7 @@ Carol Willing <carolcode@willingconsulting.com>
Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
Chris Pressey <cpressey@gmail.com>
Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com>
Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
Clinton Ryan <clint.ryan3@gmail.com>
Corey Richardson <corey@octayn.net> Elaine "See More" Nemo <corey@octayn.net>

View File

@ -3,6 +3,10 @@ sudo: required
dist: trusty
services:
- docker
addons:
apt:
packages:
- gdb
git:
depth: 2
@ -12,7 +16,7 @@ matrix:
fast_finish: true
include:
# Images used in testing PR and try-build should be run first.
- env: IMAGE=x86_64-gnu-llvm-3.9 RUST_BACKTRACE=1
- env: IMAGE=x86_64-gnu-llvm-5.0 RUST_BACKTRACE=1
if: type = pull_request OR branch = auto
- env: IMAGE=dist-x86_64-linux DEPLOY=1
@ -169,7 +173,7 @@ matrix:
- env: IMAGE=x86_64-gnu-aux
if: branch = auto
- env: IMAGE=x86_64-gnu-tools
if: branch = auto
if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri)\b)/)
- env: IMAGE=x86_64-gnu-debug
if: branch = auto
- env: IMAGE=x86_64-gnu-nopt
@ -197,7 +201,7 @@ env:
# AWS_SECRET_ACCESS_KEY=...
- secure: "j96XxTVOSUf4s4r4htIxn/fvIa5DWbMgLqWl7r8z2QfgUwscmkMXAwXuFNc7s7bGTpV/+CgDiMFFM6BAFLGKutytIF6oA02s9b+usQYnM0th7YQ2AIgm9GtMTJCJp4AoyfFmh8F2faUICBZlfVLUJ34udHEe35vOklix+0k4WDo="
# TOOLSTATE_REPO_ACCESS_TOKEN=...
- secure: "cFh8thThqEJLC98XKI5pfqflUzOlxsYPRW20AWRaYOOgYHPTiGWypTXiPbGSKaeAXTZoOA+DpQtEmefc0U6lt9dHc7a/MIaK6isFurjlnKYiLOeTruzyu1z7PWCeZ/jKXsU2RK/88DBtlNwfMdaMIeuKj14IVfpepPPL71ETbuk="
- secure: "ESfcXqv4N2VMhqi2iIyw6da9VrsA78I4iR1asouCaq4hzTTrkB4WNRrfURy6xg72gQ4nMhtRJbB0/2jmc9Cu1+g2CzXtyiL223aJ5CKrXdcvbitopQSDfp07dMWm+UED+hNFEanpErKAeU/6FM3A+J+60PMk8MCF1h9tqNRISJw="
before_install:
# We'll use the AWS cli to download/upload cached docker layers, so install
@ -230,7 +234,11 @@ install:
travis_retry curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin &&
chmod +x /usr/local/bin/sccache &&
travis_retry curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
chmod +x /usr/local/bin/stamp
chmod +x /usr/local/bin/stamp &&
travis_retry curl -f http://releases.llvm.org/6.0.0/clang+llvm-6.0.0-x86_64-apple-darwin.tar.xz | tar xJf - &&
export CC=`pwd`/clang+llvm-6.0.0-x86_64-apple-darwin/bin/clang &&
export CXX=`pwd`/clang+llvm-6.0.0-x86_64-apple-darwin/bin/clang++ &&
export AR=ar
;;
esac
@ -245,6 +253,8 @@ before_script:
export RUN_SCRIPT="$RUN_SCRIPT && src/ci/run.sh";
else
export RUN_SCRIPT="$RUN_SCRIPT && src/ci/docker/run.sh $IMAGE";
# Enable core dump on Linux.
sudo sh -c 'echo "/checkout/obj/cores/core.%p.%E" > /proc/sys/kernel/core_pattern';
fi
# Log time information from this machine and an external machine for insight into possible
@ -270,6 +280,8 @@ after_failure:
# Random attempt at debugging currently. Just poking around in here to see if
# anything shows up.
# Dump backtrace for macOS
- ls -lat $HOME/Library/Logs/DiagnosticReports/
- find $HOME/Library/Logs/DiagnosticReports
-type f
@ -280,6 +292,25 @@ after_failure:
-exec head -750 {} \;
-exec echo travis_fold":"end:crashlog \; || true
# Dump backtrace for Linux
- ln -s . checkout &&
for CORE in obj/cores/core.*; do
EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|');
if [ -f "$EXE" ]; then
printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE";
gdb -q -c "$CORE" "$EXE"
-iex 'set auto-load off'
-iex 'dir src/'
-iex 'set sysroot .'
-ex bt
-ex q;
echo travis_fold":"end:crashlog;
fi;
done || true
# see #50887
- cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
# attempt to debug anything killed by the oom killer on linux, just to see if
# it happened
- dmesg | grep -i kill
@ -297,7 +328,6 @@ before_deploy:
rm -rf obj/build/dist/doc &&
cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
fi
- travis_retry gem update --system
- ls -la deploy/$TRAVIS_COMMIT
deploy:

View File

@ -48,7 +48,7 @@ always work, and sometimes it's hard to know what to search for, so consider thi
extra credit. We won't mind if you accidentally file a duplicate report.
Similarly, to help others who encountered the bug find your issue,
consider filing an issue with with a descriptive title, which contains information that might be unique to it.
consider filing an issue with a descriptive title, which contains information that might be unique to it.
This can be the language or compiler feature used, the conditions that trigger the bug,
or part of the error message if there is any.
An example could be: **"impossible case reached" on lifetime inference for impl Trait in return position**.
@ -142,7 +142,7 @@ file. If you still have a `config.mk` file in your directory - from
### Building
[building]: #building
A default configuration shall use around 3.5 GB of disk space, whereas building a debug configuration may require more than 30 GB.
A default configuration requires around 3.5 GB of disk space, whereas building a debug configuration may require more than 30 GB.
Dependencies
- [build dependencies](README.md#building-from-source)

View File

@ -38,6 +38,7 @@ Read ["Installation"] from [The Book].
3. Build and install:
```sh
$ git submodule update --init --recursive --progress
$ ./x.py build && sudo ./x.py install
```
@ -119,7 +120,7 @@ shell with:
> python x.py build
```
Currently building Rust only works with some known versions of Visual Studio. If
Currently, building Rust only works with some known versions of Visual Studio. If
you have a more recent version installed the build system doesn't understand
then you may need to force rustbuild to use an older version. This can be done
by manually calling the appropriate vcvars file before running the bootstrap.
@ -133,7 +134,7 @@ python x.py build
[specifying-an-abi]: #specifying-an-abi
Each specific ABI can also be used from either environment (for example, using
the GNU ABI in powershell) by using an explicit build triple. The available
the GNU ABI in PowerShell) by using an explicit build triple. The available
Windows build triples are:
- GNU ABI (using GCC)
- `i686-pc-windows-gnu`
@ -179,7 +180,7 @@ the ABI used. I.e., if the ABI was `x86_64-pc-windows-msvc`, the directory will
[notes]: #notes
Since the Rust compiler is written in Rust, it must be built by a
precompiled "snapshot" version of itself (made in an earlier state of
precompiled "snapshot" version of itself (made in an earlier stage of
development). As such, source builds require a connection to the Internet, to
fetch snapshots, and an OS that can execute the available snapshot binaries.
@ -224,13 +225,16 @@ variety of channels on Mozilla's IRC network, irc.mozilla.org. The
most popular channel is [#rust], a venue for general discussion about
Rust. And a good place to ask for help would be [#rust-beginners].
Also, the [rustc guide] might be a good place to start if you want to
find out how various parts of the compiler work.
The [rustc guide] might be a good place to start if you want to find out how
various parts of the compiler work.
Also, you may find the [rustdocs for the compiler itself][rustdocs] useful.
[IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
[#rust]: irc://irc.mozilla.org/rust
[#rust-beginners]: irc://irc.mozilla.org/rust-beginners
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html
[rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
## License
[license]: #license

View File

@ -1,9 +1,581 @@
Version 1.28.0 (2018-08-02)
===========================
Language
--------
- [The `#[repr(transparent)]` attribute is now stable.][51562] This attribute
allows a Rust newtype wrapper (`struct NewType<T>(T);`) to be represented as
the inner type across Foreign Function Interface (FFI) boundaries.
- [The keywords `pure`, `sizeof`, `alignof`, and `offsetof` have been unreserved
and can now be used as identifiers.][51196]
- [The `GlobalAlloc` trait and `#[global_allocator]` attribute are now
stable.][51241] This will allow users to specify a global allocator for
their program.
- [Unit test functions marked with the `#[test]` attribute can now return
`Result<(), E: Debug>` in addition to `()`.][51298]
- [The `lifetime` specifier for `macro_rules!` is now stable.][50385] This
allows macros to easily target lifetimes.
Compiler
--------
- [The `s` and `z` optimisation levels are now stable.][50265] These optimisations
prioritise making smaller binary sizes. `z` is the same as `s` with the
exception that it does not vectorise loops, which typically results in an even
smaller binary.
- [The short error format is now stable.][49546] Specified with
`--error-format=short` this option will provide a more compressed output of
rust error messages.
- [Added a lint warning when you have duplicated `macro_export`s.][50143]
- [Reduced the number of allocations in the macro parser.][50855] This can
improve compile times of macro heavy crates on average by 5%.
Libraries
---------
- [Implemented `Default` for `&mut str`.][51306]
- [Implemented `From<bool>` for all integer and unsigned number types.][50554]
- [Implemented `Extend` for `()`.][50234]
- [The `Debug` implementation of `time::Duration` should now be more easily
human readable.][50364] Previously a `Duration` of one second would printed as
`Duration { secs: 1, nanos: 0 }` and will now be printed as `1s`.
- [Implemented `From<&String>` for `Cow<str>`, `From<&Vec<T>>` for `Cow<[T]>`,
`From<Cow<CStr>>` for `CString`, `From<CString>, From<CStr>, From<&CString>`
for `Cow<CStr>`, `From<OsString>, From<OsStr>, From<&OsString>` for
`Cow<OsStr>`, `From<&PathBuf>` for `Cow<Path>`, and `From<Cow<Path>>`
for `PathBuf`.][50170]
- [Implemented `Shl` and `Shr` for `Wrapping<u128>`
and `Wrapping<i128>`.][50465]
- [`DirEntry::metadata` now uses `fstatat` instead of `lstat` when
possible.][51050] This can provide up to a 40% speed increase.
- [Improved error messages when using `format!`.][50610]
Stabilized APIs
---------------
- [`Iterator::step_by`]
- [`Path::ancestors`]
- [`SystemTime::UNIX_EPOCH`]
- [`alloc::GlobalAlloc`]
- [`alloc::Layout`]
- [`alloc::LayoutErr`]
- [`alloc::System`]
- [`alloc::alloc`]
- [`alloc::alloc_zeroed`]
- [`alloc::dealloc`]
- [`alloc::realloc`]
- [`alloc::handle_alloc_error`]
- [`btree_map::Entry::or_default`]
- [`fmt::Alignment`]
- [`hash_map::Entry::or_default`]
- [`iter::repeat_with`]
- [`num::NonZeroUsize`]
- [`num::NonZeroU128`]
- [`num::NonZeroU16`]
- [`num::NonZeroU32`]
- [`num::NonZeroU64`]
- [`num::NonZeroU8`]
- [`ops::RangeBounds`]
- [`slice::SliceIndex`]
- [`slice::from_mut`]
- [`slice::from_ref`]
- [`{Any + Send + Sync}::downcast_mut`]
- [`{Any + Send + Sync}::downcast_ref`]
- [`{Any + Send + Sync}::is`]
Cargo
-----
- [Cargo will now no longer allow you to publish crates with build scripts that
modify the `src` directory.][cargo/5584] The `src` directory in a crate should be
considered to be immutable.
Misc
----
- [The `suggestion_applicability` field in `rustc`'s json output is now
stable.][50486] This will allow dev tools to check whether a code suggestion
would apply to them.
Compatibility Notes
-------------------
- [Rust will no longer consider trait objects with duplicated constraints to
have implementations.][51276] For example the below code will now fail
to compile.
```rust
trait Trait {}
impl Trait + Send {
fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
}
impl Trait + Send + Send {
fn test(&self) { println!("two"); }
}
```
[49546]: https://github.com/rust-lang/rust/pull/49546/
[50143]: https://github.com/rust-lang/rust/pull/50143/
[50170]: https://github.com/rust-lang/rust/pull/50170/
[50234]: https://github.com/rust-lang/rust/pull/50234/
[50265]: https://github.com/rust-lang/rust/pull/50265/
[50364]: https://github.com/rust-lang/rust/pull/50364/
[50385]: https://github.com/rust-lang/rust/pull/50385/
[50465]: https://github.com/rust-lang/rust/pull/50465/
[50486]: https://github.com/rust-lang/rust/pull/50486/
[50554]: https://github.com/rust-lang/rust/pull/50554/
[50610]: https://github.com/rust-lang/rust/pull/50610/
[50855]: https://github.com/rust-lang/rust/pull/50855/
[51050]: https://github.com/rust-lang/rust/pull/51050/
[51196]: https://github.com/rust-lang/rust/pull/51196/
[51200]: https://github.com/rust-lang/rust/pull/51200/
[51241]: https://github.com/rust-lang/rust/pull/51241/
[51276]: https://github.com/rust-lang/rust/pull/51276/
[51298]: https://github.com/rust-lang/rust/pull/51298/
[51306]: https://github.com/rust-lang/rust/pull/51306/
[51562]: https://github.com/rust-lang/rust/pull/51562/
[cargo/5584]: https://github.com/rust-lang/cargo/pull/5584/
[`Iterator::step_by`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.step_by
[`Path::ancestors`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.ancestors
[`SystemTime::UNIX_EPOCH`]: https://doc.rust-lang.org/std/time/struct.SystemTime.html#associatedconstant.UNIX_EPOCH
[`alloc::GlobalAlloc`]: https://doc.rust-lang.org/std/alloc/trait.GlobalAlloc.html
[`alloc::Layout`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html
[`alloc::LayoutErr`]: https://doc.rust-lang.org/std/alloc/struct.LayoutErr.html
[`alloc::System`]: https://doc.rust-lang.org/std/alloc/struct.System.html
[`alloc::alloc`]: https://doc.rust-lang.org/std/alloc/fn.alloc.html
[`alloc::alloc_zeroed`]: https://doc.rust-lang.org/std/alloc/fn.alloc_zeroed.html
[`alloc::dealloc`]: https://doc.rust-lang.org/std/alloc/fn.dealloc.html
[`alloc::realloc`]: https://doc.rust-lang.org/std/alloc/fn.realloc.html
[`alloc::handle_alloc_error`]: https://doc.rust-lang.org/std/alloc/fn.handle_alloc_error.html
[`btree_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default
[`fmt::Alignment`]: https://doc.rust-lang.org/std/fmt/enum.Alignment.html
[`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default
[`iter::repeat_with`]: https://doc.rust-lang.org/std/iter/fn.repeat_with.html
[`num::NonZeroUsize`]: https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html
[`num::NonZeroU128`]: https://doc.rust-lang.org/std/num/struct.NonZeroU128.html
[`num::NonZeroU16`]: https://doc.rust-lang.org/std/num/struct.NonZeroU16.html
[`num::NonZeroU32`]: https://doc.rust-lang.org/std/num/struct.NonZeroU32.html
[`num::NonZeroU64`]: https://doc.rust-lang.org/std/num/struct.NonZeroU64.html
[`num::NonZeroU8`]: https://doc.rust-lang.org/std/num/struct.NonZeroU8.html
[`ops::RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html
[`slice::SliceIndex`]: https://doc.rust-lang.org/std/slice/trait.SliceIndex.html
[`slice::from_mut`]: https://doc.rust-lang.org/std/slice/fn.from_mut.html
[`slice::from_ref`]: https://doc.rust-lang.org/std/slice/fn.from_ref.html
[`{Any + Send + Sync}::downcast_mut`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_mut-2
[`{Any + Send + Sync}::downcast_ref`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-2
[`{Any + Send + Sync}::is`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.is-2
Version 1.27.1 (2018-07-10)
===========================
Security Notes
--------------
- rustdoc would execute plugins in the /tmp/rustdoc/plugins directory
when running, which enabled executing code as some other user on a
given machine. This release fixes that vulnerability; you can read
more about this on the [blog][rustdoc-sec]. The associated CVE is [CVE-2018-1000622].
Thank you to Red Hat for responsibily disclosing this vulnerability to us.
Compatibility Notes
-------------------
- The borrow checker was fixed to avoid an additional potential unsoundness when using
match ergonomics: [#51415][51415], [#49534][49534].
[51415]: https://github.com/rust-lang/rust/issues/51415
[49534]: https://github.com/rust-lang/rust/issues/49534
[rustdoc-sec]: https://blog.rust-lang.org/2018/07/06/security-advisory-for-rustdoc.html
[CVE-2018-1000622]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=%20CVE-2018-1000622
Version 1.27.0 (2018-06-21)
==========================
Language
--------
- [Removed 'proc' from the reserved keywords list.][49699] This allows `proc` to
be used as an identifer.
- [The dyn syntax is now available.][49968] This syntax is equivalent to the
bare `Trait` syntax, and should make it clearer when being used in tandem with
`impl Trait`. Since it is equivalent to the following syntax:
`&Trait == &dyn Trait`, `&mut Trait == &mut dyn Trait`, and
`Box<Trait> == Box<dyn Trait>`.
- [Attributes on generic parameters such as types and lifetimes are
now stable.][48851] e.g.
`fn foo<#[lifetime_attr] 'a, #[type_attr] T: 'a>() {}`
- [The `#[must_use]` attribute can now also be used on functions as well as
types.][48925] It provides a lint that by default warns users when the
value returned by a function has not been used.
Compiler
--------
- [Added the `armv5te-unknown-linux-musl` target.][50423]
Libraries
---------
- [SIMD (Single Instruction Multiple Data) on x86/x86_64 is now stable.][49664]
This includes [`arch::x86`] & [`arch::x86_64`] modules which contain
SIMD intrinsics, a new macro called `is_x86_feature_detected!`, the
`#[target_feature(enable="")]` attribute, and adding `target_feature = ""` to
the `cfg` attribute.
- [A lot of methods for `[u8]`, `f32`, and `f64` previously only available in
std are now available in core.][49896]
- [The generic `Rhs` type parameter on `ops::{Shl, ShlAssign, Shr}` now defaults
to `Self`.][49630]
- [`std::str::replace` now has the `#[must_use]` attribute][50177] to clarify
that the operation isn't done in place.
- [`Clone::clone`, `Iterator::collect`, and `ToOwned::to_owned` now have
the `#[must_use]` attribute][49533] to warn about unused potentially
expensive allocations.
Stabilized APIs
---------------
- [`DoubleEndedIterator::rfind`]
- [`DoubleEndedIterator::rfold`]
- [`DoubleEndedIterator::try_rfold`]
- [`Duration::from_micros`]
- [`Duration::from_nanos`]
- [`Duration::subsec_micros`]
- [`Duration::subsec_millis`]
- [`HashMap::remove_entry`]
- [`Iterator::try_fold`]
- [`Iterator::try_for_each`]
- [`NonNull::cast`]
- [`Option::filter`]
- [`String::replace_range`]
- [`Take::set_limit`]
- [`hint::unreachable_unchecked`]
- [`os::unix::process::parent_id`]
- [`ptr::swap_nonoverlapping`]
- [`slice::rsplit_mut`]
- [`slice::rsplit`]
- [`slice::swap_with_slice`]
Cargo
-----
- [`cargo-metadata` now includes `authors`, `categories`, `keywords`,
`readme`, and `repository` fields.][cargo/5386]
- [`cargo-metadata` now includes a package's `metadata` table.][cargo/5360]
- [Added the `--target-dir` optional argument.][cargo/5393] This allows you to specify
a different directory than `target` for placing compilation artifacts.
- [Cargo will be adding automatic target inference for binaries, benchmarks,
examples, and tests in the Rust 2018 edition.][cargo/5335] If your project specifies
specific targets e.g. using `[[bin]]` and have other binaries in locations
where cargo would infer a binary, Cargo will produce a warning. You can
disable this feature ahead of time by setting any of the following `autobins`,
`autobenches`, `autoexamples`, `autotests` to false.
- [Cargo will now cache compiler information.][cargo/5359] This can be disabled by
setting `CARGO_CACHE_RUSTC_INFO=0` in your environment.
Misc
----
- [Added “The Rustc book” into the official documentation.][49707]
[“The Rustc book”] documents and teaches how to use the rustc compiler.
- [All books available on `doc.rust-lang.org` are now searchable.][49623]
Compatibility Notes
-------------------
- [Calling a `CharExt` or `StrExt` method directly on core will no longer
work.][49896] e.g. `::core::prelude::v1::StrExt::is_empty("")` will not
compile, `"".is_empty()` will still compile.
- [`Debug` output on `atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize}`
will only print the inner type.][48553] e.g.
`print!("{:?}", AtomicBool::new(true))` will print `true`
not `AtomicBool(true)`.
- [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you
could enter higher numbers but they were not supported by LLVM. Up to 512MB
alignment should cover all use cases.
[48553]: https://github.com/rust-lang/rust/pull/48553/
[48851]: https://github.com/rust-lang/rust/pull/48851/
[48925]: https://github.com/rust-lang/rust/pull/48925/
[49533]: https://github.com/rust-lang/rust/pull/49533/
[49623]: https://github.com/rust-lang/rust/pull/49623/
[49630]: https://github.com/rust-lang/rust/pull/49630/
[49664]: https://github.com/rust-lang/rust/pull/49664/
[49699]: https://github.com/rust-lang/rust/pull/49699/
[49707]: https://github.com/rust-lang/rust/pull/49707/
[49719]: https://github.com/rust-lang/rust/pull/49719/
[49896]: https://github.com/rust-lang/rust/pull/49896/
[49968]: https://github.com/rust-lang/rust/pull/49968/
[50177]: https://github.com/rust-lang/rust/pull/50177/
[50378]: https://github.com/rust-lang/rust/pull/50378/
[50398]: https://github.com/rust-lang/rust/pull/50398/
[50423]: https://github.com/rust-lang/rust/pull/50423/
[cargo/5203]: https://github.com/rust-lang/cargo/pull/5203/
[cargo/5335]: https://github.com/rust-lang/cargo/pull/5335/
[cargo/5359]: https://github.com/rust-lang/cargo/pull/5359/
[cargo/5360]: https://github.com/rust-lang/cargo/pull/5360/
[cargo/5386]: https://github.com/rust-lang/cargo/pull/5386/
[cargo/5393]: https://github.com/rust-lang/cargo/pull/5393/
[`DoubleEndedIterator::rfind`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.rfind
[`DoubleEndedIterator::rfold`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.rfold
[`DoubleEndedIterator::try_rfold`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.try_rfold
[`Duration::from_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_micros
[`Duration::from_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_nanos
[`Duration::subsec_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_micros
[`Duration::subsec_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_millis
[`HashMap::remove_entry`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.remove_entry
[`Iterator::try_fold`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_fold
[`Iterator::try_for_each`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_for_each
[`NonNull::cast`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.cast
[`Option::filter`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.filter
[`String::replace_range`]: https://doc.rust-lang.org/std/string/struct.String.html#method.replace_range
[`Take::set_limit`]: https://doc.rust-lang.org/std/io/struct.Take.html#method.set_limit
[`hint::unreachable_unchecked`]: https://doc.rust-lang.org/std/hint/fn.unreachable_unchecked.html
[`os::unix::process::parent_id`]: https://doc.rust-lang.org/std/os/unix/process/fn.parent_id.html
[`process::id`]: https://doc.rust-lang.org/std/process/fn.id.html
[`ptr::swap_nonoverlapping`]: https://doc.rust-lang.org/std/ptr/fn.swap_nonoverlapping.html
[`slice::rsplit_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rsplit_mut
[`slice::rsplit`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rsplit
[`slice::swap_with_slice`]: https://doc.rust-lang.org/std/primitive.slice.html#method.swap_with_slice
[`arch::x86_64`]: https://doc.rust-lang.org/std/arch/x86_64/index.html
[`arch::x86`]: https://doc.rust-lang.org/std/arch/x86/index.html
[“The Rustc book”]: https://doc.rust-lang.org/rustc
Version 1.26.2 (2018-06-05)
==========================
Compatibility Notes
-------------------
- [The borrow checker was fixed to avoid unsoundness when using match ergonomics][51117]
[51117]: https://github.com/rust-lang/rust/issues/51117
Version 1.26.1 (2018-05-29)
==========================
Tools
-----
- [RLS now works on Windows][50646]
- [Rustfmt stopped badly formatting text in some cases][rustfmt/2695]
Compatibility Notes
--------
- [`fn main() -> impl Trait` no longer works for non-Termination
trait][50656]
This reverts an accidental stabilization.
- [`NaN > NaN` no longer returns true in const-fn contexts][50812]
- [Prohibit using turbofish for `impl Trait` in method arguments][50950]
[50646]: https://github.com/rust-lang/rust/issues/50646
[50656]: https://github.com/rust-lang/rust/pull/50656
[50812]: https://github.com/rust-lang/rust/pull/50812
[50950]: https://github.com/rust-lang/rust/issues/50950
[rustfmt/2695]: https://github.com/rust-lang-nursery/rustfmt/issues/2695
Version 1.26.0 (2018-05-10)
==========================
Language
--------
- [Closures now implement `Copy` and/or `Clone` if all captured variables
implement either or both traits.][49299]
- [The inclusive range syntax e.g. `for x in 0..=10` is now stable.][47813]
- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere where a
lifetime can be elided.][49458]
- [`impl Trait` is now stable allowing you to have abstract types in returns
or in function parameters.][49255] e.g. `fn foo() -> impl Iterator<Item=u8>` or
`fn open(path: impl AsRef<Path>)`.
- [Pattern matching will now automatically apply dereferences.][49394]
- [128-bit integers in the form of `u128` and `i128` are now stable.][49101]
- [`main` can now return `Result<(), E: Debug>`][49162] in addition to `()`.
- [A lot of operations are now available in a const context.][46882] E.g. You
can now index into constant arrays, reference and dereference into constants,
and use Tuple struct constructors.
- [Fixed entry slice patterns are now stable.][48516] e.g.
```rust
let points = [1, 2, 3, 4];
match points {
[1, 2, 3, 4] => println!("All points were sequential."),
_ => println!("Not all points were sequential."),
}
```
Compiler
--------
- [LLD is now used as the default linker for `wasm32-unknown-unknown`.][48125]
- [Fixed exponential projection complexity on nested types.][48296]
This can provide up to a ~12% reduction in compile times for certain crates.
- [Added the `--remap-path-prefix` option to rustc.][48359] Allowing you
to remap path prefixes outputted by the compiler.
- [Added `powerpc-unknown-netbsd` target.][48281]
Libraries
---------
- [Implemented `From<u16> for usize` & `From<{u8, i16}> for isize`.][49305]
- [Added hexadecimal formatting for integers with fmt::Debug][48978]
e.g. `assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]")`
- [Implemented `Default, Hash` for `cmp::Reverse`.][48628]
- [Optimized `str::repeat` being 8x faster in large cases.][48657]
- [`ascii::escape_default` is now available in libcore.][48735]
- [Trailing commas are now supported in std and core macros.][48056]
- [Implemented `Copy, Clone` for `cmp::Reverse`][47379]
- [Implemented `Clone` for `char::{ToLowercase, ToUppercase}`.][48629]
Stabilized APIs
---------------
- [`*const T::add`]
- [`*const T::copy_to_nonoverlapping`]
- [`*const T::copy_to`]
- [`*const T::read_unaligned`]
- [`*const T::read_volatile`]
- [`*const T::read`]
- [`*const T::sub`]
- [`*const T::wrapping_add`]
- [`*const T::wrapping_sub`]
- [`*mut T::add`]
- [`*mut T::copy_to_nonoverlapping`]
- [`*mut T::copy_to`]
- [`*mut T::read_unaligned`]
- [`*mut T::read_volatile`]
- [`*mut T::read`]
- [`*mut T::replace`]
- [`*mut T::sub`]
- [`*mut T::swap`]
- [`*mut T::wrapping_add`]
- [`*mut T::wrapping_sub`]
- [`*mut T::write_bytes`]
- [`*mut T::write_unaligned`]
- [`*mut T::write_volatile`]
- [`*mut T::write`]
- [`Box::leak`]
- [`FromUtf8Error::as_bytes`]
- [`LocalKey::try_with`]
- [`Option::cloned`]
- [`btree_map::Entry::and_modify`]
- [`fs::read_to_string`]
- [`fs::read`]
- [`fs::write`]
- [`hash_map::Entry::and_modify`]
- [`iter::FusedIterator`]
- [`ops::RangeInclusive`]
- [`ops::RangeToInclusive`]
- [`process::id`]
- [`slice::rotate_left`]
- [`slice::rotate_right`]
- [`String::retain`]
Cargo
-----
- [Cargo will now output path to custom commands when `-v` is
passed with `--list`][cargo/5041]
- [The Cargo binary version is now the same as the Rust version][cargo/5083]
Misc
----
- [The second edition of "The Rust Programming Language" book is now recommended
over the first.][48404]
Compatibility Notes
-------------------
- [aliasing a `Fn` trait as `dyn` no longer works.][48481] E.g. the following
syntax is now invalid.
```
use std::ops::Fn as dyn;
fn g(_: Box<dyn(std::fmt::Debug)>) {}
```
- [The result of dereferences are no longer promoted to `'static`.][47408]
e.g.
```rust
fn main() {
const PAIR: &(i32, i32) = &(0, 1);
let _reversed_pair: &'static _ = &(PAIR.1, PAIR.0); // Doesn't work
}
```
- [Deprecate `AsciiExt` trait in favor of inherent methods.][49109]
- [`".e0"` will now no longer parse as `0.0` and will instead cause
an error.][48235]
- [Removed hoedown from rustdoc.][48274]
- [Bounds on higher-kinded lifetimes a hard error.][48326]
[46882]: https://github.com/rust-lang/rust/pull/46882
[47379]: https://github.com/rust-lang/rust/pull/47379
[47408]: https://github.com/rust-lang/rust/pull/47408
[47813]: https://github.com/rust-lang/rust/pull/47813
[48056]: https://github.com/rust-lang/rust/pull/48056
[48125]: https://github.com/rust-lang/rust/pull/48125
[48166]: https://github.com/rust-lang/rust/pull/48166
[48235]: https://github.com/rust-lang/rust/pull/48235
[48274]: https://github.com/rust-lang/rust/pull/48274
[48281]: https://github.com/rust-lang/rust/pull/48281
[48296]: https://github.com/rust-lang/rust/pull/48296
[48326]: https://github.com/rust-lang/rust/pull/48326
[48359]: https://github.com/rust-lang/rust/pull/48359
[48404]: https://github.com/rust-lang/rust/pull/48404
[48481]: https://github.com/rust-lang/rust/pull/48481
[48516]: https://github.com/rust-lang/rust/pull/48516
[48628]: https://github.com/rust-lang/rust/pull/48628
[48629]: https://github.com/rust-lang/rust/pull/48629
[48657]: https://github.com/rust-lang/rust/pull/48657
[48735]: https://github.com/rust-lang/rust/pull/48735
[48978]: https://github.com/rust-lang/rust/pull/48978
[49101]: https://github.com/rust-lang/rust/pull/49101
[49109]: https://github.com/rust-lang/rust/pull/49109
[49121]: https://github.com/rust-lang/rust/pull/49121
[49162]: https://github.com/rust-lang/rust/pull/49162
[49184]: https://github.com/rust-lang/rust/pull/49184
[49234]: https://github.com/rust-lang/rust/pull/49234
[49255]: https://github.com/rust-lang/rust/pull/49255
[49299]: https://github.com/rust-lang/rust/pull/49299
[49305]: https://github.com/rust-lang/rust/pull/49305
[49394]: https://github.com/rust-lang/rust/pull/49394
[49458]: https://github.com/rust-lang/rust/pull/49458
[`*const T::add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add
[`*const T::copy_to_nonoverlapping`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to_nonoverlapping
[`*const T::copy_to`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to
[`*const T::read_unaligned`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_unaligned
[`*const T::read_volatile`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_volatile
[`*const T::read`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read
[`*const T::sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.sub
[`*const T::wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add
[`*const T::wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub
[`*mut T::add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add-1
[`*mut T::copy_to_nonoverlapping`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to_nonoverlapping-1
[`*mut T::copy_to`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.copy_to-1
[`*mut T::read_unaligned`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_unaligned-1
[`*mut T::read_volatile`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read_volatile-1
[`*mut T::read`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.read-1
[`*mut T::replace`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.replace
[`*mut T::sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.sub-1
[`*mut T::swap`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.swap
[`*mut T::wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add-1
[`*mut T::wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub-1
[`*mut T::write_bytes`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write_bytes
[`*mut T::write_unaligned`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write_unaligned
[`*mut T::write_volatile`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write_volatile
[`*mut T::write`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.write
[`Box::leak`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak
[`FromUtf8Error::as_bytes`]: https://doc.rust-lang.org/std/string/struct.FromUtf8Error.html#method.as_bytes
[`LocalKey::try_with`]: https://doc.rust-lang.org/std/thread/struct.LocalKey.html#method.try_with
[`Option::cloned`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.cloned
[`btree_map::Entry::and_modify`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.and_modify
[`fs::read_to_string`]: https://doc.rust-lang.org/std/fs/fn.read_to_string.html
[`fs::read`]: https://doc.rust-lang.org/std/fs/fn.read.html
[`fs::write`]: https://doc.rust-lang.org/std/fs/fn.write.html
[`hash_map::Entry::and_modify`]: https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.and_modify
[`iter::FusedIterator`]: https://doc.rust-lang.org/std/iter/trait.FusedIterator.html
[`ops::RangeInclusive`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html
[`ops::RangeToInclusive`]: https://doc.rust-lang.org/std/ops/struct.RangeToInclusive.html
[`process::id`]: https://doc.rust-lang.org/std/process/fn.id.html
[`slice::rotate_left`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_left
[`slice::rotate_right`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_right
[`String::retain`]: https://doc.rust-lang.org/std/string/struct.String.html#method.retain
[cargo/5041]: https://github.com/rust-lang/cargo/pull/5041
[cargo/5083]: https://github.com/rust-lang/cargo/pull/5083
Version 1.25.0 (2018-03-29)
==========================
Language
--------
- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358]
- [The `#[repr(align(x))]` attribute is now stable.][47006] [RFC 1358]
- [You can now use nested groups of imports.][47948]
e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};`
- [You can now have `|` at the start of a match arm.][47947] e.g.
@ -2535,7 +3107,7 @@ Language
[RFC 1513](https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md).
* [Add a new crate type, 'cdylib'](https://github.com/rust-lang/rust/pull/33553).
cdylibs are dynamic libraries suitable for loading by non-Rust hosts.
[RFC 1510](https://github.com/rust-lang/rfcs/blob/master/text/1510-rdylib.md).
[RFC 1510](https://github.com/rust-lang/rfcs/blob/master/text/1510-cdylib.md).
Note that Cargo does not yet directly support cdylibs.
Stabilized APIs
@ -2610,7 +3182,7 @@ Stabilized APIs
* [`UnixDatagram::shutdown`](http://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.shutdown)
* RawFd impls for `UnixDatagram`
* `{BTree,Hash}Map::values_mut`
* [`<[_]>::binary_search_by_key`](http://doc.rust-lang.org/beta/std/primitive.slice.html#method.binary_search_by_key)
* [`<[_]>::binary_search_by_key`](http://doc.rust-lang.org/std/primitive.slice.html#method.binary_search_by_key)
Libraries
---------
@ -3528,7 +4100,7 @@ Compatibility Notes
[1.6bh]: https://github.com/rust-lang/rust/pull/29811
[1.6c]: https://github.com/rust-lang/cargo/pull/2192
[1.6cc]: https://github.com/rust-lang/cargo/pull/2131
[1.6co]: http://doc.rust-lang.org/beta/core/index.html
[1.6co]: http://doc.rust-lang.org/core/index.html
[1.6dv]: https://github.com/rust-lang/rust/pull/30000
[1.6f]: https://github.com/rust-lang/rust/pull/29129
[1.6m]: https://github.com/rust-lang/rust/pull/29828

View File

@ -6,7 +6,7 @@ environment:
secure: 7Y+JiquYedOAgnUU26uL0DPzrxmTtR+qIwG6rNKSuWDffqU3vVZxbGXim9QpTO80
SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c
TOOLSTATE_REPO_ACCESS_TOKEN:
secure: PTZiSxJMVUZ0VnMR5i13E4OagbXfglj7pcskDQiKufVrDm13mLoI0vDJAEM35+bY
secure: gKGlVktr7iuqCoYSxHxDE9ltLOKU0nYDEuQxvWbNxUIW7ri5ppn8L06jQzN0GGzN
# By default schannel checks revocation of certificates unlike some other SSL
# backends, but we've historically had problems on CI where a revocation
@ -138,6 +138,20 @@ install:
- if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul
- if defined MINGW_URL set PATH=%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH%
# If we're compiling for MSVC then we, like most other distribution builders,
# switch to clang as the compiler. This'll allow us eventually to enable LTO
# amongst LLVM and rustc. Note that we only do this on MSVC as I don't think
# clang has an output mode compatible with MinGW that we need. If it does we
# should switch to clang for MinGW as well!
#
# Note that the LLVM installer is an NSIS installer
#
# Original downloaded here came from
# http://releases.llvm.org/6.0.0/LLVM-6.0.0-win64.exe
- if NOT defined MINGW_URL appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-6.0.0-win64.exe
- if NOT defined MINGW_URL .\LLVM-6.0.0-win64.exe /S /NCRC /D=C:\clang-rust
- if NOT defined MINGW_URL set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=C:\clang-rust\bin\clang-cl.exe
# Here we do a pretty heinous thing which is to mangle the MinGW installation
# we just had above. Currently, as of this writing, we're using MinGW-w64
# builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to
@ -166,8 +180,8 @@ install:
- set PATH=C:\Python27;%PATH%
# Download and install sccache
- appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-pc-windows-msvc
- mv 2018-04-02-sccache-x86_64-pc-windows-msvc sccache.exe
- appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc
- mv 2018-04-26-sccache-x86_64-pc-windows-msvc sccache.exe
- set PATH=%PATH%;%CD%
# Download and install ninja
@ -197,6 +211,11 @@ test_script:
- set NO_CCACHE=1
- sh src/ci/run.sh
on_failure:
# Dump crash log
- set PATH=%PATH%;"C:\Program Files (x86)\Windows Kits\10\Debuggers\X64"
- if exist %LOCALAPPDATA%\CrashDumps for %%f in (%LOCALAPPDATA%\CrashDumps\*) do cdb -c "k;q" -G -z "%%f"
branches:
only:
- auto

View File

@ -76,6 +76,10 @@
# passed to prefer linking to shared libraries.
#link-shared = false
# On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass
# with clang-cl, so this is special in that it only compiles LLVM with clang-cl
#clang-cl = '/path/to/clang-cl.exe'
# =============================================================================
# General build configuration options
# =============================================================================
@ -275,6 +279,9 @@
# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
#backtrace = true
# Whether to always use incremental compilation when building rustc
#incremental = false
# Build rustc with experimental parallelization
#experimental-parallel-queries = false
@ -294,9 +301,9 @@
# desired in distributions, for example.
#rpath = true
# Suppresses extraneous output from tests to ensure the output of the test
# harness is relatively clean.
#quiet-tests = false
# Emits extraneous output from tests to ensure that failures of the test
# harness are debuggable just from logfiles.
#verbose-tests = false
# Flag indicating whether tests are compiled with optimizations (the -O flag) or
# with debuginfo (the -g flag)
@ -343,12 +350,19 @@
# rustc to execute.
#lld = false
# Indicates whether some LLVM tools, like llvm-objdump, will be made available in the
# sysroot.
#llvm-tools = false
# Whether to deny warnings in crates
#deny-warnings = true
# Print backtrace on internal compiler errors during bootstrap
#backtrace-on-ice = false
# Whether to verify generated LLVM IR
#verify-llvm-ir = false
# =============================================================================
# Options for specific targets
#

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ members = [
"rustc",
"libstd",
"libtest",
"librustc_trans",
"librustc_codegen_llvm",
"tools/cargotest",
"tools/clippy",
"tools/compiletest",
@ -23,22 +23,17 @@ members = [
"tools/rustfmt",
"tools/miri",
"tools/rustdoc-themes",
# FIXME(https://github.com/rust-lang/cargo/issues/4089): move these to exclude
"tools/rls/test_data/bin_lib",
"tools/rls/test_data/borrow_error",
"tools/rls/test_data/common",
"tools/rls/test_data/deglob",
"tools/rls/test_data/features",
"tools/rls/test_data/find_all_refs_no_cfg_test",
"tools/rls/test_data/find_impls",
"tools/rls/test_data/infer_bin",
"tools/rls/test_data/infer_custom_bin",
"tools/rls/test_data/infer_lib",
"tools/rls/test_data/multiple_bins",
"tools/rls/test_data/reformat",
"tools/rls/test_data/reformat_with_range",
"tools/rls/test_data/workspace_symbol",
]
exclude = [
"tools/rls/test_data",
]
# Curiously, LLVM 7.0 will segfault if compiled with opt-level=3
# See issue https://github.com/rust-lang/rust/issues/52378
[profile.release]
opt-level = 2
[profile.bench]
opt-level = 2
# These options are controlled from our rustc wrapper script, so turn them off
# here and have them controlled elsewhere.
@ -57,11 +52,11 @@ debug-assertions = false
[patch."https://github.com/rust-lang/cargo"]
cargo = { path = "tools/cargo" }
[patch.crates-io]
[patch."https://github.com/rust-lang-nursery/rustfmt"]
# Similar to Cargo above we want the RLS to use a vendored version of `rustfmt`
# that we're shipping as well (to ensure that the rustfmt in RLS and the
# `rustfmt` executable are the same exact vesion). Unlike Cargo, however, the
# RLS depends on `rustfmt` from crates.io, so we put this in a `[patch]` section
# for crates.io
# `rustfmt` executable are the same exact version).
rustfmt-nightly = { path = "tools/rustfmt" }
[patch."https://github.com/rust-lang-nursery/rust-clippy"]
clippy_lints = { path = "tools/clippy/clippy_lints" }

View File

@ -6,7 +6,7 @@ This directory contains the source code of the rust project, including:
For more information on how various parts of the compiler work, see the [rustc guide].
Their is also useful content in the following READMEs, which are gradually being moved over to the guide:
- https://github.com/rust-lang/rust/tree/master/src/librustc/ty/maps
- https://github.com/rust-lang/rust/tree/master/src/librustc/ty/query
- https://github.com/rust-lang/rust/tree/master/src/librustc/dep_graph
- https://github.com/rust-lang/rust/blob/master/src/librustc/infer/region_constraints
- https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked

View File

@ -28,10 +28,15 @@ name = "sccache-plus-cl"
path = "bin/sccache-plus-cl.rs"
test = false
[[bin]]
name = "llvm-config-wrapper"
path = "bin/llvm-config-wrapper.rs"
test = false
[dependencies]
build_helper = { path = "../build_helper" }
cmake = "0.1.23"
filetime = "0.1"
filetime = "0.2"
num_cpus = "1.0"
getopts = "0.2"
cc = "1.0.1"

View File

@ -0,0 +1,27 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// The sheer existence of this file is an awful hack. See the comments in
// `src/bootstrap/native.rs` for why this is needed when compiling LLD.
use std::env;
use std::process::{self, Stdio, Command};
use std::io::{self, Write};
fn main() {
let real_llvm_config = env::var_os("LLVM_CONFIG_REAL").unwrap();
let mut cmd = Command::new(real_llvm_config);
cmd.args(env::args().skip(1)).stderr(Stdio::piped());
let output = cmd.output().expect("failed to spawn llvm-config");
let stdout = String::from_utf8_lossy(&output.stdout);
print!("{}", stdout.replace("\\", "/"));
io::stdout().flush().unwrap();
process::exit(output.status.code().unwrap_or(1));
}

View File

@ -268,12 +268,25 @@ fn main() {
if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
cmd.arg(format!("-Clinker={}", host_linker));
}
if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
if s == "true" {
cmd.arg("-C").arg("target-feature=+crt-static");
}
if s == "false" {
cmd.arg("-C").arg("target-feature=-crt-static");
}
}
}
if env::var_os("RUSTC_PARALLEL_QUERIES").is_some() {
cmd.arg("--cfg").arg("parallel_queries");
}
if env::var_os("RUSTC_VERIFY_LLVM_IR").is_some() {
cmd.arg("-Z").arg("verify-llvm-ir");
}
let color = match env::var("RUSTC_COLOR") {
Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"),
Err(_) => 0,
@ -283,12 +296,19 @@ fn main() {
cmd.arg("--color=always");
}
if env::var_os("RUSTC_DENY_WARNINGS").is_some() {
if env::var_os("RUSTC_DENY_WARNINGS").is_some() && env::var_os("RUSTC_EXTERNAL_TOOL").is_none()
{
cmd.arg("-Dwarnings");
cmd.arg("-Dbare_trait_objects");
}
if verbose > 1 {
eprintln!("rustc command: {:?}", cmd);
eprintln!(
"rustc command: {:?}={:?} {:?}",
bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap(),
cmd,
);
eprintln!("sysroot: {:?}", sysroot);
eprintln!("libdir: {:?}", libdir);
}
@ -308,7 +328,7 @@ fn main() {
let start = Instant::now();
let status = cmd
.status()
.expect(&format!("\n\n failed to run {:?}", cmd));
.unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
let dur = start.elapsed();
let is_test = args.iter().any(|a| a == "--test");
@ -328,7 +348,7 @@ fn main() {
}
}
let code = exec_cmd(&mut cmd).expect(&format!("\n\n failed to run {:?}", cmd));
let code = exec_cmd(&mut cmd).unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
std::process::exit(code);
}

View File

@ -35,7 +35,7 @@ fn main() {
};
let mut dylib_path = bootstrap::util::dylib_path();
dylib_path.insert(0, PathBuf::from(libdir));
dylib_path.insert(0, PathBuf::from(libdir.clone()));
let mut cmd = Command::new(rustdoc);
cmd.args(&args)
@ -69,6 +69,7 @@ fn main() {
if verbose > 1 {
eprintln!("rustdoc command: {:?}", cmd);
eprintln!("libdir: {:?}", libdir);
}
std::process::exit(match cmd.status() {

View File

@ -16,8 +16,8 @@ use std::process::{self, Command};
fn main() {
let target = env::var("SCCACHE_TARGET").unwrap();
// Locate the actual compiler that we're invoking
env::remove_var("CC");
env::remove_var("CXX");
env::set_var("CC", env::var_os("SCCACHE_CC").unwrap());
env::set_var("CXX", env::var_os("SCCACHE_CXX").unwrap());
let mut cfg = cc::Build::new();
cfg.cargo_metadata(false)
.out_dir("/")
@ -39,6 +39,12 @@ fn main() {
cmd.arg(arg);
}
if let Ok(s) = env::var("SCCACHE_EXTRA_ARGS") {
for s in s.split_whitespace() {
cmd.arg(s);
}
}
let status = cmd.status().expect("failed to spawn");
process::exit(status.code().unwrap_or(2))
}

View File

@ -303,6 +303,19 @@ def default_build_triple():
return "{}-{}".format(cputype, ostype)
@contextlib.contextmanager
def output(filepath):
tmp = filepath + '.tmp'
with open(tmp, 'w') as f:
yield f
try:
os.remove(filepath) # PermissionError/OSError on Win32 if in use
os.rename(tmp, filepath)
except OSError:
shutil.copy2(tmp, filepath)
os.remove(tmp)
class RustBuild(object):
"""Provide all the methods required to build Rust"""
def __init__(self):
@ -346,7 +359,7 @@ class RustBuild(object):
self._download_stage0_helper(filename, "rustc")
self.fix_executable("{}/bin/rustc".format(self.bin_root()))
self.fix_executable("{}/bin/rustdoc".format(self.bin_root()))
with open(self.rustc_stamp(), 'w') as rust_stamp:
with output(self.rustc_stamp()) as rust_stamp:
rust_stamp.write(self.date)
# This is required so that we don't mix incompatible MinGW
@ -363,7 +376,7 @@ class RustBuild(object):
filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build)
self._download_stage0_helper(filename, "cargo")
self.fix_executable("{}/bin/cargo".format(self.bin_root()))
with open(self.cargo_stamp(), 'w') as cargo_stamp:
with output(self.cargo_stamp()) as cargo_stamp:
cargo_stamp.write(self.date)
def _download_stage0_helper(self, filename, pattern):
@ -489,7 +502,7 @@ class RustBuild(object):
"""
return os.path.join(self.build_dir, self.build, "stage0")
def get_toml(self, key):
def get_toml(self, key, section=None):
"""Returns the value of the given key in config.toml, otherwise returns None
>>> rb = RustBuild()
@ -501,12 +514,29 @@ class RustBuild(object):
>>> rb.get_toml("key3") is None
True
Optionally also matches the section the key appears in
>>> rb.config_toml = '[a]\\nkey = "value1"\\n[b]\\nkey = "value2"'
>>> rb.get_toml('key', 'a')
'value1'
>>> rb.get_toml('key', 'b')
'value2'
>>> rb.get_toml('key', 'c') is None
True
"""
cur_section = None
for line in self.config_toml.splitlines():
section_match = re.match(r'^\s*\[(.*)\]\s*$', line)
if section_match is not None:
cur_section = section_match.group(1)
match = re.match(r'^{}\s*=(.*)$'.format(key), line)
if match is not None:
value = match.group(1)
return self.get_string(value) or value.strip()
if section is None or section == cur_section:
return self.get_string(value) or value.strip()
return None
def cargo(self):
@ -589,7 +619,17 @@ class RustBuild(object):
env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
(os.pathsep + env["LIBRARY_PATH"]) \
if "LIBRARY_PATH" in env else ""
env["RUSTFLAGS"] = "-Cdebuginfo=2"
env["RUSTFLAGS"] = "-Cdebuginfo=2 "
build_section = "target.{}".format(self.build_triple())
target_features = []
if self.get_toml("crt-static", build_section) == "true":
target_features += ["+crt-static"]
elif self.get_toml("crt-static", build_section) == "false":
target_features += ["-crt-static"]
if target_features:
env["RUSTFLAGS"] += "-C target-feature=" + (",".join(target_features)) + " "
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
os.pathsep + env["PATH"]
if not os.path.isfile(self.cargo()):
@ -749,7 +789,7 @@ def bootstrap(help_triggered):
if build.use_vendored_sources:
if not os.path.exists('.cargo'):
os.makedirs('.cargo')
with open('.cargo/config', 'w') as cargo_config:
with output('.cargo/config') as cargo_config:
cargo_config.write("""
[source.crates-io]
replace-with = 'vendored-sources'
@ -788,6 +828,9 @@ def bootstrap(help_triggered):
env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
env["BOOTSTRAP_PYTHON"] = sys.executable
env["BUILD_DIR"] = build.build_dir
env["RUSTC_BOOTSTRAP"] = '1'
env["CARGO"] = build.cargo()
env["RUSTC"] = build.rustc()
run(args, env=env, verbose=build.verbose)

File diff suppressed because it is too large Load Diff

View File

@ -249,7 +249,7 @@ lazy_static! {
pub struct Cache(
RefCell<HashMap<
TypeId,
Box<Any>, // actually a HashMap<Step, Interned<Step::Output>>
Box<dyn Any>, // actually a HashMap<Step, Interned<Step::Output>>
>>
);

View File

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

View File

@ -12,7 +12,7 @@
use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot};
use builder::{RunConfig, Builder, ShouldRun, Step};
use tool::{self, prepare_tool_cargo};
use tool::{self, prepare_tool_cargo, SourceType};
use {Compiler, Mode};
use cache::{INTERNER, Interned};
use std::path::PathBuf;
@ -40,10 +40,10 @@ impl Step for Std {
let target = self.target;
let compiler = builder.compiler(0, builder.config.build);
let out_dir = builder.stage_out(compiler, Mode::Libstd);
let out_dir = builder.stage_out(compiler, Mode::Std);
builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "check");
let mut cargo = builder.cargo(compiler, Mode::Std, target, "check");
std_cargo(builder, &compiler, target, &mut cargo);
let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
@ -87,11 +87,11 @@ impl Step for Rustc {
let compiler = builder.compiler(0, builder.config.build);
let target = self.target;
let stage_out = builder.stage_out(compiler, Mode::Librustc);
let stage_out = builder.stage_out(compiler, Mode::Rustc);
builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target));
builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "check");
rustc_cargo(builder, &mut cargo);
let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage));
@ -118,7 +118,7 @@ impl Step for CodegenBackend {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.all_krates("rustc_trans")
run.all_krates("rustc_codegen_llvm")
}
fn make_run(run: RunConfig) {
@ -137,14 +137,14 @@ impl Step for CodegenBackend {
let target = self.target;
let backend = self.backend;
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "check");
let features = builder.rustc_features().to_string();
cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_trans/Cargo.toml"));
cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
rustc_cargo_env(builder, &mut cargo);
// We won't build LLVM if it's not available, as it shouldn't affect `check`.
let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
run_cargo(builder,
cargo.arg("--features").arg(features),
&codegen_backend_stamp(builder, compiler, target, backend),
@ -175,10 +175,10 @@ impl Step for Test {
let compiler = builder.compiler(0, builder.config.build);
let target = self.target;
let out_dir = builder.stage_out(compiler, Mode::Libtest);
let out_dir = builder.stage_out(compiler, Mode::Test);
builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "check");
let mut cargo = builder.cargo(compiler, Mode::Test, target, "check");
test_cargo(builder, &compiler, target, &mut cargo);
let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
@ -219,9 +219,11 @@ impl Step for Rustdoc {
let mut cargo = prepare_tool_cargo(builder,
compiler,
Mode::ToolRustc,
target,
"check",
"src/tools/rustdoc");
"src/tools/rustdoc",
SourceType::InTree);
let _folder = builder.fold_output(|| format!("stage{}-rustdoc", compiler.stage));
println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target);
@ -236,7 +238,7 @@ impl Step for Rustdoc {
builder.ensure(tool::CleanTools {
compiler,
target,
mode: Mode::Tool,
cause: Mode::Rustc,
});
}
}
@ -244,33 +246,34 @@ impl Step for Rustdoc {
/// 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(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Libstd, target).join(".libstd-check.stamp")
builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
}
/// Cargo's output path for libtest in a given stage, compiled by a particular
/// compiler for the specified target.
pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Libtest, target).join(".libtest-check.stamp")
builder.cargo_out(compiler, Mode::Test, target).join(".libtest-check.stamp")
}
/// Cargo's output path for librustc in a given stage, compiled by a particular
/// compiler for the specified target.
pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
}
/// Cargo's output path for librustc_trans in a given stage, compiled by a particular
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
/// compiler for the specified target and backend.
fn codegen_backend_stamp(builder: &Builder,
compiler: Compiler,
target: Interned<String>,
backend: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Librustc, target)
.join(format!(".librustc_trans-{}-check.stamp", backend))
builder.cargo_out(compiler, Mode::Codegen, target)
.join(format!(".librustc_codegen_llvm-{}-check.stamp", backend))
}
/// Cargo's output path for rustdoc in a given stage, compiled by a particular
/// compiler for the specified target.
pub fn rustdoc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Tool, target).join(".rustdoc-check.stamp")
builder.cargo_out(compiler, Mode::ToolRustc, target)
.join(".rustdoc-check.stamp")
}

View File

@ -24,7 +24,6 @@ use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str;
use std::cmp::min;
use build_helper::{output, mtime, up_to_date};
use filetime::FileTime;
@ -68,6 +67,16 @@ impl Step for Std {
let target = self.target;
let compiler = self.compiler;
if builder.config.keep_stage.contains(&compiler.stage) {
builder.info("Warning: Using a potentially old libstd. This may not behave well.");
builder.ensure(StdLink {
compiler: compiler,
target_compiler: compiler,
target,
});
return;
}
builder.ensure(StartupObjects { compiler, target });
if builder.force_use_stage1(compiler, target) {
@ -98,9 +107,9 @@ impl Step for Std {
copy_musl_third_party_objects(builder, target, &libdir);
}
let out_dir = builder.cargo_out(compiler, Mode::Libstd, target);
let out_dir = builder.cargo_out(compiler, Mode::Std, target);
builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build");
let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
std_cargo(builder, &compiler, target, &mut cargo);
let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
@ -240,7 +249,7 @@ impl Step for StdLink {
builder.ensure(tool::CleanTools {
compiler: target_compiler,
target,
mode: Mode::Libstd,
cause: Mode::Std,
});
}
}
@ -353,6 +362,16 @@ impl Step for Test {
builder.ensure(Std { compiler, target });
if builder.config.keep_stage.contains(&compiler.stage) {
builder.info("Warning: Using a potentially old libtest. This may not behave well.");
builder.ensure(TestLink {
compiler: compiler,
target_compiler: compiler,
target,
});
return;
}
if builder.force_use_stage1(compiler, target) {
builder.ensure(Test {
compiler: builder.compiler(1, builder.config.build),
@ -368,9 +387,9 @@ impl Step for Test {
return;
}
let out_dir = builder.cargo_out(compiler, Mode::Libtest, target);
let out_dir = builder.cargo_out(compiler, Mode::Test, target);
builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build");
let mut cargo = builder.cargo(compiler, Mode::Test, target, "build");
test_cargo(builder, &compiler, target, &mut cargo);
let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
@ -431,7 +450,7 @@ impl Step for TestLink {
builder.ensure(tool::CleanTools {
compiler: target_compiler,
target,
mode: Mode::Libtest,
cause: Mode::Test,
});
}
}
@ -469,6 +488,16 @@ impl Step for Rustc {
builder.ensure(Test { compiler, target });
if builder.config.keep_stage.contains(&compiler.stage) {
builder.info("Warning: Using a potentially old librustc. This may not behave well.");
builder.ensure(RustcLink {
compiler: compiler,
target_compiler: compiler,
target,
});
return;
}
if builder.force_use_stage1(compiler, target) {
builder.ensure(Rustc {
compiler: builder.compiler(1, builder.config.build),
@ -489,11 +518,11 @@ impl Step for Rustc {
compiler: builder.compiler(self.compiler.stage, builder.config.build),
target: builder.config.build,
});
let cargo_out = builder.cargo_out(compiler, Mode::Librustc, target);
let cargo_out = builder.cargo_out(compiler, Mode::Rustc, target);
builder.clear_if_dirty(&cargo_out, &libstd_stamp(builder, compiler, target));
builder.clear_if_dirty(&cargo_out, &libtest_stamp(builder, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build");
rustc_cargo(builder, &mut cargo);
let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage));
@ -585,7 +614,7 @@ impl Step for RustcLink {
builder.ensure(tool::CleanTools {
compiler: target_compiler,
target,
mode: Mode::Librustc,
cause: Mode::Rustc,
});
}
}
@ -603,7 +632,7 @@ impl Step for CodegenBackend {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.all_krates("rustc_trans")
run.all_krates("rustc_codegen_llvm")
}
fn make_run(run: RunConfig) {
@ -625,6 +654,14 @@ impl Step for CodegenBackend {
builder.ensure(Rustc { compiler, target });
if builder.config.keep_stage.contains(&compiler.stage) {
builder.info("Warning: Using a potentially old codegen backend. \
This may not behave well.");
// Codegen backends are linked separately from this step today, so we don't do
// anything here.
return;
}
if builder.force_use_stage1(compiler, target) {
builder.ensure(CodegenBackend {
compiler: builder.compiler(1, builder.config.build),
@ -634,18 +671,18 @@ impl Step for CodegenBackend {
return;
}
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build");
let mut features = builder.rustc_features().to_string();
cargo.arg("--manifest-path")
.arg(builder.src.join("src/librustc_trans/Cargo.toml"));
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
rustc_cargo_env(builder, &mut cargo);
features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
let tmp_stamp = builder.cargo_out(compiler, Mode::Librustc, target)
let tmp_stamp = builder.cargo_out(compiler, Mode::Codegen, target)
.join(".tmp.stamp");
let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
let files = run_cargo(builder,
cargo.arg("--features").arg(features),
&tmp_stamp,
@ -656,7 +693,7 @@ impl Step for CodegenBackend {
let mut files = files.into_iter()
.filter(|f| {
let filename = f.file_name().unwrap().to_str().unwrap();
is_dylib(filename) && filename.contains("rustc_trans-")
is_dylib(filename) && filename.contains("rustc_codegen_llvm-")
});
let codegen_backend = match files.next() {
Some(f) => f,
@ -697,7 +734,7 @@ pub fn build_codegen_backend(builder: &Builder,
compiler.stage, &compiler.host, target, backend));
// Pass down configuration from the LLVM build into the build of
// librustc_llvm and librustc_trans.
// librustc_llvm and librustc_codegen_llvm.
if builder.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
@ -762,7 +799,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
t!(t!(File::open(&stamp)).read_to_string(&mut dylib));
let file = Path::new(&dylib);
let filename = file.file_name().unwrap().to_str().unwrap();
// change `librustc_trans-xxxxxx.so` to `librustc_trans-llvm.so`
// change `librustc_codegen_llvm-xxxxxx.so` to `librustc_codegen_llvm-llvm.so`
let target_filename = {
let dash = filename.find("-").unwrap();
let dot = filename.find(".").unwrap();
@ -786,36 +823,39 @@ fn copy_lld_to_sysroot(builder: &Builder,
.join("bin");
t!(fs::create_dir_all(&dst));
let exe = exe("lld", &target);
builder.copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe));
let src_exe = exe("lld", &target);
let dst_exe = exe("rust-lld", &target);
// we prepend this bin directory to the user PATH when linking Rust binaries. To
// avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
builder.copy(&lld_install_root.join("bin").join(&src_exe), &dst.join(&dst_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(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp")
}
/// Cargo's output path for libtest in a given stage, compiled by a particular
/// compiler for the specified target.
pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
builder.cargo_out(compiler, Mode::Test, target).join(".libtest.stamp")
}
/// Cargo's output path for librustc in a given stage, compiled by a particular
/// compiler for the specified target.
pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp")
}
/// Cargo's output path for librustc_trans in a given stage, compiled by a particular
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
/// compiler for the specified target and backend.
fn codegen_backend_stamp(builder: &Builder,
compiler: Compiler,
target: Interned<String>,
backend: Interned<String>) -> PathBuf {
builder.cargo_out(compiler, Mode::Librustc, target)
.join(format!(".librustc_trans-{}.stamp", backend))
builder.cargo_out(compiler, Mode::Codegen, target)
.join(format!(".librustc_codegen_llvm-{}.stamp", backend))
}
pub fn compiler_file(builder: &Builder,
@ -873,7 +913,7 @@ impl Step for Assemble {
type Output = Compiler;
fn should_run(run: ShouldRun) -> ShouldRun {
run.all_krates("rustc-main")
run.never()
}
/// Prepare a new compiler from the artifacts in `stage`
@ -915,28 +955,16 @@ impl Step for Assemble {
// link to these. (FIXME: Is that correct? It seems to be correct most
// of the time but I think we do link to these for stage2/bin compilers
// when not performing a full bootstrap).
if builder.config.keep_stage.map_or(false, |s| target_compiler.stage <= s) {
builder.verbose("skipping compilation of compiler due to --keep-stage");
let compiler = build_compiler;
for stage in 0..min(target_compiler.stage, builder.config.keep_stage.unwrap()) {
let target_compiler = builder.compiler(stage, target_compiler.host);
let target = target_compiler.host;
builder.ensure(StdLink { compiler, target_compiler, target });
builder.ensure(TestLink { compiler, target_compiler, target });
builder.ensure(RustcLink { compiler, target_compiler, target });
}
} else {
builder.ensure(Rustc {
builder.ensure(Rustc {
compiler: build_compiler,
target: target_compiler.host,
});
for &backend in builder.config.rust_codegen_backends.iter() {
builder.ensure(CodegenBackend {
compiler: build_compiler,
target: target_compiler.host,
backend,
});
for &backend in builder.config.rust_codegen_backends.iter() {
builder.ensure(CodegenBackend {
compiler: build_compiler,
target: target_compiler.host,
backend,
});
}
}
let lld_install = if builder.config.lld_enabled {
@ -971,8 +999,8 @@ impl Step for Assemble {
}
// Link the compiler binary itself into place
let out_dir = builder.cargo_out(build_compiler, Mode::Librustc, host);
let rustc = out_dir.join(exe("rustc", &*host));
let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
let rustc = out_dir.join(exe("rustc_binary", &*host));
let bindir = sysroot.join("bin");
t!(fs::create_dir_all(&bindir));
let compiler = builder.rustc(target_compiler);
@ -1049,7 +1077,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check:
!filename.ends_with(".lib") &&
!is_dylib(&filename) &&
!(is_check && filename.ends_with(".rmeta")) {
return;
continue;
}
let filename = Path::new(&*filename);
@ -1057,14 +1085,14 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check:
// If this was an output file in the "host dir" we don't actually
// worry about it, it's not relevant for us.
if filename.starts_with(&host_root_dir) {
return;
continue;
}
// If this was output in the `deps` dir then this is a precise file
// name (hash included) so we start tracking it.
if filename.starts_with(&target_deps_dir) {
deps.push(filename.to_path_buf());
return;
continue;
}
// Otherwise this was a "top level artifact" which right now doesn't
@ -1163,7 +1191,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check:
pub fn stream_cargo(
builder: &Builder,
cargo: &mut Command,
cb: &mut FnMut(CargoMessage),
cb: &mut dyn FnMut(CargoMessage),
) -> bool {
if builder.config.dry_run {
return true;

View File

@ -23,7 +23,6 @@ use std::cmp;
use num_cpus;
use toml;
use util::exe;
use cache::{INTERNER, Interned};
use flags::Flags;
pub use flags::Subcommand;
@ -64,7 +63,7 @@ pub struct Config {
pub on_fail: Option<String>,
pub stage: Option<u32>,
pub keep_stage: Option<u32>,
pub keep_stage: Vec<u32>,
pub src: PathBuf,
pub jobs: Option<u32>,
pub cmd: Subcommand,
@ -82,11 +81,13 @@ pub struct Config {
pub llvm_version_check: bool,
pub llvm_static_stdcpp: bool,
pub llvm_link_shared: bool,
pub llvm_clang_cl: Option<String>,
pub llvm_targets: Option<String>,
pub llvm_experimental_targets: String,
pub llvm_link_jobs: Option<u32>,
pub lld_enabled: bool,
pub llvm_tools_enabled: bool,
// rust codegen options
pub rust_optimize: bool,
@ -104,6 +105,7 @@ pub struct Config {
pub rust_dist_src: bool,
pub rust_codegen_backends: Vec<Interned<String>>,
pub rust_codegen_backends_dir: String,
pub rust_verify_llvm_ir: bool,
pub build: Interned<String>,
pub hosts: Vec<Interned<String>>,
@ -124,7 +126,7 @@ pub struct Config {
// misc
pub low_priority: bool,
pub channel: String,
pub quiet_tests: bool,
pub verbose_tests: bool,
pub test_miri: bool,
pub save_toolstates: Option<PathBuf>,
pub print_step_timings: bool,
@ -250,6 +252,7 @@ struct Llvm {
experimental_targets: Option<String>,
link_jobs: Option<u32>,
link_shared: Option<bool>,
clang_cl: Option<String>
}
#[derive(Deserialize, Default, Clone)]
@ -299,15 +302,18 @@ struct Rust {
ignore_git: Option<bool>,
debug: Option<bool>,
dist_src: Option<bool>,
quiet_tests: Option<bool>,
verbose_tests: Option<bool>,
test_miri: Option<bool>,
incremental: Option<bool>,
save_toolstates: Option<String>,
codegen_backends: Option<Vec<String>>,
codegen_backends_dir: Option<String>,
wasm_syscall: Option<bool>,
lld: Option<bool>,
llvm_tools: Option<bool>,
deny_warnings: Option<bool>,
backtrace_on_ice: Option<bool>,
verify_llvm_ir: Option<bool>,
}
/// TOML representation of how each build target is configured.
@ -362,9 +368,8 @@ impl Config {
config.src = Config::path_from_python("SRC");
config.out = Config::path_from_python("BUILD_DIR");
let stage0_root = config.out.join(&config.build).join("stage0/bin");
config.initial_rustc = stage0_root.join(exe("rustc", &config.build));
config.initial_cargo = stage0_root.join(exe("cargo", &config.build));
config.initial_rustc = Config::path_from_python("RUSTC");
config.initial_cargo = Config::path_from_python("CARGO");
config
}
@ -504,6 +509,7 @@ impl Config {
config.llvm_experimental_targets = llvm.experimental_targets.clone()
.unwrap_or("WebAssembly".to_string());
config.llvm_link_jobs = llvm.link_jobs;
config.llvm_clang_cl = llvm.clang_cl.clone();
}
if let Some(ref rust) = toml.rust {
@ -524,16 +530,22 @@ impl Config {
set(&mut config.backtrace, rust.backtrace);
set(&mut config.channel, rust.channel.clone());
set(&mut config.rust_dist_src, rust.dist_src);
set(&mut config.quiet_tests, rust.quiet_tests);
set(&mut config.verbose_tests, rust.verbose_tests);
set(&mut config.test_miri, rust.test_miri);
// in the case "false" is set explicitly, do not overwrite the command line args
if let Some(true) = rust.incremental {
config.incremental = true;
}
set(&mut config.wasm_syscall, rust.wasm_syscall);
set(&mut config.lld_enabled, rust.lld);
set(&mut config.llvm_tools_enabled, rust.llvm_tools);
config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false);
config.rustc_default_linker = rust.default_linker.clone();
config.musl_root = rust.musl_root.clone().map(PathBuf::from);
config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings));
set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
if let Some(ref backends) = rust.codegen_backends {
config.rust_codegen_backends = backends.iter()

View File

@ -47,7 +47,7 @@ o("optimize-tests", "rust.optimize-tests", "build tests with optimizations")
o("experimental-parallel-queries", "rust.experimental-parallel-queries", "build rustc with experimental parallelization")
o("test-miri", "rust.test-miri", "run miri's test suite")
o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata")
o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests")
o("verbose-tests", "rust.verbose-tests", "enable verbose output when running tests")
o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds")
o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds")
o("local-rust", None, "use an installed rustc rather than downloading a snapshot")
@ -335,6 +335,7 @@ for key in known_args:
elif option.name == 'full-tools':
set('rust.codegen-backends', ['llvm', 'emscripten'])
set('rust.lld', True)
set('rust.llvm-tools', True)
set('build.extended', True)
elif option.name == 'option-checking':
# this was handled above
@ -431,7 +432,7 @@ for section_key in config:
# order that we read it in.
p("")
p("writing `config.toml` in current directory")
with open('config.toml', 'w') as f:
with bootstrap.output('config.toml') as f:
for section in section_order:
if section == 'target':
for target in targets:
@ -441,7 +442,7 @@ with open('config.toml', 'w') as f:
for line in sections[section]:
f.write(line + "\n")
with open('Makefile', 'w') as f:
with bootstrap.output('Makefile') as f:
contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in')
contents = open(contents).read()
contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/')

View File

@ -26,7 +26,7 @@ use std::process::{Command, Stdio};
use build_helper::output;
use {Compiler, Mode};
use {Compiler, Mode, LLVM_TOOLS};
use channel;
use util::{libdir, is_dylib, exe};
use builder::{Builder, RunConfig, ShouldRun, Step};
@ -41,8 +41,12 @@ pub fn pkgname(builder: &Builder, component: &str) -> String {
format!("{}-{}", component, builder.cargo_package_vers())
} else if component == "rls" {
format!("{}-{}", component, builder.rls_package_vers())
} else if component == "clippy" {
format!("{}-{}", component, builder.clippy_package_vers())
} else if component == "rustfmt" {
format!("{}-{}", component, builder.rustfmt_package_vers())
} else if component == "llvm-tools" {
format!("{}-{}", component, builder.llvm_tools_package_vers())
} else {
assert!(component.starts_with("rust"));
format!("{}-{}", component, builder.rust_package_vers())
@ -304,6 +308,14 @@ fn make_win_dist(
builder.copy_to_folder(&src, &target_bin_dir);
}
// Warn windows-gnu users that the bundled GCC cannot compile C files
builder.create(
&target_bin_dir.join("GCC-WARNING.txt"),
"gcc.exe contained in this folder cannot be used for compiling C files - it is only\
used as a linker. In order to be able to compile projects containing C code use\
the GCC provided by MinGW or Cygwin."
);
//Copy platform libs to platform-specific lib directory
let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
@ -394,7 +406,7 @@ impl Step for Rustc {
let compiler = self.compiler;
let host = self.compiler.host;
builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, compiler.host));
builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host));
let name = pkgname(builder, "rustc");
let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
let _ = fs::remove_dir_all(&image);
@ -489,12 +501,13 @@ impl Step for Rustc {
// Copy over lld if it's there
if builder.config.lld_enabled {
let exe = exe("lld", &compiler.host);
let exe = exe("rust-lld", &compiler.host);
let src = builder.sysroot_libdir(compiler, host)
.parent()
.unwrap()
.join("bin")
.join(&exe);
// for the rationale about this rename check `compile::copy_lld_to_sysroot`
let dst = image.join("lib/rustlib")
.join(&*host)
.join("bin")
@ -722,7 +735,7 @@ impl Step for Analysis {
let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
let src = builder.stage_out(compiler, Mode::Libstd)
let src = builder.stage_out(compiler, Mode::Std)
.join(target).join(builder.cargo_dir()).join("deps");
let image_src = src.join("save-analysis");
@ -951,13 +964,16 @@ impl Step for PlainSourceTarball {
has_cargo_vendor |= line.starts_with("cargo-vendor ");
}
if !has_cargo_vendor {
let mut cmd = Command::new(&builder.initial_cargo);
cmd.arg("install")
.arg("--force")
let mut cmd = builder.cargo(
builder.compiler(0, builder.config.build),
Mode::ToolBootstrap,
builder.config.build,
"install"
);
cmd.arg("--force")
.arg("--debug")
.arg("--vers").arg(CARGO_VENDOR_VERSION)
.arg("cargo-vendor")
.env("RUSTC", &builder.initial_rustc);
.arg("cargo-vendor");
if let Some(dir) = builder.openssl_install_dir(builder.config.build) {
builder.ensure(native::Openssl {
target: builder.config.build,
@ -1178,6 +1194,87 @@ impl Step for Rls {
}
}
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Clippy {
pub stage: u32,
pub target: Interned<String>,
}
impl Step for Clippy {
type Output = Option<PathBuf>;
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path("clippy")
}
fn make_run(run: RunConfig) {
run.builder.ensure(Clippy {
stage: run.builder.top_stage,
target: run.target,
});
}
fn run(self, builder: &Builder) -> Option<PathBuf> {
let stage = self.stage;
let target = self.target;
assert!(builder.config.extended);
builder.info(&format!("Dist clippy stage{} ({})", stage, target));
let src = builder.src.join("src/tools/clippy");
let release_num = builder.release_num("clippy");
let name = pkgname(builder, "clippy");
let version = builder.clippy_info.version(builder, &release_num);
let tmp = tmpdir(builder);
let image = tmp.join("clippy-image");
drop(fs::remove_dir_all(&image));
builder.create_dir(&image);
// Prepare the image directory
// We expect clippy to build, because we've exited this step above if tool
// state for clippy isn't testing.
let clippy = builder.ensure(tool::Clippy {
compiler: builder.compiler(stage, builder.config.build),
target, extra_features: Vec::new()
}).or_else(|| { println!("Unable to build clippy, skipping dist"); None })?;
let cargoclippy = builder.ensure(tool::CargoClippy {
compiler: builder.compiler(stage, builder.config.build),
target, extra_features: Vec::new()
}).or_else(|| { println!("Unable to build cargo clippy, skipping dist"); None })?;
builder.install(&clippy, &image.join("bin"), 0o755);
builder.install(&cargoclippy, &image.join("bin"), 0o755);
let doc = image.join("share/doc/clippy");
builder.install(&src.join("README.md"), &doc, 0o644);
builder.install(&src.join("LICENSE"), &doc, 0o644);
// Prepare the overlay
let overlay = tmp.join("clippy-overlay");
drop(fs::remove_dir_all(&overlay));
t!(fs::create_dir_all(&overlay));
builder.install(&src.join("README.md"), &overlay, 0o644);
builder.install(&src.join("LICENSE"), &doc, 0o644);
builder.create(&overlay.join("version"), &version);
// Generate the installer tarball
let mut cmd = rust_installer(builder);
cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=clippy-ready-to-serve.")
.arg("--image-dir").arg(&image)
.arg("--work-dir").arg(&tmpdir(builder))
.arg("--output-dir").arg(&distdir(builder))
.arg("--non-installed-overlay").arg(&overlay)
.arg(format!("--package-name={}-{}", name, target))
.arg("--legacy-manifest-dirs=rustlib,cargo")
.arg("--component-name=clippy-preview");
builder.run(&mut cmd);
Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
}
}
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustfmt {
@ -1298,6 +1395,8 @@ impl Step for Extended {
let cargo_installer = builder.ensure(Cargo { stage, target });
let rustfmt_installer = builder.ensure(Rustfmt { stage, target });
let rls_installer = builder.ensure(Rls { stage, target });
let llvm_tools_installer = builder.ensure(LlvmTools { stage, target });
let clippy_installer = builder.ensure(Clippy { stage, target });
let mingw_installer = builder.ensure(Mingw { host: target });
let analysis_installer = builder.ensure(Analysis {
compiler: builder.compiler(stage, self.host),
@ -1334,7 +1433,9 @@ impl Step for Extended {
tarballs.push(rustc_installer);
tarballs.push(cargo_installer);
tarballs.extend(rls_installer.clone());
tarballs.extend(clippy_installer.clone());
tarballs.extend(rustfmt_installer.clone());
tarballs.extend(llvm_tools_installer.clone());
tarballs.push(analysis_installer);
tarballs.push(std_installer);
if builder.config.docs {
@ -1402,6 +1503,9 @@ impl Step for Extended {
if rls_installer.is_none() {
contents = filter(&contents, "rls");
}
if clippy_installer.is_none() {
contents = filter(&contents, "clippy");
}
if rustfmt_installer.is_none() {
contents = filter(&contents, "rustfmt");
}
@ -1439,6 +1543,9 @@ impl Step for Extended {
if rls_installer.is_some() {
prepare("rls");
}
if clippy_installer.is_some() {
prepare("clippy");
}
// create an 'uninstall' package
builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
@ -1467,6 +1574,8 @@ impl Step for Extended {
format!("{}-{}", name, target)
} else if name == "rls" {
"rls-preview".to_string()
} else if name == "clippy" {
"clippy-preview".to_string()
} else {
name.to_string()
};
@ -1483,6 +1592,9 @@ impl Step for Extended {
if rls_installer.is_some() {
prepare("rls");
}
if clippy_installer.is_some() {
prepare("clippy");
}
if target.contains("windows-gnu") {
prepare("rust-mingw");
}
@ -1563,6 +1675,18 @@ impl Step for Extended {
.arg("-out").arg(exe.join("RlsGroup.wxs"))
.arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
}
if clippy_installer.is_some() {
builder.run(Command::new(&heat)
.current_dir(&exe)
.arg("dir")
.arg("clippy")
.args(&heat_flags)
.arg("-cg").arg("ClippyGroup")
.arg("-dr").arg("Clippy")
.arg("-var").arg("var.ClippyDir")
.arg("-out").arg(exe.join("ClippyGroup.wxs"))
.arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
}
builder.run(Command::new(&heat)
.current_dir(&exe)
.arg("dir")
@ -1605,6 +1729,9 @@ impl Step for Extended {
if rls_installer.is_some() {
cmd.arg("-dRlsDir=rls");
}
if clippy_installer.is_some() {
cmd.arg("-dClippyDir=clippy");
}
if target.contains("windows-gnu") {
cmd.arg("-dGccDir=rust-mingw");
}
@ -1620,6 +1747,9 @@ impl Step for Extended {
if rls_installer.is_some() {
candle("RlsGroup.wxs".as_ref());
}
if clippy_installer.is_some() {
candle("ClippyGroup.wxs".as_ref());
}
candle("AnalysisGroup.wxs".as_ref());
if target.contains("windows-gnu") {
@ -1649,6 +1779,9 @@ impl Step for Extended {
if rls_installer.is_some() {
cmd.arg("RlsGroup.wixobj");
}
if clippy_installer.is_some() {
cmd.arg("ClippyGroup.wixobj");
}
if target.contains("windows-gnu") {
cmd.arg("GccGroup.wixobj");
@ -1734,7 +1867,9 @@ impl Step for HashSign {
cmd.arg(builder.rust_package_vers());
cmd.arg(builder.package_vers(&builder.release_num("cargo")));
cmd.arg(builder.package_vers(&builder.release_num("rls")));
cmd.arg(builder.package_vers(&builder.release_num("clippy")));
cmd.arg(builder.package_vers(&builder.release_num("rustfmt")));
cmd.arg(builder.llvm_tools_package_vers());
cmd.arg(addr);
builder.create_dir(&distdir(builder));
@ -1745,3 +1880,87 @@ impl Step for HashSign {
assert!(status.success());
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct LlvmTools {
pub stage: u32,
pub target: Interned<String>,
}
impl Step for LlvmTools {
type Output = Option<PathBuf>;
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path("llvm-tools")
}
fn make_run(run: RunConfig) {
run.builder.ensure(LlvmTools {
stage: run.builder.top_stage,
target: run.target,
});
}
fn run(self, builder: &Builder) -> Option<PathBuf> {
let stage = self.stage;
let target = self.target;
assert!(builder.config.extended);
/* run only if llvm-config isn't used */
if let Some(config) = builder.config.target_config.get(&target) {
if let Some(ref _s) = config.llvm_config {
builder.info(&format!("Skipping LlvmTools stage{} ({}): external LLVM",
stage, target));
return None;
}
}
builder.info(&format!("Dist LlvmTools stage{} ({})", stage, target));
let src = builder.src.join("src/llvm");
let name = pkgname(builder, "llvm-tools");
let tmp = tmpdir(builder);
let image = tmp.join("llvm-tools-image");
drop(fs::remove_dir_all(&image));
// Prepare the image directory
let bindir = builder
.llvm_out(target)
.join("bin");
let dst = image.join("lib/rustlib")
.join(target)
.join("bin");
t!(fs::create_dir_all(&dst));
for tool in LLVM_TOOLS {
let exe = bindir.join(exe(tool, &target));
builder.install(&exe, &dst, 0o755);
}
// Prepare the overlay
let overlay = tmp.join("llvm-tools-overlay");
drop(fs::remove_dir_all(&overlay));
builder.create_dir(&overlay);
builder.install(&src.join("README.txt"), &overlay, 0o644);
builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
builder.create(&overlay.join("version"), &builder.llvm_tools_vers());
// Generate the installer tarball
let mut cmd = rust_installer(builder);
cmd.arg("generate")
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
.arg("--success-message=llvm-tools-installed.")
.arg("--image-dir").arg(&image)
.arg("--work-dir").arg(&tmpdir(builder))
.arg("--output-dir").arg(&distdir(builder))
.arg("--non-installed-overlay").arg(&overlay)
.arg(format!("--package-name={}-{}", name, target))
.arg("--legacy-manifest-dirs=rustlib,cargo")
.arg("--component-name=llvm-tools-preview");
builder.run(&mut cmd);
Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
}
}

View File

@ -28,7 +28,7 @@ use build_helper::up_to_date;
use util::symlink_dir;
use builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
use tool::Tool;
use tool::{self, prepare_tool_cargo, Tool, SourceType};
use compile;
use cache::{INTERNER, Interned};
use config::Config;
@ -70,7 +70,7 @@ macro_rules! book {
book!(
Nomicon, "src/doc/nomicon", "nomicon";
Reference, "src/doc/reference", "reference";
Rustdoc, "src/doc/rustdoc", "rustdoc";
RustdocBook, "src/doc/rustdoc", "rustdoc";
RustcBook, "src/doc/rustc", "rustc";
RustByExample, "src/doc/rust-by-example", "rust-by-example";
);
@ -272,6 +272,12 @@ impl Step for TheBook {
name: INTERNER.intern_string(format!("{}/second-edition", name)),
});
// build book 2018 edition
builder.ensure(Rustbook {
target,
name: INTERNER.intern_string(format!("{}/2018-edition", name)),
});
// build the version info page and CSS
builder.ensure(Standalone {
compiler,
@ -457,7 +463,7 @@ impl Step for Std {
};
builder.ensure(compile::Std { compiler, target });
let out_dir = builder.stage_out(compiler, Mode::Libstd)
let out_dir = builder.stage_out(compiler, Mode::Std)
.join(target).join("doc");
// Here what we're doing is creating a *symlink* (directory junction on
@ -477,7 +483,7 @@ impl Step for Std {
builder.clear_if_dirty(&my_out, &rustdoc);
t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "doc");
let mut cargo = builder.cargo(compiler, Mode::Std, target, "doc");
compile::std_cargo(builder, &compiler, target, &mut cargo);
// Keep a whitelist so we do not build internal stdlib crates, these will be
@ -540,7 +546,7 @@ impl Step for Test {
builder.ensure(Std { stage, target });
builder.ensure(compile::Test { compiler, target });
let out_dir = builder.stage_out(compiler, Mode::Libtest)
let out_dir = builder.stage_out(compiler, Mode::Test)
.join(target).join("doc");
// See docs in std above for why we symlink
@ -548,7 +554,7 @@ impl Step for Test {
builder.clear_if_dirty(&my_out, &rustdoc);
t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "doc");
let mut cargo = builder.cargo(compiler, Mode::Test, target, "doc");
compile::test_cargo(builder, &compiler, target, &mut cargo);
cargo.arg("--no-deps").arg("-p").arg("test");
@ -608,7 +614,7 @@ impl Step for WhitelistedRustc {
builder.ensure(Std { stage, target });
builder.ensure(compile::Rustc { compiler, target });
let out_dir = builder.stage_out(compiler, Mode::Librustc)
let out_dir = builder.stage_out(compiler, Mode::Rustc)
.join(target).join("doc");
// See docs in std above for why we symlink
@ -616,7 +622,7 @@ impl Step for WhitelistedRustc {
builder.clear_if_dirty(&my_out, &rustdoc);
t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
compile::rustc_cargo(builder, &mut cargo);
// We don't want to build docs for internal compiler dependencies in this
@ -665,8 +671,12 @@ impl Step for Rustc {
let stage = self.stage;
let target = self.target;
builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
// This is the intended out directory for compiler documentation.
let out = builder.compiler_doc_out(target);
t!(fs::create_dir_all(&out));
// Get the correct compiler for this stage.
let compiler = builder.compiler(stage, builder.config.build);
let rustdoc = builder.rustdoc(compiler.host);
let compiler = if builder.force_use_stage1(compiler, target) {
@ -676,22 +686,24 @@ impl Step for Rustc {
};
if !builder.config.compiler_docs {
builder.info(&format!("\tskipping - compiler docs disabled"));
builder.info(&format!("\tskipping - compiler/librustdoc docs disabled"));
return;
}
// Build libstd docs so that we generate relative links
// Build libstd docs so that we generate relative links.
builder.ensure(Std { stage, target });
// Build rustc.
builder.ensure(compile::Rustc { compiler, target });
let out_dir = builder.stage_out(compiler, Mode::Librustc)
.join(target).join("doc");
// We do not symlink to the same shared folder that already contains std library
// documentation from previous steps as we do not want to include that.
let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc");
builder.clear_if_dirty(&out, &rustdoc);
t!(symlink_dir_force(&builder.config, &out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
// Build cargo command.
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
cargo.env("RUSTDOCFLAGS", "--document-private-items");
compile::rustc_cargo(builder, &mut cargo);
@ -729,6 +741,87 @@ fn find_compiler_crates(
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustdoc {
stage: u32,
target: Interned<String>,
}
impl Step for Rustdoc {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
run.krate("rustdoc-tool")
}
fn make_run(run: RunConfig) {
run.builder.ensure(Rustdoc {
stage: run.builder.top_stage,
target: run.target,
});
}
/// Generate compiler documentation.
///
/// This will generate all documentation for compiler and dependencies.
/// Compiler documentation is distributed separately, so we make sure
/// we do not merge it with the other documentation from std, test and
/// proc_macros. This is largely just a wrapper around `cargo doc`.
fn run(self, builder: &Builder) {
let stage = self.stage;
let target = self.target;
builder.info(&format!("Documenting stage{} rustdoc ({})", stage, target));
// This is the intended out directory for compiler documentation.
let out = builder.compiler_doc_out(target);
t!(fs::create_dir_all(&out));
// Get the correct compiler for this stage.
let compiler = builder.compiler(stage, builder.config.build);
let rustdoc = builder.rustdoc(compiler.host);
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler
};
if !builder.config.compiler_docs {
builder.info(&format!("\tskipping - compiler/librustdoc docs disabled"));
return;
}
// Build libstd docs so that we generate relative links.
builder.ensure(Std { stage, target });
// Build rustdoc.
builder.ensure(tool::Rustdoc { host: compiler.host });
// Symlink compiler docs to the output directory of rustdoc documentation.
let out_dir = builder.stage_out(compiler, Mode::ToolRustc)
.join(target)
.join("doc");
t!(fs::create_dir_all(&out_dir));
builder.clear_if_dirty(&out, &rustdoc);
t!(symlink_dir_force(&builder.config, &out, &out_dir));
// Build cargo command.
let mut cargo = prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
target,
"doc",
"src/tools/rustdoc",
SourceType::InTree,
);
cargo.env("RUSTDOCFLAGS", "--document-private-items");
builder.run(&mut cargo);
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex {
target: Interned<String>,

View File

@ -19,10 +19,10 @@ use std::process;
use getopts::Options;
use {Build, DocTests};
use builder::Builder;
use config::Config;
use metadata;
use builder::Builder;
use {Build, DocTests};
use cache::{Interned, INTERNER};
@ -31,7 +31,7 @@ pub struct Flags {
pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo
pub on_fail: Option<String>,
pub stage: Option<u32>,
pub keep_stage: Option<u32>,
pub keep_stage: Vec<u32>,
pub host: Vec<Interned<String>>,
pub target: Vec<Interned<String>>,
@ -59,6 +59,9 @@ pub enum Subcommand {
},
Test {
paths: Vec<PathBuf>,
/// Whether to automatically update stderr/stdout files
bless: bool,
compare_mode: Option<String>,
test_args: Vec<String>,
rustc_args: Vec<String>,
fail_fast: bool,
@ -90,7 +93,8 @@ impl Default for Subcommand {
impl Flags {
pub fn parse(args: &[String]) -> Flags {
let mut extra_help = String::new();
let mut subcommand_help = format!("\
let mut subcommand_help = format!(
"\
Usage: x.py <subcommand> [options] [<paths>...]
Subcommands:
@ -103,7 +107,8 @@ Subcommands:
dist Build distribution artifacts
install Install distribution artifacts
To learn more about a subcommand, run `./x.py <subcommand> -h`");
To learn more about a subcommand, run `./x.py <subcommand> -h`"
);
let mut opts = Options::new();
// Options common to all subcommands
@ -117,37 +122,43 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
opts.optopt("", "on-fail", "command to run on failure", "CMD");
opts.optflag("", "dry-run", "dry run; don't build anything");
opts.optopt("", "stage", "stage to build", "N");
opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling", "N");
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
opts.optflag("h", "help", "print this help message");
opts.optopt("", "warnings", "if value is deny, will deny warnings, otherwise use default",
"VALUE");
opts.optopt(
"",
"warnings",
"if value is deny, will deny warnings, otherwise use default",
"VALUE",
);
opts.optopt("", "error-format", "rustc error format", "FORMAT");
// fn usage()
let usage = |exit_code: i32, opts: &Options, subcommand_help: &str, extra_help: &str| -> ! {
println!("{}", opts.usage(subcommand_help));
if !extra_help.is_empty() {
println!("{}", extra_help);
}
process::exit(exit_code);
};
let usage =
|exit_code: i32, opts: &Options, subcommand_help: &str, extra_help: &str| -> ! {
println!("{}", opts.usage(subcommand_help));
if !extra_help.is_empty() {
println!("{}", extra_help);
}
process::exit(exit_code);
};
// We can't use getopt to parse the options until we have completed specifying which
// options are valid, but under the current implementation, some options are conditional on
// the subcommand. Therefore we must manually identify the subcommand first, so that we can
// complete the definition of the options. Then we can use the getopt::Matches object from
// there on out.
let subcommand = args.iter().find(|&s|
let subcommand = args.iter().find(|&s| {
(s == "build")
|| (s == "check")
|| (s == "test")
|| (s == "bench")
|| (s == "doc")
|| (s == "clean")
|| (s == "dist")
|| (s == "install"));
|| (s == "check")
|| (s == "test")
|| (s == "bench")
|| (s == "doc")
|| (s == "clean")
|| (s == "dist")
|| (s == "install")
});
let subcommand = match subcommand {
Some(s) => s,
None => {
@ -162,7 +173,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
// Some subcommands get extra options
match subcommand.as_str() {
"test" => {
"test" => {
opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
opts.optmulti("", "test-args", "extra arguments", "ARGS");
opts.optmulti(
@ -173,10 +184,25 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
);
opts.optflag("", "no-doc", "do not run doc tests");
opts.optflag("", "doc", "only run doc tests");
},
"bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
"clean" => { opts.optflag("", "all", "clean all build artifacts"); },
_ => { },
opts.optflag(
"",
"bless",
"update all stderr/stdout files of failing ui tests",
);
opts.optopt(
"",
"compare-mode",
"mode describing what file the actual ui output will be compared to",
"COMPARE MODE",
);
}
"bench" => {
opts.optmulti("", "test-args", "extra arguments", "ARGS");
}
"clean" => {
opts.optflag("", "all", "clean all build artifacts");
}
_ => {}
};
// Done specifying what options are possible, so do the getopts parsing
@ -196,21 +222,24 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
if check_subcommand != subcommand {
pass_sanity_check = false;
}
},
}
None => {
pass_sanity_check = false;
}
}
if !pass_sanity_check {
println!("{}\n", subcommand_help);
println!("Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
You may need to move some options to after the subcommand.\n");
println!(
"Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
You may need to move some options to after the subcommand.\n"
);
process::exit(1);
}
// Extra help text for some commands
match subcommand.as_str() {
"build" => {
subcommand_help.push_str("\n
subcommand_help.push_str(
"\n
Arguments:
This subcommand accepts a number of paths to directories to the crates
and/or artifacts to compile. For example:
@ -232,10 +261,12 @@ Arguments:
This will first build everything once (like --stage 0 without further
arguments would), and then use the compiler built in stage 0 to build
src/libtest and its dependencies.
Once this is done, build/$ARCH/stage1 contains a usable compiler.");
Once this is done, build/$ARCH/stage1 contains a usable compiler.",
);
}
"check" => {
subcommand_help.push_str("\n
subcommand_help.push_str(
"\n
Arguments:
This subcommand accepts a number of paths to directories to the crates
and/or artifacts to compile. For example:
@ -247,10 +278,12 @@ Arguments:
also that since we use `cargo check`, by default this will automatically enable incremental
compilation, so there's no need to pass it separately, though it won't hurt. We also completely
ignore the stage passed, as there's no way to compile in non-stage 0 without actually building
the compiler.");
the compiler.",
);
}
"test" => {
subcommand_help.push_str("\n
subcommand_help.push_str(
"\n
Arguments:
This subcommand accepts a number of paths to directories to tests that
should be compiled and run. For example:
@ -258,15 +291,19 @@ Arguments:
./x.py test src/test/run-pass
./x.py test src/libstd --test-args hash_map
./x.py test src/libstd --stage 0
./x.py test src/test/ui --bless
./x.py test src/test/ui --compare-mode nll
If no arguments are passed then the complete artifacts for that stage are
compiled and tested.
./x.py test
./x.py test --stage 1");
./x.py test --stage 1",
);
}
"doc" => {
subcommand_help.push_str("\n
subcommand_help.push_str(
"\n
Arguments:
This subcommand accepts a number of paths to directories of documentation
to build. For example:
@ -278,12 +315,16 @@ Arguments:
If no arguments are passed then everything is documented:
./x.py doc
./x.py doc --stage 1");
./x.py doc --stage 1",
);
}
_ => { }
_ => {}
};
// Get any optional paths which occur after the subcommand
let paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
let paths = matches.free[1..]
.iter()
.map(|p| p.into())
.collect::<Vec<PathBuf>>();
let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| {
if fs::metadata("config.toml").is_ok() {
@ -302,9 +343,12 @@ Arguments:
let maybe_rules_help = Builder::get_help(&build, subcommand.as_str());
extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
} else if subcommand.as_str() != "clean" {
extra_help.push_str(format!(
"Run `./x.py {} -h -v` to see a list of available paths.",
subcommand).as_str());
extra_help.push_str(
format!(
"Run `./x.py {} -h -v` to see a list of available paths.",
subcommand
).as_str(),
);
}
// User passed in -h/--help?
@ -313,36 +357,28 @@ Arguments:
}
let cmd = match subcommand.as_str() {
"build" => {
Subcommand::Build { paths: paths }
}
"check" => {
Subcommand::Check { paths: paths }
}
"test" => {
Subcommand::Test {
paths,
test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
doc_tests: if matches.opt_present("doc") {
DocTests::Only
} else if matches.opt_present("no-doc") {
DocTests::No
} else {
DocTests::Yes
}
}
}
"bench" => {
Subcommand::Bench {
paths,
test_args: matches.opt_strs("test-args"),
}
}
"doc" => {
Subcommand::Doc { paths: paths }
}
"build" => Subcommand::Build { paths: paths },
"check" => Subcommand::Check { paths: paths },
"test" => Subcommand::Test {
paths,
bless: matches.opt_present("bless"),
compare_mode: matches.opt_str("compare-mode"),
test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
doc_tests: if matches.opt_present("doc") {
DocTests::Only
} else if matches.opt_present("no-doc") {
DocTests::No
} else {
DocTests::Yes
},
},
"bench" => Subcommand::Bench {
paths,
test_args: matches.opt_strs("test-args"),
},
"doc" => Subcommand::Doc { paths: paths },
"clean" => {
if paths.len() > 0 {
println!("\nclean does not take a path argument\n");
@ -353,39 +389,38 @@ Arguments:
all: matches.opt_present("all"),
}
}
"dist" => {
Subcommand::Dist {
paths,
}
}
"install" => {
Subcommand::Install {
paths,
}
}
"dist" => Subcommand::Dist { paths },
"install" => Subcommand::Install { paths },
_ => {
usage(1, &opts, &subcommand_help, &extra_help);
}
};
Flags {
verbose: matches.opt_count("verbose"),
stage: matches.opt_str("stage").map(|j| j.parse().unwrap()),
dry_run: matches.opt_present("dry-run"),
on_fail: matches.opt_str("on-fail"),
rustc_error_format: matches.opt_str("error-format"),
keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()),
keep_stage: matches.opt_strs("keep-stage")
.into_iter().map(|j| j.parse().unwrap())
.collect(),
host: split(matches.opt_strs("host"))
.into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(),
.into_iter()
.map(|x| INTERNER.intern_string(x))
.collect::<Vec<_>>(),
target: split(matches.opt_strs("target"))
.into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(),
.into_iter()
.map(|x| INTERNER.intern_string(x))
.collect::<Vec<_>>(),
config: cfg_file,
jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),
cmd,
incremental: matches.opt_present("incremental"),
exclude: split(matches.opt_strs("exclude"))
.into_iter().map(|p| p.into()).collect::<Vec<_>>(),
.into_iter()
.map(|p| p.into())
.collect::<Vec<_>>(),
warnings: matches.opt_str("warnings").map(|v| v == "deny"),
}
}
@ -394,9 +429,11 @@ Arguments:
impl Subcommand {
pub fn test_args(&self) -> Vec<&str> {
match *self {
Subcommand::Test { ref test_args, .. } |
Subcommand::Bench { ref test_args, .. } => {
test_args.iter().flat_map(|s| s.split_whitespace()).collect()
Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
test_args
.iter()
.flat_map(|s| s.split_whitespace())
.collect()
}
_ => Vec::new(),
}
@ -404,9 +441,10 @@ impl Subcommand {
pub fn rustc_args(&self) -> Vec<&str> {
match *self {
Subcommand::Test { ref rustc_args, .. } => {
rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
}
Subcommand::Test { ref rustc_args, .. } => rustc_args
.iter()
.flat_map(|s| s.split_whitespace())
.collect(),
_ => Vec::new(),
}
}
@ -424,8 +462,27 @@ impl Subcommand {
_ => DocTests::Yes,
}
}
pub fn bless(&self) -> bool {
match *self {
Subcommand::Test { bless, .. } => bless,
_ => false,
}
}
pub fn compare_mode(&self) -> Option<&str> {
match *self {
Subcommand::Test {
ref compare_mode, ..
} => compare_mode.as_ref().map(|s| &s[..]),
_ => None,
}
}
}
fn split(s: Vec<String>) -> Vec<String> {
s.iter().flat_map(|s| s.split(',')).map(|s| s.to_string()).collect()
s.iter()
.flat_map(|s| s.split(','))
.map(|s| s.to_string())
.collect()
}

View File

@ -39,6 +39,9 @@ pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
pub fn install_rls(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "rls", "rls", stage, Some(host));
}
pub fn install_clippy(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "clippy", "clippy", stage, Some(host));
}
pub fn install_rustfmt(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "rustfmt", "rustfmt", stage, Some(host));
@ -72,7 +75,7 @@ fn install_sh(
let libdir_default = PathBuf::from("lib");
let mandir_default = datadir_default.join("man");
let prefix = builder.config.prefix.as_ref().map_or(prefix_default, |p| {
fs::canonicalize(p).expect(&format!("could not canonicalize {}", p.display()))
fs::canonicalize(p).unwrap_or_else(|_| panic!("could not canonicalize {}", p.display()))
});
let sysconfdir = builder.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
let datadir = builder.config.datadir.as_ref().unwrap_or(&datadir_default);
@ -216,6 +219,14 @@ install!((self, builder, _config),
builder.info(&format!("skipping Install RLS stage{} ({})", self.stage, self.target));
}
};
Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
if builder.ensure(dist::Clippy { stage: self.stage, target: self.target }).is_some() ||
Self::should_install(builder) {
install_clippy(builder, self.stage, self.target);
} else {
builder.info(&format!("skipping Install clippy stage{} ({})", self.stage, self.target));
}
};
Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() ||
Self::should_install(builder) {

View File

@ -113,8 +113,10 @@
//! More documentation can be found in each respective module below, and you can
//! also check out the `src/bootstrap/README.md` file for more information.
#![deny(bare_trait_objects)]
#![deny(warnings)]
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#[macro_use]
extern crate build_helper;
@ -177,7 +179,7 @@ mod toolstate;
#[cfg(windows)]
mod job;
#[cfg(unix)]
#[cfg(all(unix, not(target_os = "haiku")))]
mod job {
use libc;
@ -188,7 +190,7 @@ mod job {
}
}
#[cfg(not(any(unix, windows)))]
#[cfg(any(target_os = "haiku", not(any(unix, windows))))]
mod job {
pub unsafe fn setup(_build: &mut ::Build) {
}
@ -199,6 +201,15 @@ use flags::Subcommand;
use cache::{Interned, INTERNER};
use toolstate::ToolState;
const LLVM_TOOLS: &[&str] = &[
"llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
"llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume
"llvm-objdump", // used to disassemble programs
"llvm-profdata", // used to inspect and merge files generated by profiles
"llvm-size", // used to prints the size of the linker sections of a program
"llvm-strip", // used to discard symbols from binary files to reduce their size
];
/// A structure representing a Rust compiler.
///
/// Each compiler has a `stage` that it is associated with and a `host` that
@ -240,6 +251,7 @@ pub struct Build {
rust_info: channel::GitInfo,
cargo_info: channel::GitInfo,
rls_info: channel::GitInfo,
clippy_info: channel::GitInfo,
rustfmt_info: channel::GitInfo,
local_rebuild: bool,
fail_fast: bool,
@ -280,7 +292,8 @@ pub struct Build {
struct Crate {
name: Interned<String>,
version: String,
deps: Vec<Interned<String>>,
deps: HashSet<Interned<String>>,
id: String,
path: PathBuf,
doc_step: String,
build_step: String,
@ -307,16 +320,37 @@ impl Crate {
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Mode {
/// Build the standard library, placing output in the "stageN-std" directory.
Libstd,
Std,
/// Build libtest, placing output in the "stageN-test" directory.
Libtest,
Test,
/// Build librustc and compiler libraries, placing output in the "stageN-rustc" directory.
Librustc,
/// Build librustc, and compiler libraries, placing output in the "stageN-rustc" directory.
Rustc,
/// Build some tool, placing output in the "stageN-tools" directory.
Tool,
/// Build codegen libraries, placing output in the "stageN-codegen" directory
Codegen,
/// Build some tools, placing output in the "stageN-tools" directory. The
/// "other" here is for miscellaneous sets of tools that are built using the
/// bootstrap compiler in its entirety (target libraries and all).
/// Typically these tools compile with stable Rust.
ToolBootstrap,
/// Compile a tool which uses all libraries we compile (up to rustc).
/// Doesn't use the stage0 compiler libraries like "other", and includes
/// tools like rustdoc, cargo, rls, etc.
ToolStd,
ToolRustc,
}
impl Mode {
pub fn is_tool(&self) -> bool {
match self {
Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => true,
_ => false
}
}
}
impl Build {
@ -340,6 +374,7 @@ impl Build {
let rust_info = channel::GitInfo::new(&config, &src);
let cargo_info = channel::GitInfo::new(&config, &src.join("src/tools/cargo"));
let rls_info = channel::GitInfo::new(&config, &src.join("src/tools/rls"));
let clippy_info = channel::GitInfo::new(&config, &src.join("src/tools/clippy"));
let rustfmt_info = channel::GitInfo::new(&config, &src.join("src/tools/rustfmt"));
let mut build = Build {
@ -361,6 +396,7 @@ impl Build {
rust_info,
cargo_info,
rls_info,
clippy_info,
rustfmt_info,
cc: HashMap::new(),
cxx: HashMap::new(),
@ -517,10 +553,13 @@ impl Build {
/// The mode indicates what the root directory is for.
fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
let suffix = match mode {
Mode::Libstd => "-std",
Mode::Libtest => "-test",
Mode::Tool => "-tools",
Mode::Librustc => "-rustc",
Mode::Std => "-std",
Mode::Test => "-test",
Mode::Codegen => "-rustc",
Mode::Rustc => "-rustc",
Mode::ToolBootstrap => "-bootstrap-tools",
Mode::ToolStd => "-tools",
Mode::ToolRustc => "-tools",
};
self.out.join(&*compiler.host)
.join(format!("stage{}{}", compiler.stage, suffix))
@ -592,12 +631,20 @@ impl Build {
Path::new(llvm_bindir.trim()).join(exe("FileCheck", &*target))
} else {
let base = self.llvm_out(self.config.build).join("build");
let exe = exe("FileCheck", &*target);
if !self.config.ninja && self.config.build.contains("msvc") {
base.join("Release/bin").join(exe)
let base = if !self.config.ninja && self.config.build.contains("msvc") {
if self.config.llvm_optimize {
if self.config.llvm_release_debuginfo {
base.join("RelWithDebInfo")
} else {
base.join("Release")
}
} else {
base.join("Debug")
}
} else {
base.join("bin").join(exe)
}
base
};
base.join("bin").join(exe("FileCheck", &*target))
}
}
@ -621,8 +668,12 @@ impl Build {
/// Returns the libdir of the snapshot compiler.
fn rustc_snapshot_libdir(&self) -> PathBuf {
self.rustc_snapshot_sysroot().join(libdir(&self.config.build))
}
/// Returns the sysroot of the snapshot compiler.
fn rustc_snapshot_sysroot(&self) -> &Path {
self.initial_rustc.parent().unwrap().parent().unwrap()
.join(libdir(&self.config.build))
}
/// Runs a command, printing out nice contextual information if it fails.
@ -936,11 +987,24 @@ impl Build {
self.package_vers(&self.release_num("rls"))
}
/// Returns the value of `package_vers` above for clippy
fn clippy_package_vers(&self) -> String {
self.package_vers(&self.release_num("clippy"))
}
/// Returns the value of `package_vers` above for rustfmt
fn rustfmt_package_vers(&self) -> String {
self.package_vers(&self.release_num("rustfmt"))
}
fn llvm_tools_package_vers(&self) -> String {
self.package_vers(&self.rust_version())
}
fn llvm_tools_vers(&self) -> String {
self.rust_version()
}
/// Returns the `version` string associated with this compiler for Rust
/// itself.
///
@ -1112,13 +1176,13 @@ impl Build {
/// Copies the `src` directory recursively to `dst`. Both are assumed to exist
/// when this function is called. Unwanted files or directories can be skipped
/// by returning `false` from the filter function.
pub fn cp_filtered(&self, src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) {
pub fn cp_filtered(&self, src: &Path, dst: &Path, filter: &dyn Fn(&Path) -> bool) {
// Immediately recurse with an empty relative path
self.recurse_(src, dst, Path::new(""), filter)
}
// Inner function does the actual work
fn recurse_(&self, src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) {
fn recurse_(&self, src: &Path, dst: &Path, relative: &Path, filter: &dyn Fn(&Path) -> bool) {
for f in self.read_dir(src) {
let path = f.path();
let name = path.file_name().unwrap();

View File

@ -11,6 +11,7 @@
use std::collections::HashMap;
use std::process::Command;
use std::path::PathBuf;
use std::collections::HashSet;
use build_helper::output;
use serde_json;
@ -45,45 +46,17 @@ struct ResolveNode {
}
pub fn build(build: &mut Build) {
build_krate(build, "src/libstd");
build_krate(build, "src/libtest");
build_krate(build, "src/rustc");
}
let mut resolves = Vec::new();
build_krate(&build.std_features(), build, &mut resolves, "src/libstd");
build_krate("", build, &mut resolves, "src/libtest");
build_krate(&build.rustc_features(), build, &mut resolves, "src/rustc");
fn build_krate(build: &mut Build, krate: &str) {
// Run `cargo metadata` to figure out what crates we're testing.
//
// Down below we're going to call `cargo test`, but to test the right set
// of packages we're going to have to know what `-p` arguments to pass it
// to know what crates to test. Here we run `cargo metadata` to learn about
// the dependency graph and what `-p` arguments there are.
let mut cargo = Command::new(&build.initial_cargo);
cargo.arg("metadata")
.arg("--format-version").arg("1")
.arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml"));
let output = output(&mut cargo);
let output: Output = serde_json::from_str(&output).unwrap();
let mut id2name = HashMap::new();
for package in output.packages {
if package.source.is_none() {
let name = INTERNER.intern_string(package.name);
id2name.insert(package.id, name);
let mut path = PathBuf::from(package.manifest_path);
path.pop();
build.crates.insert(name, Crate {
build_step: format!("build-crate-{}", name),
doc_step: format!("doc-crate-{}", name),
test_step: format!("test-crate-{}", name),
bench_step: format!("bench-crate-{}", name),
name,
version: package.version,
deps: Vec::new(),
path,
});
}
let mut id2name = HashMap::with_capacity(build.crates.len());
for (name, krate) in build.crates.iter() {
id2name.insert(krate.id.clone(), name.clone());
}
for node in output.resolve.nodes {
for node in resolves {
let name = match id2name.get(&node.id) {
Some(name) => name,
None => continue,
@ -95,7 +68,42 @@ fn build_krate(build: &mut Build, krate: &str) {
Some(dep) => dep,
None => continue,
};
krate.deps.push(*dep);
krate.deps.insert(*dep);
}
}
}
fn build_krate(features: &str, build: &mut Build, resolves: &mut Vec<ResolveNode>, krate: &str) {
// Run `cargo metadata` to figure out what crates we're testing.
//
// Down below we're going to call `cargo test`, but to test the right set
// of packages we're going to have to know what `-p` arguments to pass it
// to know what crates to test. Here we run `cargo metadata` to learn about
// the dependency graph and what `-p` arguments there are.
let mut cargo = Command::new(&build.initial_cargo);
cargo.arg("metadata")
.arg("--format-version").arg("1")
.arg("--features").arg(features)
.arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml"));
let output = output(&mut cargo);
let output: Output = serde_json::from_str(&output).unwrap();
for package in output.packages {
if package.source.is_none() {
let name = INTERNER.intern_string(package.name);
let mut path = PathBuf::from(package.manifest_path);
path.pop();
build.crates.insert(name, Crate {
build_step: format!("build-crate-{}", name),
doc_step: format!("doc-crate-{}", name),
test_step: format!("test-crate-{}", name),
bench_step: format!("bench-crate-{}", name),
name,
version: package.version,
id: package.id,
deps: HashSet::new(),
path,
});
}
}
resolves.extend(output.resolve.nodes);
}

View File

@ -167,8 +167,22 @@ impl Step for Llvm {
// which saves both memory during parallel links and overall disk space
// for the tools. We don't distribute any of those tools, so this is
// just a local concern. However, it doesn't work well everywhere.
if target.contains("linux-gnu") || target.contains("apple-darwin") {
cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
//
// If we are shipping llvm tools then we statically link them LLVM
if (target.contains("linux-gnu") || target.contains("apple-darwin")) &&
!builder.config.llvm_tools_enabled {
cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
}
// For distribution we want the LLVM tools to be *statically* linked to libstdc++
if builder.config.llvm_tools_enabled {
if !target.contains("windows") {
if target.contains("apple") {
cfg.define("CMAKE_EXE_LINKER_FLAGS", "-static-libstdc++");
} else {
cfg.define("CMAKE_EXE_LINKER_FLAGS", "-Wl,-Bsymbolic -static-libstdc++");
}
}
}
if target.contains("msvc") {
@ -242,12 +256,12 @@ fn check_llvm_version(builder: &Builder, llvm_config: &Path) {
let version = output(cmd.arg("--version"));
let mut parts = version.split('.').take(2)
.filter_map(|s| s.parse::<u32>().ok());
if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
if major > 3 || (major == 3 && minor >= 9) {
if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
if major >= 5 {
return
}
}
panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version)
panic!("\n\nbad LLVM version: {}, need >=5.0\n\n", version)
}
fn configure_cmake(builder: &Builder,
@ -275,21 +289,53 @@ fn configure_cmake(builder: &Builder,
return
}
let cc = builder.cc(target);
let cxx = builder.cxx(target).unwrap();
let (cc, cxx) = match builder.config.llvm_clang_cl {
Some(ref cl) => (cl.as_ref(), cl.as_ref()),
None => (builder.cc(target), builder.cxx(target).unwrap()),
};
// Handle msvc + ninja + ccache specially (this is what the bots use)
if target.contains("msvc") &&
builder.config.ninja &&
builder.config.ccache.is_some() {
let mut cc = env::current_exe().expect("failed to get cwd");
cc.set_file_name("sccache-plus-cl.exe");
builder.config.ccache.is_some()
{
let mut wrap_cc = env::current_exe().expect("failed to get cwd");
wrap_cc.set_file_name("sccache-plus-cl.exe");
cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
.define("CMAKE_CXX_COMPILER", sanitize_cc(&cc));
cfg.define("CMAKE_C_COMPILER", sanitize_cc(&wrap_cc))
.define("CMAKE_CXX_COMPILER", sanitize_cc(&wrap_cc));
cfg.env("SCCACHE_PATH",
builder.config.ccache.as_ref().unwrap())
.env("SCCACHE_TARGET", target);
.env("SCCACHE_TARGET", target)
.env("SCCACHE_CC", &cc)
.env("SCCACHE_CXX", &cxx);
// Building LLVM on MSVC can be a little ludicrous at times. We're so far
// off the beaten path here that I'm not really sure this is even half
// supported any more. Here we're trying to:
//
// * Build LLVM on MSVC
// * Build LLVM with `clang-cl` instead of `cl.exe`
// * Build a project with `sccache`
// * Build for 32-bit as well
// * Build with Ninja
//
// For `cl.exe` there are different binaries to compile 32/64 bit which
// we use but for `clang-cl` there's only one which internally
// multiplexes via flags. As a result it appears that CMake's detection
// of a compiler's architecture and such on MSVC **doesn't** pass any
// custom flags we pass in CMAKE_CXX_FLAGS below. This means that if we
// use `clang-cl.exe` it's always diagnosed as a 64-bit compiler which
// definitely causes problems since all the env vars are pointing to
// 32-bit libraries.
//
// To hack aroudn this... again... we pass an argument that's
// unconditionally passed in the sccache shim. This'll get CMake to
// correctly diagnose it's doing a 32-bit compilation and LLVM will
// internally configure itself appropriately.
if builder.config.llvm_clang_cl.is_some() && target.contains("i686") {
cfg.env("SCCACHE_EXTRA_ARGS", "-m32");
}
// If ccache is configured we inform the build a little differently hwo
// to invoke ccache while also invoking our compilers.
@ -368,9 +414,27 @@ impl Step for Lld {
let mut cfg = cmake::Config::new(builder.src.join("src/tools/lld"));
configure_cmake(builder, target, &mut cfg, true);
// This is an awful, awful hack. Discovered when we migrated to using
// clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
// tree, will execute `llvm-config --cmakedir` and then tell CMake about
// that directory for later processing. Unfortunately if this path has
// forward slashes in it (which it basically always does on Windows)
// then CMake will hit a syntax error later on as... something isn't
// escaped it seems?
//
// Instead of attempting to fix this problem in upstream CMake and/or
// LLVM/LLD we just hack around it here. This thin wrapper will take the
// output from llvm-config and replace all instances of `\` with `/` to
// ensure we don't hit the same bugs with escaping. It means that you
// can't build on a system where your paths require `\` on Windows, but
// there's probably a lot of reasons you can't do that other than this.
let llvm_config_shim = env::current_exe()
.unwrap()
.with_file_name("llvm-config-wrapper");
cfg.out_dir(&out_dir)
.profile("Release")
.define("LLVM_CONFIG_PATH", llvm_config)
.env("LLVM_CONFIG_REAL", llvm_config)
.define("LLVM_CONFIG_PATH", llvm_config_shim)
.define("LLVM_INCLUDE_TESTS", "OFF");
cfg.build();
@ -546,8 +610,10 @@ impl Step for Openssl {
"arm-linux-androideabi" => "android",
"arm-unknown-linux-gnueabi" => "linux-armv4",
"arm-unknown-linux-gnueabihf" => "linux-armv4",
"armv6-unknown-netbsd-eabihf" => "BSD-generic32",
"armv7-linux-androideabi" => "android-armv7",
"armv7-unknown-linux-gnueabihf" => "linux-armv4",
"armv7-unknown-netbsd-eabihf" => "BSD-generic32",
"i586-unknown-linux-gnu" => "linux-elf",
"i586-unknown-linux-musl" => "linux-elf",
"i686-apple-darwin" => "darwin-i386-cc",
@ -565,6 +631,7 @@ impl Step for Openssl {
"powerpc-unknown-netbsd" => "BSD-generic32",
"powerpc64-unknown-linux-gnu" => "linux-ppc64",
"powerpc64le-unknown-linux-gnu" => "linux-ppc64le",
"powerpc64le-unknown-linux-musl" => "linux-ppc64le",
"s390x-unknown-linux-gnu" => "linux64-s390x",
"sparc-unknown-linux-gnu" => "linux-sparcv9",
"sparc64-unknown-linux-gnu" => "linux64-sparcv9",

View File

@ -15,25 +15,26 @@
use std::env;
use std::ffi::OsString;
use std::iter;
use std::fmt;
use std::fs::{self, File};
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::Read;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::Command;
use build_helper::{self, output};
use builder::{Kind, RunConfig, ShouldRun, Builder, Compiler, Step};
use Crate as CargoCrate;
use cache::{INTERNER, Interned};
use builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use cache::{Interned, INTERNER};
use compile;
use dist;
use flags::Subcommand;
use native;
use tool::{self, Tool};
use util::{self, dylib_path, dylib_path_var};
use {Mode, DocTests};
use tool::{self, Tool, SourceType};
use toolstate::ToolState;
use util::{self, dylib_path, dylib_path_var};
use Crate as CargoCrate;
use {DocTests, Mode};
const ADB_TEST_DIR: &str = "/data/tmp/work";
@ -46,6 +47,16 @@ pub enum TestKind {
Bench,
}
impl From<Kind> for TestKind {
fn from(kind: Kind) -> Self {
match kind {
Kind::Test => TestKind::Test,
Kind::Bench => TestKind::Bench,
_ => panic!("unexpected kind in crate: {:?}", kind),
}
}
}
impl TestKind {
// Return the cargo subcommand for this test kind
fn subcommand(self) -> &'static str {
@ -113,13 +124,18 @@ impl Step for Linkcheck {
builder.default_doc(None);
let _time = util::timeit(&builder);
try_run(builder, builder.tool_cmd(Tool::Linkchecker)
.arg(builder.out.join(host).join("doc")));
try_run(
builder,
builder
.tool_cmd(Tool::Linkchecker)
.arg(builder.out.join(host).join("doc")),
);
}
fn should_run(run: ShouldRun) -> ShouldRun {
let builder = run.builder;
run.path("src/tools/linkchecker").default_condition(builder.config.docs)
run.path("src/tools/linkchecker")
.default_condition(builder.config.docs)
}
fn make_run(run: RunConfig) {
@ -154,7 +170,10 @@ impl Step for Cargotest {
/// test` to ensure that we don't regress the test suites there.
fn run(self, builder: &Builder) {
let compiler = builder.compiler(self.stage, self.host);
builder.ensure(compile::Rustc { compiler, target: compiler.host });
builder.ensure(compile::Rustc {
compiler,
target: compiler.host,
});
// Note that this is a short, cryptic, and not scoped directory name. This
// is currently to minimize the length of path on Windows where we otherwise
@ -164,10 +183,13 @@ impl Step for Cargotest {
let _time = util::timeit(&builder);
let mut cmd = builder.tool_cmd(Tool::CargoTest);
try_run(builder, cmd.arg(&builder.initial_cargo)
.arg(&out_dir)
.env("RUSTC", builder.rustc(compiler))
.env("RUSTDOC", builder.rustdoc(compiler.host)));
try_run(
builder,
cmd.arg(&builder.initial_cargo)
.arg(&out_dir)
.env("RUSTC", builder.rustc(compiler))
.env("RUSTDOC", builder.rustdoc(compiler.host)),
);
}
}
@ -196,21 +218,30 @@ impl Step for Cargo {
fn run(self, builder: &Builder) {
let compiler = builder.compiler(self.stage, self.host);
builder.ensure(tool::Cargo { compiler, target: self.host });
let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test");
cargo.arg("--manifest-path").arg(builder.src.join("src/tools/cargo/Cargo.toml"));
builder.ensure(tool::Cargo {
compiler,
target: self.host,
});
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
Mode::ToolRustc,
self.host,
"test",
"src/tools/cargo",
SourceType::Submodule);
if !builder.fail_fast {
cargo.arg("--no-fail-fast");
}
// Don't build tests dynamically, just a pain to work with
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
// Don't run cross-compile tests, we may not have cross-compiled libstd libs
// available.
cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
try_run(builder, cargo.env("PATH", &path_for_cargo(builder, compiler)));
try_run(
builder,
cargo.env("PATH", &path_for_cargo(builder, compiler)),
);
}
}
@ -253,12 +284,18 @@ impl Step for Rls {
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
Mode::ToolRustc,
host,
"test",
"src/tools/rls");
"src/tools/rls",
SourceType::Submodule);
// Don't build tests dynamically, just a pain to work with
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
// Copy `src/tools/rls/test_data` to a writable drive.
let test_workspace_path = builder.out.join("rls-test-data");
let test_data_path = test_workspace_path.join("test_data");
builder.create_dir(&test_data_path);
builder.cp_r(&builder.src.join("src/tools/rls/test_data"), &test_data_path);
cargo.env("RLS_TEST_WORKSPACE_DIR", test_workspace_path);
builder.add_rustc_lib_path(compiler, &mut cargo);
@ -307,12 +344,15 @@ impl Step for Rustfmt {
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
Mode::ToolRustc,
host,
"test",
"src/tools/rustfmt");
"src/tools/rustfmt",
SourceType::Submodule);
// Don't build tests dynamically, just a pain to work with
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
let dir = testdir(builder, compiler.host);
t!(fs::create_dir_all(&dir));
cargo.env("RUSTFMT_TEST_DIR", dir);
builder.add_rustc_lib_path(compiler, &mut cargo);
@ -357,11 +397,14 @@ impl Step for Miri {
extra_features: Vec::new(),
});
if let Some(miri) = miri {
let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
cargo.arg("--manifest-path").arg(builder.src.join("src/tools/miri/Cargo.toml"));
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
Mode::ToolRustc,
host,
"test",
"src/tools/miri",
SourceType::Submodule);
// Don't build tests dynamically, just a pain to work with
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
// miri tests need to know about the stage sysroot
cargo.env("MIRI_SYSROOT", builder.sysroot(compiler));
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
@ -413,16 +456,21 @@ impl Step for Clippy {
extra_features: Vec::new(),
});
if let Some(clippy) = clippy {
let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
cargo.arg("--manifest-path").arg(builder.src.join("src/tools/clippy/Cargo.toml"));
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
Mode::ToolRustc,
host,
"test",
"src/tools/clippy",
SourceType::Submodule);
// Don't build tests dynamically, just a pain to work with
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
// clippy tests need to know about the stage sysroot
cargo.env("SYSROOT", builder.sysroot(compiler));
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
let host_libs = builder.stage_out(compiler, Mode::Tool).join(builder.cargo_dir());
let host_libs = builder
.stage_out(compiler, Mode::ToolRustc)
.join(builder.cargo_dir());
cargo.env("HOST_LIBS", host_libs);
// clippy tests need to find the driver
cargo.env("CLIPPY_DRIVER_PATH", clippy);
@ -464,23 +512,30 @@ impl Step for RustdocTheme {
fn make_run(run: RunConfig) {
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
run.builder.ensure(RustdocTheme {
compiler: compiler,
});
run.builder.ensure(RustdocTheme { compiler: compiler });
}
fn run(self, builder: &Builder) {
let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
cmd.arg(rustdoc.to_str().unwrap())
.arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap())
.env("RUSTC_STAGE", self.compiler.stage.to_string())
.env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
.env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
.env("RUSTDOC_REAL", builder.rustdoc(self.compiler.host))
.env("RUSTDOC_CRATE_VERSION", builder.rust_version())
.env("RUSTC_BOOTSTRAP", "1");
.arg(
builder
.src
.join("src/librustdoc/html/static/themes")
.to_str()
.unwrap(),
)
.env("RUSTC_STAGE", self.compiler.stage.to_string())
.env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
.env(
"RUSTDOC_LIBDIR",
builder.sysroot_libdir(self.compiler, self.compiler.host),
)
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
.env("RUSTDOC_REAL", builder.rustdoc(self.compiler.host))
.env("RUSTDOC_CRATE_VERSION", builder.rust_version())
.env("RUSTC_BOOTSTRAP", "1");
if let Some(linker) = builder.linker(self.compiler.host) {
cmd.env("RUSTC_TARGET_LINKER", linker);
}
@ -520,7 +575,9 @@ impl Step for RustdocJS {
});
builder.run(&mut command);
} else {
builder.info(&format!("No nodejs found, skipping \"src/test/rustdoc-js\" tests"));
builder.info(&format!(
"No nodejs found, skipping \"src/test/rustdoc-js\" tests"
));
}
}
}
@ -556,6 +613,7 @@ impl Step for RustdocUi {
target: self.target,
mode: "ui",
suite: "rustdoc-ui",
path: None,
compare_mode: None,
})
}
@ -581,7 +639,7 @@ impl Step for Tidy {
if !builder.config.vendor {
cmd.arg("--no-vendor");
}
if builder.config.quiet_tests {
if !builder.config.verbose_tests {
cmd.arg("--quiet");
}
@ -660,7 +718,7 @@ macro_rules! test_definitions {
const ONLY_HOSTS: bool = $host;
fn should_run(run: ShouldRun) -> ShouldRun {
run.path($path)
run.suite_path($path)
}
fn make_run(run: RunConfig) {
@ -678,6 +736,7 @@ macro_rules! test_definitions {
target: self.target,
mode: $mode,
suite: $suite,
path: Some($path),
compare_mode: $compare_mode,
})
}
@ -850,6 +909,7 @@ struct Compiletest {
target: Interned<String>,
mode: &'static str,
suite: &'static str,
path: Option<&'static str>,
compare_mode: Option<&'static str>,
}
@ -870,7 +930,9 @@ impl Step for Compiletest {
let target = self.target;
let mode = self.mode;
let suite = self.suite;
let compare_mode = self.compare_mode;
// Path for test suite
let suite_path = self.path.unwrap_or("");
// Skip codegen tests if they aren't enabled in configuration.
if !builder.config.codegen_tests && suite == "codegen" {
@ -899,19 +961,21 @@ impl Step for Compiletest {
builder.ensure(dist::DebuggerScripts {
sysroot: builder.sysroot(compiler),
host: target
host: target,
});
}
if suite.ends_with("fulldeps") ||
// FIXME: Does pretty need librustc compiled? Note that there are
// fulldeps test suites with mode = pretty as well.
mode == "pretty" ||
mode == "rustdoc" {
mode == "pretty"
{
builder.ensure(compile::Rustc { compiler, target });
}
builder.ensure(compile::Test { compiler, target });
if builder.no_std(target) != Some(true) {
builder.ensure(compile::Test { compiler, target });
}
builder.ensure(native::TestHelpers { target });
builder.ensure(RemoteCopyLibs { compiler, target });
@ -920,26 +984,40 @@ impl Step for Compiletest {
// compiletest currently has... a lot of arguments, so let's just pass all
// of them!
cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
cmd.arg("--compile-lib-path")
.arg(builder.rustc_libdir(compiler));
cmd.arg("--run-lib-path")
.arg(builder.sysroot_libdir(compiler, target));
cmd.arg("--rustc-path").arg(builder.rustc(compiler));
let is_rustdoc_ui = suite.ends_with("rustdoc-ui");
// Avoid depending on rustdoc when we don't need it.
if mode == "rustdoc" ||
(mode == "run-make" && suite.ends_with("fulldeps")) ||
(mode == "ui" && is_rustdoc_ui) {
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host));
if mode == "rustdoc"
|| (mode == "run-make" && suite.ends_with("fulldeps"))
|| (mode == "ui" && is_rustdoc_ui)
{
cmd.arg("--rustdoc-path")
.arg(builder.rustdoc(compiler.host));
}
cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite));
cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
cmd.arg("--src-base")
.arg(builder.src.join("src/test").join(suite));
cmd.arg("--build-base")
.arg(testdir(builder, compiler.host).join(suite));
cmd.arg("--stage-id")
.arg(format!("stage{}-{}", compiler.stage, target));
cmd.arg("--mode").arg(mode);
cmd.arg("--target").arg(target);
cmd.arg("--host").arg(&*compiler.host);
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
cmd.arg("--llvm-filecheck")
.arg(builder.llvm_filecheck(builder.config.build));
if builder.config.cmd.bless() {
cmd.arg("--bless");
}
let compare_mode = builder.config.cmd.compare_mode().or(self.compare_mode);
if let Some(ref nodejs) = builder.config.nodejs {
cmd.arg("--nodejs").arg(nodejs);
@ -969,8 +1047,10 @@ impl Step for Compiletest {
cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
let mut targetflags = flags.clone();
targetflags.push(format!("-Lnative={}",
builder.test_helpers_out(target).display()));
targetflags.push(format!(
"-Lnative={}",
builder.test_helpers_out(target).display()
));
cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
cmd.arg("--docck-python").arg(builder.python());
@ -994,13 +1074,34 @@ impl Step for Compiletest {
cmd.arg("--lldb-python-dir").arg(dir);
}
cmd.args(&builder.config.cmd.test_args());
// Get paths from cmd args
let paths = match &builder.config.cmd {
Subcommand::Test { ref paths, .. } => &paths[..],
_ => &[],
};
// Get test-args by striping suite path
let mut test_args: Vec<&str> = paths
.iter()
.map(|p| {
match p.strip_prefix(".") {
Ok(path) => path,
Err(_) => p,
}
})
.filter(|p| p.starts_with(suite_path) && p.is_file())
.map(|p| p.strip_prefix(suite_path).unwrap().to_str().unwrap())
.collect();
test_args.append(&mut builder.config.cmd.test_args());
cmd.args(&test_args);
if builder.is_verbose() {
cmd.arg("--verbose");
}
if builder.config.quiet_tests {
if !builder.config.verbose_tests {
cmd.arg("--quiet");
}
@ -1022,32 +1123,44 @@ impl Step for Compiletest {
if !builder.config.dry_run && suite == "run-make-fulldeps" {
let llvm_components = output(Command::new(&llvm_config).arg("--components"));
let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
cmd.arg("--cc").arg(builder.cc(target))
.arg("--cxx").arg(builder.cxx(target).unwrap())
.arg("--cflags").arg(builder.cflags(target).join(" "))
.arg("--llvm-components").arg(llvm_components.trim())
.arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
cmd.arg("--cc")
.arg(builder.cc(target))
.arg("--cxx")
.arg(builder.cxx(target).unwrap())
.arg("--cflags")
.arg(builder.cflags(target).join(" "))
.arg("--llvm-components")
.arg(llvm_components.trim())
.arg("--llvm-cxxflags")
.arg(llvm_cxxflags.trim());
if let Some(ar) = builder.ar(target) {
cmd.arg("--ar").arg(ar);
}
}
}
if suite == "run-make-fulldeps" && !builder.config.llvm_enabled {
builder.info(
&format!("Ignoring run-make test suite as they generally don't work without LLVM"));
builder.info(&format!(
"Ignoring run-make test suite as they generally don't work without LLVM"
));
return;
}
if suite != "run-make-fulldeps" {
cmd.arg("--cc").arg("")
.arg("--cxx").arg("")
.arg("--cflags").arg("")
.arg("--llvm-components").arg("")
.arg("--llvm-cxxflags").arg("");
cmd.arg("--cc")
.arg("")
.arg("--cxx")
.arg("")
.arg("--cflags")
.arg("")
.arg("--llvm-components")
.arg("")
.arg("--llvm-cxxflags")
.arg("");
}
if builder.remote_tested(target) {
cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
cmd.arg("--remote-test-client")
.arg(builder.tool_exe(Tool::RemoteTestClient));
}
// Running a C compiler on MSVC requires a few env vars to be set, to be
@ -1080,7 +1193,7 @@ impl Step for Compiletest {
if target.contains("android") {
// Assume that cc for this target comes from the android sysroot
cmd.arg("--android-cross-path")
.arg(builder.cc(target).parent().unwrap().parent().unwrap());
.arg(builder.cc(target).parent().unwrap().parent().unwrap());
} else {
cmd.arg("--android-cross-path").arg("");
}
@ -1088,16 +1201,20 @@ impl Step for Compiletest {
builder.ci_env.force_coloring_in_ci(&mut cmd);
let _folder = builder.fold_output(|| format!("test_{}", suite));
builder.info(&format!("Check compiletest suite={} mode={} ({} -> {})",
suite, mode, &compiler.host, target));
builder.info(&format!(
"Check compiletest suite={} mode={} ({} -> {})",
suite, mode, &compiler.host, target
));
let _time = util::timeit(&builder);
try_run(builder, &mut cmd);
if let Some(compare_mode) = compare_mode {
cmd.arg("--compare-mode").arg(compare_mode);
let _folder = builder.fold_output(|| format!("test_{}_{}", suite, compare_mode));
builder.info(&format!("Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
suite, mode, compare_mode, &compiler.host, target));
builder.info(&format!(
"Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
suite, mode, compare_mode, &compiler.host, target
));
let _time = util::timeit(&builder);
try_run(builder, &mut cmd);
}
@ -1128,7 +1245,10 @@ impl Step for DocTest {
fn run(self, builder: &Builder) {
let compiler = self.compiler;
builder.ensure(compile::Test { compiler, target: compiler.host });
builder.ensure(compile::Test {
compiler,
target: compiler.host,
});
// Do a breadth-first traversal of the `src/doc` directory and just run
// tests for all files that end in `*.md`
@ -1140,7 +1260,7 @@ impl Step for DocTest {
while let Some(p) = stack.pop() {
if p.is_dir() {
stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
continue
continue;
}
if p.extension().and_then(|s| s.to_str()) != Some("md") {
@ -1158,17 +1278,15 @@ impl Step for DocTest {
files.sort();
let mut toolstate = ToolState::TestPass;
for file in files {
let test_result = markdown_test(builder, compiler, &file);
if self.is_ext_doc {
let toolstate = if test_result {
ToolState::TestPass
} else {
ToolState::TestFail
};
builder.save_toolstate(self.name, toolstate);
if !markdown_test(builder, compiler, &file) {
toolstate = ToolState::TestFail;
}
}
if self.is_ext_doc {
builder.save_toolstate(self.name, toolstate);
}
}
}
@ -1247,7 +1365,10 @@ impl Step for ErrorIndex {
fn run(self, builder: &Builder) {
let compiler = self.compiler;
builder.ensure(compile::Std { compiler, target: compiler.host });
builder.ensure(compile::Std {
compiler,
target: compiler.host,
});
let dir = testdir(builder, compiler.host);
t!(fs::create_dir_all(&dir));
@ -1259,7 +1380,6 @@ impl Step for ErrorIndex {
.env("CFG_BUILD", &builder.config.build)
.env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir());
let _folder = builder.fold_output(|| "test_error_index");
builder.info(&format!("Testing error-index stage{}", compiler.stage));
let _time = util::timeit(&builder);
@ -1277,7 +1397,7 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool
return true;
}
}
Err(_) => {},
Err(_) => {}
}
builder.info(&format!("doc tests for: {}", markdown.display()));
@ -1290,10 +1410,10 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool
let test_args = builder.config.cmd.test_args().join(" ");
cmd.arg("--test-args").arg(test_args);
if builder.config.quiet_tests {
try_run_quiet(builder, &mut cmd)
} else {
if builder.config.verbose_tests {
try_run(builder, &mut cmd)
} else {
try_run_quiet(builder, &mut cmd)
}
}
@ -1320,13 +1440,7 @@ impl Step for CrateLibrustc {
for krate in builder.in_tree_crates("rustc-main") {
if run.path.ends_with(&krate.path) {
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();
builder.ensure(CrateLibrustc {
compiler,
@ -1342,7 +1456,7 @@ impl Step for CrateLibrustc {
builder.ensure(Crate {
compiler: self.compiler,
target: self.target,
mode: Mode::Librustc,
mode: Mode::Rustc,
test_kind: self.test_kind,
krate: self.krate,
});
@ -1372,13 +1486,7 @@ impl Step for CrateNotDefault {
let builder = run.builder;
let compiler = builder.compiler(builder.top_stage, run.host);
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();
builder.ensure(CrateNotDefault {
compiler,
@ -1399,14 +1507,13 @@ impl Step for CrateNotDefault {
builder.ensure(Crate {
compiler: self.compiler,
target: self.target,
mode: Mode::Libstd,
mode: Mode::Std,
test_kind: self.test_kind,
krate: INTERNER.intern_str(self.krate),
});
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Crate {
pub compiler: Compiler,
@ -1424,10 +1531,11 @@ impl Step for Crate {
let builder = run.builder;
run = run.krate("test");
for krate in run.builder.in_tree_crates("std") {
if krate.is_local(&run.builder) &&
!krate.name.contains("jemalloc") &&
!(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) &&
krate.name != "dlmalloc" {
if krate.is_local(&run.builder)
&& !krate.name.contains("jemalloc")
&& !(krate.name.starts_with("rustc_") && krate.name.ends_with("san"))
&& krate.name != "dlmalloc"
{
run = run.path(krate.local_path(&builder).to_str().unwrap());
}
}
@ -1439,13 +1547,7 @@ impl Step for Crate {
let compiler = builder.compiler(builder.top_stage, run.host);
let make = |mode: Mode, krate: &CargoCrate| {
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();
builder.ensure(Crate {
compiler,
@ -1458,12 +1560,12 @@ impl Step for Crate {
for krate in builder.in_tree_crates("std") {
if run.path.ends_with(&krate.local_path(&builder)) {
make(Mode::Libstd, krate);
make(Mode::Std, krate);
}
}
for krate in builder.in_tree_crates("test") {
if run.path.ends_with(&krate.local_path(&builder)) {
make(Mode::Libtest, krate);
make(Mode::Test, krate);
}
}
}
@ -1498,13 +1600,13 @@ impl Step for Crate {
let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
match mode {
Mode::Libstd => {
Mode::Std => {
compile::std_cargo(builder, &compiler, target, &mut cargo);
}
Mode::Libtest => {
Mode::Test => {
compile::test_cargo(builder, &compiler, target, &mut cargo);
}
Mode::Librustc => {
Mode::Rustc => {
builder.ensure(compile::Rustc { compiler, target });
compile::rustc_cargo(builder, &mut cargo);
}
@ -1543,43 +1645,64 @@ impl Step for Crate {
cargo.arg("--");
cargo.args(&builder.config.cmd.test_args());
if builder.config.quiet_tests {
if !builder.config.verbose_tests {
cargo.arg("--quiet");
}
if target.contains("emscripten") {
cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
builder.config.nodejs.as_ref().expect("nodejs not configured"));
cargo.env(
format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
builder
.config
.nodejs
.as_ref()
.expect("nodejs not configured"),
);
} else if target.starts_with("wasm32") {
// Warn about running tests without the `wasm_syscall` feature enabled.
// The javascript shim implements the syscall interface so that test
// output can be correctly reported.
if !builder.config.wasm_syscall {
builder.info(&format!("Libstd was built without `wasm_syscall` feature enabled: \
test output may not be visible."));
builder.info(&format!(
"Libstd was built without `wasm_syscall` feature enabled: \
test output may not be visible."
));
}
// On the wasm32-unknown-unknown target we're using LTO which is
// incompatible with `-C prefer-dynamic`, so disable that here
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
let node = builder.config.nodejs.as_ref()
let node = builder
.config
.nodejs
.as_ref()
.expect("nodejs not configured");
let runner = format!("{} {}/src/etc/wasm32-shim.js",
node.display(),
builder.src.display());
let runner = format!(
"{} {}/src/etc/wasm32-shim.js",
node.display(),
builder.src.display()
);
cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), &runner);
} else if builder.remote_tested(target) {
cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
format!("{} run",
builder.tool_exe(Tool::RemoteTestClient).display()));
cargo.env(
format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
format!("{} run", builder.tool_exe(Tool::RemoteTestClient).display()),
);
}
let _folder = builder.fold_output(|| {
format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate)
format!(
"{}_stage{}-{}",
test_kind.subcommand(),
compiler.stage,
krate
)
});
builder.info(&format!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage,
&compiler.host, target));
builder.info(&format!(
"{} {} stage{} ({} -> {})",
test_kind, krate, compiler.stage, &compiler.host, target
));
let _time = util::timeit(&builder);
try_run(builder, &mut cargo);
}
@ -1603,13 +1726,7 @@ impl Step for CrateRustdoc {
fn make_run(run: RunConfig) {
let builder = run.builder;
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();
builder.ensure(CrateRustdoc {
host: run.host,
@ -1622,12 +1739,15 @@ impl Step for CrateRustdoc {
let compiler = builder.compiler(builder.top_stage, self.host);
let target = compiler.host;
builder.ensure(compile::Rustc { compiler, target });
let mut cargo = tool::prepare_tool_cargo(builder,
compiler,
Mode::ToolRustc,
target,
test_kind.subcommand(),
"src/tools/rustdoc");
"src/tools/rustdoc",
SourceType::InTree);
if test_kind.subcommand() == "test" && !builder.fail_fast {
cargo.arg("--no-fail-fast");
}
@ -1637,15 +1757,16 @@ impl Step for CrateRustdoc {
cargo.arg("--");
cargo.args(&builder.config.cmd.test_args());
if builder.config.quiet_tests {
if !builder.config.verbose_tests {
cargo.arg("--quiet");
}
let _folder = builder.fold_output(|| {
format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage)
});
builder.info(&format!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage,
&compiler.host, target));
let _folder = builder
.fold_output(|| format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage));
builder.info(&format!(
"{} rustdoc stage{} ({} -> {})",
test_kind, compiler.stage, &compiler.host, target
));
let _time = util::timeit(&builder);
try_run(builder, &mut cargo);
@ -1653,12 +1774,13 @@ impl Step for CrateRustdoc {
}
fn envify(s: &str) -> String {
s.chars().map(|c| {
match c {
s.chars()
.map(|c| match c {
'-' => '_',
c => c,
}
}).flat_map(|c| c.to_uppercase()).collect()
})
.flat_map(|c| c.to_uppercase())
.collect()
}
/// Some test suites are run inside emulators or on remote devices, and most
@ -1687,7 +1809,7 @@ impl Step for RemoteCopyLibs {
let compiler = self.compiler;
let target = self.target;
if !builder.remote_tested(target) {
return
return;
}
builder.ensure(compile::Test { compiler, target });
@ -1695,15 +1817,18 @@ impl Step for RemoteCopyLibs {
builder.info(&format!("REMOTE copy libs to emulator ({})", target));
t!(fs::create_dir_all(builder.out.join("tmp")));
let server = builder.ensure(tool::RemoteTestServer { compiler, target });
let server = builder.ensure(tool::RemoteTestServer {
compiler: compiler.with_stage(0),
target,
});
// Spawn the emulator and wait for it to come online
let tool = builder.tool_exe(Tool::RemoteTestClient);
let mut cmd = Command::new(&tool);
cmd.arg("spawn-emulator")
.arg(target)
.arg(&server)
.arg(builder.out.join("tmp"));
.arg(target)
.arg(&server)
.arg(builder.out.join("tmp"));
if let Some(rootfs) = builder.qemu_rootfs(target) {
cmd.arg(rootfs);
}
@ -1714,9 +1839,7 @@ impl Step for RemoteCopyLibs {
let f = t!(f);
let name = f.file_name().into_string().unwrap();
if util::is_dylib(&name) {
builder.run(Command::new(&tool)
.arg("push")
.arg(f.path()));
builder.run(Command::new(&tool).arg("push").arg(f.path()));
}
}
}
@ -1749,17 +1872,21 @@ impl Step for Distcheck {
let mut cmd = Command::new("tar");
cmd.arg("-xzf")
.arg(builder.ensure(dist::PlainSourceTarball))
.arg("--strip-components=1")
.current_dir(&dir);
.arg(builder.ensure(dist::PlainSourceTarball))
.arg("--strip-components=1")
.current_dir(&dir);
builder.run(&mut cmd);
builder.run(Command::new("./configure")
.args(&builder.config.configure_args)
.arg("--enable-vendor")
.current_dir(&dir));
builder.run(Command::new(build_helper::make(&builder.config.build))
.arg("check")
.current_dir(&dir));
builder.run(
Command::new("./configure")
.args(&builder.config.configure_args)
.arg("--enable-vendor")
.current_dir(&dir),
);
builder.run(
Command::new(build_helper::make(&builder.config.build))
.arg("check")
.current_dir(&dir),
);
// Now make sure that rust-src has all of libstd's dependencies
builder.info(&format!("Distcheck rust-src"));
@ -1769,17 +1896,19 @@ impl Step for Distcheck {
let mut cmd = Command::new("tar");
cmd.arg("-xzf")
.arg(builder.ensure(dist::Src))
.arg("--strip-components=1")
.current_dir(&dir);
.arg(builder.ensure(dist::Src))
.arg("--strip-components=1")
.current_dir(&dir);
builder.run(&mut cmd);
let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
builder.run(Command::new(&builder.initial_cargo)
.arg("generate-lockfile")
.arg("--manifest-path")
.arg(&toml)
.current_dir(&dir));
builder.run(
Command::new(&builder.initial_cargo)
.arg("generate-lockfile")
.arg("--manifest-path")
.arg(&toml)
.current_dir(&dir),
);
}
}
@ -1795,11 +1924,11 @@ impl Step for Bootstrap {
fn run(self, builder: &Builder) {
let mut cmd = Command::new(&builder.initial_cargo);
cmd.arg("test")
.current_dir(builder.src.join("src/bootstrap"))
.env("RUSTFLAGS", "-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
.env("RUSTC", &builder.initial_rustc);
.current_dir(builder.src.join("src/bootstrap"))
.env("RUSTFLAGS", "-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
.env("RUSTC", &builder.initial_rustc);
if let Some(flags) = option_env!("RUSTFLAGS") {
// Use the same rustc flags for testing as for "normal" compilation,
// so that Cargo doesnt recompile the entire dependency graph every time:
@ -1810,6 +1939,9 @@ impl Step for Bootstrap {
cmd.arg("--no-fail-fast");
}
cmd.arg("--").args(&builder.config.cmd.test_args());
// rustbuild tests are racy on directory creation so just run them one at a time.
// Since there's not many this shouldn't be a problem.
cmd.arg("--test-threads=1");
try_run(builder, &mut cmd);
}

View File

@ -10,8 +10,10 @@
use std::fs;
use std::env;
use std::iter;
use std::path::PathBuf;
use std::process::{Command, exit};
use std::collections::HashSet;
use Mode;
use Compiler;
@ -27,7 +29,7 @@ use toolstate::ToolState;
pub struct CleanTools {
pub compiler: Compiler,
pub target: Interned<String>,
pub mode: Mode,
pub cause: Mode,
}
impl Step for CleanTools {
@ -40,23 +42,23 @@ impl Step for CleanTools {
fn run(self, builder: &Builder) {
let compiler = self.compiler;
let target = self.target;
let mode = self.mode;
let cause = self.cause;
// This is for the original compiler, but if we're forced to use stage 1, then
// std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
// we copy the libs forward.
let tools_dir = builder.stage_out(compiler, Mode::Tool);
let tools_dir = builder.stage_out(compiler, Mode::ToolRustc);
let compiler = if builder.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host)
} else {
compiler
};
for &cur_mode in &[Mode::Libstd, Mode::Libtest, Mode::Librustc] {
for &cur_mode in &[Mode::Std, Mode::Test, Mode::Rustc] {
let stamp = match cur_mode {
Mode::Libstd => libstd_stamp(builder, compiler, target),
Mode::Libtest => libtest_stamp(builder, compiler, target),
Mode::Librustc => librustc_stamp(builder, compiler, target),
Mode::Std => libstd_stamp(builder, compiler, target),
Mode::Test => libtest_stamp(builder, compiler, target),
Mode::Rustc => librustc_stamp(builder, compiler, target),
_ => panic!(),
};
@ -66,13 +68,19 @@ impl Step for CleanTools {
// If we are a rustc tool, and std changed, we also need to clear ourselves out -- our
// dependencies depend on std. Therefore, we iterate up until our own mode.
if mode == cur_mode {
if cause == cur_mode {
break;
}
}
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum SourceType {
InTree,
Submodule,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct ToolBuild {
compiler: Compiler,
@ -80,7 +88,8 @@ struct ToolBuild {
tool: &'static str,
path: &'static str,
mode: Mode,
is_ext_tool: bool,
is_optional_tool: bool,
source_type: SourceType,
extra_features: Vec<String>,
}
@ -100,16 +109,28 @@ impl Step for ToolBuild {
let target = self.target;
let tool = self.tool;
let path = self.path;
let is_ext_tool = self.is_ext_tool;
let is_optional_tool = self.is_optional_tool;
match self.mode {
Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
Mode::Tool => panic!("unexpected Mode::Tool for tool build")
Mode::ToolRustc => {
builder.ensure(compile::Rustc { compiler, target })
}
Mode::ToolStd => {
builder.ensure(compile::Std { compiler, target })
}
Mode::ToolBootstrap => {} // uses downloaded stage0 compiler libs
_ => panic!("unexpected Mode for tool build")
}
let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
let mut cargo = prepare_tool_cargo(
builder,
compiler,
self.mode,
target,
"build",
path,
self.source_type,
);
cargo.arg("--features").arg(self.extra_features.join(" "));
let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
@ -117,8 +138,13 @@ impl Step for ToolBuild {
let mut duplicates = Vec::new();
let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| {
// Only care about big things like the RLS/Cargo for now
if tool != "rls" && tool != "cargo" {
return
match tool {
| "rls"
| "cargo"
| "clippy-driver"
=> {}
_ => return,
}
let (id, features, filenames) = match msg {
compile::CargoMessage::CompilerArtifact {
@ -177,12 +203,22 @@ impl Step for ToolBuild {
typically means that something was recompiled because \
a transitive dependency has different features activated \
than in a previous build:\n");
println!("the following dependencies are duplicated although they \
have the same features enabled:");
for (id, cur, prev) in duplicates.drain_filter(|(_, cur, prev)| cur.2 == prev.2) {
println!(" {}", id);
// same features
println!(" `{}` ({:?})\n `{}` ({:?})", cur.0, cur.1, prev.0, prev.1);
}
println!("the following dependencies have different features:");
for (id, cur, prev) in duplicates {
println!(" {}", id);
println!(" `{}` enabled features {:?} at {:?}",
cur.0, cur.2, cur.1);
println!(" `{}` enabled features {:?} at {:?}",
prev.0, prev.2, prev.1);
let cur_features: HashSet<_> = cur.2.into_iter().collect();
let prev_features: HashSet<_> = prev.2.into_iter().collect();
println!(" `{}` additionally enabled features {:?} at {:?}",
cur.0, &cur_features - &prev_features, cur.1);
println!(" `{}` additionally enabled features {:?} at {:?}",
prev.0, &prev_features - &cur_features, prev.1);
}
println!("");
panic!("tools should not compile multiple copies of the same crate");
@ -195,13 +231,13 @@ impl Step for ToolBuild {
});
if !is_expected {
if !is_ext_tool {
if !is_optional_tool {
exit(1);
} else {
return None;
}
} else {
let cargo_out = builder.cargo_out(compiler, Mode::Tool, target)
let cargo_out = builder.cargo_out(compiler, self.mode, target)
.join(exe(tool, &compiler.host));
let bin = builder.tools_dir(compiler).join(exe(tool, &compiler.host));
builder.copy(&cargo_out, &bin);
@ -213,11 +249,13 @@ impl Step for ToolBuild {
pub fn prepare_tool_cargo(
builder: &Builder,
compiler: Compiler,
mode: Mode,
target: Interned<String>,
command: &'static str,
path: &'static str,
source_type: SourceType,
) -> Command {
let mut cargo = builder.cargo(compiler, Mode::Tool, target, command);
let mut cargo = builder.cargo(compiler, mode, target, command);
let dir = builder.src.join(path);
cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
@ -225,6 +263,10 @@ pub fn prepare_tool_cargo(
// stages and such and it's just easier if they're not dynamically linked.
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
if source_type == SourceType::Submodule {
cargo.env("RUSTC_EXTERNAL_TOOL", "1");
}
if let Some(dir) = builder.openssl_install_dir(target) {
cargo.env("OPENSSL_STATIC", "1");
cargo.env("OPENSSL_DIR", dir);
@ -252,14 +294,31 @@ pub fn prepare_tool_cargo(
}
macro_rules! tool {
($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
#[derive(Copy, Clone)]
($($name:ident, $path:expr, $tool_name:expr, $mode:expr
$(,llvm_tools = $llvm:expr)* $(,is_external_tool = $external:expr)*;)+) => {
#[derive(Copy, PartialEq, Eq, Clone)]
pub enum Tool {
$(
$name,
)+
}
impl Tool {
pub fn get_mode(&self) -> Mode {
let mode = match self {
$(Tool::$name => $mode,)+
};
mode
}
/// Whether this tool requires LLVM to run
pub fn uses_llvm_tools(&self) -> bool {
match self {
$(Tool::$name => false $(|| $llvm)*,)+
}
}
}
impl<'a> Builder<'a> {
pub fn tool_exe(&self, tool: Tool) -> PathBuf {
let stage = self.tool_default_stage(tool);
@ -313,7 +372,12 @@ macro_rules! tool {
tool: $tool_name,
mode: $mode,
path: $path,
is_ext_tool: false,
is_optional_tool: false,
source_type: if false $(|| $external)* {
SourceType::Submodule
} else {
SourceType::InTree
},
extra_features: Vec::new(),
}).expect("expected to build -- essential tool")
}
@ -323,17 +387,18 @@ macro_rules! tool {
}
tool!(
Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
RustInstaller, "src/tools/rust-installer", "fabricate", Mode::Libstd;
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::Libstd;
Rustbook, "src/tools/rustbook", "rustbook", Mode::ToolBootstrap;
ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::ToolRustc;
UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::ToolBootstrap;
Tidy, "src/tools/tidy", "tidy", Mode::ToolBootstrap;
Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::ToolBootstrap;
CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolBootstrap;
Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolBootstrap, llvm_tools = true;
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolBootstrap;
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolBootstrap;
RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolBootstrap,
is_external_tool = true;
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::ToolBootstrap;
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@ -361,9 +426,10 @@ impl Step for RemoteTestServer {
compiler: self.compiler,
target: self.target,
tool: "remote-test-server",
mode: Mode::Libstd,
mode: Mode::ToolStd,
path: "src/tools/remote-test-server",
is_ext_tool: false,
is_optional_tool: false,
source_type: SourceType::InTree,
extra_features: Vec::new(),
}).expect("expected to build -- essential tool")
}
@ -411,11 +477,15 @@ impl Step for Rustdoc {
target: builder.config.build,
});
let mut cargo = prepare_tool_cargo(builder,
build_compiler,
target,
"build",
"src/tools/rustdoc");
let mut cargo = prepare_tool_cargo(
builder,
build_compiler,
Mode::ToolRustc,
target,
"build",
"src/tools/rustdoc",
SourceType::InTree,
);
// Most tools don't get debuginfo, but rustdoc should.
cargo.env("RUSTC_DEBUGINFO", builder.config.rust_debuginfo.to_string())
@ -429,8 +499,8 @@ impl Step for Rustdoc {
// Cargo adds a number of paths to the dylib search path on windows, which results in
// the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
// rustdoc a different name.
let tool_rustdoc = builder.cargo_out(build_compiler, Mode::Tool, target)
.join(exe("rustdoc-tool-binary", &target_compiler.host));
let tool_rustdoc = builder.cargo_out(build_compiler, Mode::ToolRustc, target)
.join(exe("rustdoc_tool_binary", &target_compiler.host));
// don't create a stage0-sysroot/bin directory.
if target_compiler.stage > 0 {
@ -484,9 +554,10 @@ impl Step for Cargo {
compiler: self.compiler,
target: self.target,
tool: "cargo",
mode: Mode::Librustc,
mode: Mode::ToolRustc,
path: "src/tools/cargo",
is_ext_tool: false,
is_optional_tool: false,
source_type: SourceType::Submodule,
extra_features: Vec::new(),
}).expect("expected to build -- essential tool")
}
@ -532,10 +603,11 @@ macro_rules! tool_extended {
compiler: $sel.compiler,
target: $sel.target,
tool: $tool_name,
mode: Mode::Librustc,
mode: Mode::ToolRustc,
path: $path,
extra_features: $sel.extra_features,
is_ext_tool: true,
is_optional_tool: true,
source_type: SourceType::Submodule,
})
}
}
@ -545,6 +617,14 @@ macro_rules! tool_extended {
tool_extended!((self, builder),
Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", {};
CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", {
// Clippy depends on procedural macros (serde), which requires a full host
// compiler to be available, so we need to depend on that.
builder.ensure(compile::Rustc {
compiler: self.compiler,
target: builder.config.build,
});
};
Clippy, clippy, "src/tools/clippy", "clippy-driver", {
// Clippy depends on procedural macros (serde), which requires a full host
// compiler to be available, so we need to depend on that.
@ -560,8 +640,7 @@ tool_extended!((self, builder),
target: self.target,
extra_features: Vec::new(),
});
let channel = &builder.config.channel;
if clippy.is_some() && channel != "stable" && channel != "beta" {
if clippy.is_some() {
self.extra_features.push("clippy".to_owned());
}
builder.ensure(native::Openssl {
@ -583,7 +662,7 @@ impl<'a> Builder<'a> {
pub fn tool_cmd(&self, tool: Tool) -> Command {
let mut cmd = Command::new(self.tool_exe(tool));
let compiler = self.compiler(self.tool_default_stage(tool), self.config.build);
self.prepare_tool_cmd(compiler, &mut cmd);
self.prepare_tool_cmd(compiler, tool, &mut cmd);
cmd
}
@ -591,11 +670,15 @@ impl<'a> Builder<'a> {
///
/// Notably this munges the dynamic library lookup path to point to the
/// right location to run `compiler`.
fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
fn prepare_tool_cmd(&self, compiler: Compiler, tool: Tool, cmd: &mut Command) {
let host = &compiler.host;
let mut paths: Vec<PathBuf> = vec![
PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
let mut lib_paths: Vec<PathBuf> = vec![
if compiler.stage == 0 && tool != Tool::ErrorIndex {
self.build.rustc_snapshot_libdir()
} else {
PathBuf::from(&self.sysroot_libdir(compiler, compiler.host))
},
self.cargo_out(compiler, tool.get_mode(), *host).join("deps"),
];
// On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
@ -610,11 +693,48 @@ impl<'a> Builder<'a> {
}
for path in env::split_paths(v) {
if !curpaths.contains(&path) {
paths.push(path);
lib_paths.push(path);
}
}
}
}
add_lib_path(paths, cmd);
// Add the llvm/bin directory to PATH since it contains lots of
// useful, platform-independent tools
if tool.uses_llvm_tools() {
if let Some(llvm_bin_path) = self.llvm_bin_path() {
if host.contains("windows") {
// On Windows, PATH and the dynamic library path are the same,
// so we just add the LLVM bin path to lib_path
lib_paths.push(llvm_bin_path);
} else {
let old_path = env::var_os("PATH").unwrap_or_default();
let new_path = env::join_paths(iter::once(llvm_bin_path)
.chain(env::split_paths(&old_path)))
.expect("Could not add LLVM bin path to PATH");
cmd.env("PATH", new_path);
}
}
}
add_lib_path(lib_paths, cmd);
}
fn llvm_bin_path(&self) -> Option<PathBuf> {
if self.config.llvm_enabled && !self.config.dry_run {
let llvm_config = self.ensure(native::Llvm {
target: self.config.build,
emscripten: false,
});
// Add the llvm/bin directory to PATH since it contains lots of
// useful, platform-independent tools
let llvm_bin_path = llvm_config.parent()
.expect("Expected llvm-config to be contained in directory");
assert!(llvm_bin_path.is_dir());
Some(llvm_bin_path.to_path_buf())
} else {
None
}
}
}

View File

@ -92,10 +92,7 @@ pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf {
file.push_str(".exe");
}
for c in components {
buf.push(c);
}
buf.extend(components);
buf.push(file);
buf

View File

@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::{SystemTime, UNIX_EPOCH};
use std::{env, fs};
use std::thread;
/// A helper macro to `unwrap` a result except also print out details like:
///
@ -179,7 +180,9 @@ pub struct NativeLibBoilerplate {
impl Drop for NativeLibBoilerplate {
fn drop(&mut self) {
t!(File::create(self.out_dir.join("rustbuild.timestamp")));
if !thread::panicking() {
t!(File::create(self.out_dir.join("rustbuild.timestamp")));
}
}
}
@ -223,24 +226,34 @@ pub fn native_lib_boilerplate(
}
}
pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result<NativeLibBoilerplate, ()> {
let (link_name, search_path) = match &*env::var("TARGET").unwrap() {
pub fn sanitizer_lib_boilerplate(sanitizer_name: &str)
-> Result<(NativeLibBoilerplate, String), ()>
{
let (link_name, search_path, dynamic) = match &*env::var("TARGET").unwrap() {
"x86_64-unknown-linux-gnu" => (
format!("clang_rt.{}-x86_64", sanitizer_name),
"build/lib/linux",
false,
),
"x86_64-apple-darwin" => (
format!("dylib=clang_rt.{}_osx_dynamic", sanitizer_name),
format!("clang_rt.{}_osx_dynamic", sanitizer_name),
"build/lib/darwin",
true,
),
_ => return Err(()),
};
native_lib_boilerplate(
let to_link = if dynamic {
format!("dylib={}", link_name)
} else {
format!("static={}", link_name)
};
let lib = native_lib_boilerplate(
"libcompiler_builtins/compiler-rt",
sanitizer_name,
&link_name,
&to_link,
search_path,
)
)?;
Ok((lib, link_name))
}
fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {

View File

@ -0,0 +1,36 @@
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
make \
file \
curl \
ca-certificates \
python2.7 \
git \
cmake \
sudo \
xz-utils \
bzip2 \
libssl-dev \
pkg-config
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV BASE_URL=https://releases.linaro.org/components/toolchain/binaries/latest/armeb-eabi/
ENV GCC_LINARO=gcc-linaro-7.2.1-2017.11-x86_64_armeb-eabi
RUN curl -sL $BASE_URL/$GCC_LINARO.tar.xz | tar -xJ
ENV PATH=$PATH:/$GCC_LINARO/bin
ENV TARGET=armebv7r-none-eabihf
ENV CC_armebv7r_none_eabihf=armeb-eabi-gcc \
CFLAGS_armebv7r_none_eabihf="-march=armv7-r"
ENV RUST_CONFIGURE_ARGS --disable-docs
ENV SCRIPT python2.7 ../x.py dist --target $TARGET

View File

@ -0,0 +1,26 @@
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
make \
file \
curl \
ca-certificates \
python2.7 \
git \
cmake \
sudo \
gdb \
xz-utils \
g++-sparc64-linux-gnu \
libssl-dev \
pkg-config
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV HOSTS=sparc64-unknown-linux-gnu
ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS

View File

@ -42,9 +42,7 @@ ENV RUST_CONFIGURE_ARGS \
# See: https://github.com/rust-lang/rust/issues/34978
ENV CFLAGS_i686_unknown_linux_musl=-Wa,-mrelax-relocations=no
ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
# FIXME remove -Wl,-melf_i386 after cc is updated to include
# https://github.com/alexcrichton/cc-rs/pull/281
ENV CFLAGS_i586_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wl,-melf_i386"
ENV CFLAGS_i586_unknown_linux_musl=-Wa,-mrelax-relocations=no
ENV TARGETS=i586-unknown-linux-gnu,i686-unknown-linux-musl

View File

@ -29,13 +29,13 @@ ENV PATH=/rustroot/bin:$PATH
ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib
ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
WORKDIR /tmp
COPY dist-i686-linux/shared.sh dist-i686-linux/build-binutils.sh /tmp/
COPY dist-x86_64-linux/shared.sh /tmp/
# We need a build of openssl which supports SNI to download artifacts from
# static.rust-lang.org. This'll be used to link into libcurl below (and used
# later as well), so build a copy of OpenSSL with dynamic libraries into our
# generic root.
COPY dist-i686-linux/build-openssl.sh /tmp/
COPY dist-x86_64-linux/build-openssl.sh /tmp/
RUN ./build-openssl.sh
# The `curl` binary on CentOS doesn't support SNI which is needed for fetching
@ -44,36 +44,43 @@ RUN ./build-openssl.sh
#
# Note that we also disable a bunch of optional features of curl that we don't
# really need.
COPY dist-i686-linux/build-curl.sh /tmp/
COPY dist-x86_64-linux/build-curl.sh /tmp/
RUN ./build-curl.sh
# binutils < 2.22 has a bug where the 32-bit executables it generates
# immediately segfault in Rust, so we need to install our own binutils.
#
# See https://github.com/rust-lang/rust/issues/20440 for more info
COPY dist-x86_64-linux/build-binutils.sh /tmp/
RUN ./build-binutils.sh
# Need a newer version of gcc than centos has to compile LLVM nowadays
COPY dist-i686-linux/build-gcc.sh /tmp/
RUN ./build-gcc.sh
# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+
COPY dist-i686-linux/build-python.sh /tmp/
RUN ./build-python.sh
# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for
# cloning, so download and build it here.
COPY dist-i686-linux/build-git.sh /tmp/
RUN ./build-git.sh
# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS
# only has 2.6.4, so build our own
COPY dist-i686-linux/build-cmake.sh /tmp/
COPY dist-x86_64-linux/build-cmake.sh /tmp/
RUN ./build-cmake.sh
# Need a newer version of gcc than centos has to compile LLVM nowadays
COPY dist-x86_64-linux/build-gcc.sh /tmp/
RUN ./build-gcc.sh
# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+
COPY dist-x86_64-linux/build-python.sh /tmp/
RUN ./build-python.sh
# Now build LLVM+Clang 6, afterwards configuring further compilations to use the
# clang/clang++ compilers.
COPY dist-x86_64-linux/build-clang.sh /tmp/
RUN ./build-clang.sh
ENV CC=clang CXX=clang++
# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for
# cloning, so download and build it here.
COPY dist-x86_64-linux/build-git.sh /tmp/
RUN ./build-git.sh
# for sanitizers, we need kernel headers files newer than the ones CentOS ships
# with so we install newer ones here
COPY dist-i686-linux/build-headers.sh /tmp/
COPY dist-x86_64-linux/build-headers.sh /tmp/
RUN ./build-headers.sh
COPY scripts/sccache.sh /scripts/
@ -84,11 +91,21 @@ ENV HOSTS=i686-unknown-linux-gnu
ENV RUST_CONFIGURE_ARGS \
--enable-full-tools \
--enable-sanitizers \
--enable-profiler
--enable-profiler \
--set target.i686-unknown-linux-gnu.linker=clang \
--build=i686-unknown-linux-gnu
ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS
ENV CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER=clang
# This is the only builder which will create source tarballs
ENV DIST_SRC 1
# This was added when we switched from gcc to clang. It's not clear why this is
# needed unfortunately, but without this the stage1 bootstrap segfaults
# somewhere inside of a build script. The build ends up just hanging instead of
# actually killing the process that segfaulted, but if the process is run
# manually in a debugger the segfault is immediately seen as well as the
# misaligned stack access.
#
# Added in #50200 there's some more logs there
ENV CFLAGS -mstackrealign
# When we build cargo in this container, we don't want it to use the system
# libcurl, instead it should compile its own.

View File

@ -1,26 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
curl https://ftp.gnu.org/gnu/binutils/binutils-2.25.1.tar.bz2 | tar xfj -
mkdir binutils-build
cd binutils-build
hide_output ../binutils-2.25.1/configure --prefix=/rustroot
hide_output make -j10
hide_output make install
cd ..
rm -rf binutils-build
rm -rf binutils-2.25.1

View File

@ -1,25 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
curl https://cmake.org/files/v3.6/cmake-3.6.3.tar.gz | tar xzf -
mkdir cmake-build
cd cmake-build
hide_output ../cmake-3.6.3/configure --prefix=/rustroot
hide_output make -j10
hide_output make install
cd ..
rm -rf cmake-build
rm -rf cmake-3.6.3

View File

@ -1,43 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
VERSION=7.51.0
curl http://cool.haxx.se/download/curl-$VERSION.tar.bz2 | tar xjf -
mkdir curl-build
cd curl-build
hide_output ../curl-$VERSION/configure \
--prefix=/rustroot \
--with-ssl=/rustroot \
--disable-sspi \
--disable-gopher \
--disable-smtp \
--disable-smb \
--disable-imap \
--disable-pop3 \
--disable-tftp \
--disable-telnet \
--disable-manual \
--disable-dict \
--disable-rtsp \
--disable-ldaps \
--disable-ldap
hide_output make -j10
hide_output make install
cd ..
rm -rf curl-build
rm -rf curl-$VERSION
yum erase -y curl

View File

@ -1,50 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
GCC=4.8.5
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
cd gcc-$GCC
# FIXME(#49246): Remove the `sed` below.
#
# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this
# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue:
# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection
# timed out" error, and even when the download completed, the file is usually corrupted. This causes
# nothing to be landed that day.
#
# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability
# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third
# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the
# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
# instead here.
#
sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
./contrib/download_prerequisites
mkdir ../gcc-build
cd ../gcc-build
hide_output ../gcc-$GCC/configure \
--prefix=/rustroot \
--enable-languages=c,c++
hide_output make -j10
hide_output make install
ln -nsf gcc /rustroot/bin/cc
cd ..
rm -rf gcc-build
rm -rf gcc-$GCC
yum erase -y gcc gcc-c++ binutils

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
cd git-2.10.0
make configure
hide_output ./configure --prefix=/rustroot
hide_output make -j10
hide_output make install
cd ..
rm -rf git-2.10.0

View File

@ -1,25 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
curl https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.2.84.tar.xz | unxz | tar x
cd linux-3.2.84
hide_output make mrproper
hide_output make INSTALL_HDR_PATH=dest headers_install
find dest/include \( -name .install -o -name ..install.cmd \) -delete
yes | cp -fr dest/include/* /usr/include
cd ..
rm -rf linux-3.2.84

View File

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
VERSION=1.0.2k
URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/openssl-$VERSION.tar.gz
curl $URL | tar xzf -
cd openssl-$VERSION
hide_output ./config --prefix=/rustroot shared -fPIC
hide_output make -j10
hide_output make install
cd ..
rm -rf openssl-$VERSION
# Make the system cert collection available to the new install.
ln -nsf /etc/pki/tls/cert.pem /rustroot/ssl/

View File

@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
curl https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz | \
tar xzf -
mkdir python-build
cd python-build
# Gotta do some hackery to tell python about our custom OpenSSL build, but other
# than that fairly normal.
CFLAGS='-I /rustroot/include' LDFLAGS='-L /rustroot/lib -L /rustroot/lib64' \
hide_output ../Python-2.7.12/configure --prefix=/rustroot
hide_output make -j10
hide_output make install
cd ..
rm -rf python-build
rm -rf Python-2.7.12

View File

@ -1,25 +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 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
hide_output() {
set +x
on_err="
echo ERROR: An error was encountered with the build.
cat /tmp/build.log
exit 1
"
trap "$on_err" ERR
bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
PING_LOOP_PID=$!
$@ &> /tmp/build.log
trap - ERR
kill $PING_LOOP_PID
set -x
}

View File

@ -80,6 +80,11 @@ RUN \
echo "# a" >> /usr/local/mips-linux-musl/bin/mips-openwrt-linux-musl-wrapper.sh && \
echo "# b" >> /usr/local/mipsel-linux-musl/bin/mipsel-openwrt-linux-musl-wrapper.sh
ENV RUN_MAKE_TARGETS=thumbv6m-none-eabi
ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7m-none-eabi
ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7em-none-eabi
ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7em-none-eabihf
ENV TARGETS=asmjs-unknown-emscripten
ENV TARGETS=$TARGETS,wasm32-unknown-emscripten
ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd
@ -98,16 +103,10 @@ ENV TARGETS=$TARGETS,thumbv7m-none-eabi
ENV TARGETS=$TARGETS,thumbv7em-none-eabi
ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
# FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271
# get fixed and cc update
ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
CC_armv5te_unknown_linux_gnueabi=arm-linux-gnueabi-gcc \
CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft" \
CC_armv5te_unknown_linux_musleabi=arm-linux-gnueabi-gcc \
CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft"
CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc
ENV RUST_CONFIGURE_ARGS \
--musl-root-armv5te=/musl-armv5te \
@ -120,7 +119,9 @@ ENV RUST_CONFIGURE_ARGS \
--enable-emscripten \
--disable-docs
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
ENV SCRIPT \
python2.7 ../x.py test --target $RUN_MAKE_TARGETS src/test/run-make && \
python2.7 ../x.py dist --target $TARGETS
# sccache
COPY scripts/sccache.sh /scripts/

View File

@ -34,12 +34,12 @@ COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV \
AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \
CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \
CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \
AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \
CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \
CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ \
AR_x86_64_fuchsia=x86_64-fuchsia-ar \
CC_x86_64_fuchsia=x86_64-fuchsia-clang \
CXX_x86_64_fuchsia=x86_64-fuchsia-clang++ \
AR_aarch64_fuchsia=aarch64-fuchsia-ar \
CC_aarch64_fuchsia=aarch64-fuchsia-clang \
CXX_aarch64_fuchsia=aarch64-fuchsia-clang++ \
AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-ar \
CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-gcc \
CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-g++ \
@ -47,8 +47,8 @@ ENV \
CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \
CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++
ENV TARGETS=x86_64-unknown-fuchsia
ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
ENV TARGETS=x86_64-fuchsia
ENV TARGETS=$TARGETS,aarch64-fuchsia
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
ENV TARGETS=$TARGETS,wasm32-unknown-unknown
ENV TARGETS=$TARGETS,x86_64-sun-solaris

View File

@ -39,7 +39,7 @@ build() {
esac
hide_output make -j$(getconf _NPROCESSORS_ONLN) $tgt
dst=/usr/local/${arch}-unknown-fuchsia
dst=/usr/local/${arch}-fuchsia
mkdir -p $dst
cp -a build-${tgt}/sysroot/include $dst/
cp -a build-${tgt}/sysroot/lib $dst/
@ -55,11 +55,11 @@ rm -rf zircon
for arch in x86_64 aarch64; do
for tool in clang clang++; do
cat >/usr/local/bin/${arch}-unknown-fuchsia-${tool} <<EOF
cat >/usr/local/bin/${arch}-fuchsia-${tool} <<EOF
#!/bin/sh
${tool} --target=${arch}-unknown-fuchsia --sysroot=/usr/local/${arch}-unknown-fuchsia "\$@"
${tool} --target=${arch}-fuchsia --sysroot=/usr/local/${arch}-fuchsia "\$@"
EOF
chmod +x /usr/local/bin/${arch}-unknown-fuchsia-${tool}
chmod +x /usr/local/bin/${arch}-fuchsia-${tool}
done
ln -s /usr/local/bin/llvm-ar /usr/local/bin/${arch}-unknown-fuchsia-ar
ln -s /usr/local/bin/llvm-ar /usr/local/bin/${arch}-fuchsia-ar
done

View File

@ -29,7 +29,7 @@ ENV PATH=/rustroot/bin:$PATH
ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib
ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
WORKDIR /tmp
COPY dist-x86_64-linux/shared.sh dist-x86_64-linux/build-binutils.sh /tmp/
COPY dist-x86_64-linux/shared.sh /tmp/
# We need a build of openssl which supports SNI to download artifacts from
# static.rust-lang.org. This'll be used to link into libcurl below (and used
@ -51,9 +51,15 @@ RUN ./build-curl.sh
# immediately segfault in Rust, so we need to install our own binutils.
#
# See https://github.com/rust-lang/rust/issues/20440 for more info
COPY dist-x86_64-linux/build-binutils.sh /tmp/
RUN ./build-binutils.sh
# Need a newer version of gcc than centos has to compile LLVM nowadays
# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS
# only has 2.6.4, so build our own
COPY dist-x86_64-linux/build-cmake.sh /tmp/
RUN ./build-cmake.sh
# Build a version of gcc capable of building LLVM 6
COPY dist-x86_64-linux/build-gcc.sh /tmp/
RUN ./build-gcc.sh
@ -61,16 +67,17 @@ RUN ./build-gcc.sh
COPY dist-x86_64-linux/build-python.sh /tmp/
RUN ./build-python.sh
# Now build LLVM+Clang 6, afterwards configuring further compilations to use the
# clang/clang++ compilers.
COPY dist-x86_64-linux/build-clang.sh /tmp/
RUN ./build-clang.sh
ENV CC=clang CXX=clang++
# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for
# cloning, so download and build it here.
COPY dist-x86_64-linux/build-git.sh /tmp/
RUN ./build-git.sh
# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS
# only has 2.6.4, so build our own
COPY dist-x86_64-linux/build-cmake.sh /tmp/
RUN ./build-cmake.sh
# for sanitizers, we need kernel headers files newer than the ones CentOS ships
# with so we install newer ones here
COPY dist-x86_64-linux/build-headers.sh /tmp/
@ -85,8 +92,10 @@ ENV RUST_CONFIGURE_ARGS \
--enable-full-tools \
--enable-sanitizers \
--enable-profiler \
--enable-compiler-docs
--enable-compiler-docs \
--set target.x86_64-unknown-linux-gnu.linker=clang
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
# This is the only builder which will create source tarballs
ENV DIST_SRC 1

View File

@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set -ex
source shared.sh
LLVM=6.0.0
mkdir clang
cd clang
curl https://releases.llvm.org/$LLVM/llvm-$LLVM.src.tar.xz | \
xz -d | \
tar xf -
cd llvm-$LLVM.src
mkdir -p tools/clang
curl https://releases.llvm.org/$LLVM/cfe-$LLVM.src.tar.xz | \
xz -d | \
tar xf - -C tools/clang --strip-components=1
mkdir ../clang-build
cd ../clang-build
# For whatever reason the default set of include paths for clang is different
# than that of gcc. As a result we need to manually include our sysroot's
# include path, /rustroot/include, to clang's default include path.
#
# Alsow there's this weird oddity with gcc where there's an 'include-fixed'
# directory that it generates. It turns out [1] that Centos 5's headers are so
# old that they're incompatible with modern C semantics. While gcc automatically
# fixes that clang doesn't account for this. Tell clang to manually include the
# fixed headers so we can successfully compile code later on.
#
# [1]: https://sourceware.org/ml/crossgcc/2008-11/msg00028.html
INC="/rustroot/include"
INC="$INC:/rustroot/lib/gcc/x86_64-unknown-linux-gnu/4.8.5/include-fixed"
INC="$INC:/usr/include"
hide_output \
cmake ../llvm-$LLVM.src \
-DCMAKE_C_COMPILER=/rustroot/bin/gcc \
-DCMAKE_CXX_COMPILER=/rustroot/bin/g++ \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/rustroot \
-DLLVM_TARGETS_TO_BUILD=X86 \
-DC_INCLUDE_DIRS="$INC"
hide_output make -j10
hide_output make install
cd ../..
rm -rf clang

View File

@ -42,7 +42,6 @@ hide_output ../gcc-$GCC/configure \
--enable-languages=c,c++
hide_output make -j10
hide_output make install
ln -nsf gcc /rustroot/bin/cc
cd ..
rm -rf gcc-build

View File

@ -36,8 +36,10 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
s3url="s3://$SCCACHE_BUCKET/docker/$cksum"
url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum"
echo "Attempting to download $s3url"
rm -f /tmp/rustci_docker_cache
set +e
loaded_images=$(curl $url | docker load | sed 's/.* sha/sha/')
retry curl -f -L -C - -o /tmp/rustci_docker_cache "$url"
loaded_images=$(docker load -i /tmp/rustci_docker_cache | sed 's/.* sha/sha/')
set -e
echo "Downloaded containers:\n$loaded_images"
fi
@ -97,6 +99,7 @@ objdir=$root_dir/obj
mkdir -p $HOME/.cargo
mkdir -p $objdir/tmp
mkdir -p $objdir/cores
args=
if [ "$SCCACHE_BUCKET" != "" ]; then
@ -116,6 +119,10 @@ fi
# goes ahead and sets it for all builders.
args="$args --privileged"
if [ "$CI" != "" ]; then
args="$args --dns 8.8.8.8 --dns 8.8.4.4 --dns 1.1.1.1 --dns 1.0.0.1"
fi
exec docker \
run \
--volume "$root_dir:/checkout:ro" \

View File

@ -32,11 +32,17 @@ shift
export CFLAGS="-fPIC $CFLAGS"
MUSL=musl-1.1.18
# FIXME: remove the patch when upate to 1.1.20
MUSL=musl-1.1.19
# may have been downloaded in a previous run
if [ ! -d $MUSL ]; then
curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf -
# Patch to fix https://github.com/rust-lang/rust/issues/48967
cd $MUSL && \
curl "https://git.musl-libc.org/cgit/musl/patch/?id=610c5a8524c3d6cd3ac5a5f1231422e7648a3791" |\
patch -p1 && \
cd -
fi
cd $MUSL

View File

@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
cmake \
sudo \
gdb \
llvm-3.9-tools \
llvm-5.0-tools \
libedit-dev \
zlib1g-dev \
xz-utils
@ -22,6 +22,6 @@ RUN sh /scripts/sccache.sh
# using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
--llvm-root=/usr/lib/llvm-3.9 \
--llvm-root=/usr/lib/llvm-5.0 \
--enable-llvm-link-shared
ENV RUST_CHECK_TARGET check

View File

@ -18,6 +18,7 @@ if __name__ == '__main__':
os_name = sys.argv[1]
toolstate_file = sys.argv[2]
current_state = sys.argv[3]
verb = sys.argv[4] # 'regressed' or 'changed'
with open(toolstate_file, 'r') as f:
toolstate = json.load(f)
@ -29,10 +30,17 @@ if __name__ == '__main__':
tool = cur['tool']
state = cur[os_name]
new_state = toolstate.get(tool, '')
if new_state < state:
if verb == 'regressed':
updated = new_state < state
elif verb == 'changed':
updated = new_state != state
else:
print('Unknown verb {}'.format(updated))
sys.exit(2)
if updated:
print(
'Error: The state of "{}" has regressed from "{}" to "{}"'
.format(tool, state, new_state)
'The state of "{}" has {} from "{}" to "{}"'
.format(tool, verb, state, new_state)
)
regressed = True

View File

@ -23,21 +23,25 @@ SIX_WEEK_CYCLE="$(( ($(date +%s) / 604800 - 3) % 6 ))"
touch "$TOOLSTATE_FILE"
# Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
set +e
python2.7 "$X_PY" test --no-fail-fast \
src/doc/book \
src/doc/nomicon \
src/doc/reference \
src/doc/rust-by-example \
src/tools/clippy \
src/tools/rls \
src/tools/rustfmt \
src/tools/miri \
src/tools/clippy
set -e
cat "$TOOLSTATE_FILE"
echo
# This function checks that if a tool's submodule changed, the tool's state must improve
verify_status() {
echo "Verifying status of $1..."
if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then
@ -57,35 +61,63 @@ verify_status() {
fi
}
# deduplicates the submodule check and the assertion that on beta some tools MUST be passing
check_dispatch() {
if [ "$1" = submodule_changed ]; then
# ignore $2 (branch id)
verify_status $3 $4
elif [ "$2" = beta ]; then
echo "Requiring test passing for $3..."
if grep -q '"'"$3"'":"\(test\|build\)-fail"' "$TOOLSTATE_FILE"; then
exit 4
fi
fi
}
# list all tools here
status_check() {
check_dispatch $1 beta book src/doc/book
check_dispatch $1 beta nomicon src/doc/nomicon
check_dispatch $1 beta reference src/doc/reference
check_dispatch $1 beta rust-by-example src/doc/rust-by-example
check_dispatch $1 beta rls src/tools/rls
check_dispatch $1 beta rustfmt src/tools/rustfmt
check_dispatch $1 beta clippy-driver src/tools/clippy
# these tools are not required for beta to successfully branch
check_dispatch $1 nightly miri src/tools/miri
}
# If this PR is intended to update one of these tools, do not let the build pass
# when they do not test-pass.
verify_status book src/doc/book
verify_status nomicon src/doc/nomicon
verify_status reference src/doc/reference
verify_status rust-by-example src/doc/rust-by-example
verify_status rls src/tool/rls
verify_status rustfmt src/tool/rustfmt
verify_status clippy-driver src/tool/clippy
verify_status miri src/tool/miri
status_check "submodule_changed"
if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
. "$(dirname $0)/repo.sh"
MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
echo "($OS CI update)" > "$MESSAGE_FILE"
commit_toolstate_change "$MESSAGE_FILE" \
CHECK_NOT="$(readlink -f "$(dirname $0)/checkregression.py")"
change_toolstate() {
# only update the history
if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then
echo 'Toolstate is not changed. Not updating.'
else
if [ $SIX_WEEK_CYCLE -eq 5 ]; then
python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed
fi
sed -i "1 a\\
$COMMIT\t$(cat "$TOOLSTATE_FILE")
" "history/$OS.tsv"
# if we are at the last week in the 6-week release cycle, reject any kind of regression.
if [ $SIX_WEEK_CYCLE -eq 5 ]; then
python2.7 "$(dirname $0)/checkregression.py" \
"$OS" "$TOOLSTATE_FILE" "rust-toolstate/_data/latest.json"
fi
rm -f "$MESSAGE_FILE"
}
if [ "$RUST_RELEASE_CHANNEL" = nightly ]; then
if [ -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
. "$(dirname $0)/repo.sh"
MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
echo "($OS CI update)" > "$MESSAGE_FILE"
commit_toolstate_change "$MESSAGE_FILE" change_toolstate
rm -f "$MESSAGE_FILE"
fi
exit 0
fi
if grep -q fail "$TOOLSTATE_FILE"; then
exit 4
fi
# abort compilation if an important tool doesn't build
# (this code is reachable if not on the nightly channel)
status_check "beta_required"

View File

@ -60,7 +60,7 @@ commit_toolstate_change() {
OLDFLAGS="$-"
set -eu
git config --global user.email '34210020+rust-toolstate-update@users.noreply.github.com'
git config --global user.email '7378925+rust-toolstate-update@users.noreply.github.com'
git config --global user.name 'Rust Toolstate Update'
git config --global credential.helper store
printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \

View File

@ -24,13 +24,16 @@ if [ "$NO_CHANGE_USER" = "" ]; then
fi
fi
# only enable core dump on Linux
if [ -f /proc/sys/kernel/core_pattern ]; then
ulimit -c unlimited
fi
ci_dir=`cd $(dirname $0) && pwd`
source "$ci_dir/shared.sh"
if [ "$TRAVIS" == "true" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-quiet-tests"
else
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings"
if [ "$TRAVIS" != "true" ] || [ "$TRAVIS_BRANCH" == "auto" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
fi
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"

View File

@ -21,11 +21,12 @@ function retry {
while true; do
"$@" && break || {
if [[ $n -lt $max ]]; then
sleep $n # don't retry immediately
((n++))
echo "Command failed. Attempt $n/$max:"
else
echo "The command has failed after $n attempts."
exit 1
return 1
fi
}
done

@ -1 +1 @@
Subproject commit f51127530d46b9acbf4747c859da185e771cfcf3
Subproject commit f475da63a18d50217459a601cbef69a4bcac5e71

View File

@ -101,29 +101,24 @@ properties: `ident`, `non_null`, `non_eol`, `non_single_quote` and
### Identifiers
The `ident` production is any nonempty Unicode[^non_ascii_idents] string of
The `ident` production is any nonempty Unicode string of
the following form:
[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
gated. This is expected to improve soon.
- The first character is in one of the following ranges `U+0041` to `U+005A`
("A" to "Z"), `U+0061` to `U+007A` ("a" to "z"), or `U+005F` ("\_").
- The remaining characters are in the range `U+0030` to `U+0039` ("0" to "9"),
or any of the prior valid initial characters.
- The first character has property `XID_start`
- The remaining characters have property `XID_continue`
that does _not_ occur in the set of [keywords](#keywords).
> **Note**: `XID_start` and `XID_continue` as character properties cover the
> character ranges used to form the more familiar C and Java language-family
> identifiers.
as long as the identifier does _not_ occur in the set of [keywords](#keywords).
### Delimiter-restricted productions
Some productions are defined by exclusion of particular Unicode characters:
- `non_null` is any single Unicode character aside from `U+0000` (null)
- `non_eol` is `non_null` restricted to exclude `U+000A` (`'\n'`)
- `non_single_quote` is `non_null` restricted to exclude `U+0027` (`'`)
- `non_double_quote` is `non_null` restricted to exclude `U+0022` (`"`)
- `non_eol` is any single Unicode character aside from `U+000A` (`'\n'`)
- `non_single_quote` is any single Unicode character aside from `U+0027` (`'`)
- `non_double_quote` is any single Unicode character aside from `U+0022` (`"`)
## Comments

View File

@ -55,7 +55,7 @@ Configure the output that \fBrustc\fR will produce. Each emission may also have
an optional explicit output \fIPATH\fR specified for that particular emission
kind. This path takes precedence over the \fB-o\fR option.
.TP
\fB\-\-print\fR [crate\-name|file\-names|sysroot]
\fB\-\-print\fR [crate\-name|\:file\-names|\:sysroot|\:cfg|\:target\-list|\:target\-cpus|\:target\-features|\:relocation\-models|\:code\-models|\:tls\-models|\:target\-spec\-json|\:native\-static\-libs]
Comma separated list of compiler information to print on stdout.
.TP
\fB\-g\fR

@ -1 +1 @@
Subproject commit 748a5e6742db4a21c4c630a58087f818828e8a0a
Subproject commit 66ef7373409d1979c2839db8886ac2ec9b6a58cd

@ -1 +1 @@
Subproject commit 134f419ee62714590b04712fe6072253bc2a7822
Subproject commit 219e261ddb833a5683627b0a9be87a0f4486abb9

@ -1 +1 @@
Subproject commit eebda16e4b45f2eed4310cf7b9872cc752278163
Subproject commit d2a64395a5210a61d3512a3a5c615f5c47699443

View File

@ -69,7 +69,7 @@ for details on how to format and write long error codes.
[librustc_passes](https://github.com/rust-lang/rust/blob/master/src/librustc_passes/diagnostics.rs),
[librustc_privacy](https://github.com/rust-lang/rust/blob/master/src/librustc_privacy/diagnostics.rs),
[librustc_resolve](https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/diagnostics.rs),
[librustc_trans](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/diagnostics.rs),
[librustc_codegen_llvm](https://github.com/rust-lang/rust/blob/master/src/librustc_codegen_llvm/diagnostics.rs),
[librustc_plugin](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/diagnostics.rs),
[librustc_typeck](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/diagnostics.rs).
* Explanations have full markdown support. Use it, especially to highlight

View File

@ -64,7 +64,7 @@ To fix it, do as the help message suggests:
```rust
#![feature(dyn_trait)]
#![deny(bare_trait_object)]
#![deny(bare_trait_objects)]
trait Trait { }

View File

@ -91,43 +91,6 @@ The legacy_directory_ownership warning is issued when
The warning can be fixed by renaming the parent module to "mod.rs" and moving
it into its own directory if appropriate.
## legacy-imports
This lint detects names that resolve to ambiguous glob imports. Some example
code that triggers this lint:
```rust,ignore
pub struct Foo;
mod bar {
struct Foo;
mod baz {
use *;
use bar::*;
fn f(_: Foo) {}
}
}
```
This will produce:
```text
error: `Foo` is ambiguous
--> src/main.rs:9:17
|
7 | use *;
| - `Foo` could refer to the name imported here
8 | use bar::*;
| ------ `Foo` could also refer to the name imported here
9 | fn f(_: Foo) {}
| ^^^
|
= note: #[deny(legacy_imports)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #38260 <https://github.com/rust-lang/rust/issues/38260>
```
## missing-fragment-specifier
@ -239,3 +202,44 @@ error: invalid `crate_type` value
| ^^^^^^^^^^^^^^^^^^^^
|
```
## incoherent-fundamental-impls
This lint detects potentially-conflicting impls that were erroneously allowed. Some
example code that triggers this lint:
```rust,ignore
pub trait Trait1<X> {
type Output;
}
pub trait Trait2<X> {}
pub struct A;
impl<X, T> Trait1<X> for T where T: Trait2<X> {
type Output = ();
}
impl<X> Trait1<Box<X>> for A {
type Output = i32;
}
```
This will produce:
```text
error: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
--> src/main.rs:13:1
|
9 | impl<X, T> Trait1<X> for T where T: Trait2<X> {
| --------------------------------------------- first implementation here
...
13 | impl<X> Trait1<Box<X>> for A {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
|
= note: #[deny(incoherent_fundamental_impls)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
= note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
```

View File

@ -117,47 +117,6 @@ warning: found struct without foreign-function-safe representation annotation in
|
```
## incoherent-fundamental-impls
This lint detects potentially-conflicting impls that were erroneously allowed. Some
example code that triggers this lint:
```rust
pub trait Trait1<X> {
type Output;
}
pub trait Trait2<X> {}
pub struct A;
impl<X, T> Trait1<X> for T where T: Trait2<X> {
type Output = ();
}
impl<X> Trait1<Box<X>> for A {
type Output = i32;
}
```
This will produce:
```text
warning: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
--> src/main.rs:13:1
|
9 | impl<X, T> Trait1<X> for T where T: Trait2<X> {
| --------------------------------------------- first implementation here
...
13 | impl<X> Trait1<Box<X>> for A {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
|
= note: #[warn(incoherent_fundamental_impls)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
= note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
```
## late-bound-lifetime-arguments
This lint detects detects generic lifetime arguments in path segments with

View File

@ -79,8 +79,9 @@ from your example, but are important to make the tests work. Consider
an example block that looks like this:
```text
/// Some documentation.
# fn foo() {}
/// /// Some documentation.
/// # fn foo() {} // this function will be hidden
/// println!("Hello, World!");
```
It will render like this:
@ -88,6 +89,7 @@ It will render like this:
```rust
/// Some documentation.
# fn foo() {}
println!("Hello, World!");
```
Yes, that's right: you can add lines that start with `# `, and they will
@ -168,37 +170,73 @@ By repeating all parts of the example, you can ensure that your example still
compiles, while only showing the parts that are relevant to that part of your
explanation.
Another case where the use of `#` is handy is when you want to ignore
error handling. Lets say you want the following,
The `#`-hiding of lines can be prevented by using two consecutive hashes
`##`. This only needs to be done with with the first `#` which would've
otherwise caused hiding. If we have a string literal like the following,
which has a line that starts with a `#`:
```rust
let s = "foo
## bar # baz";
```
We can document it by escaping the initial `#`:
```text
/// let s = "foo
/// ## bar # baz";
```
## Using `?` in doc tests
When writing an example, it is rarely useful to include a complete error
handling, as it would add significant amounts of boilerplate code. Instead, you
may want the following:
```ignore
/// ```
/// use std::io;
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// ```
```
The problem is that `?` returns a `Result<T, E>` and test functions
don't return anything so this will give a mismatched types error.
The problem is that `?` returns a `Result<T, E>` and test functions don't
return anything, so this will give a mismatched types error.
You can get around this limitation by manually adding a `main` that returns
`Result<T, E>`, because `Result<T, E>` implements the `Termination` trait:
```ignore
/// A doc test using ?
///
/// ```
/// use std::io;
/// # fn foo() -> io::Result<()> {
///
/// fn main() -> io::Result<()> {
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// Ok(())
/// }
/// ```
```
Together with the `# ` from the section above, you arrive at a solution that
appears to the reader as the initial idea but works with doc tests:
```ignore
/// ```
/// use std::io;
/// # fn main() -> io::Result<()> {
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// # Ok(())
/// # }
/// ```
# fn foo() {}
```
You can get around this by wrapping the code in a function. This catches
and swallows the `Result<T, E>` when running tests on the docs. This
pattern appears regularly in the standard library.
### Documenting macros
## Documenting macros
Heres an example of documenting a macro:
@ -268,10 +306,10 @@ not actually pass as a test.
# fn foo() {}
```
`compile_fail` tells `rustdoc` that the compilation should fail. If it
compiles, then the test will fail. However please note that code failing
with the current Rust release may work in a future release, as new features
are added.
The `no_run` attribute will compile your code, but not run it. This is
important for examples such as "Here's how to retrieve a web page,"
which you would want to ensure compiles, but might be run in a test
environment that has no network access.
```text
/// ```compile_fail
@ -280,7 +318,31 @@ are added.
/// ```
```
The `no_run` attribute will compile your code, but not run it. This is
important for examples such as "Here's how to retrieve a web page,"
which you would want to ensure compiles, but might be run in a test
environment that has no network access.
`compile_fail` tells `rustdoc` that the compilation should fail. If it
compiles, then the test will fail. However please note that code failing
with the current Rust release may work in a future release, as new features
are added.
## Syntax reference
The *exact* syntax for code blocks, including the edge cases, can be found
in the [Fenced Code Blocks](https://spec.commonmark.org/0.28/#fenced-code-blocks)
section of the CommonMark specification.
Rustdoc also accepts *indented* code blocks as an alternative to fenced
code blocks: instead of surrounding your code with three backticks, you
can indent each line by four or more spaces.
``````markdown
let foo = "foo";
assert_eq!(foo, "foo");
``````
These, too, are documented in the CommonMark specification, in the
[Indented Code Blocks](https://spec.commonmark.org/0.28/#indented-code-blocks)
section.
However, it's preferable to use fenced code blocks over indented code blocks.
Not only are fenced code blocks considered more idiomatic for Rust code,
but there is no way to use directives such as `ignore` or `should_panic` with
indented code blocks.

View File

@ -5,8 +5,8 @@ Rustdoc has a concept called "passes". These are transformations that
In addition to the passes below, check out the docs for these flags:
* [`--passes`](command-line-arguments.html#--passes-add-more-rustdoc-passes)
* [`--no-defaults`](command-line-arguments.html#--no-defaults-dont-run-default-passes)
* [`--passes`](command-line-arguments.html#a--passes-add-more-rustdoc-passes)
* [`--no-defaults`](command-line-arguments.html#a--no-defaults-dont-run-default-passes)
## Default passes

View File

@ -1,3 +1,3 @@
% The Rust Tutorial
This tutorial has been deprecated in favor of [the Book](book/index.html). Go check that out instead!
This tutorial has been deprecated in favor of [the Book](book/index.html), which is available free online and in dead tree form. Go check that out instead!

View File

@ -1,8 +1,8 @@
# `box_syntax`
The tracking issue for this feature is: [#27779]
The tracking issue for this feature is: [#49733]
[#27779]: https://github.com/rust-lang/rust/issues/27779
[#49733]: https://github.com/rust-lang/rust/issues/49733
See also [`box_patterns`](language-features/box-patterns.html)

View File

@ -1,72 +0,0 @@
# `global_allocator`
The tracking issue for this feature is: [#27389]
[#27389]: https://github.com/rust-lang/rust/issues/27389
------------------------
Rust programs may need to change the allocator that they're running with from
time to time. This use case is distinct from an allocator-per-collection (e.g. a
`Vec` with a custom allocator) and instead is more related to changing the
global default allocator, e.g. what `Vec<T>` uses by default.
Currently Rust programs don't have a specified global allocator. The compiler
may link to a version of [jemalloc] on some platforms, but this is not
guaranteed. Libraries, however, like cdylibs and staticlibs are guaranteed
to use the "system allocator" which means something like `malloc` on Unixes and
`HeapAlloc` on Windows.
[jemalloc]: https://github.com/jemalloc/jemalloc
The `#[global_allocator]` attribute, however, allows configuring this choice.
You can use this to implement a completely custom global allocator to route all
default allocation requests to a custom object. Defined in [RFC 1974] usage
looks like:
[RFC 1974]: https://github.com/rust-lang/rfcs/pull/1974
```rust
#![feature(global_allocator, allocator_api, heap_api)]
use std::alloc::{GlobalAlloc, System, Layout, Opaque};
use std::ptr::NonNull;
struct MyAllocator;
unsafe impl GlobalAlloc for MyAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
System.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
System.dealloc(ptr, layout)
}
}
#[global_allocator]
static GLOBAL: MyAllocator = MyAllocator;
fn main() {
// This `Vec` will allocate memory through `GLOBAL` above
let mut v = Vec::new();
v.push(1);
}
```
And that's it! The `#[global_allocator]` attribute is applied to a `static`
which implements the `Alloc` trait in the `std::alloc` module. Note, though,
that the implementation is defined for `&MyAllocator`, not just `MyAllocator`.
You may wish, however, to also provide `Alloc for MyAllocator` for other use
cases.
A crate can only have one instance of `#[global_allocator]` and this instance
may be loaded through a dependency. For example `#[global_allocator]` above
could have been placed in one of the dependencies loaded through `extern crate`.
Note that `Alloc` itself is an `unsafe` trait, with much documentation on the
trait itself about usage and for implementors. Extra care should be taken when
implementing a global allocator as well as the allocator may be called from many
portions of the standard library, such as the panicking routine. As a result it
is highly recommended to not panic during allocation and work in as many
situations with as few dependencies as possible as well.

View File

@ -0,0 +1,67 @@
# `infer_outlives_requirements`
The tracking issue for this feature is: [#44493]
[#44493]: https://github.com/rust-lang/rust/issues/44493
------------------------
The `infer_outlives_requirements` feature indicates that certain
outlives requirements can be infered by the compiler rather than
stating them explicitly.
For example, currently generic struct definitions that contain
references, require where-clauses of the form T: 'a. By using
this feature the outlives predicates will be infered, although
they may still be written explicitly.
```rust,ignore (pseudo-Rust)
struct Foo<'a, T>
where T: 'a // <-- currently required
{
bar: &'a T,
}
```
## Examples:
```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer T: 'a
struct Foo<'a, T> {
bar: &'a T,
}
```
```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer `U: 'b`
struct Foo<'b, U> {
bar: Bar<'b, U>
}
struct Bar<'a, T> where T: 'a {
x: &'a (),
y: T,
}
```
```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer `b': 'a`
struct Foo<'a, 'b, T> {
x: &'a &'b T
}
```
```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer `<T as std::iter::Iterator>::Item : 'a`
struct Foo<'a, T: Iterator> {
bar: &'a T::Item
```

View File

@ -0,0 +1,45 @@
# `infer_static_outlives_requirements`
The tracking issue for this feature is: [#44493]
[#44493]: https://github.com/rust-lang/rust/issues/44493
------------------------
The `infer_static_outlives_requirements` feature indicates that certain
`'static` outlives requirements can be infered by the compiler rather than
stating them explicitly.
Note: It is an accompanying feature to `infer_outlives_requirements`,
which must be enabled to infer outlives requirements.
For example, currently generic struct definitions that contain
references, require where-clauses of the form T: 'static. By using
this feature the outlives predicates will be infered, although
they may still be written explicitly.
```rust,ignore (pseudo-Rust)
struct Foo<U> where U: 'static { // <-- currently required
bar: Bar<U>
}
struct Bar<T: 'static> {
x: T,
}
```
## Examples:
```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
#![feature(infer_static_outlives_requirements)]
#[rustc_outlives]
// Implicitly infer U: 'static
struct Foo<U> {
bar: Bar<U>
}
struct Bar<T: 'static> {
x: T,
}
```

View File

@ -0,0 +1,28 @@
# `irrefutable_let_patterns`
The tracking issue for this feature is: [#44495]
[#44495]: https://github.com/rust-lang/rust/issues/44495
------------------------
This feature changes the way that "irrefutable patterns" are handled
in the `if let` and `while let` forms. An *irrefutable pattern* is one
that cannot fail to match -- for example, the `_` pattern matches any
value, and hence it is "irrefutable". Without this feature, using an
irrefutable pattern in an `if let` gives a hard error (since often
this indicates programmer error). But when the feature is enabled, the
error becomes a lint (since in some cases irrefutable patterns are
expected). This means you can use `#[allow]` to silence the lint:
```rust
#![feature(irrefutable_let_patterns)]
#[allow(irrefutable_let_patterns)]
fn main() {
// These two examples used to be errors, but now they
// trigger a lint (that is allowed):
if let _ = 5 {}
while let _ = 5 { break; }
}
```

View File

@ -19,6 +19,7 @@ sugar for dynamic allocations via `malloc` and `free`:
#![feature(lang_items, box_syntax, start, libc, core_intrinsics)]
#![no_std]
use core::intrinsics;
use core::panic::PanicInfo;
extern crate libc;
@ -50,7 +51,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
}
#[lang = "eh_personality"] extern fn rust_eh_personality() {}
#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } }
#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } }
#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
#[no_mangle] pub extern fn rust_eh_register_frames () {}
#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
@ -110,6 +111,7 @@ in the same format as C:
#![feature(start)]
#![no_std]
use core::intrinsics;
use core::panic::PanicInfo;
// Pull in the system libc library for what crt0.o likely requires.
extern crate libc;
@ -134,12 +136,9 @@ pub extern fn rust_eh_personality() {
pub extern fn rust_eh_unwind_resume() {
}
#[lang = "panic_fmt"]
#[lang = "panic_impl"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32,
_column: u32) -> ! {
pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
unsafe { intrinsics::abort() }
}
```
@ -155,6 +154,7 @@ compiler's name mangling too:
#![no_std]
#![no_main]
use core::intrinsics;
use core::panic::PanicInfo;
// Pull in the system libc library for what crt0.o likely requires.
extern crate libc;
@ -179,12 +179,9 @@ pub extern fn rust_eh_personality() {
pub extern fn rust_eh_unwind_resume() {
}
#[lang = "panic_fmt"]
#[lang = "panic_impl"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32,
_column: u32) -> ! {
pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
unsafe { intrinsics::abort() }
}
```
@ -215,7 +212,7 @@ called. The language item's name is `eh_personality`.
The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
compiler. When a panic happens, this controls the message that's displayed on
the screen. While the language item's name is `panic_fmt`, the symbol name is
the screen. While the language item's name is `panic_impl`, the symbol name is
`rust_begin_panic`.
A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume`
@ -259,8 +256,8 @@ the source code.
- `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH)
- `panic`: `libcore/panicking.rs`
- `panic_bounds_check`: `libcore/panicking.rs`
- `panic_fmt`: `libcore/panicking.rs`
- `panic_fmt`: `libstd/panicking.rs`
- `panic_impl`: `libcore/panicking.rs`
- `panic_impl`: `libstd/panicking.rs`
- Allocations
- `owned_box`: `liballoc/boxed.rs`
- `exchange_malloc`: `liballoc/heap.rs`

View File

@ -1,13 +1,15 @@
# `macro_at_most_once_rep`
The tracking issue for this feature is: TODO(mark-i-m)
NOTE: This feature is only available in the 2018 Edition.
The tracking issue for this feature is: #48075
With this feature gate enabled, one can use `?` as a Kleene operator meaning "0
or 1 repetitions" in a macro definition. Previously only `+` and `*` were allowed.
For example:
```rust
```rust,ignore
#![feature(macro_at_most_once_rep)]
macro_rules! foo {

View File

@ -1,14 +0,0 @@
# `macro_lifetime_matcher`
The tracking issue for this feature is: [#46895]
With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry:
* `lifetime`: a lifetime. Examples: 'static, 'a.
A `lifetime` variable may be followed by anything.
[#46895]: https://github.com/rust-lang/rust/issues/46895
[frags]: ../book/first-edition/macros.html#syntactic-requirements
------------------------

View File

@ -0,0 +1,17 @@
# `macro_literal_matcher`
The tracking issue for this feature is: [#35625]
The RFC is: [rfc#1576].
With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry:
* `literal`: a literal. Examples: 2, "string", 'c'
A `literal` may be followed by anything, similarly to the `ident` specifier.
[rfc#1576]: http://rust-lang.github.io/rfcs/1576-macros-literal-matcher.html
[#35625]: https://github.com/rust-lang/rust/issues/35625
[frags]: ../book/first-edition/macros.html#syntactic-requirements
------------------------

View File

@ -183,6 +183,8 @@ that warns about any item named `lintme`.
```rust,ignore
#![feature(plugin_registrar)]
#![feature(box_syntax, rustc_private)]
#![feature(macro_vis_matcher)]
#![feature(macro_at_most_once_rep)]
extern crate syntax;
@ -208,7 +210,7 @@ impl LintPass for Pass {
impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
if it.ident.name.as_str() == "lintme" {
if it.ident.as_str() == "lintme" {
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
}
}

View File

@ -1,241 +0,0 @@
# `proc_macro`
The tracking issue for this feature is: [#38356]
[#38356]: https://github.com/rust-lang/rust/issues/38356
------------------------
This feature flag guards the new procedural macro features as laid out by [RFC 1566], which alongside the now-stable
[custom derives], provide stabilizable alternatives to the compiler plugin API (which requires the use of
perma-unstable internal APIs) for programmatically modifying Rust code at compile-time.
The two new procedural macro kinds are:
* Function-like procedural macros which are invoked like regular declarative macros, and:
* Attribute-like procedural macros which can be applied to any item which built-in attributes can
be applied to, and which can take arguments in their invocation as well.
Additionally, this feature flag implicitly enables the [`use_extern_macros`](language-features/use-extern-macros.html) feature,
which allows macros to be imported like any other item with `use` statements, as compared to
applying `#[macro_use]` to an `extern crate` declaration. It is important to note that procedural macros may
**only** be imported in this manner, and will throw an error otherwise.
You **must** declare the `proc_macro` feature in both the crate declaring these new procedural macro kinds as well as
in any crates that use them.
### Common Concepts
As with custom derives, procedural macros may only be declared in crates of the `proc-macro` type, and must be public
functions. No other public items may be declared in `proc-macro` crates, but private items are fine.
To declare your crate as a `proc-macro` crate, simply add:
```toml
[lib]
proc-macro = true
```
to your `Cargo.toml`.
Unlike custom derives, however, the name of the function implementing the procedural macro is used directly as the
procedural macro's name, so choose carefully.
Additionally, both new kinds of procedural macros return a `TokenStream` which *wholly* replaces the original
invocation and its input.
#### Importing
As referenced above, the new procedural macros are not meant to be imported via `#[macro_use]` and will throw an
error if they are. Instead, they are meant to be imported like any other item in Rust, with `use` statements:
```rust,ignore
#![feature(proc_macro)]
// Where `my_proc_macros` is some crate of type `proc_macro`
extern crate my_proc_macros;
// And declares a `#[proc_macro] pub fn my_bang_macro()` at its root.
use my_proc_macros::my_bang_macro;
fn main() {
println!("{}", my_bang_macro!());
}
```
#### Error Reporting
Any panics in a procedural macro implementation will be caught by the compiler and turned into an error message pointing
to the problematic invocation. Thus, it is important to make your panic messages as informative as possible: use
`Option::expect` instead of `Option::unwrap` and `Result::expect` instead of `Result::unwrap`, and inform the user of
the error condition as unambiguously as you can.
#### `TokenStream`
The `proc_macro::TokenStream` type is hardcoded into the signatures of procedural macro functions for both input and
output. It is a wrapper around the compiler's internal representation for a given chunk of Rust code.
### Function-like Procedural Macros
These are procedural macros that are invoked like regular declarative macros. They are declared as public functions in
crates of the `proc_macro` type and using the `#[proc_macro]` attribute. The name of the declared function becomes the
name of the macro as it is to be imported and used. The function must be of the kind `fn(TokenStream) -> TokenStream`
where the sole argument is the input to the macro and the return type is the macro's output.
This kind of macro can expand to anything that is valid for the context it is invoked in, including expressions and
statements, as well as items.
**Note**: invocations of this kind of macro require a wrapping `[]`, `{}` or `()` like regular macros, but these do not
appear in the input, only the tokens between them. The tokens between the braces do not need to be valid Rust syntax.
<span class="filename">my_macro_crate/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
// This is always necessary to get the `TokenStream` typedef.
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro]
pub fn say_hello(_input: TokenStream) -> TokenStream {
// This macro will accept any input because it ignores it.
// To enforce correctness in macros which don't take input,
// you may want to add `assert!(_input.to_string().is_empty());`.
"println!(\"Hello, world!\")".parse().unwrap()
}
```
<span class="filename">my_macro_user/Cargo.toml</span>
```toml
[dependencies]
my_macro_crate = { path = "<relative path to my_macro_crate>" }
```
<span class="filename">my_macro_user/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
extern crate my_macro_crate;
use my_macro_crate::say_hello;
fn main() {
say_hello!();
}
```
As expected, this prints `Hello, world!`.
### Attribute-like Procedural Macros
These are arguably the most powerful flavor of procedural macro as they can be applied anywhere attributes are allowed.
They are declared as public functions in crates of the `proc-macro` type, using the `#[proc_macro_attribute]` attribute.
The name of the function becomes the name of the attribute as it is to be imported and used. The function must be of the
kind `fn(TokenStream, TokenStream) -> TokenStream` where:
The first argument represents any metadata for the attribute (see [the reference chapter on attributes][refr-attr]).
Only the metadata itself will appear in this argument, for example:
* `#[my_macro]` will get an empty string.
* `#[my_macro = "string"]` will get `= "string"`.
* `#[my_macro(ident)]` will get `(ident)`.
* etc.
The second argument is the item that the attribute is applied to. It can be a function, a type definition,
an impl block, an `extern` block, or a module—attribute invocations can take the inner form (`#![my_attr]`)
or outer form (`#[my_attr]`).
The return type is the output of the macro which *wholly* replaces the item it was applied to. Thus, if your intention
is to merely modify an item, it *must* be copied to the output. The output must be an item; expressions, statements
and bare blocks are not allowed.
There is no restriction on how many items an attribute-like procedural macro can emit as long as they are valid in
the given context.
<span class="filename">my_macro_crate/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
extern crate proc_macro;
use proc_macro::TokenStream;
/// Adds a `/// ### Panics` docstring to the end of the input's documentation
///
/// Does not assert that its receiver is a function or method.
#[proc_macro_attribute]
pub fn panics_note(args: TokenStream, input: TokenStream) -> TokenStream {
let args = args.to_string();
let mut input = input.to_string();
assert!(args.starts_with("= \""), "`#[panics_note]` requires an argument of the form \
`#[panics_note = \"panic note here\"]`");
// Get just the bare note string
let panics_note = args.trim_matches(&['=', ' ', '"'][..]);
// The input will include all docstrings regardless of where the attribute is placed,
// so we need to find the last index before the start of the item
let insert_idx = idx_after_last_docstring(&input);
// And insert our `### Panics` note there so it always appears at the end of an item's docs
input.insert_str(insert_idx, &format!("/// # Panics \n/// {}\n", panics_note));
input.parse().unwrap()
}
// `proc-macro` crates can contain any kind of private item still
fn idx_after_last_docstring(input: &str) -> usize {
// Skip docstring lines to find the start of the item proper
input.lines().skip_while(|line| line.trim_left().starts_with("///")).next()
// Find the index of the first non-docstring line in the input
// Note: assumes this exact line is unique in the input
.and_then(|line_after| input.find(line_after))
// No docstrings in the input
.unwrap_or(0)
}
```
<span class="filename">my_macro_user/Cargo.toml</span>
```toml
[dependencies]
my_macro_crate = { path = "<relative path to my_macro_crate>" }
```
<span class="filename">my_macro_user/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
extern crate my_macro_crate;
use my_macro_crate::panics_note;
/// Do the `foo` thing.
#[panics_note = "Always."]
pub fn foo() {
panic!()
}
```
Then the rendered documentation for `pub fn foo` will look like this:
> `pub fn foo()`
>
> ----
> Do the `foo` thing.
> # Panics
> Always.
[RFC 1566]: https://github.com/rust-lang/rfcs/blob/master/text/1566-proc-macros.md
[custom derives]: https://doc.rust-lang.org/book/procedural-macros.html
[rust-lang/rust#41430]: https://github.com/rust-lang/rust/issues/41430
[refr-attr]: https://doc.rust-lang.org/reference/attributes.html

View File

@ -1,176 +0,0 @@
# `repr_transparent`
The tracking issue for this feature is: [#43036]
[#43036]: https://github.com/rust-lang/rust/issues/43036
------------------------
This feature enables the `repr(transparent)` attribute on structs, which enables
the use of newtypes without the usual ABI implications of wrapping the value in
a struct.
## Background
It's sometimes useful to add additional type safety by introducing *newtypes*.
For example, code that handles numeric quantities in different units such as
millimeters, centimeters, grams, kilograms, etc. may want to use the type system
to rule out mistakes such as adding millimeters to grams:
```rust
use std::ops::Add;
struct Millimeters(f64);
struct Grams(f64);
impl Add<Millimeters> for Millimeters {
type Output = Millimeters;
fn add(self, other: Millimeters) -> Millimeters {
Millimeters(self.0 + other.0)
}
}
// Likewise: impl Add<Grams> for Grams {}
```
Other uses of newtypes include using `PhantomData` to add lifetimes to raw
pointers or to implement the "phantom types" pattern. See the [PhantomData]
documentation and [the Nomicon][nomicon-phantom] for more details.
The added type safety is especially useful when interacting with C or other
languages. However, in those cases we need to ensure the newtypes we add do not
introduce incompatibilities with the C ABI.
## Newtypes in FFI
Luckily, `repr(C)` newtypes are laid out just like the type they wrap on all
platforms which Rust currently supports, and likely on many more. For example,
consider this C declaration:
```C
struct Object {
double weight; //< in grams
double height; //< in millimeters
// ...
}
void frobnicate(struct Object *);
```
While using this C code from Rust, we could add `repr(C)` to the `Grams` and
`Millimeters` newtypes introduced above and use them to add some type safety
while staying compatible with the memory layout of `Object`:
```rust,no_run
#[repr(C)]
struct Grams(f64);
#[repr(C)]
struct Millimeters(f64);
#[repr(C)]
struct Object {
weight: Grams,
height: Millimeters,
// ...
}
extern {
fn frobnicate(_: *mut Object);
}
```
This works even when adding some `PhantomData` fields, because they are
zero-sized and therefore don't have to affect the memory layout.
However, there's more to the ABI than just memory layout: there's also the
question of how function call arguments and return values are passed. Many
common ABI treat a struct containing a single field differently from that field
itself, at least when the field is a scalar (e.g., integer or float or pointer).
To continue the above example, suppose the C library also exposes a function
like this:
```C
double calculate_weight(double height);
```
Using our newtypes on the Rust side like this will cause an ABI mismatch on many
platforms:
```rust,ignore
extern {
fn calculate_weight(height: Millimeters) -> Grams;
}
```
For example, on x86_64 Linux, Rust will pass the argument in an integer
register, while the C function expects the argument to be in a floating-point
register. Likewise, the C function will return the result in a floating-point
register while Rust will expect it in an integer register.
Note that this problem is not specific to floats: To give another example,
32-bit x86 linux will pass and return `struct Foo(i32);` on the stack while
`i32` is placed in registers.
## Enter `repr(transparent)`
So while `repr(C)` happens to do the right thing with respect to memory layout,
it's not quite the right tool for newtypes in FFI. Instead of declaring a C
struct, we need to communicate to the Rust compiler that our newtype is just for
type safety on the Rust side. This is what `repr(transparent)` does.
The attribute can be applied to a newtype-like structs that contains a single
field. It indicates that the newtype should be represented exactly like that
field's type, i.e., the newtype should be ignored for ABI purpopses: not only is
it laid out the same in memory, it is also passed identically in function calls.
In the above example, the ABI mismatches can be prevented by making the newtypes
`Grams` and `Millimeters` transparent like this:
```rust
#![feature(repr_transparent)]
#[repr(transparent)]
struct Grams(f64);
#[repr(transparent)]
struct Millimeters(f64);
```
In addition to that single field, any number of zero-sized fields are permitted,
including but not limited to `PhantomData`:
```rust
#![feature(repr_transparent)]
use std::marker::PhantomData;
struct Foo { /* ... */ }
#[repr(transparent)]
struct FooPtrWithLifetime<'a>(*const Foo, PhantomData<&'a Foo>);
#[repr(transparent)]
struct NumberWithUnit<T, U>(T, PhantomData<U>);
struct CustomZst;
#[repr(transparent)]
struct PtrWithCustomZst<'a> {
ptr: FooPtrWithLifetime<'a>,
some_marker: CustomZst,
}
```
Transparent structs can be nested: `PtrWithCustomZst` is also represented
exactly like `*const Foo`.
Because `repr(transparent)` delegates all representation concerns to another
type, it is incompatible with all other `repr(..)` attributes. It also cannot be
applied to enums, unions, empty structs, structs whose fields are all
zero-sized, or structs with *multiple* non-zero-sized fields.
[PhantomData]: https://doc.rust-lang.org/std/marker/struct.PhantomData.html
[nomicon-phantom]: https://doc.rust-lang.org/nomicon/phantom-data.html

View File

@ -0,0 +1,35 @@
# `tool_lints`
The tracking issue for this feature is: [#44690]
[#44690]: https://github.com/rust-lang/rust/issues/44690
------------------------
Tool lints let you use scoped lints, to `allow`, `warn`, `deny` or `forbid` lints of
certain tools.
Currently `clippy` is the only available lint tool.
It is recommended for lint tools to implement the scoped lints like this:
- `#[_(TOOL_NAME::lintname)]`: for lint names
- `#[_(TOOL_NAME::lintgroup)]`: for groups of lints
- `#[_(TOOL_NAME::all)]`: for (almost[^1]) all lints
## An example
```rust
#![feature(tool_lints)]
#![warn(clippy::pedantic)]
#[allow(clippy::filter_map)]
fn main() {
let v = vec![0; 10];
let _ = v.into_iter().filter(|&x| x < 1).map(|x| x + 1).collect::<Vec<_>>();
println!("No filter_map()!");
}
```
[^1]: Some defined lint groups can be excluded here.

View File

@ -87,11 +87,13 @@ This condition can be met using `#[used]` and `#[link_section]` plus a linker
script.
``` rust,ignore
#![feature(lang_items)]
#![feature(panic_implementation)]
#![feature(used)]
#![no_main]
#![no_std]
use core::panic::PanicInfo;
extern "C" fn reset_handler() -> ! {
loop {}
}
@ -100,8 +102,10 @@ extern "C" fn reset_handler() -> ! {
#[used]
static RESET_HANDLER: extern "C" fn() -> ! = reset_handler;
#[lang = "panic_fmt"]
fn panic_fmt() {}
#[panic_implementation]
fn panic_impl(info: &PanicInfo) -> ! {
loop {}
}
```
``` text

View File

@ -1,13 +0,0 @@
# `alloc_jemalloc`
The tracking issue for this feature is: [#33082]
[#33082]: https://github.com/rust-lang/rust/issues/33082
See also [`alloc_system`](library-features/alloc-system.html).
------------------------
This feature has been replaced by [the `jemallocator` crate on crates.io.][jemallocator].
[jemallocator]: https://crates.io/crates/jemallocator

View File

@ -1,77 +0,0 @@
# `alloc_system`
The tracking issue for this feature is: [#32838]
[#32838]: https://github.com/rust-lang/rust/issues/32838
See also [`global_allocator`](language-features/global-allocator.html).
------------------------
The compiler currently ships two default allocators: `alloc_system` and
`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
are normal Rust crates and contain an implementation of the routines to
allocate and deallocate memory. The standard library is not compiled assuming
either one, and the compiler will decide which allocator is in use at
compile-time depending on the type of output artifact being produced.
Binaries generated by the compiler will use `alloc_jemalloc` by default (where
available). In this situation the compiler "controls the world" in the sense of
it has power over the final link. Primarily this means that the allocator
decision can be left up the compiler.
Dynamic and static libraries, however, will use `alloc_system` by default. Here
Rust is typically a 'guest' in another application or another world where it
cannot authoritatively decide what allocator is in use. As a result it resorts
back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
memory.
# Switching Allocators
Although the compiler's default choices may work most of the time, it's often
necessary to tweak certain aspects. Overriding the compiler's decision about
which allocator is in use is done through the `#[global_allocator]` attribute:
```rust,no_run
#![feature(alloc_system, global_allocator, allocator_api)]
extern crate alloc_system;
use alloc_system::System;
#[global_allocator]
static A: System = System;
fn main() {
let a = Box::new(4); // Allocates from the system allocator.
println!("{}", a);
}
```
In this example the binary generated will not link to jemalloc by default but
instead use the system allocator. Conversely to generate a dynamic library which
uses jemalloc by default one would write:
(The `alloc_jemalloc` crate cannot be used to control the global allocator,
crate.ios `jemallocator` crate provides equivalent functionality.)
```toml
# Cargo.toml
[dependencies]
jemallocator = "0.1"
```
```rust,ignore
#![feature(global_allocator)]
#![crate_type = "dylib"]
extern crate jemallocator;
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
pub fn foo() {
let a = Box::new(4); // Allocates from jemalloc.
println!("{}", a);
}
# fn main() {}
```

View File

@ -1,13 +0,0 @@
# `entry_or_default`
The tracking issue for this feature is: [#44324]
[#44324]: https://github.com/rust-lang/rust/issues/44324
------------------------
The `entry_or_default` feature adds a new method to `hash_map::Entry`
and `btree_map::Entry`, `or_default`, when `V: Default`. This method is
semantically identical to `or_insert_with(Default::default)`, and will
insert the default value for the type if no entry exists for the current
key.

View File

@ -122,7 +122,7 @@ traits = {
for (trait, supers, errs) in [('Clone', [], 1),
('PartialEq', [], 2),
('PartialOrd', ['PartialEq'], 5),
('PartialOrd', ['PartialEq'], 1),
('Eq', ['PartialEq'], 1),
('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1),
('Debug', [], 1),

View File

@ -346,15 +346,19 @@ def check_tree_attr(tree, path, attr, pat, regexp):
def check_tree_text(tree, path, pat, regexp):
path = normalize_xpath(path)
ret = False
for e in tree.findall(path):
try:
value = flatten(e)
except KeyError:
continue
else:
ret = check_string(value, pat, regexp)
if ret:
break
try:
for e in tree.findall(path):
try:
value = flatten(e)
except KeyError:
continue
else:
ret = check_string(value, pat, regexp)
if ret:
break
except Exception as e:
print('Failed to get path "{}"'.format(path))
raise e
return ret

View File

@ -806,9 +806,6 @@ class CompilerDefs(object):
use {{Intrinsic, Type}};
use IntrinsicDef::Named;
// The default inlining settings trigger a pathological behaviour in
// LLVM, which causes makes compilation very slow. See #28273.
#[inline(never)]
pub fn find(name: &str) -> Option<Intrinsic> {{
if !name.starts_with("{0}") {{ return None }}
Some(match &name["{0}".len()..] {{'''.format(platform.platform_prefix())

View File

@ -21,6 +21,6 @@ GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
# different/specific command (defaults to `gdb`).
RUST_GDB="${RUST_GDB:-gdb}"
PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" ${RUST_GDB} \
-d "$GDB_PYTHON_MODULE_DIRECTORY" \
--directory="$GDB_PYTHON_MODULE_DIRECTORY" \
-iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \
"$@"

View File

@ -107,6 +107,10 @@ 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); },
sin: Math.sin,
sinf: Math.sin,
cos: Math.cos,
cosf: Math.cos,
log: Math.log,
log2: Math.log2,
log10: Math.log10,

View File

@ -2,6 +2,8 @@
authors = ["The Rust Project Developers"]
name = "alloc"
version = "0.0.0"
autotests = false
autobenches = false
[lib]
name = "alloc"

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