mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-13 10:29:16 +00:00
resolved upstream merge conflicts
This commit is contained in:
commit
56016cb1e0
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -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
21
.gitignore
vendored
@ -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
3
.gitmodules
vendored
@ -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
|
||||
|
1
.mailmap
1
.mailmap
@ -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>
|
||||
|
40
.travis.yml
40
.travis.yml
@ -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:
|
||||
|
@ -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)
|
||||
|
14
README.md
14
README.md
@ -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
|
||||
|
580
RELEASES.md
580
RELEASES.md
@ -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
|
||||
|
25
appveyor.yml
25
appveyor.yml
@ -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
|
||||
|
@ -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
|
||||
#
|
||||
|
2161
src/Cargo.lock
2161
src/Cargo.lock
File diff suppressed because it is too large
Load Diff
@ -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" }
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
27
src/bootstrap/bin/llvm-config-wrapper.rs
Normal file
27
src/bootstrap/bin/llvm-config-wrapper.rs
Normal 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));
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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
@ -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>>
|
||||
>>
|
||||
);
|
||||
|
||||
|
@ -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>,
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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 + '/')
|
||||
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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 doesn’t 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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
36
src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile
Normal file
36
src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile
Normal 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
|
26
src/ci/docker/disabled/dist-sparc64-linux/Dockerfile
Normal file
26
src/ci/docker/disabled/dist-sparc64-linux/Dockerfile
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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/
|
@ -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
|
@ -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
|
||||
}
|
@ -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/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
64
src/ci/docker/dist-x86_64-linux/build-clang.sh
Executable file
64
src/ci/docker/dist-x86_64-linux/build-clang.sh
Executable 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
|
@ -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
|
||||
|
@ -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" \
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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" \
|
||||
|
@ -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"
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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 { }
|
||||
|
||||
|
@ -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`
|
||||
```
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
Here’s 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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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!
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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.
|
@ -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
|
||||
```
|
@ -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,
|
||||
}
|
||||
```
|
||||
|
@ -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; }
|
||||
}
|
||||
```
|
@ -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`
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
------------------------
|
@ -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
|
||||
|
||||
------------------------
|
@ -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'");
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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
|
35
src/doc/unstable-book/src/language-features/tool-lints.md
Normal file
35
src/doc/unstable-book/src/language-features/tool-lints.md
Normal 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.
|
@ -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
|
||||
|
@ -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
|
@ -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.io’s `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() {}
|
||||
```
|
@ -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.
|
@ -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),
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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" \
|
||||
"$@"
|
||||
|
@ -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,
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user