mirror of
https://git.proxmox.com/git/rustc
synced 2026-01-08 20:03:08 +00:00
Imported Upstream version 1.8.0+dfsg1
This commit is contained in:
parent
9cc50fc6f5
commit
7453a54e52
@ -6,6 +6,7 @@ links to the major sections:
|
||||
|
||||
* [Feature Requests](#feature-requests)
|
||||
* [Bug Reports](#bug-reports)
|
||||
* [The Build System](#the-build-system)
|
||||
* [Pull Requests](#pull-requests)
|
||||
* [Writing Documentation](#writing-documentation)
|
||||
* [Issue Triage](#issue-triage)
|
||||
@ -77,6 +78,70 @@ to do this is to invoke `rustc` like this:
|
||||
$ RUST_BACKTRACE=1 rustc ...
|
||||
```
|
||||
|
||||
## The Build System
|
||||
|
||||
Rust's build system allows you to bootstrap the compiler, run tests &
|
||||
benchmarks, generate documentation, install a fresh build of Rust, and more.
|
||||
It's your best friend when working on Rust, allowing you to compile & test
|
||||
your contributions before submission.
|
||||
|
||||
All the configuration for the build system lives in [the `mk` directory][mkdir]
|
||||
in the project root. It can be hard to follow in places, as it uses some
|
||||
advanced Make features which make for some challenging reading. If you have
|
||||
questions on the build system internals, try asking in
|
||||
[`#rust-internals`][pound-rust-internals].
|
||||
|
||||
[mkdir]: https://github.com/rust-lang/rust/tree/master/mk/
|
||||
|
||||
### Configuration
|
||||
|
||||
Before you can start building the compiler you need to configure the build for
|
||||
your system. In most cases, that will just mean using the defaults provided
|
||||
for Rust. Configuring involves invoking the `configure` script in the project
|
||||
root.
|
||||
|
||||
```
|
||||
./configure
|
||||
```
|
||||
|
||||
There are large number of options accepted by this script to alter the
|
||||
configuration used later in the build process. Some options to note:
|
||||
|
||||
- `--enable-debug` - Build a debug version of the compiler (disables optimizations)
|
||||
- `--enable-optimize` - Enable optimizations (can be used with `--enable-debug`
|
||||
to make a debug build with optimizations)
|
||||
- `--disable-valgrind-rpass` - Don't run tests with valgrind
|
||||
- `--enable-clang` - Prefer clang to gcc for building dependencies (e.g., LLVM)
|
||||
- `--enable-ccache` - Invoke clang/gcc with ccache to re-use object files between builds
|
||||
- `--enable-compiler-docs` - Build compiler documentation
|
||||
|
||||
To see a full list of options, run `./configure --help`.
|
||||
|
||||
### Useful Targets
|
||||
|
||||
Some common make targets are:
|
||||
|
||||
- `make rustc-stage1` - build up to (and including) the first stage. For most
|
||||
cases we don't need to build the stage2 compiler, so we can save time by not
|
||||
building it. The stage1 compiler is a fully functioning compiler and
|
||||
(probably) will be enough to determine if your change works as expected.
|
||||
- `make check` - build the full compiler & run all tests (takes a while). This
|
||||
is what gets run by the continuous integration system against your pull
|
||||
request. You should run this before submitting to make sure your tests pass
|
||||
& everything builds in the correct manner.
|
||||
- `make check-stage1-std NO_REBUILD=1` - test the standard library without
|
||||
rebuilding the entire compiler
|
||||
- `make check TESTNAME=<substring-of-test-name>` - Run a matching set of tests.
|
||||
- `TESTNAME` should be a substring of the tests to match against e.g. it could
|
||||
be the fully qualified test name, or just a part of it.
|
||||
`TESTNAME=collections::hash::map::test_map::test_capacity_not_less_than_len`
|
||||
or `TESTNAME=test_capacity_not_less_than_len`.
|
||||
- `make check-stage1-rpass TESTNAME=<substring-of-test-name>` - Run a single
|
||||
rpass test with the stage1 compiler (this will be quicker than running the
|
||||
command above as we only build the stage1 compiler, not the entire thing).
|
||||
You can also leave off the `-rpass` to run all stage1 test types.
|
||||
- `make check-stage1-coretest` - Run stage1 tests in `libcore`.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Pull requests are the primary mechanism we use to change Rust. GitHub itself
|
||||
|
||||
@ -6,8 +6,8 @@ terms.
|
||||
|
||||
Longer version:
|
||||
|
||||
The Rust Project is copyright 2016, The Rust Project
|
||||
Developers (given in the file AUTHORS.txt).
|
||||
The Rust Project is copyright 2010, The Rust Project
|
||||
Developers.
|
||||
|
||||
Licensed under the Apache License, Version 2.0
|
||||
<LICENSE-APACHE or
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2016 The Rust Project Developers
|
||||
Copyright (c) 2010 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
|
||||
11
Makefile.in
11
Makefile.in
@ -100,6 +100,10 @@
|
||||
# // Having trouble figuring out which test is failing? Turn off parallel tests
|
||||
# make check-stage1-std RUST_TEST_THREADS=1
|
||||
#
|
||||
# // To make debug!() and other logging calls visible, reconfigure:
|
||||
# ./configure --enable-debug-assertions
|
||||
# make ....
|
||||
#
|
||||
# If you really feel like getting your hands dirty, then:
|
||||
#
|
||||
# run `make nitty-gritty`
|
||||
@ -220,19 +224,12 @@ endif
|
||||
# The test suite
|
||||
ifneq ($(strip $(findstring check,$(MAKECMDGOALS)) \
|
||||
$(findstring test,$(MAKECMDGOALS)) \
|
||||
$(findstring perf,$(MAKECMDGOALS)) \
|
||||
$(findstring tidy,$(MAKECMDGOALS))),)
|
||||
CFG_INFO := $(info cfg: including test rules)
|
||||
include $(CFG_SRC_DIR)mk/tests.mk
|
||||
include $(CFG_SRC_DIR)mk/grammar.mk
|
||||
endif
|
||||
|
||||
# Performance and benchmarking
|
||||
ifneq ($(findstring perf,$(MAKECMDGOALS)),)
|
||||
CFG_INFO := $(info cfg: including perf rules)
|
||||
include $(CFG_SRC_DIR)mk/perf.mk
|
||||
endif
|
||||
|
||||
# Copy all the distributables to another directory for binary install
|
||||
ifneq ($(strip $(findstring prepare,$(MAKECMDGOALS)) \
|
||||
$(findstring dist,$(MAKECMDGOALS)) \
|
||||
|
||||
@ -9,7 +9,7 @@ and documentation.
|
||||
|
||||
Read ["Installing Rust"] from [The Book].
|
||||
|
||||
["Installing Rust"]: https://doc.rust-lang.org/book/installing-rust.html
|
||||
["Installing Rust"]: https://doc.rust-lang.org/book/getting-started.html#installing-rust
|
||||
[The Book]: https://doc.rust-lang.org/book/index.html
|
||||
|
||||
## Building from Source
|
||||
@ -17,7 +17,7 @@ Read ["Installing Rust"] from [The Book].
|
||||
1. Make sure you have installed the dependencies:
|
||||
|
||||
* `g++` 4.7 or `clang++` 3.x
|
||||
* `python` 2.7 or later (but not 3.x)
|
||||
* `python` 2.7 (but not 3.x)
|
||||
* GNU `make` 3.81 or later
|
||||
* `curl`
|
||||
* `git`
|
||||
|
||||
253
RELEASES.md
253
RELEASES.md
@ -1,6 +1,224 @@
|
||||
Version 1.8.0 (2016-04-14)
|
||||
==========================
|
||||
|
||||
Language
|
||||
--------
|
||||
|
||||
* Rust supports overloading of compound assignment statements like
|
||||
`+=` by implementing the [`AddAssign`], [`SubAssign`],
|
||||
[`MulAssign`], [`DivAssign`], [`RemAssign`], [`BitAndAssign`],
|
||||
[`BitOrAssign`], [`BitXorAssign`], [`ShlAssign`], or [`ShrAssign`]
|
||||
traits. [RFC 953].
|
||||
* Empty structs can be defined with braces, as in `struct Foo { }`, in
|
||||
addition to the non-braced form, `struct Foo;`. [RFC 218].
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
* Stabilized APIs:
|
||||
* [`str::encode_utf16`][] (renamed from `utf16_units`)
|
||||
* [`str::EncodeUtf16`][] (renamed from `Utf16Units`)
|
||||
* [`Ref::map`]
|
||||
* [`RefMut::map`]
|
||||
* [`ptr::drop_in_place`]
|
||||
* [`time::Instant`]
|
||||
* [`time::SystemTime`]
|
||||
* [`Instant::now`]
|
||||
* [`Instant::duration_since`][] (renamed from `duration_from_earlier`)
|
||||
* [`Instant::elapsed`]
|
||||
* [`SystemTime::now`]
|
||||
* [`SystemTime::duration_since`][] (renamed from `duration_from_earlier`)
|
||||
* [`SystemTime::elapsed`]
|
||||
* Various `Add`/`Sub` impls for `Time` and `SystemTime`
|
||||
* [`SystemTimeError`]
|
||||
* [`SystemTimeError::duration`]
|
||||
* Various impls for `SystemTimeError`
|
||||
* [`UNIX_EPOCH`]
|
||||
* [`AddAssign`], [`SubAssign`], [`MulAssign`], [`DivAssign`],
|
||||
[`RemAssign`], [`BitAndAssign`], [`BitOrAssign`],
|
||||
[`BitXorAssign`], [`ShlAssign`], [`ShrAssign`].
|
||||
* [The `write!` and `writeln!` macros correctly emit errors if any of
|
||||
their arguments can't be formatted][1.8w].
|
||||
* [Various I/O functions support large files on 32-bit Linux][1.8l].
|
||||
* [The Unix-specific `raw` modules, which contain a number of
|
||||
redefined C types are deprecated][1.8r], including `os::raw::unix`,
|
||||
`os::raw::macos`, and `os::raw::linux`. These modules defined types
|
||||
such as `ino_t` and `dev_t`. The inconsistency of these definitions
|
||||
across platforms was making it difficult to implement `std`
|
||||
correctly. Those that need these definitions should use the `libc`
|
||||
crate. [RFC 1415].
|
||||
* The Unix-specific `MetadataExt` traits, including
|
||||
`os::unix::fs::MetadataExt`, which expose values such as inode
|
||||
numbers [no longer return platform-specific types][1.8r], but
|
||||
instead return widened integers. [RFC 1415].
|
||||
* [`btree_set::{IntoIter, Iter, Range}` are covariant][1.8cv].
|
||||
* [Atomic loads and stores are not volatile][1.8a].
|
||||
* [All types in `sync::mpsc` implement `fmt::Debug`][1.8mp].
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
* [Inlining hash functions lead to a 3% compile-time improvement in
|
||||
some workloads][1.8h].
|
||||
* When using jemalloc, its symbols are [unprefixed so that it
|
||||
overrides the libc malloc implementation][1.8h]. This means that for
|
||||
rustc, LLVM is now using jemalloc, which results in a 6%
|
||||
compile-time improvement on a specific workload.
|
||||
* [Avoid quadratic growth in function size due to cleanups][1.8cu].
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
* [32-bit MSVC builds finally implement unwinding][1.8ms].
|
||||
i686-pc-windows-msvc is now considered a tier-1 platform.
|
||||
* [The `--print targets` flag prints a list of supported targets][1.8t].
|
||||
* [The `--print cfg` flag prints the `cfg`s defined for the current
|
||||
target][1.8cf].
|
||||
* [`rustc` can be built with an new Cargo-based build system, written
|
||||
in Rust][1.8b]. It will eventually replace Rust's Makefile-based
|
||||
build system. To enable it configure with `configure --rustbuild`.
|
||||
* [Errors for non-exhaustive `match` patterns now list up to 3 missing
|
||||
variants while also indicating the total number of missing variants
|
||||
if more than 3][1.8m].
|
||||
* [Executable stacks are disabled on Linux and BSD][1.8nx].
|
||||
* The Rust Project now publishes binary releases of the standard
|
||||
library for a number of tier-2 targets:
|
||||
`armv7-unknown-linux-gnueabihf`, `powerpc-unknown-linux-gnu`,
|
||||
`powerpc64-unknown-linux-gnu`, `powerpc64le-unknown-linux-gnu`
|
||||
`x86_64-rumprun-netbsd`. These can be installed with
|
||||
tools such as [multirust][1.8mr].
|
||||
|
||||
Cargo
|
||||
-----
|
||||
|
||||
* [`cargo init` creates a new Cargo project in the current
|
||||
directory][1.8ci]. It is otherwise like `cargo new`.
|
||||
* [Cargo has configuration keys for `-v` and
|
||||
`--color`][1.8cc]. `verbose` and `color`, respectively, go in the
|
||||
`[term]` section of `.cargo/config`.
|
||||
* [Configuration keys that evaluate to strings or integers can be set
|
||||
via environment variables][1.8ce]. For example the `build.jobs` key
|
||||
can be set via `CARGO_BUILD_JOBS`. Environment variables take
|
||||
precedence over config files.
|
||||
* [Target-specific dependencies support Rust `cfg` syntax for
|
||||
describing targets][1.8cfg] so that dependencies for multiple
|
||||
targets can be specified together. [RFC 1361].
|
||||
* [The environment variables `CARGO_TARGET_ROOT`, `RUSTC`, and
|
||||
`RUSTDOC` take precedence over the `build.target-dir`,
|
||||
`build.rustc`, and `build.rustdoc` configuration values][1.8cv].
|
||||
* [The child process tree is killed on Windows when Cargo is
|
||||
killed][1.8ck].
|
||||
* [The `build.target` configuration value sets the target platform,
|
||||
like `--target`][1.8ct].
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
|
||||
* [Unstable compiler flags have been further restricted][1.8u]. Since
|
||||
1.0 `-Z` flags have been considered unstable, and other flags that
|
||||
were considered unstable additionally required passing `-Z
|
||||
unstable-options` to access. Unlike unstable language and library
|
||||
features though, these options have been accessible on the stable
|
||||
release channel. Going forward, *new unstable flags will not be
|
||||
available on the stable release channel*, and old unstable flags
|
||||
will warn about their usage. In the future, all unstable flags will
|
||||
be unavailable on the stable release channel.
|
||||
* [It is no longer possible to `match` on empty enum variants using
|
||||
the `Variant(..)` syntax][1.8v]. This has been a warning since 1.6.
|
||||
* The Unix-specific `MetadataExt` traits, including
|
||||
`os::unix::fs::MetadataExt`, which expose values such as inode
|
||||
numbers [no longer return platform-specific types][1.8r], but
|
||||
instead return widened integers. [RFC 1415].
|
||||
* [Modules sourced from the filesystem cannot appear within arbitrary
|
||||
blocks, but only within other modules][1.8m].
|
||||
* [`--cfg` compiler flags are parsed strictly as identifiers][1.8c].
|
||||
* On Unix, [stack overflow triggers a runtime abort instead of a
|
||||
SIGSEGV][1.8so].
|
||||
* [`Command::spawn` and its equivalents return an error if any of
|
||||
its command-line arguments contain interior `NUL`s][1.8n].
|
||||
* [Tuple and unit enum variants from other crates are in the type
|
||||
namespace][1.8tn].
|
||||
* [On Windows `rustc` emits `.lib` files for the `staticlib` library
|
||||
type instead of `.a` files][1.8st]. Additionally, for the MSVC
|
||||
toolchain, `rustc` emits import libraries named `foo.dll.lib`
|
||||
instead of `foo.lib`.
|
||||
|
||||
|
||||
[1.8a]: https://github.com/rust-lang/rust/pull/30962
|
||||
[1.8b]: https://github.com/rust-lang/rust/pull/31123
|
||||
[1.8c]: https://github.com/rust-lang/rust/pull/31530
|
||||
[1.8cc]: https://github.com/rust-lang/cargo/pull/2397
|
||||
[1.8ce]: https://github.com/rust-lang/cargo/pull/2398
|
||||
[1.8cf]: https://github.com/rust-lang/rust/pull/31278
|
||||
[1.8cfg]: https://github.com/rust-lang/cargo/pull/2328
|
||||
[1.8ci]: https://github.com/rust-lang/cargo/pull/2081
|
||||
[1.8ck]: https://github.com/rust-lang/cargo/pull/2370
|
||||
[1.8ct]: https://github.com/rust-lang/cargo/pull/2335
|
||||
[1.8cu]: https://github.com/rust-lang/rust/pull/31390
|
||||
[1.8cv]: https://github.com/rust-lang/cargo/issues/2365
|
||||
[1.8cv]: https://github.com/rust-lang/rust/pull/30998
|
||||
[1.8h]: https://github.com/rust-lang/rust/pull/31460
|
||||
[1.8l]: https://github.com/rust-lang/rust/pull/31668
|
||||
[1.8m]: https://github.com/rust-lang/rust/pull/31020
|
||||
[1.8m]: https://github.com/rust-lang/rust/pull/31534
|
||||
[1.8mp]: https://github.com/rust-lang/rust/pull/30894
|
||||
[1.8mr]: https://users.rust-lang.org/t/multirust-0-8-with-cross-std-installation/4901
|
||||
[1.8ms]: https://github.com/rust-lang/rust/pull/30448
|
||||
[1.8n]: https://github.com/rust-lang/rust/pull/31056
|
||||
[1.8nx]: https://github.com/rust-lang/rust/pull/30859
|
||||
[1.8r]: https://github.com/rust-lang/rust/pull/31551
|
||||
[1.8so]: https://github.com/rust-lang/rust/pull/31333
|
||||
[1.8st]: https://github.com/rust-lang/rust/pull/29520
|
||||
[1.8t]: https://github.com/rust-lang/rust/pull/31358
|
||||
[1.8tn]: https://github.com/rust-lang/rust/pull/30882
|
||||
[1.8u]: https://github.com/rust-lang/rust/pull/31793
|
||||
[1.8v]: https://github.com/rust-lang/rust/pull/31757
|
||||
[1.8w]: https://github.com/rust-lang/rust/pull/31904
|
||||
[RFC 1361]: https://github.com/rust-lang/rfcs/blob/master/text/1361-cargo-cfg-dependencies.md
|
||||
[RFC 1415]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
|
||||
[RFC 218]: https://github.com/rust-lang/rfcs/blob/master/text/0218-empty-struct-with-braces.md
|
||||
[RFC 953]: https://github.com/rust-lang/rfcs/blob/master/text/0953-op-assign.md
|
||||
[`AddAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.AddAssign.html
|
||||
[`BitAndAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.BitAndAssign.html
|
||||
[`BitOrAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.BitOrAssign.html
|
||||
[`BitXorAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.BitXorAssign.html
|
||||
[`DivAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.DivAssign.html
|
||||
[`Instant::duration_since`]: http://doc.rust-lang.org/nightly/std/time/struct.Instant.html#method.duration_since
|
||||
[`Instant::elapsed`]: http://doc.rust-lang.org/nightly/std/time/struct.Instant.html#method.elapsed
|
||||
[`Instant::now`]: http://doc.rust-lang.org/nightly/std/time/struct.Instant.html#method.now
|
||||
[`MulAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.MulAssign.html
|
||||
[`Ref::map`]: http://doc.rust-lang.org/nightly/std/cell/struct.Ref.html#method.map
|
||||
[`RefMut::map`]: http://doc.rust-lang.org/nightly/std/cell/struct.RefMut.html#method.map
|
||||
[`RemAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.RemAssign.html
|
||||
[`ShlAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.ShlAssign.html
|
||||
[`ShrAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.ShrAssign.html
|
||||
[`SubAssign`]: http://doc.rust-lang.org/nightly/std/ops/trait.SubAssign.html
|
||||
[`SystemTime::duration_since`]: http://doc.rust-lang.org/nightly/std/time/struct.SystemTime.html#method.duration_since
|
||||
[`SystemTime::elapsed`]: http://doc.rust-lang.org/nightly/std/time/struct.SystemTime.html#method.elapsed
|
||||
[`SystemTime::now`]: http://doc.rust-lang.org/nightly/std/time/struct.SystemTime.html#method.now
|
||||
[`SystemTimeError::duration`]: http://doc.rust-lang.org/nightly/std/time/struct.SystemTimeError.html#method.duration
|
||||
[`SystemTimeError`]: http://doc.rust-lang.org/nightly/std/time/struct.SystemTimeError.html
|
||||
[`UNIX_EPOCH`]: http://doc.rust-lang.org/nightly/std/time/constant.UNIX_EPOCH.html
|
||||
[`ptr::drop_in_place`]: http://doc.rust-lang.org/nightly/std/ptr/fn.drop_in_place.html
|
||||
[`str::EncodeUtf16`]: http://doc.rust-lang.org/nightly/std/str/struct.EncodeUtf16.html
|
||||
[`str::encode_utf16`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.encode_utf16
|
||||
[`time::Instant`]: http://doc.rust-lang.org/nightly/std/time/struct.Instant.html
|
||||
[`time::SystemTime`]: http://doc.rust-lang.org/nightly/std/time/struct.SystemTime.html
|
||||
|
||||
|
||||
Version 1.7.0 (2016-03-03)
|
||||
==========================
|
||||
|
||||
Language
|
||||
--------
|
||||
|
||||
* Soundness fixes to the interactions between associated types and
|
||||
lifetimes, specified in [RFC 1214], [now generate errors][1.7sf] for
|
||||
code that violates the new rules. This is a significant change that
|
||||
is known to break existing code, so it has emitted warnings for the
|
||||
new error cases since 1.4 to give crate authors time to adapt. The
|
||||
details of what is changing are subtle; read the RFC for more.
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
@ -49,17 +267,6 @@ Libraries
|
||||
* [`IntoStringError::into_cstring`]
|
||||
* [`IntoStringError::utf8_error`]
|
||||
* `Error for IntoStringError`
|
||||
* Hashing
|
||||
* [`std::hash::BuildHasher`]
|
||||
* [`BuildHasher::Hasher`]
|
||||
* [`BuildHasher::build_hasher`]
|
||||
* [`std::hash::BuildHasherDefault`]
|
||||
* [`HashMap::with_hasher`]
|
||||
* [`HashMap::with_capacity_and_hasher`]
|
||||
* [`HashSet::with_hasher`]
|
||||
* [`HashSet::with_capacity_and_hasher`]
|
||||
* [`std::collections::hash_map::RandomState`]
|
||||
* [`RandomState::new`]
|
||||
* [Validating UTF-8 is faster by a factor of between 7 and 14x for
|
||||
ASCII input][1.7utf8]. This means that creating `String`s and `str`s
|
||||
from bytes is faster.
|
||||
@ -81,6 +288,9 @@ Libraries
|
||||
Misc
|
||||
----
|
||||
|
||||
* [The `--error-format=json` flag to `rustc` causes it to emit errors
|
||||
in JSON format][1.7j]. This is an unstable flag and so also requires
|
||||
the `-Z unstable-options` flag.
|
||||
* [When running tests with `--test`, rustdoc will pass `--cfg`
|
||||
arguments to the compiler][1.7dt].
|
||||
* [The compiler is built with RPATH information by default][1.7rpa].
|
||||
@ -102,12 +312,6 @@ Cargo
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
|
||||
* Soundness fixes to the interactions between associated types and
|
||||
lifetimes, specified in [RFC 1214], [now generate errors][1.7sf] for
|
||||
code that violates the new rules. This is a significant change that
|
||||
is known to break existing code, so it has emitted warnings for the
|
||||
new error cases since 1.4 to give crate authors time to adapt. The
|
||||
details of what is changing are subtle; read the RFC for more.
|
||||
* [Several bugs in the compiler's visibility calculations were
|
||||
fixed][1.7v]. Since this was found to break significant amounts of
|
||||
code, the new errors will be emitted as warnings for several release
|
||||
@ -130,6 +334,7 @@ Compatibility Notes
|
||||
[1.7dta]: https://github.com/rust-lang/rust/pull/30394
|
||||
[1.7f]: https://github.com/rust-lang/rust/pull/30672
|
||||
[1.7h]: https://github.com/rust-lang/rust/pull/30818
|
||||
[1.7j]: https://github.com/rust-lang/rust/pull/30711
|
||||
[1.7ll]: https://github.com/rust-lang/rust/pull/30663
|
||||
[1.7m]: https://github.com/rust-lang/rust/pull/30381
|
||||
[1.7p]: https://github.com/rust-lang/rust/pull/30681
|
||||
@ -140,15 +345,11 @@ Compatibility Notes
|
||||
[1.7utf8]: https://github.com/rust-lang/rust/pull/30740
|
||||
[1.7v]: https://github.com/rust-lang/rust/pull/29973
|
||||
[RFC 1214]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md
|
||||
[`BuildHasher::Hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hasher.html
|
||||
[`BuildHasher::build_hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.BuildHasher.html#tymethod.build_hasher
|
||||
[`clone_from_slice`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.clone_from_slice
|
||||
[`sort_by_key`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.sort_by_key
|
||||
[`CString::into_bytes_with_nul`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.into_bytes_with_nul
|
||||
[`CString::into_bytes`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.into_bytes
|
||||
[`CString::into_string`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.into_string
|
||||
[`HashMap::with_capacity_and_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashMap.html#method.with_capacity_and_hasher
|
||||
[`HashMap::with_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashMap.html#method.with_hasher
|
||||
[`HashSet::with_capacity_and_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.with_capacity_and_hasher
|
||||
[`HashSet::with_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.with_hasher
|
||||
[`IntoStringError::into_cstring`]: http://doc.rust-lang.org/nightly/std/ffi/struct.IntoStringError.html#method.into_cstring
|
||||
[`IntoStringError::utf8_error`]: http://doc.rust-lang.org/nightly/std/ffi/struct.IntoStringError.html#method.utf8_error
|
||||
[`Ipv4Addr::is_broadcast`]: http://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#method.is_broadcast
|
||||
@ -161,12 +362,10 @@ Compatibility Notes
|
||||
[`Ipv6Addr::is_multicast`]: http://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#method.is_multicast
|
||||
[`Ipv6Addr::is_unspecified`]: http://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#method.is_unspecified
|
||||
[`Path::strip_prefix`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.strip_prefix
|
||||
[`RandomState::new`]: http://doc.rust-lang.org/nightly/std/collections/hash_map/struct.RandomState.html#method.new
|
||||
[`String::as_mut_str`]: http://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_str
|
||||
[`String::as_str`]: http://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_str
|
||||
[`Vec::as_mut_slice`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_slice
|
||||
[`Vec::as_slice`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_slice
|
||||
[`clone_from_slice`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.clone_from_slice
|
||||
[`ffi::IntoStringError`]: http://doc.rust-lang.org/nightly/std/ffi/struct.IntoStringError.html
|
||||
[`i32::checked_neg`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.checked_neg
|
||||
[`i32::checked_rem`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.checked_rem
|
||||
@ -182,10 +381,6 @@ Compatibility Notes
|
||||
[`i32::overflowing_sub`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.overflowing_sub
|
||||
[`i32::saturating_mul`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.saturating_mul
|
||||
[`path::StripPrefixError`]: http://doc.rust-lang.org/nightly/std/path/struct.StripPrefixError.html
|
||||
[`sort_by_key`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.sort_by_key
|
||||
[`std::collections::hash_map::RandomState`]: http://doc.rust-lang.org/nightly/std/collections/hash_map/struct.RandomState.html
|
||||
[`std::hash::BuildHasherDefault`]: http://doc.rust-lang.org/nightly/std/hash/struct.BuildHasherDefault.html
|
||||
[`std::hash::BuildHasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.BuildHasher.html
|
||||
[`u32::checked_neg`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.checked_neg
|
||||
[`u32::checked_rem`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.checked_rem
|
||||
[`u32::checked_shl`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.checked_shl
|
||||
|
||||
226
configure
vendored
226
configure
vendored
@ -1,5 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/bash is.
|
||||
if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
|
||||
POSIX_SHELL="true"
|
||||
export POSIX_SHELL
|
||||
exec /usr/bin/env bash $0 "$@"
|
||||
fi
|
||||
unset POSIX_SHELL # clear it so if we invoke other scripts, they run as bash as well
|
||||
|
||||
msg() {
|
||||
echo "configure: $*"
|
||||
}
|
||||
@ -334,14 +342,6 @@ enable_if_not_disabled() {
|
||||
fi
|
||||
}
|
||||
|
||||
to_llvm_triple() {
|
||||
case $1 in
|
||||
i686-w64-mingw32) echo i686-pc-windows-gnu ;;
|
||||
x86_64-w64-mingw32) echo x86_64-pc-windows-gnu ;;
|
||||
*) echo $1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
to_gnu_triple() {
|
||||
case $1 in
|
||||
i686-pc-windows-gnu) echo i686-w64-mingw32 ;;
|
||||
@ -424,6 +424,11 @@ case $CFG_OSTYPE in
|
||||
CFG_OSTYPE=apple-darwin
|
||||
;;
|
||||
|
||||
SunOS)
|
||||
CFG_OSTYPE=sun-solaris
|
||||
CFG_CPUTYPE=$(isainfo -n)
|
||||
;;
|
||||
|
||||
MINGW*)
|
||||
# msys' `uname` does not print gcc configuration, but prints msys
|
||||
# configuration. so we cannot believe `uname -m`:
|
||||
@ -550,7 +555,7 @@ CFG_SELF="$0"
|
||||
CFG_CONFIGURE_ARGS="$@"
|
||||
|
||||
|
||||
case "${CFG_SRC_DIR}" in
|
||||
case "${CFG_SRC_DIR}" in
|
||||
*\ * )
|
||||
err "The path to the rust source directory contains spaces, which is not supported"
|
||||
;;
|
||||
@ -601,6 +606,7 @@ opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
|
||||
opt dist-host-only 0 "only install bins for the host architecture"
|
||||
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
|
||||
opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
|
||||
opt rustbuild 0 "use the rust and cargo based build system"
|
||||
|
||||
# Optimization and debugging options. These may be overridden by the release channel, etc.
|
||||
opt_nosave optimize 1 "build optimized rust code"
|
||||
@ -620,7 +626,7 @@ valopt llvm-root "" "set LLVM root"
|
||||
valopt python "" "set path to python"
|
||||
valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
|
||||
valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
|
||||
valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path (deprecated)"
|
||||
valopt android-cross-path "" "Android NDK standalone path (deprecated)"
|
||||
valopt i686-linux-android-ndk "" "i686-linux-android NDK standalone path"
|
||||
valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
|
||||
valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path"
|
||||
@ -646,12 +652,6 @@ valopt_nosave host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples"
|
||||
valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
|
||||
valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
|
||||
|
||||
# Temporarily support old triples until buildbots get updated
|
||||
CFG_BUILD=$(to_llvm_triple $CFG_BUILD)
|
||||
putvar CFG_BUILD # Yes, this creates a duplicate entry, but the last one wins.
|
||||
CFG_HOST=$(to_llvm_triple $CFG_HOST)
|
||||
CFG_TARGET=$(to_llvm_triple $CFG_TARGET)
|
||||
|
||||
# On Windows this determines root of the subtree for target libraries.
|
||||
# Host runtime libs always go to 'bin'.
|
||||
valopt libdir "${CFG_PREFIX}/lib" "install libraries"
|
||||
@ -729,12 +729,12 @@ step_msg "looking for build programs"
|
||||
|
||||
probe_need CFG_CURLORWGET curl wget
|
||||
if [ -z "$CFG_PYTHON_PROVIDED" ]; then
|
||||
probe_need CFG_PYTHON python2.7 python2.6 python2 python
|
||||
probe_need CFG_PYTHON python2.7 python2 python
|
||||
fi
|
||||
|
||||
python_version=$($CFG_PYTHON -V 2>&1)
|
||||
if [ $(echo $python_version | grep -c '^Python 2\.[4567]') -ne 1 ]; then
|
||||
err "Found $python_version, but LLVM requires Python 2.4-2.7"
|
||||
if [ $(echo $python_version | grep -c '^Python 2\.7') -ne 1 ]; then
|
||||
err "Found $python_version, but Python 2.7 is required"
|
||||
fi
|
||||
|
||||
# If we have no git directory then we are probably a tarball distribution
|
||||
@ -865,9 +865,8 @@ fi
|
||||
# Force bitrig to build with clang; gcc doesn't like us there
|
||||
if [ $CFG_OSTYPE = unknown-bitrig ]
|
||||
then
|
||||
step_msg "on Bitrig, forcing use of clang, disabling jemalloc"
|
||||
step_msg "on Bitrig, forcing use of clang"
|
||||
CFG_ENABLE_CLANG=1
|
||||
CFG_DISABLE_JEMALLOC=1
|
||||
fi
|
||||
|
||||
# default gcc version under OpenBSD maybe too old, try using egcc, which is a
|
||||
@ -887,9 +886,6 @@ then
|
||||
CXX="${CXX:-eg++}"
|
||||
fi
|
||||
fi
|
||||
|
||||
step_msg "on OpenBSD, disabling jemalloc"
|
||||
CFG_DISABLE_JEMALLOC=1
|
||||
fi
|
||||
|
||||
# OS X 10.9, gcc is actually clang. This can cause some confusion in the build
|
||||
@ -1044,7 +1040,7 @@ then
|
||||
esac
|
||||
else
|
||||
case $CFG_CLANG_VERSION in
|
||||
(3.2* | 3.3* | 3.4* | 3.5* | 3.6* | 3.7* | 3.8*)
|
||||
(3.2* | 3.3* | 3.4* | 3.5* | 3.6* | 3.7* | 3.8* | 3.9*)
|
||||
step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
|
||||
;;
|
||||
(*)
|
||||
@ -1171,7 +1167,7 @@ do
|
||||
;;
|
||||
|
||||
|
||||
*-musl)
|
||||
x86_64-*-musl)
|
||||
if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
|
||||
then
|
||||
err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
|
||||
@ -1179,12 +1175,6 @@ do
|
||||
;;
|
||||
|
||||
*-msvc)
|
||||
# Currently the build system is not configured to build jemalloc
|
||||
# with MSVC, so we omit this optional dependency.
|
||||
step_msg "targeting MSVC, disabling jemalloc"
|
||||
CFG_DISABLE_JEMALLOC=1
|
||||
putvar CFG_DISABLE_JEMALLOC
|
||||
|
||||
# There are some MSYS python builds which will auto-translate
|
||||
# windows-style paths to MSYS-style paths in Python itself.
|
||||
# Unfortunately this breaks LLVM's build system as somewhere along
|
||||
@ -1293,12 +1283,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
||||
putvar CFG_MSVC_LIB_PATH_${bits}
|
||||
;;
|
||||
|
||||
*-rumprun-netbsd)
|
||||
step_msg "targeting rumprun-netbsd, disabling jemalloc"
|
||||
CFG_DISABLE_JEMALLOC=1
|
||||
putvar CFG_DISABLE_JEMALLOC
|
||||
;;
|
||||
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
@ -1314,96 +1298,107 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
step_msg "making directories"
|
||||
if [ -z "$CFG_ENABLE_RUSTBUILD" ]; then
|
||||
|
||||
for i in \
|
||||
doc doc/std doc/extra \
|
||||
dl tmp dist
|
||||
do
|
||||
make_dir $i
|
||||
done
|
||||
step_msg "making directories"
|
||||
|
||||
for t in $CFG_HOST
|
||||
do
|
||||
make_dir $t/llvm
|
||||
done
|
||||
|
||||
for t in $CFG_HOST
|
||||
do
|
||||
make_dir $t/rustllvm
|
||||
done
|
||||
|
||||
for t in $CFG_TARGET
|
||||
do
|
||||
make_dir $t/rt
|
||||
for s in 0 1 2 3
|
||||
for i in \
|
||||
doc doc/std doc/extra \
|
||||
dl tmp dist
|
||||
do
|
||||
make_dir $t/rt/stage$s
|
||||
make_dir $t/rt/jemalloc
|
||||
make_dir $t/rt/compiler-rt
|
||||
for i in \
|
||||
isaac sync test \
|
||||
arch/i386 arch/x86_64 arch/arm arch/aarch64 arch/mips arch/powerpc
|
||||
make_dir $i
|
||||
done
|
||||
|
||||
for t in $CFG_HOST
|
||||
do
|
||||
make_dir $t/llvm
|
||||
done
|
||||
|
||||
for t in $CFG_HOST
|
||||
do
|
||||
make_dir $t/rustllvm
|
||||
done
|
||||
|
||||
for t in $CFG_TARGET
|
||||
do
|
||||
make_dir $t/rt
|
||||
for s in 0 1 2 3
|
||||
do
|
||||
make_dir $t/rt/stage$s/$i
|
||||
make_dir $t/rt/stage$s
|
||||
make_dir $t/rt/jemalloc
|
||||
make_dir $t/rt/compiler-rt
|
||||
for i in \
|
||||
isaac sync test \
|
||||
arch/i386 arch/x86_64 arch/arm arch/aarch64 arch/mips arch/powerpc
|
||||
do
|
||||
make_dir $t/rt/stage$s/$i
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
for h in $CFG_HOST
|
||||
do
|
||||
for t in $CFG_TARGET
|
||||
do
|
||||
# host lib dir stage0
|
||||
make_dir $h/stage0/lib
|
||||
for h in $CFG_HOST
|
||||
do
|
||||
for t in $CFG_TARGET
|
||||
do
|
||||
# host bin dir stage0
|
||||
make_dir $h/stage0/bin
|
||||
|
||||
# target bin dir stage0
|
||||
make_dir $h/stage0/lib/rustlib/$t/bin
|
||||
# host lib dir stage0
|
||||
make_dir $h/stage0/lib
|
||||
|
||||
# target lib dir stage0
|
||||
make_dir $h/stage0/lib/rustlib/$t/lib
|
||||
# host test dir stage0
|
||||
make_dir $h/stage0/test
|
||||
|
||||
for i in 0 1 2 3
|
||||
do
|
||||
# host bin dir
|
||||
make_dir $h/stage$i/bin
|
||||
# target bin dir stage0
|
||||
make_dir $h/stage0/lib/rustlib/$t/bin
|
||||
|
||||
# host lib dir
|
||||
make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE
|
||||
# target lib dir stage0
|
||||
make_dir $h/stage0/lib/rustlib/$t/lib
|
||||
|
||||
# host test dir
|
||||
make_dir $h/stage$i/test
|
||||
for i in 1 2 3
|
||||
do
|
||||
# host bin dir
|
||||
make_dir $h/stage$i/bin
|
||||
|
||||
# target bin dir
|
||||
make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE/rustlib/$t/bin
|
||||
# host lib dir
|
||||
make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE
|
||||
|
||||
# target lib dir
|
||||
make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE/rustlib/$t/lib
|
||||
done
|
||||
done
|
||||
# host test dir
|
||||
make_dir $h/stage$i/test
|
||||
|
||||
make_dir $h/test/run-pass
|
||||
make_dir $h/test/run-pass-valgrind
|
||||
make_dir $h/test/run-pass-fulldeps
|
||||
make_dir $h/test/run-fail
|
||||
make_dir $h/test/run-fail-fulldeps
|
||||
make_dir $h/test/compile-fail
|
||||
make_dir $h/test/parse-fail
|
||||
make_dir $h/test/compile-fail-fulldeps
|
||||
make_dir $h/test/bench
|
||||
make_dir $h/test/perf
|
||||
make_dir $h/test/pretty
|
||||
make_dir $h/test/debuginfo-gdb
|
||||
make_dir $h/test/debuginfo-lldb
|
||||
make_dir $h/test/codegen
|
||||
make_dir $h/test/rustdoc
|
||||
done
|
||||
# target bin dir
|
||||
make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE/rustlib/$t/bin
|
||||
|
||||
# target lib dir
|
||||
make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE/rustlib/$t/lib
|
||||
done
|
||||
done
|
||||
|
||||
make_dir $h/test/run-pass
|
||||
make_dir $h/test/run-pass-valgrind
|
||||
make_dir $h/test/run-pass-fulldeps
|
||||
make_dir $h/test/run-fail
|
||||
make_dir $h/test/run-fail-fulldeps
|
||||
make_dir $h/test/compile-fail
|
||||
make_dir $h/test/parse-fail
|
||||
make_dir $h/test/compile-fail-fulldeps
|
||||
make_dir $h/test/bench
|
||||
make_dir $h/test/perf
|
||||
make_dir $h/test/pretty
|
||||
make_dir $h/test/debuginfo-gdb
|
||||
make_dir $h/test/debuginfo-lldb
|
||||
make_dir $h/test/codegen
|
||||
make_dir $h/test/codegen-units
|
||||
make_dir $h/test/rustdoc
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
# Configure submodules
|
||||
step_msg "configuring submodules"
|
||||
|
||||
# Have to be in the top of src directory for this
|
||||
if [ -z $CFG_DISABLE_MANAGE_SUBMODULES ]
|
||||
if [ -z $CFG_DISABLE_MANAGE_SUBMODULES ] && [ -z $CFG_ENABLE_RUSTBUILD ]
|
||||
then
|
||||
cd ${CFG_SRC_DIR}
|
||||
|
||||
@ -1462,7 +1457,11 @@ do
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z $CFG_LLVM_ROOT ]
|
||||
if [ -n "$CFG_ENABLE_RUSTBUILD" ]
|
||||
then
|
||||
msg "not configuring LLVM, rustbuild in use"
|
||||
do_reconfigure=0
|
||||
elif [ -z $CFG_LLVM_ROOT ]
|
||||
then
|
||||
LLVM_BUILD_DIR=${CFG_BUILD_DIR}$t/llvm
|
||||
if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]
|
||||
@ -1793,8 +1792,15 @@ do
|
||||
putvar $CFG_LLVM_INST_DIR
|
||||
done
|
||||
|
||||
if [ -n "$CFG_ENABLE_RUSTBUILD" ]
|
||||
then
|
||||
INPUT_MAKEFILE=src/bootstrap/mk/Makefile.in
|
||||
else
|
||||
INPUT_MAKEFILE=Makefile.in
|
||||
fi
|
||||
|
||||
msg
|
||||
copy_if_changed ${CFG_SRC_DIR}Makefile.in ./Makefile
|
||||
copy_if_changed ${CFG_SRC_DIR}${INPUT_MAKEFILE} ./Makefile
|
||||
move_if_changed config.tmp config.mk
|
||||
rm -f config.tmp
|
||||
touch config.stamp
|
||||
|
||||
50
man/rustc.1
50
man/rustc.1
@ -6,9 +6,7 @@ rustc \- The Rust compiler
|
||||
[\fIOPTIONS\fR] \fIINPUT\fR
|
||||
|
||||
.SH DESCRIPTION
|
||||
This program is a compiler for the Rust language, available at
|
||||
.UR https://www.rust\-lang.org
|
||||
.UE .
|
||||
This program is a compiler for the Rust language, available at https://www.rust\-lang.org.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
@ -53,10 +51,9 @@ Comma separated list of types of crates for the compiler to emit.
|
||||
Specify the name of the crate being built.
|
||||
.TP
|
||||
\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info][=\fIPATH\fR]
|
||||
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.
|
||||
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]
|
||||
Comma separated list of compiler information to print on stdout.
|
||||
@ -68,13 +65,11 @@ Equivalent to \fI\-C\ debuginfo=2\fR.
|
||||
Equivalent to \fI\-C\ opt\-level=2\fR.
|
||||
.TP
|
||||
\fB\-o\fR \fIFILENAME\fR
|
||||
Write output to \fIFILENAME\fR.
|
||||
Ignored if multiple \fI\-\-emit\fR outputs are specified which don't have an
|
||||
explicit path otherwise.
|
||||
Write output to \fIFILENAME\fR. Ignored if multiple \fI\-\-emit\fR outputs are specified which
|
||||
don't have an explicit path otherwise.
|
||||
.TP
|
||||
\fB\-\-out\-dir\fR \fIDIR\fR
|
||||
Write output to compiler\[hy]chosen filename in \fIDIR\fR.
|
||||
Ignored if \fI\-o\fR is specified.
|
||||
Write output to compiler\[hy]chosen filename in \fIDIR\fR. Ignored if \fI\-o\fR is specified.
|
||||
Defaults to the current directory.
|
||||
.TP
|
||||
\fB\-\-explain\fR \fIOPT\fR
|
||||
@ -83,12 +78,26 @@ Provide a detailed explanation of an error message.
|
||||
\fB\-\-test\fR
|
||||
Build a test harness.
|
||||
.TP
|
||||
\fB\-\-target\fR \fITRIPLE\fR
|
||||
Target triple \fIcpu\fR\-\fImanufacturer\fR\-\fIkernel\fR[\-\fIos\fR]
|
||||
to compile for (see chapter 3.4 of
|
||||
.UR http://www.sourceware.org/autobook/
|
||||
.UE
|
||||
for details).
|
||||
\fB\-\-target\fR \fITARGET\fR
|
||||
Target triple for which the code is compiled. This option defaults to the host’s target
|
||||
triple. The target triple has the general format <arch><sub>\-<vendor>\-<sys>\-<abi>, where:
|
||||
.RS
|
||||
.TP
|
||||
.B <arch>
|
||||
x86, arm, thumb, mips, etc.
|
||||
.TP
|
||||
.B <sub>
|
||||
for example on ARM: v5, v6m, v7a, v7m, etc.
|
||||
.TP
|
||||
.B <vendor>
|
||||
pc, apple, nvidia, ibm, etc.
|
||||
.TP
|
||||
.B <sys>
|
||||
none, linux, win32, darwin, cuda, etc.
|
||||
.TP
|
||||
.B <abi>
|
||||
eabi, gnu, android, macho, elf, etc.
|
||||
.RE
|
||||
.TP
|
||||
\fB\-W help\fR
|
||||
Print 'lint' options and default settings.
|
||||
@ -287,10 +296,7 @@ To build an executable with debug info:
|
||||
.BR rustdoc (1)
|
||||
|
||||
.SH "BUGS"
|
||||
See
|
||||
.UR https://github.com/rust\-lang/rust/issues
|
||||
.UE
|
||||
for issues.
|
||||
See https://github.com/rust\-lang/rust/issues for issues.
|
||||
|
||||
.SH "AUTHOR"
|
||||
See \fIAUTHORS.txt\fR in the Rust source distribution.
|
||||
|
||||
@ -8,10 +8,8 @@ rustdoc \- generate documentation from Rust source code
|
||||
.SH DESCRIPTION
|
||||
This tool generates API reference documentation by extracting comments from
|
||||
source code written in the Rust language, available at
|
||||
.UR https://www.rust\-lang.org
|
||||
.UE .
|
||||
It accepts several input formats and provides several output formats
|
||||
for the generated documentation.
|
||||
<\fBhttps://www.rust-lang.org\fR>. It accepts several input formats and
|
||||
provides several output formats for the generated documentation.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
@ -131,9 +129,7 @@ The generated HTML can be viewed with any standard web browser.
|
||||
.BR rustc (1)
|
||||
|
||||
.SH "BUGS"
|
||||
See
|
||||
.UR https://github.com/rust\-lang/rust/issues
|
||||
.UE
|
||||
See <\fBhttps://github.com/rust\-lang/rust/issues\fR>
|
||||
for issues.
|
||||
|
||||
.SH "AUTHOR"
|
||||
|
||||
@ -8,8 +8,8 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a
|
||||
CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfloat-abi=soft $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfloat-abi=soft $(CFLAGS)
|
||||
CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfloat-abi=soft $(CFLAGS) -march=armv6 -marm
|
||||
CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfloat-abi=soft $(CFLAGS) -march=armv6 -marm
|
||||
CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g
|
||||
CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabi := -Wl,--export-dynamic,--dynamic-list=
|
||||
|
||||
@ -8,8 +8,8 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a
|
||||
CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS)
|
||||
CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS) -march=armv6 -marm
|
||||
CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS) -march=armv6 -marm
|
||||
CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g
|
||||
CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynamic-list=
|
||||
|
||||
26
mk/cfg/armv7-unknown-linux-gnueabihf.mk
Normal file
26
mk/cfg/armv7-unknown-linux-gnueabihf.mk
Normal file
@ -0,0 +1,26 @@
|
||||
# armv7-unknown-linux-gnueabihf configuration
|
||||
CROSS_PREFIX_armv7-unknown-linux-gnueabihf=arm-linux-gnueabihf-
|
||||
CC_armv7-unknown-linux-gnueabihf=gcc
|
||||
CXX_armv7-unknown-linux-gnueabihf=g++
|
||||
CPP_armv7-unknown-linux-gnueabihf=gcc -E
|
||||
AR_armv7-unknown-linux-gnueabihf=ar
|
||||
CFG_LIB_NAME_armv7-unknown-linux-gnueabihf=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_armv7-unknown-linux-gnueabihf=lib$(1).a
|
||||
CFG_LIB_GLOB_armv7-unknown-linux-gnueabihf=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_armv7-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_armv7-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS) -march=armv7-a
|
||||
CFG_GCCISH_CFLAGS_armv7-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS) -march=armv7-a
|
||||
CFG_GCCISH_CXXFLAGS_armv7-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_armv7-unknown-linux-gnueabihf := -shared -fPIC -g
|
||||
CFG_GCCISH_DEF_FLAG_armv7-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynamic-list=
|
||||
CFG_LLC_FLAGS_armv7-unknown-linux-gnueabihf :=
|
||||
CFG_INSTALL_NAME_ar,-unknown-linux-gnueabihf =
|
||||
CFG_EXE_SUFFIX_armv7-unknown-linux-gnueabihf :=
|
||||
CFG_WINDOWSY_armv7-unknown-linux-gnueabihf :=
|
||||
CFG_UNIXY_armv7-unknown-linux-gnueabihf := 1
|
||||
CFG_LDPATH_armv7-unknown-linux-gnueabihf :=
|
||||
CFG_RUN_armv7-unknown-linux-gnueabihf=$(2)
|
||||
CFG_RUN_TARG_armv7-unknown-linux-gnueabihf=$(call CFG_RUN_armv7-unknown-linux-gnueabihf,,$(2))
|
||||
RUSTC_FLAGS_armv7-unknown-linux-gnueabihf :=
|
||||
RUSTC_CROSS_FLAGS_armv7-unknown-linux-gnueabihf :=
|
||||
CFG_GNU_TRIPLE_armv7-unknown-linux-gnueabihf := armv7-unknown-linux-gnueabihf
|
||||
@ -14,8 +14,8 @@ CFG_LIB_GLOB_armv7s-apple-ios = lib$(1)-*.a
|
||||
CFG_INSTALL_ONLY_RLIB_armv7s-apple-ios = 1
|
||||
CFG_STATIC_LIB_NAME_armv7s-apple-ios=lib$(1).a
|
||||
CFG_LIB_DSYM_GLOB_armv7s-apple-ios = lib$(1)-*.a.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_armv7s-apple-ios := -arch armv7s -mfpu=vfp4 $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios)
|
||||
CFG_GCCISH_CFLAGS_armv7s-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -mfpu=vfp4 -arch armv7s
|
||||
CFG_JEMALLOC_CFLAGS_armv7s-apple-ios := -arch armv7s $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios)
|
||||
CFG_GCCISH_CFLAGS_armv7s-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -arch armv7s
|
||||
CFG_GCCISH_CXXFLAGS_armv7s-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -I$(CFG_IOS_SDK_armv7s-apple-ios)/usr/include/c++/4.2.1
|
||||
CFG_GCCISH_LINK_FLAGS_armv7s-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7s-apple-ios) -Wl,-no_compact_unwind
|
||||
CFG_GCCISH_DEF_FLAG_armv7s-apple-ios := -Wl,-exported_symbols_list,
|
||||
|
||||
24
mk/cfg/asmjs-unknown-emscripten.mk
Normal file
24
mk/cfg/asmjs-unknown-emscripten.mk
Normal file
@ -0,0 +1,24 @@
|
||||
# asmjs-unknown-emscripten configuration
|
||||
CC_asmjs-unknown-emscripten=emcc
|
||||
CXX_asmjs-unknown-emscripten=em++
|
||||
CPP_asmjs-unknown-emscripten=$(CPP)
|
||||
AR_asmjs-unknown-emscripten=emar
|
||||
CFG_LIB_NAME_asmjs-unknown-emscripten=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_asmjs-unknown-emscripten=lib$(1).a
|
||||
CFG_LIB_GLOB_asmjs-unknown-emscripten=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_asmjs-unknown-emscripten=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_asmjs-unknown-emscripten := -m32 $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_asmjs-unknown-emscripten := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
|
||||
CFG_GCCISH_CXXFLAGS_asmjs-unknown-emscripten := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_asmjs-unknown-emscripten := -shared -fPIC -ldl -pthread -lrt -g -m32
|
||||
CFG_GCCISH_DEF_FLAG_asmjs-unknown-emscripten := -Wl,--export-dynamic,--dynamic-list=
|
||||
CFG_LLC_FLAGS_asmjs-unknown-emscripten :=
|
||||
CFG_INSTALL_NAME_asmjs-unknown-emscripten =
|
||||
CFG_EXE_SUFFIX_asmjs-unknown-emscripten =
|
||||
CFG_WINDOWSY_asmjs-unknown-emscripten :=
|
||||
CFG_UNIXY_asmjs-unknown-emscripten := 1
|
||||
CFG_LDPATH_asmjs-unknown-emscripten :=
|
||||
CFG_RUN_asmjs-unknown-emscripten=$(2)
|
||||
CFG_RUN_TARG_asmjs-unknown-emscripten=$(call CFG_RUN_asmjs-unknown-emscripten,,$(2))
|
||||
CFG_GNU_TRIPLE_asmjs-unknown-emscripten := asmjs-unknown-emscripten
|
||||
CFG_DISABLE_JEMALLOC_asmjs-unknown-emscripten := 1
|
||||
23
mk/cfg/i586-unknown-linux-gnu.mk
Normal file
23
mk/cfg/i586-unknown-linux-gnu.mk
Normal file
@ -0,0 +1,23 @@
|
||||
# i586-unknown-linux-gnu configuration
|
||||
CC_i586-unknown-linux-gnu=$(CC)
|
||||
CXX_i586-unknown-linux-gnu=$(CXX)
|
||||
CPP_i586-unknown-linux-gnu=$(CPP)
|
||||
AR_i586-unknown-linux-gnu=$(AR)
|
||||
CFG_LIB_NAME_i586-unknown-linux-gnu=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_i586-unknown-linux-gnu=lib$(1).a
|
||||
CFG_LIB_GLOB_i586-unknown-linux-gnu=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_i586-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
|
||||
CFG_GCCISH_CXXFLAGS_i586-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_i586-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
|
||||
CFG_GCCISH_DEF_FLAG_i586-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||
CFG_LLC_FLAGS_i586-unknown-linux-gnu :=
|
||||
CFG_INSTALL_NAME_i586-unknown-linux-gnu =
|
||||
CFG_EXE_SUFFIX_i586-unknown-linux-gnu =
|
||||
CFG_WINDOWSY_i586-unknown-linux-gnu :=
|
||||
CFG_UNIXY_i586-unknown-linux-gnu := 1
|
||||
CFG_LDPATH_i586-unknown-linux-gnu :=
|
||||
CFG_RUN_i586-unknown-linux-gnu=$(2)
|
||||
CFG_RUN_TARG_i586-unknown-linux-gnu=$(call CFG_RUN_i586-unknown-linux-gnu,,$(2))
|
||||
CFG_GNU_TRIPLE_i586-unknown-linux-gnu := i586-unknown-linux-gnu
|
||||
@ -25,3 +25,5 @@ CFG_GNU_TRIPLE_i686-pc-windows-gnu := i686-w64-mingw32
|
||||
CFG_THIRD_PARTY_OBJECTS_i686-pc-windows-gnu := crt2.o dllcrt2.o
|
||||
CFG_INSTALLED_OBJECTS_i686-pc-windows-gnu := crt2.o dllcrt2.o rsbegin.o rsend.o
|
||||
CFG_RUSTRT_HAS_STARTUP_OBJS_i686-pc-windows-gnu := 1
|
||||
# FIXME(#31030) - there's not a great reason to disable jemalloc here
|
||||
CFG_DISABLE_JEMALLOC_i686-pc-windows-gnu := 1
|
||||
|
||||
@ -22,3 +22,7 @@ CFG_LDPATH_i686-pc-windows-msvc :=
|
||||
CFG_RUN_i686-pc-windows-msvc=$(2)
|
||||
CFG_RUN_TARG_i686-pc-windows-msvc=$(call CFG_RUN_i686-pc-windows-msvc,,$(2))
|
||||
CFG_GNU_TRIPLE_i686-pc-windows-msvc := i686-pc-win32
|
||||
|
||||
# Currently the build system is not configured to build jemalloc
|
||||
# with MSVC, so we omit this optional dependency.
|
||||
CFG_DISABLE_JEMALLOC_i686-pc-windows-msvc := 1
|
||||
|
||||
28
mk/cfg/i686-unknown-linux-musl.mk
Normal file
28
mk/cfg/i686-unknown-linux-musl.mk
Normal file
@ -0,0 +1,28 @@
|
||||
# i686-unknown-linux-musl configuration
|
||||
CC_i686-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc
|
||||
CXX_i686-unknown-linux-musl=notaprogram
|
||||
CPP_i686-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -E
|
||||
AR_i686-unknown-linux-musl=$(AR)
|
||||
CFG_INSTALL_ONLY_RLIB_i686-unknown-linux-musl = 1
|
||||
CFG_LIB_NAME_i686-unknown-linux-musl=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_i686-unknown-linux-musl=lib$(1).a
|
||||
CFG_LIB_GLOB_i686-unknown-linux-musl=lib$(1)-*.so
|
||||
CFG_JEMALLOC_CFLAGS_i686-unknown-linux-musl := -m32 -Wl,-melf_i386
|
||||
CFG_GCCISH_CFLAGS_i686-unknown-linux-musl := -Wall -Werror -g -fPIC -m32 -Wl,-melf_i386
|
||||
CFG_GCCISH_CXXFLAGS_i686-unknown-linux-musl :=
|
||||
CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-musl :=
|
||||
CFG_GCCISH_DEF_FLAG_i686-unknown-linux-musl :=
|
||||
CFG_LLC_FLAGS_i686-unknown-linux-musl :=
|
||||
CFG_INSTALL_NAME_i686-unknown-linux-musl =
|
||||
CFG_EXE_SUFFIX_i686-unknown-linux-musl =
|
||||
CFG_WINDOWSY_i686-unknown-linux-musl :=
|
||||
CFG_UNIXY_i686-unknown-linux-musl := 1
|
||||
CFG_LDPATH_i686-unknown-linux-musl :=
|
||||
CFG_RUN_i686-unknown-linux-musl=$(2)
|
||||
CFG_RUN_TARG_i686-unknown-linux-musl=$(call CFG_RUN_i686-unknown-linux-musl,,$(2))
|
||||
CFG_GNU_TRIPLE_i686-unknown-linux-musl := i686-unknown-linux-musl
|
||||
CFG_THIRD_PARTY_OBJECTS_i686-unknown-linux-musl := crt1.o crti.o crtn.o
|
||||
CFG_INSTALLED_OBJECTS_i686-unknown-linux-musl := crt1.o crti.o crtn.o
|
||||
|
||||
NATIVE_DEPS_libc_T_i686-unknown-linux-musl += libc.a
|
||||
NATIVE_DEPS_std_T_i686-unknown-linux-musl += libunwind.a crt1.o crti.o crtn.o
|
||||
@ -20,5 +20,5 @@ CFG_UNIXY_mips-unknown-linux-gnu := 1
|
||||
CFG_LDPATH_mips-unknown-linux-gnu :=
|
||||
CFG_RUN_mips-unknown-linux-gnu=
|
||||
CFG_RUN_TARG_mips-unknown-linux-gnu=
|
||||
RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2" -C soft-float
|
||||
RUSTC_FLAGS_mips-unknown-linux-gnu :=
|
||||
CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu
|
||||
|
||||
24
mk/cfg/mips-unknown-linux-musl.mk
Normal file
24
mk/cfg/mips-unknown-linux-musl.mk
Normal file
@ -0,0 +1,24 @@
|
||||
# mips-unknown-linux-musl configuration
|
||||
CC_mips-unknown-linux-musl=mips-linux-musl-gcc
|
||||
CXX_mips-unknown-linux-musl=mips-linux-musl-g++
|
||||
CPP_mips-unknown-linux-musl=mips-linux-musl-gcc -E
|
||||
AR_mips-unknown-linux-musl=mips-linux-musl-ar
|
||||
CFG_LIB_NAME_mips-unknown-linux-musl=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_mips-unknown-linux-musl=lib$(1).a
|
||||
CFG_LIB_GLOB_mips-unknown-linux-musl=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_mips-unknown-linux-musl=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_mips-unknown-linux-musl := -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_mips-unknown-linux-musl := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
|
||||
CFG_GCCISH_CXXFLAGS_mips-unknown-linux-musl := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-musl := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
|
||||
CFG_GCCISH_DEF_FLAG_mips-unknown-linux-musl := -Wl,--export-dynamic,--dynamic-list=
|
||||
CFG_LLC_FLAGS_mips-unknown-linux-musl :=
|
||||
CFG_INSTALL_NAME_mips-unknown-linux-musl =
|
||||
CFG_EXE_SUFFIX_mips-unknown-linux-musl =
|
||||
CFG_WINDOWSY_mips-unknown-linux-musl :=
|
||||
CFG_UNIXY_mips-unknown-linux-musl := 1
|
||||
CFG_LDPATH_mips-unknown-linux-musl :=
|
||||
CFG_RUN_mips-unknown-linux-musl=
|
||||
CFG_RUN_TARG_mips-unknown-linux-musl=
|
||||
RUSTC_FLAGS_mips-unknown-linux-musl :=
|
||||
CFG_GNU_TRIPLE_mips-unknown-linux-musl := mips-unknown-linux-musl
|
||||
@ -20,5 +20,5 @@ CFG_UNIXY_mipsel-unknown-linux-gnu := 1
|
||||
CFG_LDPATH_mipsel-unknown-linux-gnu :=
|
||||
CFG_RUN_mipsel-unknown-linux-gnu=
|
||||
CFG_RUN_TARG_mipsel-unknown-linux-gnu=
|
||||
RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32"
|
||||
RUSTC_FLAGS_mipsel-unknown-linux-gnu :=
|
||||
CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu
|
||||
|
||||
24
mk/cfg/mipsel-unknown-linux-musl.mk
Normal file
24
mk/cfg/mipsel-unknown-linux-musl.mk
Normal file
@ -0,0 +1,24 @@
|
||||
# mipsel-unknown-linux-musl configuration
|
||||
CC_mipsel-unknown-linux-musl=mipsel-linux-musl-gcc
|
||||
CXX_mipsel-unknown-linux-musl=mipsel-linux-musl-g++
|
||||
CPP_mipsel-unknown-linux-musl=mipsel-linux-musl-gcc
|
||||
AR_mipsel-unknown-linux-musl=mipsel-linux-musl-ar
|
||||
CFG_LIB_NAME_mipsel-unknown-linux-musl=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_mipsel-unknown-linux-musl=lib$(1).a
|
||||
CFG_LIB_GLOB_mipsel-unknown-linux-musl=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_mipsel-unknown-linux-musl=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_mipsel-unknown-linux-musl := -mips32 -mabi=32 $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_mipsel-unknown-linux-musl := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
|
||||
CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-musl := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-musl := -shared -fPIC -g -mips32
|
||||
CFG_GCCISH_DEF_FLAG_mipsel-unknown-linux-musl := -Wl,--export-dynamic,--dynamic-list=
|
||||
CFG_LLC_FLAGS_mipsel-unknown-linux-musl :=
|
||||
CFG_INSTALL_NAME_mipsel-unknown-linux-musl =
|
||||
CFG_EXE_SUFFIX_mipsel-unknown-linux-musl :=
|
||||
CFG_WINDOWSY_mipsel-unknown-linux-musl :=
|
||||
CFG_UNIXY_mipsel-unknown-linux-musl := 1
|
||||
CFG_LDPATH_mipsel-unknown-linux-musl :=
|
||||
CFG_RUN_mipsel-unknown-linux-musl=
|
||||
CFG_RUN_TARG_mipsel-unknown-linux-musl=
|
||||
RUSTC_FLAGS_mipsel-unknown-linux-musl :=
|
||||
CFG_GNU_TRIPLE_mipsel-unknown-linux-musl := mipsel-unknown-linux-musl
|
||||
@ -1,5 +1,5 @@
|
||||
# powerpc64-unknown-linux-gnu configuration
|
||||
CROSS_PREFIX_powerpc64-unknown-linux-gnu=powerpc64-linux-gnu-
|
||||
CROSS_PREFIX_powerpc64-unknown-linux-gnu=powerpc-linux-gnu-
|
||||
CC_powerpc64-unknown-linux-gnu=$(CC)
|
||||
CXX_powerpc64-unknown-linux-gnu=$(CXX)
|
||||
CPP_powerpc64-unknown-linux-gnu=$(CPP)
|
||||
@ -8,6 +8,7 @@ CFG_LIB_NAME_powerpc64-unknown-linux-gnu=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_powerpc64-unknown-linux-gnu=lib$(1).a
|
||||
CFG_LIB_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_powerpc64-unknown-linux-gnu := -m64
|
||||
CFG_CFLAGS_powerpc64-unknown-linux-gnu := -m64 $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_powerpc64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
|
||||
CFG_GCCISH_CXXFLAGS_powerpc64-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
||||
|
||||
@ -25,3 +25,5 @@ CFG_GNU_TRIPLE_x86_64-pc-windows-gnu := x86_64-w64-mingw32
|
||||
CFG_THIRD_PARTY_OBJECTS_x86_64-pc-windows-gnu := crt2.o dllcrt2.o
|
||||
CFG_INSTALLED_OBJECTS_x86_64-pc-windows-gnu := crt2.o dllcrt2.o rsbegin.o rsend.o
|
||||
CFG_RUSTRT_HAS_STARTUP_OBJS_x86_64-pc-windows-gnu := 1
|
||||
# FIXME(#31030) - there's not a great reason to disable jemalloc here
|
||||
CFG_DISABLE_JEMALLOC_x86_64-pc-windows-gnu := 1
|
||||
|
||||
@ -22,3 +22,7 @@ CFG_LDPATH_x86_64-pc-windows-msvc :=
|
||||
CFG_RUN_x86_64-pc-windows-msvc=$(2)
|
||||
CFG_RUN_TARG_x86_64-pc-windows-msvc=$(call CFG_RUN_x86_64-pc-windows-msvc,,$(2))
|
||||
CFG_GNU_TRIPLE_x86_64-pc-windows-msvc := x86_64-pc-win32
|
||||
|
||||
# Currently the build system is not configured to build jemalloc
|
||||
# with MSVC, so we omit this optional dependency.
|
||||
CFG_DISABLE_JEMALLOC_x86_64-pc-windows-msvc := 1
|
||||
|
||||
@ -22,3 +22,4 @@ CFG_LDPATH_x86_64-rumprun-netbsd :=
|
||||
CFG_RUN_x86_64-rumprun-netbsd=$(2)
|
||||
CFG_RUN_TARG_x86_64-rumprun-netbsd=$(call CFG_RUN_x86_64-rumprun-netbsd,,$(2))
|
||||
CFG_GNU_TRIPLE_x86_64-rumprun-netbsd := x86_64-rumprun-netbsd
|
||||
CFG_DISABLE_JEMALLOC_x86_64-rumprun-netbsd := 1
|
||||
|
||||
23
mk/cfg/x86_64-sun-solaris.mk
Normal file
23
mk/cfg/x86_64-sun-solaris.mk
Normal file
@ -0,0 +1,23 @@
|
||||
# x86_64-sun-solaris configuration
|
||||
CROSS_PREFIX_x86_64-sun-solaris=x86_64-sun-solaris2.11-
|
||||
CC_x86_64-sun-solaris=$(CC)
|
||||
CXX_x86_64-sun-solaris=$(CXX)
|
||||
CPP_x86_64-sun-solaris=$(CPP)
|
||||
AR_x86_64-sun-solaris=$(AR)
|
||||
CFG_LIB_NAME_x86_64-sun-solaris=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_x86_64-sun-solaris=lib$(1).a
|
||||
CFG_LIB_GLOB_x86_64-sun-solaris=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_x86_64-sun-solaris=$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_x86_64-sun-solaris := -I/usr/local/include $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_x86_64-sun-solaris := -Wall -Werror -g -D_POSIX_PTHREAD_SEMANTICS -fPIC -I/usr/local/include $(CFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_x86_64-sun-solaris := -shared -fPIC -g -pthread -lrt
|
||||
CFG_GCCISH_DEF_FLAG_x86_64-sun-solaris := -Wl,--export-dynamic,--dynamic-list=
|
||||
CFG_LLC_FLAGS_x86_64-sun-solaris :=
|
||||
CFG_INSTALL_NAME_x86_64-sun-solaris =
|
||||
CFG_EXE_SUFFIX_x86_64-sun-solaris :=
|
||||
CFG_WINDOWSY_x86_64-sun-solaris :=
|
||||
CFG_UNIXY_x86_64-sun-solaris := 1
|
||||
CFG_LDPATH_x86_64-sun-solaris :=
|
||||
CFG_RUN_x86_64-sun-solaris=$(2)
|
||||
CFG_RUN_TARG_x86_64-sun-solaris=$(call CFG_RUN_x86_64-sun-solaris,,$(2))
|
||||
CFG_GNU_TRIPLE_x86_64-sun-solaris := x86_64-sun-solaris
|
||||
@ -20,3 +20,4 @@ CFG_LDPATH_x86_64-unknown-bitrig :=
|
||||
CFG_RUN_x86_64-unknown-bitrig=$(2)
|
||||
CFG_RUN_TARG_x86_64-unknown-bitrig=$(call CFG_RUN_x86_64-unknown-bitrig,,$(2))
|
||||
CFG_GNU_TRIPLE_x86_64-unknown-bitrig := x86_64-unknown-bitrig
|
||||
CFG_DISABLE_JEMALLOC_x86_64-unknown-bitrig := 1
|
||||
|
||||
@ -21,3 +21,4 @@ CFG_RUN_x86_64-unknown-openbsd=$(2)
|
||||
CFG_RUN_TARG_x86_64-unknown-openbsd=$(call CFG_RUN_x86_64-unknown-openbsd,,$(2))
|
||||
CFG_GNU_TRIPLE_x86_64-unknown-openbsd := x86_64-unknown-openbsd
|
||||
RUSTC_FLAGS_x86_64-unknown-openbsd=-C linker=$(call FIND_COMPILER,$(CC))
|
||||
CFG_DISABLE_JEMALLOC_x86_64-unknown-openbsd := 1
|
||||
|
||||
45
mk/crates.mk
45
mk/crates.mk
@ -53,17 +53,18 @@ TARGET_CRATES := libc std flate arena term \
|
||||
serialize getopts collections test rand \
|
||||
log graphviz core rbml alloc \
|
||||
rustc_unicode rustc_bitflags \
|
||||
alloc_system
|
||||
alloc_system alloc_jemalloc
|
||||
RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \
|
||||
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
|
||||
rustc_data_structures rustc_front rustc_platform_intrinsics \
|
||||
rustc_plugin rustc_metadata rustc_passes
|
||||
HOST_CRATES := syntax syntax_ext $(RUSTC_CRATES) rustdoc fmt_macros
|
||||
TOOLS := compiletest rustdoc rustc rustbook error-index-generator
|
||||
TOOLS := compiletest rustdoc rustc rustbook error_index_generator
|
||||
|
||||
DEPS_core :=
|
||||
DEPS_alloc := core libc alloc_system
|
||||
DEPS_alloc_system := core libc
|
||||
DEPS_alloc_jemalloc := core libc native:jemalloc
|
||||
DEPS_collections := core alloc rustc_unicode
|
||||
DEPS_libc := core
|
||||
DEPS_rand := core
|
||||
@ -102,11 +103,11 @@ DEPS_rustc_front := std syntax log serialize
|
||||
DEPS_rustc_lint := rustc log syntax
|
||||
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
|
||||
DEPS_rustc_metadata := rustc rustc_front syntax rbml
|
||||
DEPS_rustc_passes := syntax rustc core
|
||||
DEPS_rustc_passes := syntax rustc core rustc_front
|
||||
DEPS_rustc_mir := rustc rustc_front syntax
|
||||
DEPS_rustc_resolve := arena rustc rustc_front log syntax
|
||||
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
|
||||
DEPS_rustc_plugin := rustc rustc_metadata syntax
|
||||
DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir
|
||||
DEPS_rustc_privacy := rustc rustc_front log syntax
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \
|
||||
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
|
||||
@ -120,12 +121,12 @@ TOOL_DEPS_compiletest := test getopts
|
||||
TOOL_DEPS_rustdoc := rustdoc
|
||||
TOOL_DEPS_rustc := rustc_driver
|
||||
TOOL_DEPS_rustbook := std rustdoc
|
||||
TOOL_DEPS_error-index-generator := rustdoc syntax serialize
|
||||
TOOL_DEPS_error_index_generator := rustdoc syntax serialize
|
||||
TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs
|
||||
TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs
|
||||
TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
|
||||
TOOL_SOURCE_rustbook := $(S)src/rustbook/main.rs
|
||||
TOOL_SOURCE_error-index-generator := $(S)src/error-index-generator/main.rs
|
||||
TOOL_SOURCE_error_index_generator := $(S)src/error_index_generator/main.rs
|
||||
|
||||
ONLY_RLIB_core := 1
|
||||
ONLY_RLIB_libc := 1
|
||||
@ -135,17 +136,15 @@ ONLY_RLIB_collections := 1
|
||||
ONLY_RLIB_rustc_unicode := 1
|
||||
ONLY_RLIB_rustc_bitflags := 1
|
||||
ONLY_RLIB_alloc_system := 1
|
||||
ONLY_RLIB_alloc_jemalloc := 1
|
||||
|
||||
TARGET_SPECIFIC_alloc_jemalloc := 1
|
||||
|
||||
# Documented-by-default crates
|
||||
DOC_CRATES := std alloc collections core libc rustc_unicode
|
||||
|
||||
ifeq ($(CFG_DISABLE_JEMALLOC),)
|
||||
TARGET_CRATES += alloc_jemalloc
|
||||
DEPS_std += alloc_jemalloc
|
||||
DEPS_alloc_jemalloc := core libc native:jemalloc
|
||||
ONLY_RLIB_alloc_jemalloc := 1
|
||||
else
|
||||
RUSTFLAGS_rustc_back := --cfg disable_jemalloc
|
||||
RUSTFLAGS_rustc_back := --cfg 'feature="jemalloc"'
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
@ -161,12 +160,32 @@ CRATES := $(TARGET_CRATES) $(HOST_CRATES)
|
||||
define RUST_CRATE
|
||||
CRATEFILE_$(1) := $$(SREL)src/lib$(1)/lib.rs
|
||||
RSINPUTS_$(1) := $$(call rwildcard,$(S)src/lib$(1)/,*.rs)
|
||||
RUST_DEPS_$(1) := $$(filter-out native:%,$$(DEPS_$(1)))
|
||||
NATIVE_DEPS_$(1) := $$(patsubst native:%,%,$$(filter native:%,$$(DEPS_$(1))))
|
||||
endef
|
||||
|
||||
$(foreach crate,$(CRATES),$(eval $(call RUST_CRATE,$(crate))))
|
||||
|
||||
# $(1) - crate
|
||||
# $(2) - target
|
||||
define RUST_CRATE_DEPS
|
||||
RUST_DEPS_$(1)_T_$(2) := $$(filter-out native:%,$$(DEPS_$(1)))
|
||||
endef
|
||||
|
||||
$(foreach target,$(CFG_TARGET),\
|
||||
$(foreach crate,$(CRATES),$(eval $(call RUST_CRATE_DEPS,$(crate),$(target)))))
|
||||
|
||||
# $(1) - target
|
||||
# $(2) - crate
|
||||
define DEFINE_TARGET_CRATES
|
||||
ifndef TARGET_SPECIFIC_$(2)
|
||||
TARGET_CRATES_$(1) += $(2)
|
||||
endif
|
||||
endef
|
||||
|
||||
$(foreach target,$(CFG_TARGET),\
|
||||
$(foreach crate,$(TARGET_CRATES),\
|
||||
$(eval $(call DEFINE_TARGET_CRATES,$(target),$(crate)))))
|
||||
|
||||
# Similar to the macro above for crates, this macro is for tools
|
||||
#
|
||||
# $(1) is the crate to generate variables for
|
||||
|
||||
@ -48,11 +48,13 @@ PKG_FILES := \
|
||||
$(S)configure $(S)Makefile.in \
|
||||
$(S)man \
|
||||
$(addprefix $(S)src/, \
|
||||
bootstrap \
|
||||
build_helper \
|
||||
compiletest \
|
||||
doc \
|
||||
driver \
|
||||
etc \
|
||||
error-index-generator \
|
||||
error_index_generator \
|
||||
$(foreach crate,$(CRATES),lib$(crate)) \
|
||||
libcollectionstest \
|
||||
libcoretest \
|
||||
@ -60,6 +62,7 @@ PKG_FILES := \
|
||||
rt \
|
||||
rtstartup \
|
||||
rustllvm \
|
||||
rustc \
|
||||
snapshots.txt \
|
||||
rust-installer \
|
||||
rustbook \
|
||||
|
||||
19
mk/docs.mk
19
mk/docs.mk
@ -59,9 +59,10 @@ RUSTBOOK_EXE = $(HBIN2_H_$(CFG_BUILD))/rustbook$(X_$(CFG_BUILD))
|
||||
# ./configure
|
||||
RUSTBOOK = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(RUSTBOOK_EXE)
|
||||
|
||||
# The error-index-generator executable...
|
||||
ERR_IDX_GEN_EXE = $(HBIN2_H_$(CFG_BUILD))/error-index-generator$(X_$(CFG_BUILD))
|
||||
# The error_index_generator executable...
|
||||
ERR_IDX_GEN_EXE = $(HBIN2_H_$(CFG_BUILD))/error_index_generator$(X_$(CFG_BUILD))
|
||||
ERR_IDX_GEN = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE)
|
||||
ERR_IDX_GEN_MD = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE) markdown
|
||||
|
||||
D := $(S)src/doc
|
||||
|
||||
@ -157,9 +158,9 @@ LIB_DOC_DEP_$(1) = \
|
||||
$$(CRATEFILE_$(1)) \
|
||||
$$(RSINPUTS_$(1)) \
|
||||
$$(RUSTDOC_EXE) \
|
||||
$$(foreach dep,$$(RUST_DEPS_$(1)), \
|
||||
$$(foreach dep,$$(RUST_DEPS_$(1)_T_$(CFG_BUILD)), \
|
||||
$$(TLIB2_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.$$(dep)) \
|
||||
$$(foreach dep,$$(filter $$(DOC_CRATES), $$(RUST_DEPS_$(1))), \
|
||||
$$(foreach dep,$$(filter $$(DOC_CRATES), $$(RUST_DEPS_$(1)_T_$(CFG_BUILD))), \
|
||||
doc/$$(dep)/)
|
||||
else
|
||||
LIB_DOC_DEP_$(1) = $$(CRATEFILE_$(1)) $$(RSINPUTS_$(1))
|
||||
@ -217,6 +218,12 @@ doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/
|
||||
|
||||
error-index: doc/error-index.html
|
||||
|
||||
doc/error-index.html: $(ERR_IDX_GEN_EXE) | doc/
|
||||
$(Q)$(call E, error-index-generator: $@)
|
||||
# Metadata used to generate the index is created as a side effect of
|
||||
# the build so this depends on every crate being up to date.
|
||||
doc/error-index.html: $(ERR_IDX_GEN_EXE) $(CSREQ$(2)_T_$(CFG_BUILD)_H_$(CFG_BUILD)) | doc/
|
||||
$(Q)$(call E, error_index_generator: $@)
|
||||
$(Q)$(ERR_IDX_GEN)
|
||||
|
||||
doc/error-index.md: $(ERR_IDX_GEN_EXE) $(CSREQ$(2)_T_$(CFG_BUILD)_H_$(CFG_BUILD)) | doc/
|
||||
$(Q)$(call E, error_index_generator: $@)
|
||||
$(Q)$(ERR_IDX_GEN_MD)
|
||||
|
||||
@ -21,7 +21,7 @@ define CP_HOST_STAGE_N_CRATE
|
||||
ifeq ($$(ONLY_RLIB_$(5)),)
|
||||
$$(HLIB$(2)_H_$(4))/stamp.$(5): \
|
||||
$$(TLIB$(1)_T_$(3)_H_$(4))/stamp.$(5) \
|
||||
$$(RUST_DEPS_$(5):%=$$(HLIB$(2)_H_$(4))/stamp.%) \
|
||||
$$(RUST_DEPS_$(5)_T_$(3):%=$$(HLIB$(2)_H_$(4))/stamp.%) \
|
||||
| $$(HLIB$(2)_H_$(4))/
|
||||
@$$(call E, cp: $$(@D)/lib$(5))
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES, \
|
||||
|
||||
@ -108,7 +108,7 @@ endif
|
||||
define INSTALL_RUNTIME_TARGET_N
|
||||
install-runtime-target-$(1)-host-$(2): $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2))
|
||||
$$(Q)$$(call ADB_SHELL,mkdir,$(CFG_RUNTIME_PUSH_DIR))
|
||||
$$(Q)$$(foreach crate,$$(TARGET_CRATES), \
|
||||
$$(Q)$$(foreach crate,$$(TARGET_CRATES_$(1)), \
|
||||
$$(call ADB_PUSH,$$(TL$(1)$(2))/$$(call CFG_LIB_GLOB_$(1),$$(crate)), \
|
||||
$$(CFG_RUNTIME_PUSH_DIR));)
|
||||
endef
|
||||
@ -116,7 +116,7 @@ endef
|
||||
define INSTALL_RUNTIME_TARGET_CLEANUP_N
|
||||
install-runtime-target-$(1)-cleanup:
|
||||
$$(Q)$$(call ADB,remount)
|
||||
$$(Q)$$(foreach crate,$$(TARGET_CRATES), \
|
||||
$$(Q)$$(foreach crate,$$(TARGET_CRATES_$(1)), \
|
||||
$$(call ADB_SHELL,rm,$$(CFG_RUNTIME_PUSH_DIR)/$$(call CFG_LIB_GLOB_$(1),$$(crate)));)
|
||||
endef
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ $(foreach host,$(CFG_HOST), \
|
||||
define LLVM_LINKAGE_DEPS
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc_llvm: $$(LLVM_LINKAGE_PATH_$(2))
|
||||
RUSTFLAGS$(1)_rustc_llvm_T_$(2) += $$(shell echo $$(LLVM_ALL_COMPONENTS_$(2)) | tr '-' '_' |\
|
||||
sed -e 's/^ //;s/\([^ ]*\)/\-\-cfg have_component_\1/g')
|
||||
sed -e 's/^ //;s/\([^ ]*\)/\-\-cfg "llvm_component=\\"\1\\""/g')
|
||||
endef
|
||||
|
||||
$(foreach source,$(CFG_HOST), \
|
||||
|
||||
19
mk/main.mk
19
mk/main.mk
@ -13,12 +13,12 @@
|
||||
######################################################################
|
||||
|
||||
# The version number
|
||||
CFG_RELEASE_NUM=1.7.0
|
||||
CFG_RELEASE_NUM=1.8.0
|
||||
|
||||
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
|
||||
# NB Make sure it starts with a dot to conform to semver pre-release
|
||||
# versions (section 9)
|
||||
CFG_PRERELEASE_VERSION=.4
|
||||
CFG_PRERELEASE_VERSION=.2
|
||||
|
||||
# Append a version-dependent hash to each library, so we can install different
|
||||
# versions in the same place
|
||||
@ -361,6 +361,9 @@ export CFG_DISABLE_UNSTABLE_FEATURES
|
||||
export RUSTC_BOOTSTRAP_KEY:=$(CFG_BOOTSTRAP_KEY)
|
||||
endif
|
||||
export CFG_BOOTSTRAP_KEY
|
||||
ifdef CFG_MUSL_ROOT
|
||||
export CFG_MUSL_ROOT
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# Per-stage targets and runner
|
||||
@ -429,7 +432,7 @@ TSREQ$(1)_T_$(2)_H_$(3) = \
|
||||
# target
|
||||
SREQ$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TSREQ$(1)_T_$(2)_H_$(3)) \
|
||||
$$(foreach dep,$$(TARGET_CRATES), \
|
||||
$$(foreach dep,$$(TARGET_CRATES_$(2)), \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \
|
||||
tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-$$(call TRIPLE_TO_DEBUGGER_SCRIPT_SETTING,$(2)).done
|
||||
|
||||
@ -438,7 +441,7 @@ SREQ$(1)_T_$(2)_H_$(3) = \
|
||||
CSREQ$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TSREQ$(1)_T_$(2)_H_$(3)) \
|
||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||
$$(foreach dep,$$(CRATES),$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep))
|
||||
$$(foreach dep,$$(HOST_CRATES),$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep))
|
||||
|
||||
ifeq ($(1),0)
|
||||
# Don't run the stage0 compiler under valgrind - that ship has sailed
|
||||
@ -522,14 +525,6 @@ STAGE$(1)_T_$(2)_H_$(3) := \
|
||||
$$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \
|
||||
$$(RUSTC_FLAGS_$(2))
|
||||
|
||||
PERF_STAGE$(1)_T_$(2)_H_$(3) := \
|
||||
$$(Q)$$(call CFG_RUN_TARG_$(3),$(1), \
|
||||
$$(CFG_PERF_TOOL) \
|
||||
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
|
||||
--cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \
|
||||
$$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \
|
||||
$$(RUSTC_FLAGS_$(2))
|
||||
|
||||
endef
|
||||
|
||||
$(foreach build,$(CFG_HOST), \
|
||||
|
||||
25
mk/perf.mk
25
mk/perf.mk
@ -1,25 +0,0 @@
|
||||
# Copyright 2012 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.
|
||||
|
||||
|
||||
ifdef CFG_PERF_TOOL
|
||||
rustc-perf$(X): $(CFG_BUILD)/stage2/bin/rustc$(X_$(CFG_BUILD))
|
||||
@$(call E, perf compile: $@)
|
||||
$(PERF_STAGE2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
|
||||
-o $@ $(COMPILER_CRATE) >rustc-perf.err 2>&1
|
||||
$(Q)rm -f $(LIBRUSTC_GLOB)
|
||||
else
|
||||
rustc-perf$(X): $(CFG_BUILD)/stage2/bin/rustc$(X_$(CFG_BUILD))
|
||||
$(Q)touch $@
|
||||
endif
|
||||
|
||||
perf: check-stage2-perf rustc-perf$(X_$(CFG_BUILD))
|
||||
$(Q)find $(CFG_BUILD)/test/perf -name \*.err | xargs cat
|
||||
$(Q)cat rustc-perf.err
|
||||
@ -77,23 +77,6 @@ define DEF_GOOD_VALGRIND
|
||||
endef
|
||||
$(foreach t,$(CFG_TARGET),$(eval $(call DEF_GOOD_VALGRIND,$(t))))
|
||||
|
||||
ifneq ($(findstring linux,$(CFG_OSTYPE)),)
|
||||
ifdef CFG_PERF
|
||||
ifneq ($(CFG_PERF_WITH_LOGFD),)
|
||||
CFG_PERF_TOOL := $(CFG_PERF) stat -r 3 --log-fd 2
|
||||
else
|
||||
CFG_PERF_TOOL := $(CFG_PERF) stat -r 3
|
||||
endif
|
||||
else
|
||||
ifdef CFG_VALGRIND
|
||||
CFG_PERF_TOOL := \
|
||||
$(CFG_VALGRIND) --tool=cachegrind --cache-sim=yes --branch-sim=yes
|
||||
else
|
||||
CFG_PERF_TOOL := /usr/bin/time --verbose
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
AR := ar
|
||||
|
||||
define SET_FROM_CFG
|
||||
@ -135,6 +118,18 @@ endef
|
||||
$(foreach target,$(CFG_TARGET), \
|
||||
$(eval $(call DEFINE_LINKER,$(target))))
|
||||
|
||||
define ADD_JEMALLOC_DEP
|
||||
ifndef CFG_DISABLE_JEMALLOC_$(1)
|
||||
ifndef CFG_DISABLE_JEMALLOC
|
||||
RUST_DEPS_std_T_$(1) += alloc_jemalloc
|
||||
TARGET_CRATES_$(1) += alloc_jemalloc
|
||||
endif
|
||||
endif
|
||||
endef
|
||||
|
||||
$(foreach target,$(CFG_TARGET), \
|
||||
$(eval $(call ADD_JEMALLOC_DEP,$(target))))
|
||||
|
||||
# The -Qunused-arguments sidesteps spurious warnings from clang
|
||||
define FILTER_FLAGS
|
||||
ifeq ($$(CFG_USING_CLANG),1)
|
||||
|
||||
@ -82,7 +82,7 @@ define PREPARE_MAN
|
||||
|
||||
endef
|
||||
|
||||
PREPARE_TOOLS = $(filter-out compiletest rustbook error-index-generator, $(TOOLS))
|
||||
PREPARE_TOOLS = $(filter-out compiletest rustbook error_index_generator, $(TOOLS))
|
||||
|
||||
|
||||
# $(1) is tool
|
||||
@ -122,7 +122,7 @@ prepare-host-lib-$(1)-$(2)-$(3)-$(4): \
|
||||
prepare-host-lib-$(1)-$(2)-$(3)-$(4): \
|
||||
PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(call PREPARE_TAR_LIB_DIR,$$(HLIB_RELATIVE$(2)_H_$(3)))
|
||||
prepare-host-lib-$(1)-$(2)-$(3)-$(4): prepare-maybe-clean-$(4) \
|
||||
$$(foreach dep,$$(RUST_DEPS_$(1)),prepare-host-lib-$$(dep)-$(2)-$(3)-$(4)) \
|
||||
$$(foreach dep,$$(RUST_DEPS_$(1)_T_$(3)),prepare-host-lib-$$(dep)-$(2)-$(3)-$(4)) \
|
||||
$$(HLIB$(2)_H_$(3))/stamp.$(1) \
|
||||
prepare-host-dirs-$(4)
|
||||
$$(if $$(findstring $(2), $$(PREPARE_STAGE)), \
|
||||
@ -147,7 +147,7 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): \
|
||||
prepare-target-$(2)-host-$(3)-$(1)-$(4): \
|
||||
PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_LIB_DIR)/rustlib/$(3)/bin
|
||||
prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
|
||||
$$(foreach crate,$$(TARGET_CRATES), \
|
||||
$$(foreach crate,$$(TARGET_CRATES_$(2)), \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) \
|
||||
$$(if $$(findstring $(2),$$(CFG_HOST)), \
|
||||
$$(foreach crate,$$(HOST_CRATES), \
|
||||
@ -161,7 +161,7 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
|
||||
$$(if $$(findstring $(3), $$(PREPARE_HOST)), \
|
||||
$$(call PREPARE_DIR,$$(PREPARE_WORKING_DEST_LIB_DIR)) \
|
||||
$$(call PREPARE_DIR,$$(PREPARE_DEST_BIN_DIR)) \
|
||||
$$(foreach crate,$$(TARGET_CRATES), \
|
||||
$$(foreach crate,$$(TARGET_CRATES_$(2)), \
|
||||
$$(if $$(or $$(findstring 1, $$(ONLY_RLIB_$$(crate))),$$(findstring 1,$$(CFG_INSTALL_ONLY_RLIB_$(2)))),, \
|
||||
$$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))) \
|
||||
$$(call PREPARE_LIB,$$(call CFG_RLIB_GLOB,$$(crate)))) \
|
||||
|
||||
33
mk/rt.mk
33
mk/rt.mk
@ -148,7 +148,15 @@ ifeq ($$(CFG_WINDOWSY_$(1)),1)
|
||||
else ifeq ($(OSTYPE_$(1)), apple-ios)
|
||||
JEMALLOC_ARGS_$(1) := --disable-tls
|
||||
else ifeq ($(findstring android, $(OSTYPE_$(1))), android)
|
||||
JEMALLOC_ARGS_$(1) := --disable-tls
|
||||
# We force android to have prefixed symbols because apparently replacement of
|
||||
# the libc allocator doesn't quite work. When this was tested (unprefixed
|
||||
# symbols), it was found that the `realpath` function in libc would allocate
|
||||
# with libc malloc (not jemalloc malloc), and then the standard library would
|
||||
# free with jemalloc free, causing a segfault.
|
||||
#
|
||||
# If the test suite passes, however, without symbol prefixes then we should be
|
||||
# good to go!
|
||||
JEMALLOC_ARGS_$(1) := --disable-tls --with-jemalloc-prefix=je_
|
||||
endif
|
||||
|
||||
ifdef CFG_ENABLE_DEBUG_JEMALLOC
|
||||
@ -186,7 +194,7 @@ JEMALLOC_LOCAL_$(1) := $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1
|
||||
$$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
|
||||
@$$(call E, make: jemalloc)
|
||||
cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
|
||||
$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \
|
||||
$$(JEMALLOC_ARGS_$(1)) $(CFG_JEMALLOC_FLAGS) \
|
||||
--build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \
|
||||
CC="$$(CC_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1))" \
|
||||
AR="$$(AR_$(1))" \
|
||||
@ -245,7 +253,7 @@ COMPRT_AR_$(1) := $$(AR_$(1))
|
||||
# We chomp -Werror here because GCC warns about the type signature of
|
||||
# builtins not matching its own and the build fails. It's a bit hacky,
|
||||
# but what can we do, we're building libclang-rt using GCC ......
|
||||
COMPRT_CFLAGS_$(1) := $$(subst -Werror,,$$(CFG_GCCISH_CFLAGS_$(1))) -std=c99
|
||||
COMPRT_CFLAGS_$(1) := $$(filter-out -Werror -Werror=*,$$(CFG_GCCISH_CFLAGS_$(1))) -std=c99
|
||||
|
||||
# FreeBSD Clang's packaging is problematic; it doesn't copy unwind.h to
|
||||
# the standard include directory. This should really be in our changes to
|
||||
@ -254,6 +262,15 @@ ifeq ($$(findstring freebsd,$(1)),freebsd)
|
||||
COMPRT_CFLAGS_$(1) += -I/usr/include/c++/v1
|
||||
endif
|
||||
|
||||
ifeq ($$(findstring emscripten,$(1)),emscripten)
|
||||
|
||||
# FIXME: emscripten doesn't use compiler-rt and can't build it without
|
||||
# further hacks
|
||||
$$(COMPRT_LIB_$(1)):
|
||||
touch $$@
|
||||
|
||||
else
|
||||
|
||||
$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS)
|
||||
@$$(call E, make: compiler-rt)
|
||||
$$(Q)$$(MAKE) -C "$(S)src/compiler-rt" \
|
||||
@ -266,7 +283,10 @@ $$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS)
|
||||
TargetTriple=$(1) \
|
||||
triple-builtins
|
||||
$$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/triple/builtins/libcompiler_rt.a $$@
|
||||
|
||||
endif # if emscripten
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# libbacktrace
|
||||
#
|
||||
@ -301,6 +321,12 @@ $$(BACKTRACE_LIB_$(1)):
|
||||
touch $$@
|
||||
else
|
||||
|
||||
ifeq ($$(findstring emscripten,$(1)),emscripten)
|
||||
# FIXME: libbacktrace doesn't understand the emscripten triple
|
||||
$$(BACKTRACE_LIB_$(1)):
|
||||
touch $$@
|
||||
else
|
||||
|
||||
ifdef CFG_ENABLE_FAST_MAKE
|
||||
BACKTRACE_DEPS := $(S)/.gitmodules
|
||||
else
|
||||
@ -348,6 +374,7 @@ $$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS)
|
||||
INCDIR=$(S)src/libbacktrace
|
||||
$$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@
|
||||
|
||||
endif # endif for emscripten
|
||||
endif # endif for msvc
|
||||
endif # endif for ios
|
||||
endif # endif for darwin
|
||||
|
||||
12
mk/target.mk
12
mk/target.mk
@ -17,14 +17,6 @@ export CFG_COMPILER_HOST_TRIPLE
|
||||
export CFG_DEFAULT_LINKER
|
||||
export CFG_DEFAULT_AR
|
||||
|
||||
# The standard libraries should be held up to a higher standard than any old
|
||||
# code, make sure that these common warnings are denied by default. These can
|
||||
# be overridden during development temporarily. For stage0, we allow warnings
|
||||
# which may be bugs in stage0 (should be fixed in stage1+)
|
||||
RUST_LIB_FLAGS_ST0 += -W warnings
|
||||
RUST_LIB_FLAGS_ST1 += -D warnings
|
||||
RUST_LIB_FLAGS_ST2 += -D warnings
|
||||
|
||||
# Macro that generates the full list of dependencies for a crate at a particular
|
||||
# stage/target/host tuple.
|
||||
#
|
||||
@ -36,7 +28,7 @@ define RUST_CRATE_FULLDEPS
|
||||
CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) := \
|
||||
$$(CRATEFILE_$(4)) \
|
||||
$$(RSINPUTS_$(4)) \
|
||||
$$(foreach dep,$$(RUST_DEPS_$(4)), \
|
||||
$$(foreach dep,$$(RUST_DEPS_$(4)_T_$(2)), \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \
|
||||
$$(foreach dep,$$(NATIVE_DEPS_$(4)), \
|
||||
$$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep))) \
|
||||
@ -155,7 +147,7 @@ ifeq ($$(CFG_RUSTRT_HAS_STARTUP_OBJS_$(2)), 1)
|
||||
# Add dependencies on Rust startup objects to all crates that depend on core.
|
||||
# This ensures that they are built after core (since they depend on it),
|
||||
# but before everything else (since they are needed for linking dylib crates).
|
||||
$$(foreach crate, $$(TARGET_CRATES), \
|
||||
$$(foreach crate, $$(TARGET_CRATES_$(2)), \
|
||||
$$(if $$(findstring core,$$(DEPS_$$(crate))), \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate))) : $$(TLIB$(1)_T_$(2)_H_$(3))/$(4).o
|
||||
endif
|
||||
|
||||
137
mk/tests.mk
137
mk/tests.mk
@ -45,16 +45,11 @@ ifdef CHECK_IGNORED
|
||||
TESTARGS += --ignored
|
||||
endif
|
||||
|
||||
# Arguments to the cfail/rfail/rpass/bench tests
|
||||
# Arguments to the cfail/rfail/rpass tests
|
||||
ifdef CFG_VALGRIND
|
||||
CTEST_RUNTOOL = --runtool "$(CFG_VALGRIND)"
|
||||
endif
|
||||
|
||||
# Arguments to the perf tests
|
||||
ifdef CFG_PERF_TOOL
|
||||
CTEST_PERF_RUNTOOL = --runtool "$(CFG_PERF_TOOL)"
|
||||
endif
|
||||
|
||||
CTEST_TESTARGS := $(TESTARGS)
|
||||
|
||||
# --bench is only relevant for crate tests, not for the compile tests
|
||||
@ -70,12 +65,6 @@ endif
|
||||
# This prevents tests from failing with some locales (fixes #17423).
|
||||
export LC_ALL=C
|
||||
|
||||
# If we're running perf then set this environment variable
|
||||
# to put the benchmarks into 'hard mode'
|
||||
ifeq ($(MAKECMDGOALS),perf)
|
||||
export RUST_BENCH=1
|
||||
endif
|
||||
|
||||
TEST_LOG_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).log
|
||||
TEST_OK_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).ok
|
||||
|
||||
@ -146,7 +135,7 @@ $(info check: android device test dir $(CFG_ADB_TEST_DIR) ready \
|
||||
$(foreach target,$(CFG_TARGET), \
|
||||
$(if $(findstring android, $(target)), \
|
||||
$(shell $(CFG_ADB) shell mkdir $(CFG_ADB_TEST_DIR)/$(target)) \
|
||||
$(foreach crate,$(TARGET_CRATES), \
|
||||
$(foreach crate,$(TARGET_CRATES_$(target)), \
|
||||
$(shell $(CFG_ADB) push $(TLIB2_T_$(target)_H_$(CFG_BUILD))/$(call CFG_LIB_GLOB_$(target),$(crate)) \
|
||||
$(CFG_ADB_TEST_DIR)/$(target))), \
|
||||
)))
|
||||
@ -309,18 +298,18 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rustdocck-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-codegen-units-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
|
||||
|
||||
@ -354,7 +343,6 @@ check-stage$(1)-T-$(2)-H-$(3)-pretty-exec: \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pretty-bench-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pretty-pretty-exec
|
||||
|
||||
endef
|
||||
@ -376,7 +364,7 @@ define TEST_RUNNER
|
||||
# parent crates.
|
||||
ifeq ($(NO_REBUILD),)
|
||||
TESTDEP_$(1)_$(2)_$(3)_$(4) = $$(SREQ$(1)_T_$(2)_H_$(3)) \
|
||||
$$(foreach crate,$$(TARGET_CRATES), \
|
||||
$$(foreach crate,$$(TARGET_CRATES_$(2)), \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) \
|
||||
$$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4))
|
||||
|
||||
@ -470,25 +458,22 @@ $(foreach host,$(CFG_HOST), \
|
||||
# Rules for the compiletest tests (rpass, rfail, etc.)
|
||||
######################################################################
|
||||
|
||||
RPASS_RS := $(wildcard $(S)src/test/run-pass/*.rs)
|
||||
RPASS_VALGRIND_RS := $(wildcard $(S)src/test/run-pass-valgrind/*.rs)
|
||||
RPASS_FULL_RS := $(wildcard $(S)src/test/run-pass-fulldeps/*.rs)
|
||||
RFAIL_FULL_RS := $(wildcard $(S)src/test/run-fail-fulldeps/*.rs)
|
||||
CFAIL_FULL_RS := $(wildcard $(S)src/test/compile-fail-fulldeps/*.rs)
|
||||
RFAIL_RS := $(wildcard $(S)src/test/run-fail/*.rs)
|
||||
CFAIL_RS := $(wildcard $(S)src/test/compile-fail/*.rs)
|
||||
PFAIL_RS := $(wildcard $(S)src/test/parse-fail/*.rs)
|
||||
BENCH_RS := $(wildcard $(S)src/test/bench/*.rs)
|
||||
PRETTY_RS := $(wildcard $(S)src/test/pretty/*.rs)
|
||||
DEBUGINFO_GDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
|
||||
DEBUGINFO_LLDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
|
||||
CODEGEN_RS := $(wildcard $(S)src/test/codegen/*.rs)
|
||||
CODEGEN_CC := $(wildcard $(S)src/test/codegen/*.cc)
|
||||
RUSTDOCCK_RS := $(wildcard $(S)src/test/rustdoc/*.rs)
|
||||
|
||||
# perf tests are the same as bench tests only they run under
|
||||
# a performance monitor.
|
||||
PERF_RS := $(wildcard $(S)src/test/bench/*.rs)
|
||||
RPASS_RS := $(call rwildcard,$(S)src/test/run-pass/,*.rs)
|
||||
RPASS_VALGRIND_RS := $(call rwildcard,$(S)src/test/run-pass-valgrind/,*.rs)
|
||||
RPASS_FULL_RS := $(call rwildcard,$(S)src/test/run-pass-fulldeps/,*.rs)
|
||||
RFAIL_FULL_RS := $(call rwildcard,$(S)src/test/run-fail-fulldeps/,*.rs)
|
||||
CFAIL_FULL_RS := $(call rwildcard,$(S)src/test/compile-fail-fulldeps/,*.rs)
|
||||
RFAIL_RS := $(call rwildcard,$(S)src/test/run-fail/,*.rs)
|
||||
RFAIL_RS := $(call rwildcard,$(S)src/test/run-fail/,*.rs)
|
||||
CFAIL_RS := $(call rwildcard,$(S)src/test/compile-fail/,*.rs)
|
||||
PFAIL_RS := $(call rwildcard,$(S)src/test/parse-fail/,*.rs)
|
||||
PRETTY_RS := $(call rwildcard,$(S)src/test/pretty/,*.rs)
|
||||
DEBUGINFO_GDB_RS := $(call rwildcard,$(S)src/test/debuginfo/,*.rs)
|
||||
DEBUGINFO_LLDB_RS := $(call rwildcard,$(S)src/test/debuginfo/,*.rs)
|
||||
CODEGEN_RS := $(call rwildcard,$(S)src/test/codegen/,*.rs)
|
||||
CODEGEN_CC := $(call rwildcard,$(S)src/test/codegen/,*.cc)
|
||||
CODEGEN_UNITS_RS := $(call rwildcard,$(S)src/test/codegen-units/,*.rs)
|
||||
RUSTDOCCK_RS := $(call rwildcard,$(S)src/test/rustdoc/,*.rs)
|
||||
|
||||
RPASS_TESTS := $(RPASS_RS)
|
||||
RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
|
||||
@ -498,12 +483,11 @@ CFAIL_FULL_TESTS := $(CFAIL_FULL_RS)
|
||||
RFAIL_TESTS := $(RFAIL_RS)
|
||||
CFAIL_TESTS := $(CFAIL_RS)
|
||||
PFAIL_TESTS := $(PFAIL_RS)
|
||||
BENCH_TESTS := $(BENCH_RS)
|
||||
PERF_TESTS := $(PERF_RS)
|
||||
PRETTY_TESTS := $(PRETTY_RS)
|
||||
DEBUGINFO_GDB_TESTS := $(DEBUGINFO_GDB_RS)
|
||||
DEBUGINFO_LLDB_TESTS := $(DEBUGINFO_LLDB_RS)
|
||||
CODEGEN_TESTS := $(CODEGEN_RS) $(CODEGEN_CC)
|
||||
CODEGEN_UNITS_TESTS := $(CODEGEN_UNITS_RS)
|
||||
RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
|
||||
|
||||
CTEST_SRC_BASE_rpass = run-pass
|
||||
@ -546,16 +530,6 @@ CTEST_BUILD_BASE_pfail = parse-fail
|
||||
CTEST_MODE_pfail = parse-fail
|
||||
CTEST_RUNTOOL_pfail = $(CTEST_RUNTOOL)
|
||||
|
||||
CTEST_SRC_BASE_bench = bench
|
||||
CTEST_BUILD_BASE_bench = bench
|
||||
CTEST_MODE_bench = run-pass
|
||||
CTEST_RUNTOOL_bench = $(CTEST_RUNTOOL)
|
||||
|
||||
CTEST_SRC_BASE_perf = bench
|
||||
CTEST_BUILD_BASE_perf = perf
|
||||
CTEST_MODE_perf = run-pass
|
||||
CTEST_RUNTOOL_perf = $(CTEST_PERF_RUNTOOL)
|
||||
|
||||
CTEST_SRC_BASE_debuginfo-gdb = debuginfo
|
||||
CTEST_BUILD_BASE_debuginfo-gdb = debuginfo-gdb
|
||||
CTEST_MODE_debuginfo-gdb = debuginfo-gdb
|
||||
@ -571,6 +545,11 @@ CTEST_BUILD_BASE_codegen = codegen
|
||||
CTEST_MODE_codegen = codegen
|
||||
CTEST_RUNTOOL_codegen = $(CTEST_RUNTOOL)
|
||||
|
||||
CTEST_SRC_BASE_codegen-units = codegen-units
|
||||
CTEST_BUILD_BASE_codegen-units = codegen-units
|
||||
CTEST_MODE_codegen-units = codegen-units
|
||||
CTEST_RUNTOOL_codegen-units = $(CTEST_RUNTOOL)
|
||||
|
||||
CTEST_SRC_BASE_rustdocck = rustdoc
|
||||
CTEST_BUILD_BASE_rustdocck = rustdoc
|
||||
CTEST_MODE_rustdocck = rustdoc
|
||||
@ -625,7 +604,7 @@ TEST_SREQ$(1)_T_$(2)_H_$(3) = \
|
||||
$$(HBIN$(1)_H_$(3))/compiletest$$(X_$(3)) \
|
||||
$$(SREQ$(1)_T_$(2)_H_$(3))
|
||||
|
||||
# Rules for the cfail/rfail/rpass/bench/perf test runner
|
||||
# Rules for the cfail/rfail/rpass test runner
|
||||
|
||||
# The tests select when to use debug configuration on their own;
|
||||
# remove directive, if present, from CFG_RUSTC_FLAGS (issue #7898).
|
||||
@ -688,16 +667,15 @@ CTEST_DEPS_cfail-full_$(1)-T-$(2)-H-$(3) = $$(CFAIL_FULL_TESTS) $$(CSREQ$(1)_T_$
|
||||
CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
|
||||
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
|
||||
CTEST_DEPS_pfail_$(1)-T-$(2)-H-$(3) = $$(PFAIL_TESTS)
|
||||
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
|
||||
CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
|
||||
CTEST_DEPS_debuginfo-gdb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_GDB_TESTS)
|
||||
CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \
|
||||
$(S)src/etc/lldb_batchmode.py \
|
||||
$(S)src/etc/lldb_rust_formatters.py
|
||||
CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
|
||||
CTEST_DEPS_codegen-units_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_UNITS_TESTS)
|
||||
CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
|
||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||
$(S)src/etc/htmldocck.py
|
||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||
$(S)src/etc/htmldocck.py
|
||||
|
||||
endef
|
||||
|
||||
@ -761,7 +739,7 @@ endif
|
||||
endef
|
||||
|
||||
CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
|
||||
bench perf debuginfo-gdb debuginfo-lldb codegen rustdocck
|
||||
debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck
|
||||
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
$(eval $(foreach target,$(CFG_TARGET), \
|
||||
@ -770,20 +748,18 @@ $(foreach host,$(CFG_HOST), \
|
||||
$(eval $(call DEF_RUN_COMPILETEST,$(stage),$(target),$(host),$(name))))))))))
|
||||
|
||||
PRETTY_NAMES = pretty-rpass pretty-rpass-valgrind pretty-rpass-full pretty-rfail-full pretty-rfail \
|
||||
pretty-bench pretty-pretty
|
||||
pretty-pretty
|
||||
PRETTY_DEPS_pretty-rpass = $(RPASS_TESTS)
|
||||
PRETTY_DEPS_pretty-rpass-valgrind = $(RPASS_VALGRIND_TESTS)
|
||||
PRETTY_DEPS_pretty-rpass-full = $(RPASS_FULL_TESTS)
|
||||
PRETTY_DEPS_pretty-rfail-full = $(RFAIL_FULL_TESTS)
|
||||
PRETTY_DEPS_pretty-rfail = $(RFAIL_TESTS)
|
||||
PRETTY_DEPS_pretty-bench = $(BENCH_TESTS)
|
||||
PRETTY_DEPS_pretty-pretty = $(PRETTY_TESTS)
|
||||
PRETTY_DIRNAME_pretty-rpass = run-pass
|
||||
PRETTY_DIRNAME_pretty-rpass-valgrind = run-pass-valgrind
|
||||
PRETTY_DIRNAME_pretty-rpass-full = run-pass-fulldeps
|
||||
PRETTY_DIRNAME_pretty-rfail-full = run-fail-fulldeps
|
||||
PRETTY_DIRNAME_pretty-rfail = run-fail
|
||||
PRETTY_DIRNAME_pretty-bench = bench
|
||||
PRETTY_DIRNAME_pretty-pretty = pretty
|
||||
|
||||
define DEF_PRETTY_FULLDEPS
|
||||
@ -917,6 +893,28 @@ $(foreach host,$(CFG_HOST), \
|
||||
$(foreach crate,$(TEST_DOC_CRATES), \
|
||||
$(eval $(call DEF_CRATE_DOC_TEST,$(stage),$(target),$(host),$(crate)))))))
|
||||
|
||||
define DEF_DOC_TEST_ERROR_INDEX
|
||||
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-error-index-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index)
|
||||
|
||||
ifeq ($(2),$$(CFG_BUILD))
|
||||
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index): \
|
||||
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
|
||||
doc/error-index.md
|
||||
$$(Q)touch $$@.start_time
|
||||
$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test doc/error-index.md
|
||||
$$(Q)touch -r $$@.start_time $$@ && rm $$@.start_time
|
||||
else
|
||||
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index):
|
||||
$$(Q)touch $$@
|
||||
endif
|
||||
endef
|
||||
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
$(foreach target,$(CFG_TARGET), \
|
||||
$(foreach stage,$(STAGES), \
|
||||
$(eval $(call DEF_DOC_TEST_ERROR_INDEX,$(stage),$(target),$(host))))))
|
||||
|
||||
######################################################################
|
||||
# Shortcut rules
|
||||
######################################################################
|
||||
@ -926,29 +924,27 @@ TEST_GROUPS = \
|
||||
$(foreach crate,$(TEST_CRATES),$(crate)) \
|
||||
$(foreach crate,$(TEST_DOC_CRATES),doc-crate-$(crate)) \
|
||||
rpass \
|
||||
rpass-valgrind \
|
||||
rpass-valgrind \
|
||||
rpass-full \
|
||||
rfail-full \
|
||||
cfail-full \
|
||||
rfail \
|
||||
cfail \
|
||||
pfail \
|
||||
bench \
|
||||
perf \
|
||||
rmake \
|
||||
rustdocck \
|
||||
debuginfo-gdb \
|
||||
debuginfo-lldb \
|
||||
codegen \
|
||||
codegen-units \
|
||||
doc \
|
||||
$(foreach docname,$(DOC_NAMES),doc-$(docname)) \
|
||||
pretty \
|
||||
pretty-rpass \
|
||||
pretty-rpass-valgrind \
|
||||
pretty-rpass-valgrind \
|
||||
pretty-rpass-full \
|
||||
pretty-rfail-full \
|
||||
pretty-rfail \
|
||||
pretty-bench \
|
||||
pretty-pretty \
|
||||
$(NULL)
|
||||
|
||||
@ -1014,7 +1010,8 @@ define DEF_CHECK_DOC_FOR_STAGE
|
||||
check-stage$(1)-docs: $$(foreach docname,$$(DOC_NAMES), \
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-$$(docname)) \
|
||||
$$(foreach crate,$$(TEST_DOC_CRATES), \
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-crate-$$(crate))
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-crate-$$(crate)) \
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-error-index-exec
|
||||
endef
|
||||
|
||||
$(foreach stage,$(STAGES), \
|
||||
@ -1052,6 +1049,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(3)))
|
||||
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(3)))
|
||||
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
export MSVC_LIB := "$$(CFG_MSVC_LIB_$$(HOST_$(3)))"
|
||||
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
$(S)src/test/run-make/%/Makefile \
|
||||
$$(CSREQ$(1)_T_$(2)_H_$(3))
|
||||
@ -1073,7 +1072,9 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
$$(S) \
|
||||
$(3) \
|
||||
"$$(LLVM_LIBDIR_RUSTFLAGS_$(3))" \
|
||||
"$$(LLVM_ALL_COMPONENTS_$(3))"
|
||||
"$$(LLVM_ALL_COMPONENTS_$(3))" \
|
||||
"$$(LLVM_CXXFLAGS_$(3))" \
|
||||
'$$(CXX_$(3))'
|
||||
@touch -r $$@.start_time $$@ && rm $$@.start_time
|
||||
else
|
||||
# FIXME #11094 - The above rule doesn't work right for multiple targets
|
||||
|
||||
92
src/bootstrap/Cargo.lock
generated
Normal file
92
src/bootstrap/Cargo.lock
generated
Normal file
@ -0,0 +1,92 @@
|
||||
[root]
|
||||
name = "bootstrap"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_helper"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
29
src/bootstrap/Cargo.toml
Normal file
29
src/bootstrap/Cargo.toml
Normal file
@ -0,0 +1,29 @@
|
||||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "bootstrap"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "bootstrap"
|
||||
path = "lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "bootstrap"
|
||||
path = "main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "rustc"
|
||||
path = "rustc.rs"
|
||||
|
||||
[dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
cmake = "0.1.10"
|
||||
filetime = "0.1"
|
||||
num_cpus = "0.2"
|
||||
toml = "0.1"
|
||||
getopts = "0.2"
|
||||
rustc-serialize = "0.3"
|
||||
winapi = "0.2"
|
||||
kernel32-sys = "0.2"
|
||||
gcc = "0.3.17"
|
||||
libc = "0.2"
|
||||
110
src/bootstrap/README.md
Normal file
110
src/bootstrap/README.md
Normal file
@ -0,0 +1,110 @@
|
||||
# Bootstrapping Rust
|
||||
|
||||
This is an in-progress README which is targeted at helping to explain how Rust
|
||||
is bootstrapped and in general some of the technical details of the build
|
||||
system.
|
||||
|
||||
> **Note**: This build system is currently under active development and is not
|
||||
> intended to be the primarily used one just yet. The makefiles are currently
|
||||
> the ones that are still "guaranteed to work" as much as possible at least.
|
||||
|
||||
## Using the new build system
|
||||
|
||||
When configuring Rust via `./configure`, pass the following to enable building
|
||||
via this build system:
|
||||
|
||||
```
|
||||
./configure --enable-rustbuild
|
||||
```
|
||||
|
||||
## ...
|
||||
|
||||
## Directory Layout
|
||||
|
||||
This build system houses all output under the `target` directory, which looks
|
||||
like this:
|
||||
|
||||
```
|
||||
# Root folder of all output. Everything is scoped underneath here
|
||||
build/
|
||||
|
||||
# Location where the stage0 compiler downloads are all cached. This directory
|
||||
# only contains the tarballs themselves as they're extracted elsewhere.
|
||||
cache/
|
||||
2015-12-19/
|
||||
2016-01-15/
|
||||
2016-01-21/
|
||||
...
|
||||
|
||||
# Output directory for building this build system itself. The stage0
|
||||
# cargo/rustc are used to build the build system into this location.
|
||||
bootstrap/
|
||||
debug/
|
||||
release/
|
||||
|
||||
# Each remaining directory is scoped by the "host" triple of compilation at
|
||||
# hand.
|
||||
x86_64-unknown-linux-gnu/
|
||||
|
||||
# The build artifacts for the `compiler-rt` library for the target this
|
||||
# folder is under. The exact layout here will likely depend on the platform,
|
||||
# and this is also built with CMake so the build system is also likely
|
||||
# different.
|
||||
compiler-rt/build/
|
||||
|
||||
# Output folder for LLVM if it is compiled for this target
|
||||
llvm/
|
||||
|
||||
# build folder (e.g. the platform-specific build system). Like with
|
||||
# compiler-rt this is compiled with CMake
|
||||
build/
|
||||
|
||||
# Installation of LLVM. Note that we run the equivalent of 'make install'
|
||||
# for LLVM to setup these folders.
|
||||
bin/
|
||||
lib/
|
||||
include/
|
||||
share/
|
||||
...
|
||||
|
||||
# Location where the stage0 Cargo and Rust compiler are unpacked. This
|
||||
# directory is purely an extracted and overlaid tarball of these two (done
|
||||
# by the bootstrapy python script). In theory the build system does not
|
||||
# modify anything under this directory afterwards.
|
||||
stage0/
|
||||
|
||||
# These to build directories are the cargo output directories for builds of
|
||||
# the standard library and compiler, respectively. Internally these may also
|
||||
# have other target directories, which represent artifacts being compiled
|
||||
# from the host to the specified target.
|
||||
#
|
||||
# Essentially, each of these directories is filled in by one `cargo`
|
||||
# invocation. The build system instruments calling Cargo in the right order
|
||||
# with the right variables to ensure these are filled in correctly.
|
||||
stageN-std/
|
||||
stageN-rustc/
|
||||
|
||||
# This is a special case of the above directories, **not** filled in via
|
||||
# Cargo but rather the build system itself. The stage0 compiler already has
|
||||
# a set of target libraries for its own host triple (in its own sysroot)
|
||||
# inside of stage0/. When we run the stage0 compiler to bootstrap more
|
||||
# things, however, we don't want to use any of these libraries (as those are
|
||||
# the ones that we're building). So essentially, when the stage1 compiler is
|
||||
# being compiled (e.g. after libstd has been built), *this* is used as the
|
||||
# sysroot for the stage0 compiler being run.
|
||||
#
|
||||
# Basically this directory is just a temporary artifact use to configure the
|
||||
# stage0 compiler to ensure that the libstd we just built is used to
|
||||
# compile the stage1 compiler.
|
||||
stage0-rustc/lib/
|
||||
|
||||
# These output directories are intended to be standalone working
|
||||
# implementations of the compiler (corresponding to each stage). The build
|
||||
# system will link (using hard links) output from stageN-{std,rustc} into
|
||||
# each of these directories.
|
||||
#
|
||||
# In theory there is no extra build output in these directories.
|
||||
stage1/
|
||||
stage2/
|
||||
stage3/
|
||||
```
|
||||
317
src/bootstrap/bootstrap.py
Normal file
317
src/bootstrap/bootstrap.py
Normal file
@ -0,0 +1,317 @@
|
||||
# Copyright 2015-2016 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.
|
||||
|
||||
import argparse
|
||||
import contextlib
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
|
||||
def get(url, path, verbose=False):
|
||||
print("downloading " + url)
|
||||
# see http://serverfault.com/questions/301128/how-to-download
|
||||
if sys.platform == 'win32':
|
||||
run(["PowerShell.exe", "/nologo", "-Command",
|
||||
"(New-Object System.Net.WebClient).DownloadFile('" + url +
|
||||
"', '" + path + "')"], verbose=verbose)
|
||||
else:
|
||||
run(["curl", "-o", path, url], verbose=verbose)
|
||||
|
||||
def unpack(tarball, dst, verbose=False, match=None):
|
||||
print("extracting " + tarball)
|
||||
fname = os.path.basename(tarball).replace(".tar.gz", "")
|
||||
with contextlib.closing(tarfile.open(tarball)) as tar:
|
||||
for p in tar.getnames():
|
||||
if "/" not in p:
|
||||
continue
|
||||
name = p.replace(fname + "/", "", 1)
|
||||
if match is not None and not name.startswith(match):
|
||||
continue
|
||||
name = name[len(match) + 1:]
|
||||
|
||||
fp = os.path.join(dst, name)
|
||||
if verbose:
|
||||
print(" extracting " + p)
|
||||
tar.extract(p, dst)
|
||||
tp = os.path.join(dst, p)
|
||||
if os.path.isdir(tp) and os.path.exists(fp):
|
||||
continue
|
||||
shutil.move(tp, fp)
|
||||
shutil.rmtree(os.path.join(dst, fname))
|
||||
|
||||
def run(args, verbose=False):
|
||||
if verbose:
|
||||
print("running: " + ' '.join(args))
|
||||
sys.stdout.flush()
|
||||
# Use Popen here instead of call() as it apparently allows powershell on
|
||||
# Windows to not lock up waiting for input presumably.
|
||||
ret = subprocess.Popen(args)
|
||||
code = ret.wait()
|
||||
if code != 0:
|
||||
if not verbose:
|
||||
print("failed to run: " + ' '.join(args))
|
||||
raise RuntimeError("failed to run command")
|
||||
|
||||
class RustBuild:
|
||||
def download_rust_nightly(self):
|
||||
cache_dst = os.path.join(self.build_dir, "cache")
|
||||
rustc_cache = os.path.join(cache_dst, self.snap_rustc_date())
|
||||
cargo_cache = os.path.join(cache_dst, self.snap_cargo_date())
|
||||
if not os.path.exists(rustc_cache):
|
||||
os.makedirs(rustc_cache)
|
||||
if not os.path.exists(cargo_cache):
|
||||
os.makedirs(cargo_cache)
|
||||
|
||||
if self.rustc().startswith(self.bin_root()) and \
|
||||
(not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
|
||||
shutil.rmtree(self.bin_root())
|
||||
filename = "rust-std-nightly-" + self.build + ".tar.gz"
|
||||
url = "https://static.rust-lang.org/dist/" + self.snap_rustc_date()
|
||||
tarball = os.path.join(rustc_cache, filename)
|
||||
if not os.path.exists(tarball):
|
||||
get(url + "/" + filename, tarball, verbose=self.verbose)
|
||||
unpack(tarball, self.bin_root(),
|
||||
match="rust-std-" + self.build,
|
||||
verbose=self.verbose)
|
||||
|
||||
filename = "rustc-nightly-" + self.build + ".tar.gz"
|
||||
url = "https://static.rust-lang.org/dist/" + self.snap_rustc_date()
|
||||
tarball = os.path.join(rustc_cache, filename)
|
||||
if not os.path.exists(tarball):
|
||||
get(url + "/" + filename, tarball, verbose=self.verbose)
|
||||
unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose)
|
||||
with open(self.rustc_stamp(), 'w') as f:
|
||||
f.write(self.snap_rustc_date())
|
||||
|
||||
if self.cargo().startswith(self.bin_root()) and \
|
||||
(not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
|
||||
filename = "cargo-nightly-" + self.build + ".tar.gz"
|
||||
url = "https://static.rust-lang.org/cargo-dist/" + self.snap_cargo_date()
|
||||
tarball = os.path.join(cargo_cache, filename)
|
||||
if not os.path.exists(tarball):
|
||||
get(url + "/" + filename, tarball, verbose=self.verbose)
|
||||
unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose)
|
||||
with open(self.cargo_stamp(), 'w') as f:
|
||||
f.write(self.snap_cargo_date())
|
||||
|
||||
def snap_cargo_date(self):
|
||||
return self._cargo_date
|
||||
|
||||
def snap_rustc_date(self):
|
||||
return self._rustc_date
|
||||
|
||||
def rustc_stamp(self):
|
||||
return os.path.join(self.bin_root(), '.rustc-stamp')
|
||||
|
||||
def cargo_stamp(self):
|
||||
return os.path.join(self.bin_root(), '.cargo-stamp')
|
||||
|
||||
def rustc_out_of_date(self):
|
||||
if not os.path.exists(self.rustc_stamp()):
|
||||
return True
|
||||
with open(self.rustc_stamp(), 'r') as f:
|
||||
return self.snap_rustc_date() != f.read()
|
||||
|
||||
def cargo_out_of_date(self):
|
||||
if not os.path.exists(self.cargo_stamp()):
|
||||
return True
|
||||
with open(self.cargo_stamp(), 'r') as f:
|
||||
return self.snap_cargo_date() != f.read()
|
||||
|
||||
def bin_root(self):
|
||||
return os.path.join(self.build_dir, self.build, "stage0")
|
||||
|
||||
def get_toml(self, key):
|
||||
for line in self.config_toml.splitlines():
|
||||
if line.startswith(key + ' ='):
|
||||
return self.get_string(line)
|
||||
return None
|
||||
|
||||
def get_mk(self, key):
|
||||
for line in iter(self.config_mk.splitlines()):
|
||||
if line.startswith(key):
|
||||
return line[line.find(':=') + 2:].strip()
|
||||
return None
|
||||
|
||||
def cargo(self):
|
||||
config = self.get_toml('cargo')
|
||||
if config:
|
||||
return config
|
||||
return os.path.join(self.bin_root(), "bin/cargo" + self.exe_suffix())
|
||||
|
||||
def rustc(self):
|
||||
config = self.get_toml('rustc')
|
||||
if config:
|
||||
return config
|
||||
config = self.get_mk('CFG_LOCAL_RUST')
|
||||
if config:
|
||||
return config + '/bin/rustc' + self.exe_suffix()
|
||||
return os.path.join(self.bin_root(), "bin/rustc" + self.exe_suffix())
|
||||
|
||||
def get_string(self, line):
|
||||
start = line.find('"')
|
||||
end = start + 1 + line[start+1:].find('"')
|
||||
return line[start+1:end]
|
||||
|
||||
def exe_suffix(self):
|
||||
if sys.platform == 'win32':
|
||||
return '.exe'
|
||||
else:
|
||||
return ''
|
||||
|
||||
def parse_nightly_dates(self):
|
||||
nightlies = os.path.join(self.rust_root, "src/nightlies.txt")
|
||||
with open(nightlies, 'r') as nightlies:
|
||||
rustc, cargo = nightlies.read().split("\n")[:2]
|
||||
assert rustc.startswith("rustc: ")
|
||||
assert cargo.startswith("cargo: ")
|
||||
self._rustc_date = rustc[len("rustc: "):]
|
||||
self._cargo_date = cargo[len("cargo: "):]
|
||||
|
||||
def build_bootstrap(self):
|
||||
env = os.environ.copy()
|
||||
env["CARGO_TARGET_DIR"] = os.path.join(self.build_dir, "bootstrap")
|
||||
env["RUSTC"] = self.rustc()
|
||||
env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib")
|
||||
env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib")
|
||||
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
|
||||
os.pathsep + env["PATH"]
|
||||
self.run([self.cargo(), "build", "--manifest-path",
|
||||
os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")],
|
||||
env)
|
||||
|
||||
def run(self, args, env):
|
||||
proc = subprocess.Popen(args, env = env)
|
||||
ret = proc.wait()
|
||||
if ret != 0:
|
||||
sys.exit(ret)
|
||||
|
||||
def build_triple(self):
|
||||
config = self.get_toml('build')
|
||||
if config:
|
||||
return config
|
||||
config = self.get_mk('CFG_BUILD')
|
||||
if config:
|
||||
return config
|
||||
try:
|
||||
ostype = subprocess.check_output(['uname', '-s']).strip()
|
||||
cputype = subprocess.check_output(['uname', '-m']).strip()
|
||||
except FileNotFoundError:
|
||||
if sys.platform == 'win32':
|
||||
return 'x86_64-pc-windows-msvc'
|
||||
else:
|
||||
raise
|
||||
|
||||
# Darwin's `uname -s` lies and always returns i386. We have to use
|
||||
# sysctl instead.
|
||||
if ostype == 'Darwin' and cputype == 'i686':
|
||||
sysctl = subprocess.check_output(['sysctl', 'hw.optional.x86_64'])
|
||||
if sysctl.contains(': 1'):
|
||||
cputype = 'x86_64'
|
||||
|
||||
# The goal here is to come up with the same triple as LLVM would,
|
||||
# at least for the subset of platforms we're willing to target.
|
||||
if ostype == 'Linux':
|
||||
ostype = 'unknown-linux-gnu'
|
||||
elif ostype == 'FreeBSD':
|
||||
ostype = 'unknown-freebsd'
|
||||
elif ostype == 'DragonFly':
|
||||
ostype = 'unknown-dragonfly'
|
||||
elif ostype == 'Bitrig':
|
||||
ostype = 'unknown-bitrig'
|
||||
elif ostype == 'OpenBSD':
|
||||
ostype = 'unknown-openbsd'
|
||||
elif ostype == 'NetBSD':
|
||||
ostype = 'unknown-netbsd'
|
||||
elif ostype == 'Darwin':
|
||||
ostype = 'apple-darwin'
|
||||
elif ostype.startswith('MINGW'):
|
||||
# msys' `uname` does not print gcc configuration, but prints msys
|
||||
# configuration. so we cannot believe `uname -m`:
|
||||
# msys1 is always i686 and msys2 is always x86_64.
|
||||
# instead, msys defines $MSYSTEM which is MINGW32 on i686 and
|
||||
# MINGW64 on x86_64.
|
||||
ostype = 'pc-windows-gnu'
|
||||
cputype = 'i686'
|
||||
if os.environ.get('MSYSTEM') == 'MINGW64':
|
||||
cputype = 'x86_64'
|
||||
elif ostype.startswith('MSYS'):
|
||||
ostype = 'pc-windows-gnu'
|
||||
elif ostype.startswith('CYGWIN_NT'):
|
||||
cputype = 'i686'
|
||||
if ostype.endswith('WOW64'):
|
||||
cputype = 'x86_64'
|
||||
ostype = 'pc-windows-gnu'
|
||||
else:
|
||||
raise ValueError("unknown OS type: " + ostype)
|
||||
|
||||
if cputype in {'i386', 'i486', 'i686', 'i786', 'x86'}:
|
||||
cputype = 'i686'
|
||||
elif cputype in {'xscale', 'arm'}:
|
||||
cputype = 'arm'
|
||||
elif cputype == 'armv7l':
|
||||
cputype = 'arm'
|
||||
ostype += 'eabihf'
|
||||
elif cputype == 'aarch64':
|
||||
cputype = 'aarch64'
|
||||
elif cputype in {'powerpc', 'ppc', 'ppc64'}:
|
||||
cputype = 'powerpc'
|
||||
elif cputype in {'amd64', 'x86_64', 'x86-64', 'x64'}:
|
||||
cputype = 'x86_64'
|
||||
else:
|
||||
raise ValueError("unknown cpu type: " + cputype)
|
||||
|
||||
return cputype + '-' + ostype
|
||||
|
||||
parser = argparse.ArgumentParser(description='Build rust')
|
||||
parser.add_argument('--config')
|
||||
parser.add_argument('-v', '--verbose', action='store_true')
|
||||
|
||||
args = [a for a in sys.argv if a != '-h']
|
||||
args, _ = parser.parse_known_args(args)
|
||||
|
||||
# Configure initial bootstrap
|
||||
rb = RustBuild()
|
||||
rb.config_toml = ''
|
||||
rb.config_mk = ''
|
||||
rb.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
|
||||
rb.build_dir = os.path.join(os.getcwd(), "build")
|
||||
rb.verbose = args.verbose
|
||||
|
||||
try:
|
||||
with open(args.config or 'config.toml') as config:
|
||||
rb.config_toml = config.read()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
rb.config_mk = open('config.mk').read()
|
||||
except:
|
||||
pass
|
||||
|
||||
# Fetch/build the bootstrap
|
||||
rb.build = rb.build_triple()
|
||||
rb.parse_nightly_dates()
|
||||
rb.download_rust_nightly()
|
||||
sys.stdout.flush()
|
||||
rb.build_bootstrap()
|
||||
sys.stdout.flush()
|
||||
|
||||
# Run the bootstrap
|
||||
args = [os.path.join(rb.build_dir, "bootstrap/debug/bootstrap")]
|
||||
args.extend(sys.argv[1:])
|
||||
args.append('--src')
|
||||
args.append(rb.rust_root)
|
||||
args.append('--build')
|
||||
args.append(rb.build)
|
||||
env = os.environ.copy()
|
||||
env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
|
||||
rb.run(args, env)
|
||||
98
src/bootstrap/build/cc.rs
Normal file
98
src/bootstrap/build/cc.rs
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::{cc2ar, output};
|
||||
use gcc;
|
||||
|
||||
use build::Build;
|
||||
use build::config::Target;
|
||||
|
||||
pub fn find(build: &mut Build) {
|
||||
// For all targets we're going to need a C compiler for building some shims
|
||||
// and such as well as for being a linker for Rust code.
|
||||
for target in build.config.target.iter() {
|
||||
let mut cfg = gcc::Config::new();
|
||||
cfg.cargo_metadata(false).opt_level(0).debug(false)
|
||||
.target(target).host(&build.config.build);
|
||||
|
||||
let config = build.config.target_config.get(target);
|
||||
if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
|
||||
cfg.compiler(cc);
|
||||
} else {
|
||||
set_compiler(&mut cfg, "gcc", target, config);
|
||||
}
|
||||
|
||||
let compiler = cfg.get_compiler();
|
||||
let ar = cc2ar(compiler.path(), target);
|
||||
build.verbose(&format!("CC_{} = {:?}", target, compiler.path()));
|
||||
build.verbose(&format!("AR_{} = {:?}", target, ar));
|
||||
build.cc.insert(target.to_string(), (compiler, ar));
|
||||
}
|
||||
|
||||
// For all host triples we need to find a C++ compiler as well
|
||||
for host in build.config.host.iter() {
|
||||
let mut cfg = gcc::Config::new();
|
||||
cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true)
|
||||
.target(host).host(&build.config.build);
|
||||
let config = build.config.target_config.get(host);
|
||||
if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
|
||||
cfg.compiler(cxx);
|
||||
} else {
|
||||
set_compiler(&mut cfg, "g++", host, config);
|
||||
}
|
||||
let compiler = cfg.get_compiler();
|
||||
build.verbose(&format!("CXX_{} = {:?}", host, compiler.path()));
|
||||
build.cxx.insert(host.to_string(), compiler);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_compiler(cfg: &mut gcc::Config,
|
||||
gnu_compiler: &str,
|
||||
target: &str,
|
||||
config: Option<&Target>) {
|
||||
match target {
|
||||
// When compiling for android we may have the NDK configured in the
|
||||
// config.toml in which case we look there. Otherwise the default
|
||||
// compiler already takes into account the triple in question.
|
||||
t if t.contains("android") => {
|
||||
if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
|
||||
let compiler = format!("{}-{}", target, gnu_compiler);
|
||||
cfg.compiler(ndk.join("bin").join(compiler));
|
||||
}
|
||||
}
|
||||
|
||||
// The default gcc version from OpenBSD may be too old, try using egcc,
|
||||
// which is a gcc version from ports, if this is the case.
|
||||
t if t.contains("openbsd") => {
|
||||
let c = cfg.get_compiler();
|
||||
if !c.path().ends_with(gnu_compiler) {
|
||||
return
|
||||
}
|
||||
|
||||
let output = output(c.to_command().arg("--version"));
|
||||
let i = match output.find(" 4.") {
|
||||
Some(i) => i,
|
||||
None => return,
|
||||
};
|
||||
match output[i + 3..].chars().next().unwrap() {
|
||||
'0' ... '6' => {}
|
||||
_ => return,
|
||||
}
|
||||
let alternative = format!("e{}", gnu_compiler);
|
||||
if Command::new(&alternative).output().is_ok() {
|
||||
cfg.compiler(alternative);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
82
src/bootstrap/build/channel.rs
Normal file
82
src/bootstrap/build/channel.rs
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::output;
|
||||
|
||||
use build::Build;
|
||||
use build::util::mtime;
|
||||
|
||||
pub fn collect(build: &mut Build) {
|
||||
let mut main_mk = String::new();
|
||||
t!(t!(File::open(build.src.join("mk/main.mk"))).read_to_string(&mut main_mk));
|
||||
let mut release_num = "";
|
||||
let mut prerelease_version = "";
|
||||
for line in main_mk.lines() {
|
||||
if line.starts_with("CFG_RELEASE_NUM") {
|
||||
release_num = line.split('=').skip(1).next().unwrap().trim();
|
||||
}
|
||||
if line.starts_with("CFG_PRERELEASE_VERSION") {
|
||||
prerelease_version = line.split('=').skip(1).next().unwrap().trim();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: this is duplicating makefile logic
|
||||
match &build.config.channel[..] {
|
||||
"stable" => {
|
||||
build.release = release_num.to_string();
|
||||
build.unstable_features = false;
|
||||
}
|
||||
"beta" => {
|
||||
build.release = format!("{}-beta{}", release_num,
|
||||
prerelease_version);
|
||||
build.unstable_features = false;
|
||||
}
|
||||
"nightly" => {
|
||||
build.release = format!("{}-nightly", release_num);
|
||||
build.unstable_features = true;
|
||||
}
|
||||
_ => {
|
||||
build.release = format!("{}-dev", release_num);
|
||||
build.unstable_features = true;
|
||||
}
|
||||
}
|
||||
build.version = build.release.clone();
|
||||
|
||||
if fs::metadata(build.src.join(".git")).is_ok() {
|
||||
let ver_date = output(Command::new("git").current_dir(&build.src)
|
||||
.arg("log").arg("-1")
|
||||
.arg("--date=short")
|
||||
.arg("--pretty=format:%cd"));
|
||||
let ver_hash = output(Command::new("git").current_dir(&build.src)
|
||||
.arg("rev-parse").arg("HEAD"));
|
||||
let short_ver_hash = output(Command::new("git")
|
||||
.current_dir(&build.src)
|
||||
.arg("rev-parse")
|
||||
.arg("--short=9")
|
||||
.arg("HEAD"));
|
||||
let ver_date = ver_date.trim().to_string();
|
||||
let ver_hash = ver_hash.trim().to_string();
|
||||
let short_ver_hash = short_ver_hash.trim().to_string();
|
||||
build.version.push_str(&format!(" ({} {})", short_ver_hash,
|
||||
ver_date));
|
||||
build.ver_date = Some(ver_date.to_string());
|
||||
build.ver_hash = Some(ver_hash);
|
||||
build.short_ver_hash = Some(short_ver_hash);
|
||||
}
|
||||
|
||||
build.bootstrap_key = mtime(Path::new("config.toml")).seconds()
|
||||
.to_string();
|
||||
}
|
||||
|
||||
36
src/bootstrap/build/clean.rs
Normal file
36
src/bootstrap/build/clean.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use build::Build;
|
||||
|
||||
pub fn clean(build: &Build) {
|
||||
for host in build.config.host.iter() {
|
||||
|
||||
let out = build.out.join(host);
|
||||
|
||||
rm_rf(build, &out.join("compiler-rt"));
|
||||
|
||||
for stage in 0..4 {
|
||||
rm_rf(build, &out.join(format!("stage{}", stage)));
|
||||
rm_rf(build, &out.join(format!("stage{}-std", stage)));
|
||||
rm_rf(build, &out.join(format!("stage{}-rustc", stage)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rm_rf(build: &Build, path: &Path) {
|
||||
if path.exists() {
|
||||
build.verbose(&format!("removing `{}`", path.display()));
|
||||
t!(fs::remove_dir_all(path));
|
||||
}
|
||||
}
|
||||
287
src/bootstrap/build/compile.rs
Normal file
287
src/bootstrap/build/compile.rs
Normal file
@ -0,0 +1,287 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::output;
|
||||
|
||||
use build::util::{exe, staticlib, libdir, mtime, is_dylib};
|
||||
use build::{Build, Compiler};
|
||||
|
||||
/// Build the standard library.
|
||||
///
|
||||
/// This will build the standard library for a particular stage of the build
|
||||
/// using the `compiler` targeting the `target` architecture. The artifacts
|
||||
/// created will also be linked into the sysroot directory.
|
||||
pub fn std<'a>(build: &'a Build, stage: u32, target: &str,
|
||||
compiler: &Compiler<'a>) {
|
||||
let host = compiler.host;
|
||||
println!("Building stage{} std artifacts ({} -> {})", stage,
|
||||
host, target);
|
||||
|
||||
// Move compiler-rt into place as it'll be required by the compiler when
|
||||
// building the standard library to link the dylib of libstd
|
||||
let libdir = build.sysroot_libdir(stage, &host, target);
|
||||
let _ = fs::remove_dir_all(&libdir);
|
||||
t!(fs::create_dir_all(&libdir));
|
||||
t!(fs::hard_link(&build.compiler_rt_built.borrow()[target],
|
||||
libdir.join(staticlib("compiler-rt", target))));
|
||||
|
||||
build_startup_objects(build, target, &libdir);
|
||||
|
||||
let out_dir = build.cargo_out(stage, &host, true, target);
|
||||
build.clear_if_dirty(&out_dir, &build.compiler_path(compiler));
|
||||
let mut cargo = build.cargo(stage, compiler, true, target, "build");
|
||||
cargo.arg("--features").arg(build.std_features())
|
||||
.arg("--manifest-path")
|
||||
.arg(build.src.join("src/rustc/std_shim/Cargo.toml"));
|
||||
|
||||
if let Some(target) = build.config.target_config.get(target) {
|
||||
if let Some(ref jemalloc) = target.jemalloc {
|
||||
cargo.env("JEMALLOC_OVERRIDE", jemalloc);
|
||||
}
|
||||
}
|
||||
if let Some(ref p) = build.config.musl_root {
|
||||
if target.contains("musl") {
|
||||
cargo.env("MUSL_ROOT", p);
|
||||
}
|
||||
}
|
||||
|
||||
build.run(&mut cargo);
|
||||
std_link(build, stage, target, compiler, host);
|
||||
}
|
||||
|
||||
/// Link all libstd rlibs/dylibs into the sysroot location.
|
||||
///
|
||||
/// Links those artifacts generated in the given `stage` for `target` produced
|
||||
/// by `compiler` into `host`'s sysroot.
|
||||
pub fn std_link(build: &Build,
|
||||
stage: u32,
|
||||
target: &str,
|
||||
compiler: &Compiler,
|
||||
host: &str) {
|
||||
let libdir = build.sysroot_libdir(stage, host, target);
|
||||
let out_dir = build.cargo_out(stage, compiler.host, true, target);
|
||||
|
||||
// If we're linking one compiler host's output into another, then we weren't
|
||||
// called from the `std` method above. In that case we clean out what's
|
||||
// already there and then also link compiler-rt into place.
|
||||
if host != compiler.host {
|
||||
let _ = fs::remove_dir_all(&libdir);
|
||||
t!(fs::create_dir_all(&libdir));
|
||||
t!(fs::hard_link(&build.compiler_rt_built.borrow()[target],
|
||||
libdir.join(staticlib("compiler-rt", target))));
|
||||
}
|
||||
add_to_sysroot(&out_dir, &libdir);
|
||||
}
|
||||
|
||||
/// Build and prepare startup objects like rsbegin.o and rsend.o
|
||||
///
|
||||
/// These are primarily used on Windows right now for linking executables/dlls.
|
||||
/// They don't require any library support as they're just plain old object
|
||||
/// files, so we just use the nightly snapshot compiler to always build them (as
|
||||
/// no other compilers are guaranteed to be available).
|
||||
fn build_startup_objects(build: &Build, target: &str, into: &Path) {
|
||||
if !target.contains("pc-windows-gnu") {
|
||||
return
|
||||
}
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = build.compiler_path(&compiler);
|
||||
|
||||
for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
|
||||
let file = t!(file);
|
||||
build.run(Command::new(&compiler)
|
||||
.arg("--emit=obj")
|
||||
.arg("--out-dir").arg(into)
|
||||
.arg(file.path()));
|
||||
}
|
||||
|
||||
for obj in ["crt2.o", "dllcrt2.o"].iter() {
|
||||
t!(fs::copy(compiler_file(build.cc(target), obj), into.join(obj)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the compiler.
|
||||
///
|
||||
/// This will build the compiler for a particular stage of the build using
|
||||
/// the `compiler` targeting the `target` architecture. The artifacts
|
||||
/// created will also be linked into the sysroot directory.
|
||||
pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str,
|
||||
compiler: &Compiler<'a>) {
|
||||
let host = compiler.host;
|
||||
println!("Building stage{} compiler artifacts ({} -> {})", stage,
|
||||
host, target);
|
||||
|
||||
let out_dir = build.cargo_out(stage, &host, false, target);
|
||||
build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target));
|
||||
|
||||
let mut cargo = build.cargo(stage, compiler, false, target, "build");
|
||||
cargo.arg("--features").arg(build.rustc_features(stage))
|
||||
.arg("--manifest-path")
|
||||
.arg(build.src.join("src/rustc/Cargo.toml"));
|
||||
|
||||
// In stage0 we may not need to build as many executables
|
||||
if stage == 0 {
|
||||
cargo.arg("--bin").arg("rustc");
|
||||
}
|
||||
|
||||
// Set some configuration variables picked up by build scripts and
|
||||
// the compiler alike
|
||||
cargo.env("CFG_RELEASE", &build.release)
|
||||
.env("CFG_RELEASE_CHANNEL", &build.config.channel)
|
||||
.env("CFG_VERSION", &build.version)
|
||||
.env("CFG_BOOTSTRAP_KEY", &build.bootstrap_key)
|
||||
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new()))
|
||||
.env("RUSTC_BOOTSTRAP_KEY", &build.bootstrap_key)
|
||||
.env("CFG_LIBDIR_RELATIVE", "lib");
|
||||
|
||||
if let Some(ref ver_date) = build.ver_date {
|
||||
cargo.env("CFG_VER_DATE", ver_date);
|
||||
}
|
||||
if let Some(ref ver_hash) = build.ver_hash {
|
||||
cargo.env("CFG_VER_HASH", ver_hash);
|
||||
}
|
||||
if !build.unstable_features {
|
||||
cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
|
||||
}
|
||||
let target_config = build.config.target_config.get(target);
|
||||
if let Some(ref s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
|
||||
cargo.env("LLVM_CONFIG", s);
|
||||
} else {
|
||||
let llvm_config = build.llvm_out(&build.config.build).join("bin")
|
||||
.join(exe("llvm-config", target));
|
||||
cargo.env("LLVM_CONFIG", llvm_config);
|
||||
}
|
||||
if build.config.llvm_static_stdcpp {
|
||||
cargo.env("LLVM_STATIC_STDCPP",
|
||||
compiler_file(build.cxx(target), "libstdc++.a"));
|
||||
}
|
||||
if let Some(ref s) = build.config.rustc_default_linker {
|
||||
cargo.env("CFG_DEFAULT_LINKER", s);
|
||||
}
|
||||
if let Some(ref s) = build.config.rustc_default_ar {
|
||||
cargo.env("CFG_DEFAULT_AR", s);
|
||||
}
|
||||
build.run(&mut cargo);
|
||||
|
||||
rustc_link(build, stage, target, compiler, compiler.host);
|
||||
}
|
||||
|
||||
/// Link all librustc rlibs/dylibs into the sysroot location.
|
||||
///
|
||||
/// Links those artifacts generated in the given `stage` for `target` produced
|
||||
/// by `compiler` into `host`'s sysroot.
|
||||
pub fn rustc_link(build: &Build,
|
||||
stage: u32,
|
||||
target: &str,
|
||||
compiler: &Compiler,
|
||||
host: &str) {
|
||||
let libdir = build.sysroot_libdir(stage, host, target);
|
||||
let out_dir = build.cargo_out(stage, compiler.host, false, target);
|
||||
add_to_sysroot(&out_dir, &libdir);
|
||||
}
|
||||
|
||||
/// Cargo's output path for the standard library in a given stage, compiled
|
||||
/// by a particular compiler for the specified target.
|
||||
fn libstd_shim(build: &Build, stage: u32, host: &str, target: &str) -> PathBuf {
|
||||
build.cargo_out(stage, host, true, target).join("libstd_shim.rlib")
|
||||
}
|
||||
|
||||
fn compiler_file(compiler: &Path, file: &str) -> String {
|
||||
output(Command::new(compiler)
|
||||
.arg(format!("-print-file-name={}", file))).trim().to_string()
|
||||
}
|
||||
|
||||
/// Prepare a new compiler from the artifacts in `stage`
|
||||
///
|
||||
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
|
||||
/// must have been previously produced by the `stage - 1` build.config.build
|
||||
/// compiler.
|
||||
pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
|
||||
assert!(stage > 0, "the stage0 compiler isn't assembled, it's downloaded");
|
||||
|
||||
// Clear out old files
|
||||
let sysroot = build.sysroot(stage, host);
|
||||
let _ = fs::remove_dir_all(&sysroot);
|
||||
t!(fs::create_dir_all(&sysroot));
|
||||
|
||||
// Link in all dylibs to the libdir
|
||||
let sysroot_libdir = sysroot.join(libdir(host));
|
||||
t!(fs::create_dir_all(&sysroot_libdir));
|
||||
let src_libdir = build.sysroot_libdir(stage - 1, &build.config.build, host);
|
||||
for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) {
|
||||
let filename = f.file_name().into_string().unwrap();
|
||||
if is_dylib(&filename) {
|
||||
t!(fs::hard_link(&f.path(), sysroot_libdir.join(&filename)));
|
||||
}
|
||||
}
|
||||
|
||||
let out_dir = build.cargo_out(stage - 1, &build.config.build, false, host);
|
||||
|
||||
// Link the compiler binary itself into place
|
||||
let rustc = out_dir.join(exe("rustc", host));
|
||||
let bindir = sysroot.join("bin");
|
||||
t!(fs::create_dir_all(&bindir));
|
||||
let compiler = build.compiler_path(&Compiler::new(stage, host));
|
||||
let _ = fs::remove_file(&compiler);
|
||||
t!(fs::hard_link(rustc, compiler));
|
||||
|
||||
// See if rustdoc exists to link it into place
|
||||
let rustdoc = exe("rustdoc", host);
|
||||
let rustdoc_src = out_dir.join(&rustdoc);
|
||||
let rustdoc_dst = bindir.join(&rustdoc);
|
||||
if fs::metadata(&rustdoc_src).is_ok() {
|
||||
let _ = fs::remove_file(&rustdoc_dst);
|
||||
t!(fs::hard_link(&rustdoc_src, &rustdoc_dst));
|
||||
}
|
||||
}
|
||||
|
||||
/// Link some files into a rustc sysroot.
|
||||
///
|
||||
/// For a particular stage this will link all of the contents of `out_dir`
|
||||
/// into the sysroot of the `host` compiler, assuming the artifacts are
|
||||
/// compiled for the specified `target`.
|
||||
fn add_to_sysroot(out_dir: &Path, sysroot_dst: &Path) {
|
||||
// Collect the set of all files in the dependencies directory, keyed
|
||||
// off the name of the library. We assume everything is of the form
|
||||
// `foo-<hash>.{rlib,so,...}`, and there could be multiple different
|
||||
// `<hash>` values for the same name (of old builds).
|
||||
let mut map = HashMap::new();
|
||||
for file in t!(fs::read_dir(out_dir.join("deps"))).map(|f| t!(f)) {
|
||||
let filename = file.file_name().into_string().unwrap();
|
||||
|
||||
// We're only interested in linking rlibs + dylibs, other things like
|
||||
// unit tests don't get linked in
|
||||
if !filename.ends_with(".rlib") &&
|
||||
!filename.ends_with(".lib") &&
|
||||
!is_dylib(&filename) {
|
||||
continue
|
||||
}
|
||||
let file = file.path();
|
||||
let dash = filename.find("-").unwrap();
|
||||
let key = (filename[..dash].to_string(),
|
||||
file.extension().unwrap().to_owned());
|
||||
map.entry(key).or_insert(Vec::new())
|
||||
.push(file.clone());
|
||||
}
|
||||
|
||||
// For all hash values found, pick the most recent one to move into the
|
||||
// sysroot, that should be the one we just built.
|
||||
for (_, paths) in map {
|
||||
let (_, path) = paths.iter().map(|path| {
|
||||
(mtime(&path).seconds(), path)
|
||||
}).max().unwrap();
|
||||
t!(fs::hard_link(&path,
|
||||
sysroot_dst.join(path.file_name().unwrap())));
|
||||
}
|
||||
}
|
||||
361
src/bootstrap/build/config.rs
Normal file
361
src/bootstrap/build/config.rs
Normal file
@ -0,0 +1,361 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
|
||||
use num_cpus;
|
||||
use rustc_serialize::Decodable;
|
||||
use toml::{Parser, Decoder, Value};
|
||||
|
||||
/// Global configuration for the entire build and/or bootstrap.
|
||||
///
|
||||
/// This structure is derived from a combination of both `config.toml` and
|
||||
/// `config.mk`. As of the time of this writing it's unlikely that `config.toml`
|
||||
/// is used all that much, so this is primarily filled out by `config.mk` which
|
||||
/// is generated from `./configure`.
|
||||
///
|
||||
/// Note that this structure is not decoded directly into, but rather it is
|
||||
/// filled out from the decoded forms of the structs below.
|
||||
#[derive(Default)]
|
||||
pub struct Config {
|
||||
pub ccache: bool,
|
||||
pub verbose: bool,
|
||||
pub submodules: bool,
|
||||
pub compiler_docs: bool,
|
||||
pub docs: bool,
|
||||
pub target_config: HashMap<String, Target>,
|
||||
|
||||
// llvm codegen options
|
||||
pub llvm_assertions: bool,
|
||||
pub llvm_optimize: bool,
|
||||
pub llvm_version_check: bool,
|
||||
pub llvm_static_stdcpp: bool,
|
||||
|
||||
// rust codegen options
|
||||
pub rust_optimize: bool,
|
||||
pub rust_codegen_units: u32,
|
||||
pub rust_debug_assertions: bool,
|
||||
pub rust_debuginfo: bool,
|
||||
pub rust_rpath: bool,
|
||||
pub rustc_default_linker: Option<String>,
|
||||
pub rustc_default_ar: Option<String>,
|
||||
|
||||
pub build: String,
|
||||
pub host: Vec<String>,
|
||||
pub target: Vec<String>,
|
||||
pub rustc: Option<String>,
|
||||
pub cargo: Option<String>,
|
||||
|
||||
// libstd features
|
||||
pub debug_jemalloc: bool,
|
||||
pub use_jemalloc: bool,
|
||||
|
||||
// misc
|
||||
pub channel: String,
|
||||
pub musl_root: Option<PathBuf>,
|
||||
pub prefix: Option<String>,
|
||||
}
|
||||
|
||||
/// Per-target configuration stored in the global configuration structure.
|
||||
#[derive(Default)]
|
||||
pub struct Target {
|
||||
pub llvm_config: Option<PathBuf>,
|
||||
pub jemalloc: Option<PathBuf>,
|
||||
pub cc: Option<PathBuf>,
|
||||
pub cxx: Option<PathBuf>,
|
||||
pub ndk: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Structure of the `config.toml` file that configuration is read from.
|
||||
///
|
||||
/// This structure uses `Decodable` to automatically decode a TOML configuration
|
||||
/// file into this format, and then this is traversed and written into the above
|
||||
/// `Config` structure.
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct TomlConfig {
|
||||
build: Option<Build>,
|
||||
llvm: Option<Llvm>,
|
||||
rust: Option<Rust>,
|
||||
target: Option<HashMap<String, TomlTarget>>,
|
||||
}
|
||||
|
||||
/// TOML representation of various global build decisions.
|
||||
#[derive(RustcDecodable, Default, Clone)]
|
||||
struct Build {
|
||||
build: Option<String>,
|
||||
host: Vec<String>,
|
||||
target: Vec<String>,
|
||||
cargo: Option<String>,
|
||||
rustc: Option<String>,
|
||||
compiler_docs: Option<bool>,
|
||||
docs: Option<bool>,
|
||||
}
|
||||
|
||||
/// TOML representation of how the LLVM build is configured.
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct Llvm {
|
||||
ccache: Option<bool>,
|
||||
assertions: Option<bool>,
|
||||
optimize: Option<bool>,
|
||||
version_check: Option<bool>,
|
||||
static_libstdcpp: Option<bool>,
|
||||
}
|
||||
|
||||
/// TOML representation of how the Rust build is configured.
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct Rust {
|
||||
optimize: Option<bool>,
|
||||
codegen_units: Option<u32>,
|
||||
debug_assertions: Option<bool>,
|
||||
debuginfo: Option<bool>,
|
||||
debug_jemalloc: Option<bool>,
|
||||
use_jemalloc: Option<bool>,
|
||||
default_linker: Option<String>,
|
||||
default_ar: Option<String>,
|
||||
channel: Option<String>,
|
||||
musl_root: Option<String>,
|
||||
rpath: Option<bool>,
|
||||
}
|
||||
|
||||
/// TOML representation of how each build target is configured.
|
||||
#[derive(RustcDecodable, Default)]
|
||||
struct TomlTarget {
|
||||
llvm_config: Option<String>,
|
||||
jemalloc: Option<String>,
|
||||
cc: Option<String>,
|
||||
cxx: Option<String>,
|
||||
android_ndk: Option<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
|
||||
let mut config = Config::default();
|
||||
config.llvm_optimize = true;
|
||||
config.use_jemalloc = true;
|
||||
config.rust_optimize = true;
|
||||
config.submodules = true;
|
||||
config.docs = true;
|
||||
config.rust_rpath = true;
|
||||
config.rust_codegen_units = 1;
|
||||
config.build = build.to_string();
|
||||
config.channel = "dev".to_string();
|
||||
|
||||
let toml = file.map(|file| {
|
||||
let mut f = t!(File::open(&file));
|
||||
let mut toml = String::new();
|
||||
t!(f.read_to_string(&mut toml));
|
||||
let mut p = Parser::new(&toml);
|
||||
let table = match p.parse() {
|
||||
Some(table) => table,
|
||||
None => {
|
||||
println!("failed to parse TOML configuration:");
|
||||
for err in p.errors.iter() {
|
||||
let (loline, locol) = p.to_linecol(err.lo);
|
||||
let (hiline, hicol) = p.to_linecol(err.hi);
|
||||
println!("{}:{}-{}:{}: {}", loline, locol, hiline,
|
||||
hicol, err.desc);
|
||||
}
|
||||
process::exit(2);
|
||||
}
|
||||
};
|
||||
let mut d = Decoder::new(Value::Table(table));
|
||||
match Decodable::decode(&mut d) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(e) => {
|
||||
println!("failed to decode TOML: {}", e);
|
||||
process::exit(2);
|
||||
}
|
||||
}
|
||||
}).unwrap_or_else(|| TomlConfig::default());
|
||||
|
||||
let build = toml.build.clone().unwrap_or(Build::default());
|
||||
set(&mut config.build, build.build.clone());
|
||||
config.host.push(config.build.clone());
|
||||
for host in build.host.iter() {
|
||||
if !config.host.contains(host) {
|
||||
config.host.push(host.clone());
|
||||
}
|
||||
}
|
||||
for target in config.host.iter().chain(&build.target) {
|
||||
if !config.target.contains(target) {
|
||||
config.target.push(target.clone());
|
||||
}
|
||||
}
|
||||
config.rustc = build.rustc;
|
||||
config.cargo = build.cargo;
|
||||
set(&mut config.compiler_docs, build.compiler_docs);
|
||||
set(&mut config.docs, build.docs);
|
||||
|
||||
if let Some(ref llvm) = toml.llvm {
|
||||
set(&mut config.ccache, llvm.ccache);
|
||||
set(&mut config.llvm_assertions, llvm.assertions);
|
||||
set(&mut config.llvm_optimize, llvm.optimize);
|
||||
set(&mut config.llvm_optimize, llvm.optimize);
|
||||
set(&mut config.llvm_version_check, llvm.version_check);
|
||||
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
|
||||
}
|
||||
if let Some(ref rust) = toml.rust {
|
||||
set(&mut config.rust_debug_assertions, rust.debug_assertions);
|
||||
set(&mut config.rust_debuginfo, rust.debuginfo);
|
||||
set(&mut config.rust_optimize, rust.optimize);
|
||||
set(&mut config.rust_rpath, rust.rpath);
|
||||
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
|
||||
set(&mut config.use_jemalloc, rust.use_jemalloc);
|
||||
set(&mut config.channel, rust.channel.clone());
|
||||
config.rustc_default_linker = rust.default_linker.clone();
|
||||
config.rustc_default_ar = rust.default_ar.clone();
|
||||
config.musl_root = rust.musl_root.clone().map(PathBuf::from);
|
||||
|
||||
match rust.codegen_units {
|
||||
Some(0) => config.rust_codegen_units = num_cpus::get() as u32,
|
||||
Some(n) => config.rust_codegen_units = n,
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref t) = toml.target {
|
||||
for (triple, cfg) in t {
|
||||
let mut target = Target::default();
|
||||
|
||||
if let Some(ref s) = cfg.llvm_config {
|
||||
target.llvm_config = Some(env::current_dir().unwrap().join(s));
|
||||
}
|
||||
if let Some(ref s) = cfg.jemalloc {
|
||||
target.jemalloc = Some(env::current_dir().unwrap().join(s));
|
||||
}
|
||||
if let Some(ref s) = cfg.android_ndk {
|
||||
target.ndk = Some(env::current_dir().unwrap().join(s));
|
||||
}
|
||||
target.cxx = cfg.cxx.clone().map(PathBuf::from);
|
||||
target.cc = cfg.cc.clone().map(PathBuf::from);
|
||||
|
||||
config.target_config.insert(triple.clone(), target);
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
pub fn update_with_config_mk(&mut self) {
|
||||
let mut config = String::new();
|
||||
File::open("config.mk").unwrap().read_to_string(&mut config).unwrap();
|
||||
for line in config.lines() {
|
||||
let mut parts = line.splitn(2, ":=").map(|s| s.trim());
|
||||
let key = parts.next().unwrap();
|
||||
let value = match parts.next() {
|
||||
Some(n) if n.starts_with('\"') => &n[1..n.len() - 1],
|
||||
Some(n) => n,
|
||||
None => continue
|
||||
};
|
||||
|
||||
macro_rules! check {
|
||||
($(($name:expr, $val:expr),)*) => {
|
||||
if value == "1" {
|
||||
$(
|
||||
if key == concat!("CFG_ENABLE_", $name) {
|
||||
$val = true;
|
||||
continue
|
||||
}
|
||||
if key == concat!("CFG_DISABLE_", $name) {
|
||||
$val = false;
|
||||
continue
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check! {
|
||||
("CCACHE", self.ccache),
|
||||
("MANAGE_SUBMODULES", self.submodules),
|
||||
("COMPILER_DOCS", self.compiler_docs),
|
||||
("DOCS", self.docs),
|
||||
("LLVM_ASSERTIONS", self.llvm_assertions),
|
||||
("OPTIMIZE_LLVM", self.llvm_optimize),
|
||||
("LLVM_VERSION_CHECK", self.llvm_version_check),
|
||||
("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp),
|
||||
("OPTIMIZE", self.rust_optimize),
|
||||
("DEBUG_ASSERTIONS", self.rust_debug_assertions),
|
||||
("DEBUGINFO", self.rust_debuginfo),
|
||||
("JEMALLOC", self.use_jemalloc),
|
||||
("DEBUG_JEMALLOC", self.debug_jemalloc),
|
||||
("RPATH", self.rust_rpath),
|
||||
}
|
||||
|
||||
match key {
|
||||
"CFG_BUILD" => self.build = value.to_string(),
|
||||
"CFG_HOST" => {
|
||||
self.host = value.split(" ").map(|s| s.to_string())
|
||||
.collect();
|
||||
}
|
||||
"CFG_TARGET" => {
|
||||
self.target = value.split(" ").map(|s| s.to_string())
|
||||
.collect();
|
||||
}
|
||||
"CFG_MUSL_ROOT" if value.len() > 0 => {
|
||||
self.musl_root = Some(PathBuf::from(value));
|
||||
}
|
||||
"CFG_DEFAULT_AR" if value.len() > 0 => {
|
||||
self.rustc_default_ar = Some(value.to_string());
|
||||
}
|
||||
"CFG_DEFAULT_LINKER" if value.len() > 0 => {
|
||||
self.rustc_default_linker = Some(value.to_string());
|
||||
}
|
||||
"CFG_RELEASE_CHANNEL" => {
|
||||
self.channel = value.to_string();
|
||||
}
|
||||
"CFG_PREFIX" => {
|
||||
self.prefix = Some(value.to_string());
|
||||
}
|
||||
"CFG_LLVM_ROOT" if value.len() > 0 => {
|
||||
let target = self.target_config.entry(self.build.clone())
|
||||
.or_insert(Target::default());
|
||||
let root = PathBuf::from(value);
|
||||
target.llvm_config = Some(root.join("bin/llvm-config"));
|
||||
}
|
||||
"CFG_JEMALLOC_ROOT" if value.len() > 0 => {
|
||||
let target = self.target_config.entry(self.build.clone())
|
||||
.or_insert(Target::default());
|
||||
target.jemalloc = Some(PathBuf::from(value));
|
||||
}
|
||||
"CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
|
||||
let target = "arm-linux-androideabi".to_string();
|
||||
let target = self.target_config.entry(target)
|
||||
.or_insert(Target::default());
|
||||
target.ndk = Some(PathBuf::from(value));
|
||||
}
|
||||
"CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => {
|
||||
let target = "i686-linux-androideabi".to_string();
|
||||
let target = self.target_config.entry(target)
|
||||
.or_insert(Target::default());
|
||||
target.ndk = Some(PathBuf::from(value));
|
||||
}
|
||||
"CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => {
|
||||
let target = "aarch64-linux-androideabi".to_string();
|
||||
let target = self.target_config.entry(target)
|
||||
.or_insert(Target::default());
|
||||
target.ndk = Some(PathBuf::from(value));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set<T>(field: &mut T, val: Option<T>) {
|
||||
if let Some(v) = val {
|
||||
*field = v;
|
||||
}
|
||||
}
|
||||
104
src/bootstrap/build/doc.rs
Normal file
104
src/bootstrap/build/doc.rs
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
use std::path::Path;
|
||||
use std::fs::{self, File};
|
||||
use std::io::prelude::*;
|
||||
|
||||
use build::{Build, Compiler};
|
||||
use build::util::up_to_date;
|
||||
|
||||
pub fn rustbook(build: &Build, stage: u32, host: &str, name: &str, out: &Path) {
|
||||
t!(fs::create_dir_all(out));
|
||||
|
||||
let out = out.join(name);
|
||||
let compiler = Compiler::new(stage, host);
|
||||
let src = build.src.join("src/doc").join(name);
|
||||
let index = out.join("index.html");
|
||||
let rustbook = build.tool(&compiler, "rustbook");
|
||||
if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
|
||||
return
|
||||
}
|
||||
println!("Rustbook stage{} ({}) - {}", stage, host, name);
|
||||
let _ = fs::remove_dir_all(&out);
|
||||
build.run(build.tool_cmd(&compiler, "rustbook")
|
||||
.arg("build")
|
||||
.arg(&src)
|
||||
.arg(out));
|
||||
}
|
||||
|
||||
pub fn standalone(build: &Build, stage: u32, host: &str, out: &Path) {
|
||||
println!("Documenting stage{} standalone ({})", stage, host);
|
||||
t!(fs::create_dir_all(out));
|
||||
|
||||
let compiler = Compiler::new(stage, host);
|
||||
|
||||
let favicon = build.src.join("src/doc/favicon.inc");
|
||||
let footer = build.src.join("src/doc/footer.inc");
|
||||
let full_toc = build.src.join("src/doc/full-toc.inc");
|
||||
t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css")));
|
||||
|
||||
let version_input = build.src.join("src/doc/version_info.html.template");
|
||||
let version_info = out.join("version_info.html");
|
||||
|
||||
if !up_to_date(&version_input, &version_info) {
|
||||
let mut info = String::new();
|
||||
t!(t!(File::open(&version_input)).read_to_string(&mut info));
|
||||
let blank = String::new();
|
||||
let short = build.short_ver_hash.as_ref().unwrap_or(&blank);
|
||||
let hash = build.ver_hash.as_ref().unwrap_or(&blank);
|
||||
let info = info.replace("VERSION", &build.release)
|
||||
.replace("SHORT_HASH", short)
|
||||
.replace("STAMP", hash);
|
||||
t!(t!(File::create(&version_info)).write_all(info.as_bytes()));
|
||||
}
|
||||
|
||||
for file in t!(fs::read_dir(build.src.join("src/doc"))) {
|
||||
let file = t!(file);
|
||||
let path = file.path();
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
if !filename.ends_with(".md") || filename == "README.md" {
|
||||
continue
|
||||
}
|
||||
|
||||
let html = out.join(filename).with_extension("html");
|
||||
let rustdoc = build.tool(&compiler, "rustdoc");
|
||||
if up_to_date(&path, &html) &&
|
||||
up_to_date(&footer, &html) &&
|
||||
up_to_date(&favicon, &html) &&
|
||||
up_to_date(&full_toc, &html) &&
|
||||
up_to_date(&version_info, &html) &&
|
||||
up_to_date(&rustdoc, &html) {
|
||||
continue
|
||||
}
|
||||
|
||||
let mut cmd = build.tool_cmd(&compiler, "rustdoc");
|
||||
cmd.arg("--html-after-content").arg(&footer)
|
||||
.arg("--html-before-content").arg(&version_info)
|
||||
.arg("--html-in-header").arg(&favicon)
|
||||
.arg("--markdown-playground-url")
|
||||
.arg("https://play.rust-lang.org/")
|
||||
.arg("-o").arg(out)
|
||||
.arg(&path);
|
||||
|
||||
if filename == "reference.md" {
|
||||
cmd.arg("--html-in-header").arg(&full_toc);
|
||||
}
|
||||
|
||||
if filename == "not_found.md" {
|
||||
cmd.arg("--markdown-no-toc")
|
||||
.arg("--markdown-css")
|
||||
.arg("https://doc.rust-lang.org/rust.css");
|
||||
} else {
|
||||
cmd.arg("--markdown-css").arg("rust.css");
|
||||
}
|
||||
build.run(&mut cmd);
|
||||
}
|
||||
}
|
||||
102
src/bootstrap/build/flags.rs
Normal file
102
src/bootstrap/build/flags.rs
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::slice;
|
||||
|
||||
use getopts::Options;
|
||||
|
||||
pub struct Flags {
|
||||
pub verbose: bool,
|
||||
pub stage: Option<u32>,
|
||||
pub build: String,
|
||||
pub host: Filter,
|
||||
pub target: Filter,
|
||||
pub step: Vec<String>,
|
||||
pub config: Option<PathBuf>,
|
||||
pub src: Option<PathBuf>,
|
||||
pub jobs: Option<u32>,
|
||||
pub args: Vec<String>,
|
||||
pub clean: bool,
|
||||
}
|
||||
|
||||
pub struct Filter {
|
||||
values: Vec<String>,
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
pub fn parse(args: &[String]) -> Flags {
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("v", "verbose", "use verbose output");
|
||||
opts.optopt("", "config", "TOML configuration file for build", "FILE");
|
||||
opts.optmulti("", "host", "host targets to build", "HOST");
|
||||
opts.reqopt("", "build", "build target of the stage0 compiler", "BUILD");
|
||||
opts.optmulti("", "target", "targets to build", "TARGET");
|
||||
opts.optmulti("s", "step", "build step to execute", "STEP");
|
||||
opts.optopt("", "stage", "stage to build", "N");
|
||||
opts.optopt("", "src", "path to repo root", "DIR");
|
||||
opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
|
||||
opts.optflag("", "clean", "clean output directory");
|
||||
opts.optflag("h", "help", "print this help message");
|
||||
|
||||
let usage = |n| -> ! {
|
||||
let brief = format!("Usage: rust.py [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
process::exit(n);
|
||||
};
|
||||
|
||||
let m = opts.parse(args).unwrap_or_else(|e| {
|
||||
println!("failed to parse options: {}", e);
|
||||
usage(1);
|
||||
});
|
||||
if m.opt_present("h") {
|
||||
usage(0);
|
||||
}
|
||||
|
||||
if m.free.len() > 0 {
|
||||
println!("free arguments are not currently accepted");
|
||||
usage(1);
|
||||
}
|
||||
|
||||
let cfg_file = m.opt_str("config").map(PathBuf::from).or_else(|| {
|
||||
if fs::metadata("config.toml").is_ok() {
|
||||
Some(PathBuf::from("config.toml"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
Flags {
|
||||
verbose: m.opt_present("v"),
|
||||
clean: m.opt_present("clean"),
|
||||
stage: m.opt_str("stage").map(|j| j.parse().unwrap()),
|
||||
build: m.opt_str("build").unwrap(),
|
||||
host: Filter { values: m.opt_strs("host") },
|
||||
target: Filter { values: m.opt_strs("target") },
|
||||
step: m.opt_strs("step"),
|
||||
config: cfg_file,
|
||||
src: m.opt_str("src").map(PathBuf::from),
|
||||
jobs: m.opt_str("jobs").map(|j| j.parse().unwrap()),
|
||||
args: m.free.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
pub fn contains(&self, name: &str) -> bool {
|
||||
self.values.len() == 0 || self.values.iter().any(|s| s == name)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> slice::Iter<String> {
|
||||
self.values.iter()
|
||||
}
|
||||
}
|
||||
111
src/bootstrap/build/job.rs
Normal file
111
src/bootstrap/build/job.rs
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
//! Job management on Windows for bootstrapping
|
||||
//!
|
||||
//! Most of the time when you're running a build system (e.g. make) you expect
|
||||
//! Ctrl-C or abnormal termination to actually terminate the entire tree of
|
||||
//! process in play, not just the one at the top. This currently works "by
|
||||
//! default" on Unix platforms because Ctrl-C actually sends a signal to the
|
||||
//! *process group* rather than the parent process, so everything will get torn
|
||||
//! down. On Windows, however, this does not happen and Ctrl-C just kills the
|
||||
//! parent process.
|
||||
//!
|
||||
//! To achieve the same semantics on Windows we use Job Objects to ensure that
|
||||
//! all processes die at the same time. Job objects have a mode of operation
|
||||
//! where when all handles to the object are closed it causes all child
|
||||
//! processes associated with the object to be terminated immediately.
|
||||
//! Conveniently whenever a process in the job object spawns a new process the
|
||||
//! child will be associated with the job object as well. This means if we add
|
||||
//! ourselves to the job object we create then everything will get torn down!
|
||||
//!
|
||||
//! Unfortunately most of the time the build system is actually called from a
|
||||
//! python wrapper (which manages things like building the build system) so this
|
||||
//! all doesn't quite cut it so far. To go the last mile we duplicate the job
|
||||
//! object handle into our parent process (a python process probably) and then
|
||||
//! close our own handle. This means that the only handle to the job object
|
||||
//! resides in the parent python process, so when python dies the whole build
|
||||
//! system dies (as one would probably expect!).
|
||||
//!
|
||||
//! Note that this module has a #[cfg(windows)] above it as none of this logic
|
||||
//! is required on Unix.
|
||||
|
||||
extern crate kernel32;
|
||||
extern crate winapi;
|
||||
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
|
||||
use self::winapi::*;
|
||||
use self::kernel32::*;
|
||||
|
||||
pub unsafe fn setup() {
|
||||
// Create a new job object for us to use
|
||||
let job = CreateJobObjectW(0 as *mut _, 0 as *const _);
|
||||
assert!(job != 0 as *mut _, "{}", io::Error::last_os_error());
|
||||
|
||||
// Indicate that when all handles to the job object are gone that all
|
||||
// process in the object should be killed. Note that this includes our
|
||||
// entire process tree by default because we've added ourselves and and our
|
||||
// children will reside in the job by default.
|
||||
let mut info = mem::zeroed::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>();
|
||||
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
let r = SetInformationJobObject(job,
|
||||
JobObjectExtendedLimitInformation,
|
||||
&mut info as *mut _ as LPVOID,
|
||||
mem::size_of_val(&info) as DWORD);
|
||||
assert!(r != 0, "{}", io::Error::last_os_error());
|
||||
|
||||
// Assign our process to this job object. Note that if this fails, one very
|
||||
// likely reason is that we are ourselves already in a job object! This can
|
||||
// happen on the build bots that we've got for Windows, or if just anyone
|
||||
// else is instrumenting the build. In this case we just bail out
|
||||
// immediately and assume that they take care of it.
|
||||
//
|
||||
// Also note that nested jobs (why this might fail) are supported in recent
|
||||
// versions of Windows, but the version of Windows that our bots are running
|
||||
// at least don't support nested job objects.
|
||||
let r = AssignProcessToJobObject(job, GetCurrentProcess());
|
||||
if r == 0 {
|
||||
CloseHandle(job);
|
||||
return
|
||||
}
|
||||
|
||||
// If we've got a parent process (e.g. the python script that called us)
|
||||
// then move ownership of this job object up to them. That way if the python
|
||||
// script is killed (e.g. via ctrl-c) then we'll all be torn down.
|
||||
//
|
||||
// If we don't have a parent (e.g. this was run directly) then we
|
||||
// intentionally leak the job object handle. When our process exits
|
||||
// (normally or abnormally) it will close the handle implicitly, causing all
|
||||
// processes in the job to be cleaned up.
|
||||
let pid = match env::var("BOOTSTRAP_PARENT_ID") {
|
||||
Ok(s) => s,
|
||||
Err(..) => return,
|
||||
};
|
||||
|
||||
let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
|
||||
assert!(parent != 0 as *mut _, "{}", io::Error::last_os_error());
|
||||
let mut parent_handle = 0 as *mut _;
|
||||
let r = DuplicateHandle(GetCurrentProcess(), job,
|
||||
parent, &mut parent_handle,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
|
||||
// If this failed, well at least we tried! An example of DuplicateHandle
|
||||
// failing in the past has been when the wrong python2 package spawed this
|
||||
// build system (e.g. the `python2` package in MSYS instead of
|
||||
// `mingw-w64-x86_64-python2`. Not sure why it failed, but the "failure
|
||||
// mode" here is that we only clean everything up when the build system
|
||||
// dies, not when the python parent does, so not too bad.
|
||||
if r != 0 {
|
||||
CloseHandle(job);
|
||||
}
|
||||
}
|
||||
475
src/bootstrap/build/mod.rs
Normal file
475
src/bootstrap/build/mod.rs
Normal file
@ -0,0 +1,475 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::{run_silent, output};
|
||||
use gcc;
|
||||
use num_cpus;
|
||||
|
||||
use build::util::{exe, mtime, libdir, add_lib_path};
|
||||
|
||||
macro_rules! t {
|
||||
($e:expr) => (match $e {
|
||||
Ok(e) => e,
|
||||
Err(e) => panic!("{} failed with {}", stringify!($e), e),
|
||||
})
|
||||
}
|
||||
|
||||
mod cc;
|
||||
mod channel;
|
||||
mod clean;
|
||||
mod compile;
|
||||
mod config;
|
||||
mod doc;
|
||||
mod flags;
|
||||
mod native;
|
||||
mod sanity;
|
||||
mod step;
|
||||
mod util;
|
||||
|
||||
#[cfg(windows)]
|
||||
mod job;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
mod job {
|
||||
pub unsafe fn setup() {}
|
||||
}
|
||||
|
||||
pub use build::config::Config;
|
||||
pub use build::flags::Flags;
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
|
||||
pub struct Compiler<'a> {
|
||||
stage: u32,
|
||||
host: &'a str,
|
||||
}
|
||||
|
||||
pub struct Build {
|
||||
// User-specified configuration via config.toml
|
||||
config: Config,
|
||||
|
||||
// User-specified configuration via CLI flags
|
||||
flags: Flags,
|
||||
|
||||
// Derived properties from the above two configurations
|
||||
cargo: PathBuf,
|
||||
rustc: PathBuf,
|
||||
src: PathBuf,
|
||||
out: PathBuf,
|
||||
release: String,
|
||||
unstable_features: bool,
|
||||
ver_hash: Option<String>,
|
||||
short_ver_hash: Option<String>,
|
||||
ver_date: Option<String>,
|
||||
version: String,
|
||||
bootstrap_key: String,
|
||||
|
||||
// Runtime state filled in later on
|
||||
cc: HashMap<String, (gcc::Tool, PathBuf)>,
|
||||
cxx: HashMap<String, gcc::Tool>,
|
||||
compiler_rt_built: RefCell<HashMap<String, PathBuf>>,
|
||||
}
|
||||
|
||||
impl Build {
|
||||
pub fn new(flags: Flags, config: Config) -> Build {
|
||||
let cwd = t!(env::current_dir());
|
||||
let src = flags.src.clone().unwrap_or(cwd.clone());
|
||||
let out = cwd.join("build");
|
||||
|
||||
let stage0_root = out.join(&config.build).join("stage0/bin");
|
||||
let rustc = match config.rustc {
|
||||
Some(ref s) => PathBuf::from(s),
|
||||
None => stage0_root.join(exe("rustc", &config.build)),
|
||||
};
|
||||
let cargo = match config.cargo {
|
||||
Some(ref s) => PathBuf::from(s),
|
||||
None => stage0_root.join(exe("cargo", &config.build)),
|
||||
};
|
||||
|
||||
Build {
|
||||
flags: flags,
|
||||
config: config,
|
||||
cargo: cargo,
|
||||
rustc: rustc,
|
||||
src: src,
|
||||
out: out,
|
||||
|
||||
release: String::new(),
|
||||
unstable_features: false,
|
||||
ver_hash: None,
|
||||
short_ver_hash: None,
|
||||
ver_date: None,
|
||||
version: String::new(),
|
||||
bootstrap_key: String::new(),
|
||||
cc: HashMap::new(),
|
||||
cxx: HashMap::new(),
|
||||
compiler_rt_built: RefCell::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(&mut self) {
|
||||
use build::step::Source::*;
|
||||
|
||||
unsafe {
|
||||
job::setup();
|
||||
}
|
||||
|
||||
if self.flags.clean {
|
||||
return clean::clean(self);
|
||||
}
|
||||
|
||||
cc::find(self);
|
||||
sanity::check(self);
|
||||
channel::collect(self);
|
||||
self.update_submodules();
|
||||
|
||||
for target in step::all(self) {
|
||||
let doc_out = self.out.join(&target.target).join("doc");
|
||||
match target.src {
|
||||
Llvm { _dummy } => {
|
||||
native::llvm(self, target.target);
|
||||
}
|
||||
CompilerRt { _dummy } => {
|
||||
native::compiler_rt(self, target.target);
|
||||
}
|
||||
Libstd { stage, compiler } => {
|
||||
compile::std(self, stage, target.target, &compiler);
|
||||
}
|
||||
Librustc { stage, compiler } => {
|
||||
compile::rustc(self, stage, target.target, &compiler);
|
||||
}
|
||||
LibstdLink { stage, compiler, host } => {
|
||||
compile::std_link(self, stage, target.target,
|
||||
&compiler, host);
|
||||
}
|
||||
LibrustcLink { stage, compiler, host } => {
|
||||
compile::rustc_link(self, stage, target.target,
|
||||
&compiler, host);
|
||||
}
|
||||
Rustc { stage: 0 } => {
|
||||
// nothing to do...
|
||||
}
|
||||
Rustc { stage } => {
|
||||
compile::assemble_rustc(self, stage, target.target);
|
||||
}
|
||||
DocBook { stage } => {
|
||||
doc::rustbook(self, stage, target.target, "book", &doc_out);
|
||||
}
|
||||
DocNomicon { stage } => {
|
||||
doc::rustbook(self, stage, target.target, "nomicon",
|
||||
&doc_out);
|
||||
}
|
||||
DocStyle { stage } => {
|
||||
doc::rustbook(self, stage, target.target, "style",
|
||||
&doc_out);
|
||||
}
|
||||
DocStandalone { stage } => {
|
||||
doc::standalone(self, stage, target.target, &doc_out);
|
||||
}
|
||||
Doc { .. } => {} // pseudo-step
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_submodules(&self) {
|
||||
if !self.config.submodules {
|
||||
return
|
||||
}
|
||||
if fs::metadata(self.src.join(".git")).is_err() {
|
||||
return
|
||||
}
|
||||
let git_submodule = || {
|
||||
let mut cmd = Command::new("git");
|
||||
cmd.current_dir(&self.src).arg("submodule");
|
||||
return cmd
|
||||
};
|
||||
let out = output(git_submodule().arg("status"));
|
||||
if !out.lines().any(|l| l.starts_with("+") || l.starts_with("-")) {
|
||||
return
|
||||
}
|
||||
|
||||
self.run(git_submodule().arg("sync"));
|
||||
self.run(git_submodule().arg("init"));
|
||||
self.run(git_submodule().arg("update"));
|
||||
self.run(git_submodule().arg("update").arg("--recursive"));
|
||||
self.run(git_submodule().arg("status").arg("--recursive"));
|
||||
self.run(git_submodule().arg("foreach").arg("--recursive")
|
||||
.arg("git").arg("clean").arg("-fdx"));
|
||||
self.run(git_submodule().arg("foreach").arg("--recursive")
|
||||
.arg("git").arg("checkout").arg("."));
|
||||
}
|
||||
|
||||
/// Clear out `dir` if our build has been flagged as dirty, and also set
|
||||
/// ourselves as dirty if `file` changes when `f` is executed.
|
||||
fn clear_if_dirty(&self, dir: &Path, input: &Path) {
|
||||
let stamp = dir.join(".stamp");
|
||||
if mtime(&stamp) < mtime(input) {
|
||||
self.verbose(&format!("Dirty - {}", dir.display()));
|
||||
let _ = fs::remove_dir_all(dir);
|
||||
}
|
||||
t!(fs::create_dir_all(dir));
|
||||
t!(File::create(stamp));
|
||||
}
|
||||
|
||||
/// Prepares an invocation of `cargo` to be run.
|
||||
///
|
||||
/// This will create a `Command` that represents a pending execution of
|
||||
/// Cargo for the specified stage, whether or not the standard library is
|
||||
/// being built, and using the specified compiler targeting `target`.
|
||||
// FIXME: aren't stage/compiler duplicated?
|
||||
fn cargo(&self, stage: u32, compiler: &Compiler, is_std: bool,
|
||||
target: &str, cmd: &str) -> Command {
|
||||
let mut cargo = Command::new(&self.cargo);
|
||||
let host = compiler.host;
|
||||
let out_dir = self.stage_out(stage, host, is_std);
|
||||
cargo.env("CARGO_TARGET_DIR", out_dir)
|
||||
.arg(cmd)
|
||||
.arg("--target").arg(target)
|
||||
.arg("-j").arg(self.jobs().to_string());
|
||||
|
||||
// Customize the compiler we're running. Specify the compiler to cargo
|
||||
// as our shim and then pass it some various options used to configure
|
||||
// how the actual compiler itself is called.
|
||||
cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc"))
|
||||
.env("RUSTC_REAL", self.compiler_path(compiler))
|
||||
.env("RUSTC_STAGE", self.stage_arg(stage, compiler).to_string())
|
||||
.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
|
||||
.env("RUSTC_CODEGEN_UNITS",
|
||||
self.config.rust_codegen_units.to_string())
|
||||
.env("RUSTC_DEBUG_ASSERTIONS",
|
||||
self.config.rust_debug_assertions.to_string())
|
||||
.env("RUSTC_SNAPSHOT", &self.rustc)
|
||||
.env("RUSTC_SYSROOT", self.sysroot(stage, host))
|
||||
.env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir())
|
||||
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "))
|
||||
.env("RUSTC_RPATH", self.config.rust_rpath.to_string())
|
||||
.env("RUSTDOC", self.tool(compiler, "rustdoc"));
|
||||
|
||||
// Specify some variuos options for build scripts used throughout the
|
||||
// build.
|
||||
//
|
||||
// FIXME: the guard against msvc shouldn't need to be here
|
||||
if !target.contains("msvc") {
|
||||
cargo.env(format!("CC_{}", target), self.cc(target))
|
||||
.env(format!("AR_{}", target), self.ar(target))
|
||||
.env(format!("CFLAGS_{}", target), self.cflags(target));
|
||||
}
|
||||
|
||||
// Environment variables *required* needed throughout the build
|
||||
//
|
||||
// FIXME: should update code to not require this env vars
|
||||
cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
|
||||
|
||||
if self.config.verbose || self.flags.verbose {
|
||||
cargo.arg("-v");
|
||||
}
|
||||
if self.config.rust_optimize {
|
||||
cargo.arg("--release");
|
||||
}
|
||||
self.add_rustc_lib_path(compiler, &mut cargo);
|
||||
return cargo
|
||||
}
|
||||
|
||||
/// Get a path to the compiler specified.
|
||||
fn compiler_path(&self, compiler: &Compiler) -> PathBuf {
|
||||
if compiler.is_snapshot(self) {
|
||||
self.rustc.clone()
|
||||
} else {
|
||||
self.sysroot(compiler.stage, compiler.host).join("bin")
|
||||
.join(exe("rustc", compiler.host))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the specified tool next to the specified compiler
|
||||
fn tool(&self, compiler: &Compiler, tool: &str) -> PathBuf {
|
||||
if compiler.is_snapshot(self) {
|
||||
assert!(tool == "rustdoc", "no tools other than rustdoc in stage0");
|
||||
let mut rustdoc = self.rustc.clone();
|
||||
rustdoc.pop();
|
||||
rustdoc.push(exe("rustdoc", &self.config.build));
|
||||
return rustdoc
|
||||
}
|
||||
let (stage, host) = (compiler.stage, compiler.host);
|
||||
self.cargo_out(stage - 1, host, false, host).join(exe(tool, host))
|
||||
}
|
||||
|
||||
/// Get a `Command` which is ready to run `tool` in `stage` built for
|
||||
/// `host`.
|
||||
#[allow(dead_code)] // this will be used soon
|
||||
fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command {
|
||||
let mut cmd = Command::new(self.tool(&compiler, tool));
|
||||
let host = compiler.host;
|
||||
let stage = compiler.stage;
|
||||
let paths = vec![
|
||||
self.cargo_out(stage - 1, host, true, host).join("deps"),
|
||||
self.cargo_out(stage - 1, host, false, host).join("deps"),
|
||||
];
|
||||
add_lib_path(paths, &mut cmd);
|
||||
return cmd
|
||||
}
|
||||
|
||||
fn stage_arg(&self, stage: u32, compiler: &Compiler) -> u32 {
|
||||
if stage == 0 && compiler.host != self.config.build {1} else {stage}
|
||||
}
|
||||
|
||||
/// Get the space-separated set of activated features for the standard
|
||||
/// library.
|
||||
fn std_features(&self) -> String {
|
||||
let mut features = String::new();
|
||||
if self.config.debug_jemalloc {
|
||||
features.push_str(" debug-jemalloc");
|
||||
}
|
||||
if self.config.use_jemalloc {
|
||||
features.push_str(" jemalloc");
|
||||
}
|
||||
return features
|
||||
}
|
||||
|
||||
/// Get the space-separated set of activated features for the compiler.
|
||||
fn rustc_features(&self, stage: u32) -> String {
|
||||
let mut features = String::new();
|
||||
if self.config.use_jemalloc {
|
||||
features.push_str(" jemalloc");
|
||||
}
|
||||
if stage > 0 {
|
||||
features.push_str(" rustdoc");
|
||||
features.push_str(" rustbook");
|
||||
}
|
||||
return features
|
||||
}
|
||||
|
||||
/// Component directory that Cargo will produce output into (e.g.
|
||||
/// release/debug)
|
||||
fn cargo_dir(&self) -> &'static str {
|
||||
if self.config.rust_optimize {"release"} else {"debug"}
|
||||
}
|
||||
|
||||
fn sysroot(&self, stage: u32, host: &str) -> PathBuf {
|
||||
if stage == 0 {
|
||||
self.stage_out(stage, host, false)
|
||||
} else {
|
||||
self.out.join(host).join(format!("stage{}", stage))
|
||||
}
|
||||
}
|
||||
|
||||
fn sysroot_libdir(&self, stage: u32, host: &str, target: &str) -> PathBuf {
|
||||
self.sysroot(stage, host).join("lib").join("rustlib")
|
||||
.join(target).join("lib")
|
||||
}
|
||||
|
||||
/// Returns the root directory for all output generated in a particular
|
||||
/// stage when running with a particular host compiler.
|
||||
///
|
||||
/// The `is_std` flag indicates whether the root directory is for the
|
||||
/// bootstrap of the standard library or for the compiler.
|
||||
fn stage_out(&self, stage: u32, host: &str, is_std: bool) -> PathBuf {
|
||||
self.out.join(host)
|
||||
.join(format!("stage{}{}", stage, if is_std {"-std"} else {"-rustc"}))
|
||||
}
|
||||
|
||||
/// Returns the root output directory for all Cargo output in a given stage,
|
||||
/// running a particular comipler, wehther or not we're building the
|
||||
/// standard library, and targeting the specified architecture.
|
||||
fn cargo_out(&self, stage: u32, host: &str, is_std: bool,
|
||||
target: &str) -> PathBuf {
|
||||
self.stage_out(stage, host, is_std).join(target).join(self.cargo_dir())
|
||||
}
|
||||
|
||||
/// Root output directory for LLVM compiled for `target`
|
||||
fn llvm_out(&self, target: &str) -> PathBuf {
|
||||
self.out.join(target).join("llvm")
|
||||
}
|
||||
|
||||
/// Root output directory for compiler-rt compiled for `target`
|
||||
fn compiler_rt_out(&self, target: &str) -> PathBuf {
|
||||
self.out.join(target).join("compiler-rt")
|
||||
}
|
||||
|
||||
fn add_rustc_lib_path(&self, compiler: &Compiler, cmd: &mut Command) {
|
||||
// Windows doesn't need dylib path munging because the dlls for the
|
||||
// compiler live next to the compiler and the system will find them
|
||||
// automatically.
|
||||
if cfg!(windows) { return }
|
||||
|
||||
add_lib_path(vec![self.rustc_libdir(compiler)], cmd);
|
||||
}
|
||||
|
||||
fn rustc_libdir(&self, compiler: &Compiler) -> PathBuf {
|
||||
if compiler.is_snapshot(self) {
|
||||
self.rustc_snapshot_libdir()
|
||||
} else {
|
||||
self.sysroot(compiler.stage, compiler.host)
|
||||
.join(libdir(compiler.host))
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_snapshot_libdir(&self) -> PathBuf {
|
||||
self.rustc.parent().unwrap().parent().unwrap()
|
||||
.join(libdir(&self.config.build))
|
||||
}
|
||||
|
||||
fn run(&self, cmd: &mut Command) {
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
run_silent(cmd)
|
||||
}
|
||||
|
||||
fn verbose(&self, msg: &str) {
|
||||
if self.flags.verbose || self.config.verbose {
|
||||
println!("{}", msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn jobs(&self) -> u32 {
|
||||
self.flags.jobs.unwrap_or(num_cpus::get() as u32)
|
||||
}
|
||||
|
||||
fn cc(&self, target: &str) -> &Path {
|
||||
self.cc[target].0.path()
|
||||
}
|
||||
|
||||
fn cflags(&self, target: &str) -> String {
|
||||
self.cc[target].0.args().iter()
|
||||
.map(|s| s.to_string_lossy())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
}
|
||||
|
||||
fn ar(&self, target: &str) -> &Path {
|
||||
&self.cc[target].1
|
||||
}
|
||||
|
||||
fn cxx(&self, target: &str) -> &Path {
|
||||
self.cxx[target].path()
|
||||
}
|
||||
|
||||
fn rustc_flags(&self, target: &str) -> Vec<String> {
|
||||
let mut base = Vec::new();
|
||||
if target != self.config.build && !target.contains("msvc") {
|
||||
base.push(format!("-Clinker={}", self.cc(target).display()));
|
||||
}
|
||||
return base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Compiler<'a> {
|
||||
fn new(stage: u32, host: &'a str) -> Compiler<'a> {
|
||||
Compiler { stage: stage, host: host }
|
||||
}
|
||||
|
||||
fn is_snapshot(&self, build: &Build) -> bool {
|
||||
self.stage == 0 && self.host == build.config.build
|
||||
}
|
||||
}
|
||||
165
src/bootstrap/build/native.rs
Normal file
165
src/bootstrap/build/native.rs
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::fs;
|
||||
|
||||
use build_helper::output;
|
||||
use cmake;
|
||||
|
||||
use build::Build;
|
||||
use build::util::{exe, staticlib};
|
||||
|
||||
pub fn llvm(build: &Build, target: &str) {
|
||||
// If we're using a custom LLVM bail out here, but we can only use a
|
||||
// custom LLVM for the build triple.
|
||||
if let Some(config) = build.config.target_config.get(target) {
|
||||
if let Some(ref s) = config.llvm_config {
|
||||
return check_llvm_version(build, s);
|
||||
}
|
||||
}
|
||||
|
||||
// If the cleaning trigger is newer than our built artifacts (or if the
|
||||
// artifacts are missing) then we keep going, otherwise we bail out.
|
||||
let dst = build.llvm_out(target);
|
||||
let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
|
||||
let llvm_config = dst.join("bin").join(exe("llvm-config", target));
|
||||
build.clear_if_dirty(&dst, &stamp);
|
||||
if fs::metadata(llvm_config).is_ok() {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = fs::remove_dir_all(&dst.join("build"));
|
||||
t!(fs::create_dir_all(&dst.join("build")));
|
||||
let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
|
||||
|
||||
// http://llvm.org/docs/CMake.html
|
||||
let mut cfg = cmake::Config::new(build.src.join("src/llvm"));
|
||||
cfg.target(target)
|
||||
.host(&build.config.build)
|
||||
.out_dir(&dst)
|
||||
.profile(if build.config.llvm_optimize {"Release"} else {"Debug"})
|
||||
.define("LLVM_ENABLE_ASSERTIONS", assertions)
|
||||
.define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC")
|
||||
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF")
|
||||
.define("LLVM_INCLUDE_DOCS", "OFF")
|
||||
.define("LLVM_ENABLE_ZLIB", "OFF")
|
||||
.define("WITH_POLLY", "OFF")
|
||||
.define("LLVM_ENABLE_TERMINFO", "OFF")
|
||||
.define("LLVM_ENABLE_LIBEDIT", "OFF")
|
||||
.define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string());
|
||||
|
||||
if target.starts_with("i686") {
|
||||
cfg.define("LLVM_BUILD_32_BITS", "ON");
|
||||
}
|
||||
|
||||
// http://llvm.org/docs/HowToCrossCompileLLVM.html
|
||||
if target != build.config.build {
|
||||
// FIXME: if the llvm root for the build triple is overridden then we
|
||||
// should use llvm-tblgen from there, also should verify that it
|
||||
// actually exists most of the time in normal installs of LLVM.
|
||||
let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen");
|
||||
cfg.define("CMAKE_CROSSCOMPILING", "True")
|
||||
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
|
||||
.define("LLVM_TABLEGEN", &host)
|
||||
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);
|
||||
}
|
||||
|
||||
// MSVC handles compiler business itself
|
||||
if !target.contains("msvc") {
|
||||
if build.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER", "ccache")
|
||||
.define("CMAKE_C_COMPILER_ARG1", build.cc(target))
|
||||
.define("CMAKE_CXX_COMPILER", "ccache")
|
||||
.define("CMAKE_CXX_COMPILER_ARG1", build.cxx(target));
|
||||
} else {
|
||||
cfg.define("CMAKE_C_COMPILER", build.cc(target))
|
||||
.define("CMAKE_CXX_COMPILER", build.cxx(target));
|
||||
}
|
||||
cfg.build_arg("-j").build_arg(build.jobs().to_string());
|
||||
}
|
||||
|
||||
// FIXME: we don't actually need to build all LLVM tools and all LLVM
|
||||
// libraries here, e.g. we just want a few components and a few
|
||||
// tools. Figure out how to filter them down and only build the right
|
||||
// tools and libs on all platforms.
|
||||
cfg.build();
|
||||
}
|
||||
|
||||
fn check_llvm_version(build: &Build, llvm_config: &Path) {
|
||||
if !build.config.llvm_version_check {
|
||||
return
|
||||
}
|
||||
|
||||
let mut cmd = Command::new(llvm_config);
|
||||
let version = output(cmd.arg("--version"));
|
||||
if version.starts_with("3.5") || version.starts_with("3.6") ||
|
||||
version.starts_with("3.7") {
|
||||
return
|
||||
}
|
||||
panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
|
||||
}
|
||||
|
||||
pub fn compiler_rt(build: &Build, target: &str) {
|
||||
let dst = build.compiler_rt_out(target);
|
||||
let arch = target.split('-').next().unwrap();
|
||||
let mode = if build.config.rust_optimize {"Release"} else {"Debug"};
|
||||
let (dir, build_target, libname) = if target.contains("linux") {
|
||||
let os = if target.contains("android") {"-android"} else {""};
|
||||
let arch = if arch.starts_with("arm") && target.contains("eabihf") {
|
||||
"armhf"
|
||||
} else {
|
||||
arch
|
||||
};
|
||||
let target = format!("clang_rt.builtins-{}{}", arch, os);
|
||||
("linux".to_string(), target.clone(), target)
|
||||
} else if target.contains("darwin") {
|
||||
let target = format!("clang_rt.builtins_{}_osx", arch);
|
||||
("builtins".to_string(), target.clone(), target)
|
||||
} else if target.contains("windows-gnu") {
|
||||
let target = format!("clang_rt.builtins-{}", arch);
|
||||
("windows".to_string(), target.clone(), target)
|
||||
} else if target.contains("windows-msvc") {
|
||||
(format!("windows/{}", mode),
|
||||
"lib/builtins/builtins".to_string(),
|
||||
format!("clang_rt.builtins-{}", arch.replace("i686", "i386")))
|
||||
} else {
|
||||
panic!("can't get os from target: {}", target)
|
||||
};
|
||||
let output = dst.join("build/lib").join(dir)
|
||||
.join(staticlib(&libname, target));
|
||||
build.compiler_rt_built.borrow_mut().insert(target.to_string(),
|
||||
output.clone());
|
||||
if fs::metadata(&output).is_ok() {
|
||||
return
|
||||
}
|
||||
let _ = fs::remove_dir_all(&dst);
|
||||
t!(fs::create_dir_all(&dst));
|
||||
let build_llvm_config = build.llvm_out(&build.config.build)
|
||||
.join("bin")
|
||||
.join(exe("llvm-config", &build.config.build));
|
||||
let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt"));
|
||||
cfg.target(target)
|
||||
.host(&build.config.build)
|
||||
.out_dir(&dst)
|
||||
.profile(mode)
|
||||
.define("LLVM_CONFIG_PATH", build_llvm_config)
|
||||
.define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target)
|
||||
.define("COMPILER_RT_BUILD_SANITIZERS", "OFF")
|
||||
.define("COMPILER_RT_BUILD_EMUTLS", "OFF")
|
||||
// inform about c/c++ compilers, the c++ compiler isn't actually used but
|
||||
// it's needed to get the initial configure to work on all platforms.
|
||||
.define("CMAKE_C_COMPILER", build.cc(target))
|
||||
.define("CMAKE_CXX_COMPILER", build.cc(target))
|
||||
.build_target(&build_target);
|
||||
cfg.build();
|
||||
}
|
||||
122
src/bootstrap/build/sanity.rs
Normal file
122
src/bootstrap/build/sanity.rs
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::output;
|
||||
|
||||
use build::Build;
|
||||
|
||||
pub fn check(build: &mut Build) {
|
||||
let mut checked = HashSet::new();
|
||||
let path = env::var_os("PATH").unwrap_or(OsString::new());
|
||||
let mut need_cmd = |cmd: &OsStr| {
|
||||
if !checked.insert(cmd.to_owned()) {
|
||||
return
|
||||
}
|
||||
for path in env::split_paths(&path).map(|p| p.join(cmd)) {
|
||||
if fs::metadata(&path).is_ok() ||
|
||||
fs::metadata(path.with_extension("exe")).is_ok() {
|
||||
return
|
||||
}
|
||||
}
|
||||
panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
|
||||
};
|
||||
|
||||
// If we've got a git directory we're gona need git to update
|
||||
// submodules and learn about various other aspects.
|
||||
if fs::metadata(build.src.join(".git")).is_ok() {
|
||||
need_cmd("git".as_ref());
|
||||
}
|
||||
|
||||
// We need cmake, but only if we're actually building LLVM
|
||||
for host in build.config.host.iter() {
|
||||
if let Some(config) = build.config.target_config.get(host) {
|
||||
if config.llvm_config.is_some() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
need_cmd("cmake".as_ref());
|
||||
break
|
||||
}
|
||||
|
||||
need_cmd("python".as_ref());
|
||||
|
||||
// We're gonna build some custom C code here and there, host triples
|
||||
// also build some C++ shims for LLVM so we need a C++ compiler.
|
||||
for target in build.config.target.iter() {
|
||||
need_cmd(build.cc(target).as_ref());
|
||||
need_cmd(build.ar(target).as_ref());
|
||||
}
|
||||
for host in build.config.host.iter() {
|
||||
need_cmd(build.cxx(host).as_ref());
|
||||
}
|
||||
|
||||
for target in build.config.target.iter() {
|
||||
// Either can't build or don't want to run jemalloc on these targets
|
||||
if target.contains("rumprun") ||
|
||||
target.contains("bitrig") ||
|
||||
target.contains("openbsd") ||
|
||||
target.contains("msvc") {
|
||||
build.config.use_jemalloc = false;
|
||||
}
|
||||
|
||||
// Can't compile for iOS unless we're on OSX
|
||||
if target.contains("apple-ios") &&
|
||||
!build.config.build.contains("apple-darwin") {
|
||||
panic!("the iOS target is only supported on OSX");
|
||||
}
|
||||
|
||||
// Make sure musl-root is valid if specified
|
||||
if target.contains("musl") {
|
||||
match build.config.musl_root {
|
||||
Some(ref root) => {
|
||||
if fs::metadata(root.join("lib/libc.a")).is_err() {
|
||||
panic!("couldn't find libc.a in musl dir: {}",
|
||||
root.join("lib").display());
|
||||
}
|
||||
if fs::metadata(root.join("lib/libunwind.a")).is_err() {
|
||||
panic!("couldn't find libunwind.a in musl dir: {}",
|
||||
root.join("lib").display());
|
||||
}
|
||||
}
|
||||
None => {
|
||||
panic!("when targeting MUSL the build.musl-root option \
|
||||
must be specified in config.toml")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if target.contains("msvc") {
|
||||
// There are three builds of cmake on windows: MSVC, MinGW, and
|
||||
// Cygwin. The Cygwin build does not have generators for Visual
|
||||
// Studio, so detect that here and error.
|
||||
let out = output(Command::new("cmake").arg("--help"));
|
||||
if !out.contains("Visual Studio") {
|
||||
panic!("
|
||||
cmake does not support Visual Studio generators.
|
||||
|
||||
This is likely due to it being an msys/cygwin build of cmake,
|
||||
rather than the required windows version, built using MinGW
|
||||
or Visual Studio.
|
||||
|
||||
If you are building under msys2 try installing the mingw-w64-x86_64-cmake
|
||||
package instead of cmake:
|
||||
|
||||
$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
||||
");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
245
src/bootstrap/build/step.rs
Normal file
245
src/bootstrap/build/step.rs
Normal file
@ -0,0 +1,245 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use build::{Build, Compiler};
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
||||
pub struct Step<'a> {
|
||||
pub src: Source<'a>,
|
||||
pub target: &'a str,
|
||||
}
|
||||
|
||||
macro_rules! targets {
|
||||
($m:ident) => {
|
||||
$m! {
|
||||
// Step representing building the stageN compiler. This is just the
|
||||
// compiler executable itself, not any of the support libraries
|
||||
(rustc, Rustc { stage: u32 }),
|
||||
|
||||
// Steps for the two main cargo builds, one for the standard library
|
||||
// and one for the compiler itself. These are parameterized over the
|
||||
// stage output they're going to be placed in along with the
|
||||
// compiler which is producing the copy of libstd or librustc
|
||||
(libstd, Libstd { stage: u32, compiler: Compiler<'a> }),
|
||||
(librustc, Librustc { stage: u32, compiler: Compiler<'a> }),
|
||||
|
||||
// Links the standard library/librustc produced by the compiler
|
||||
// provided into the host's directory also provided.
|
||||
(libstd_link, LibstdLink {
|
||||
stage: u32,
|
||||
compiler: Compiler<'a>,
|
||||
host: &'a str
|
||||
}),
|
||||
(librustc_link, LibrustcLink {
|
||||
stage: u32,
|
||||
compiler: Compiler<'a>,
|
||||
host: &'a str
|
||||
}),
|
||||
|
||||
// Steps for long-running native builds. Ideally these wouldn't
|
||||
// actually exist and would be part of build scripts, but for now
|
||||
// these are here.
|
||||
//
|
||||
// There aren't really any parameters to this, but empty structs
|
||||
// with braces are unstable so we just pick something that works.
|
||||
(llvm, Llvm { _dummy: () }),
|
||||
(compiler_rt, CompilerRt { _dummy: () }),
|
||||
(doc, Doc { stage: u32 }),
|
||||
(doc_book, DocBook { stage: u32 }),
|
||||
(doc_nomicon, DocNomicon { stage: u32 }),
|
||||
(doc_style, DocStyle { stage: u32 }),
|
||||
(doc_standalone, DocStandalone { stage: u32 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! item { ($a:item) => ($a) }
|
||||
|
||||
macro_rules! define_source {
|
||||
($(($short:ident, $name:ident { $($args:tt)* }),)*) => {
|
||||
item! {
|
||||
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
||||
pub enum Source<'a> {
|
||||
$($name { $($args)* }),*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targets!(define_source);
|
||||
|
||||
pub fn all(build: &Build) -> Vec<Step> {
|
||||
let mut ret = Vec::new();
|
||||
let mut all = HashSet::new();
|
||||
for target in top_level(build) {
|
||||
fill(build, &target, &mut ret, &mut all);
|
||||
}
|
||||
return ret;
|
||||
|
||||
fn fill<'a>(build: &'a Build,
|
||||
target: &Step<'a>,
|
||||
ret: &mut Vec<Step<'a>>,
|
||||
set: &mut HashSet<Step<'a>>) {
|
||||
if set.insert(target.clone()) {
|
||||
for dep in target.deps(build) {
|
||||
fill(build, &dep, ret, set);
|
||||
}
|
||||
ret.push(target.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn top_level(build: &Build) -> Vec<Step> {
|
||||
let mut targets = Vec::new();
|
||||
let stage = build.flags.stage.unwrap_or(2);
|
||||
|
||||
let host = Step {
|
||||
src: Source::Llvm { _dummy: () },
|
||||
target: build.flags.host.iter().next()
|
||||
.unwrap_or(&build.config.build),
|
||||
};
|
||||
let target = Step {
|
||||
src: Source::Llvm { _dummy: () },
|
||||
target: build.flags.target.iter().next().map(|x| &x[..])
|
||||
.unwrap_or(host.target)
|
||||
};
|
||||
|
||||
add_steps(build, stage, &host, &target, &mut targets);
|
||||
|
||||
if targets.len() == 0 {
|
||||
let t = Step {
|
||||
src: Source::Llvm { _dummy: () },
|
||||
target: &build.config.build,
|
||||
};
|
||||
targets.push(t.doc(stage));
|
||||
for host in build.config.host.iter() {
|
||||
if !build.flags.host.contains(host) {
|
||||
continue
|
||||
}
|
||||
let host = t.target(host);
|
||||
if host.target == build.config.build {
|
||||
targets.push(host.librustc(stage, host.compiler(stage)));
|
||||
} else {
|
||||
targets.push(host.librustc_link(stage, t.compiler(stage),
|
||||
host.target));
|
||||
}
|
||||
for target in build.config.target.iter() {
|
||||
if !build.flags.target.contains(target) {
|
||||
continue
|
||||
}
|
||||
|
||||
if host.target == build.config.build {
|
||||
targets.push(host.target(target)
|
||||
.libstd(stage, host.compiler(stage)));
|
||||
} else {
|
||||
targets.push(host.target(target)
|
||||
.libstd_link(stage, t.compiler(stage),
|
||||
host.target));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return targets
|
||||
|
||||
}
|
||||
|
||||
fn add_steps<'a>(build: &'a Build,
|
||||
stage: u32,
|
||||
host: &Step<'a>,
|
||||
target: &Step<'a>,
|
||||
targets: &mut Vec<Step<'a>>) {
|
||||
for step in build.flags.step.iter() {
|
||||
let compiler = host.target(&build.config.build).compiler(stage);
|
||||
match &step[..] {
|
||||
"libstd" => targets.push(target.libstd(stage, compiler)),
|
||||
"librustc" => targets.push(target.librustc(stage, compiler)),
|
||||
"libstd-link" => targets.push(target.libstd_link(stage, compiler,
|
||||
host.target)),
|
||||
"librustc-link" => targets.push(target.librustc_link(stage, compiler,
|
||||
host.target)),
|
||||
"rustc" => targets.push(host.rustc(stage)),
|
||||
"llvm" => targets.push(target.llvm(())),
|
||||
"compiler-rt" => targets.push(target.compiler_rt(())),
|
||||
"doc-style" => targets.push(host.doc_style(stage)),
|
||||
"doc-standalone" => targets.push(host.doc_standalone(stage)),
|
||||
"doc-nomicon" => targets.push(host.doc_nomicon(stage)),
|
||||
"doc-book" => targets.push(host.doc_book(stage)),
|
||||
"doc" => targets.push(host.doc(stage)),
|
||||
_ => panic!("unknown build target: `{}`", step),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! constructors {
|
||||
($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$(
|
||||
fn $short(&self, $($arg: $t),*) -> Step<'a> {
|
||||
Step {
|
||||
src: Source::$name { $($arg: $arg),* },
|
||||
target: self.target,
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
impl<'a> Step<'a> {
|
||||
fn compiler(&self, stage: u32) -> Compiler<'a> {
|
||||
Compiler::new(stage, self.target)
|
||||
}
|
||||
|
||||
fn target(&self, target: &'a str) -> Step<'a> {
|
||||
Step { target: target, src: self.src.clone() }
|
||||
}
|
||||
|
||||
targets!(constructors);
|
||||
|
||||
pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
|
||||
match self.src {
|
||||
Source::Rustc { stage: 0 } => {
|
||||
Vec::new()
|
||||
}
|
||||
Source::Rustc { stage } => {
|
||||
let compiler = Compiler::new(stage - 1, &build.config.build);
|
||||
vec![self.librustc(stage - 1, compiler)]
|
||||
}
|
||||
Source::Librustc { stage, compiler } => {
|
||||
vec![self.libstd(stage, compiler), self.llvm(())]
|
||||
}
|
||||
Source::Libstd { stage: _, compiler } => {
|
||||
vec![self.compiler_rt(()),
|
||||
self.rustc(compiler.stage).target(compiler.host)]
|
||||
}
|
||||
Source::LibrustcLink { stage, compiler, host } => {
|
||||
vec![self.librustc(stage, compiler),
|
||||
self.libstd_link(stage, compiler, host)]
|
||||
}
|
||||
Source::LibstdLink { stage, compiler, host } => {
|
||||
vec![self.libstd(stage, compiler),
|
||||
self.target(host).rustc(stage)]
|
||||
}
|
||||
Source::CompilerRt { _dummy } => {
|
||||
vec![self.llvm(()).target(&build.config.build)]
|
||||
}
|
||||
Source::Llvm { _dummy } => Vec::new(),
|
||||
Source::DocBook { stage } |
|
||||
Source::DocNomicon { stage } |
|
||||
Source::DocStyle { stage } |
|
||||
Source::DocStandalone { stage } => {
|
||||
vec![self.rustc(stage)]
|
||||
}
|
||||
Source::Doc { stage } => {
|
||||
vec![self.doc_book(stage), self.doc_nomicon(stage),
|
||||
self.doc_style(stage), self.doc_standalone(stage)]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
97
src/bootstrap/build/util.rs
Normal file
97
src/bootstrap/build/util.rs
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
use bootstrap::{dylib_path, dylib_path_var};
|
||||
use filetime::FileTime;
|
||||
|
||||
pub fn staticlib(name: &str, target: &str) -> String {
|
||||
if target.contains("windows-msvc") {
|
||||
format!("{}.lib", name)
|
||||
} else {
|
||||
format!("lib{}.a", name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mtime(path: &Path) -> FileTime {
|
||||
fs::metadata(path).map(|f| {
|
||||
FileTime::from_last_modification_time(&f)
|
||||
}).unwrap_or(FileTime::zero())
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // this will be used soon
|
||||
pub fn cp_r(src: &Path, dst: &Path) {
|
||||
for f in t!(fs::read_dir(src)) {
|
||||
let f = t!(f);
|
||||
let path = f.path();
|
||||
let name = path.file_name().unwrap();
|
||||
let dst = dst.join(name);
|
||||
if t!(f.file_type()).is_dir() {
|
||||
let _ = fs::remove_dir_all(&dst);
|
||||
t!(fs::create_dir(&dst));
|
||||
cp_r(&path, &dst);
|
||||
} else {
|
||||
let _ = fs::remove_file(&dst);
|
||||
t!(fs::hard_link(&path, dst));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given an executable called `name`, return the filename for the
|
||||
/// executable for a particular target.
|
||||
pub fn exe(name: &str, target: &str) -> String {
|
||||
if target.contains("windows") {
|
||||
format!("{}.exe", name)
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dylib(name: &str) -> bool {
|
||||
name.ends_with(".dylib") || name.ends_with(".so") || name.ends_with(".dll")
|
||||
}
|
||||
|
||||
pub fn libdir(target: &str) -> &'static str {
|
||||
if target.contains("windows") {"bin"} else {"lib"}
|
||||
}
|
||||
|
||||
pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
|
||||
let mut list = dylib_path();
|
||||
for path in path {
|
||||
list.insert(0, path);
|
||||
}
|
||||
cmd.env(dylib_path_var(), t!(env::join_paths(list)));
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // this will be used soon
|
||||
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
|
||||
let threshold = mtime(dst);
|
||||
let meta = t!(fs::metadata(src));
|
||||
if meta.is_dir() {
|
||||
dir_up_to_date(src, &threshold)
|
||||
} else {
|
||||
FileTime::from_last_modification_time(&meta) <= threshold
|
||||
}
|
||||
}
|
||||
|
||||
fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {
|
||||
t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
|
||||
let meta = t!(e.metadata());
|
||||
if meta.is_dir() {
|
||||
dir_up_to_date(&e.path(), threshold)
|
||||
} else {
|
||||
FileTime::from_last_modification_time(&meta) < *threshold
|
||||
}
|
||||
})
|
||||
}
|
||||
28
src/bootstrap/lib.rs
Normal file
28
src/bootstrap/lib.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn dylib_path_var() -> &'static str {
|
||||
if cfg!(target_os = "windows") {
|
||||
"PATH"
|
||||
} else if cfg!(target_os = "macos") {
|
||||
"DYLD_LIBRARY_PATH"
|
||||
} else {
|
||||
"LD_LIBRARY_PATH"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dylib_path() -> Vec<PathBuf> {
|
||||
env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new()))
|
||||
.collect()
|
||||
}
|
||||
38
src/bootstrap/main.rs
Normal file
38
src/bootstrap/main.rs
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate bootstrap;
|
||||
extern crate build_helper;
|
||||
extern crate cmake;
|
||||
extern crate filetime;
|
||||
extern crate gcc;
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
extern crate num_cpus;
|
||||
extern crate rustc_serialize;
|
||||
extern crate toml;
|
||||
|
||||
use std::env;
|
||||
|
||||
use build::{Flags, Config, Build};
|
||||
|
||||
mod build;
|
||||
|
||||
fn main() {
|
||||
let args = env::args().skip(1).collect::<Vec<_>>();
|
||||
let flags = Flags::parse(&args);
|
||||
let mut config = Config::parse(&flags.build, flags.config.clone());
|
||||
if std::fs::metadata("config.mk").is_ok() {
|
||||
config.update_with_config_mk();
|
||||
}
|
||||
Build::new(flags, config).build();
|
||||
}
|
||||
38
src/bootstrap/mk/Makefile.in
Normal file
38
src/bootstrap/mk/Makefile.in
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright 20126 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.
|
||||
|
||||
include config.mk
|
||||
include $(CFG_SRC_DIR)mk/util.mk
|
||||
|
||||
ifdef VERBOSE
|
||||
BOOTSTRAP_ARGS := -v
|
||||
else
|
||||
BOOTSTRAP_ARGS :=
|
||||
endif
|
||||
|
||||
BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py $(BOOTSTRAP_ARGS)
|
||||
|
||||
all:
|
||||
$(Q)$(BOOTSTRAP)
|
||||
|
||||
clean:
|
||||
$(Q)$(BOOTSTRAP) --clean
|
||||
|
||||
docs: doc
|
||||
doc:
|
||||
$(Q)$(BOOTSTRAP) --step doc
|
||||
style:
|
||||
$(Q)$(BOOTSTRAP) --step doc-style
|
||||
nomicon:
|
||||
$(Q)$(BOOTSTRAP) --step doc-nomicon
|
||||
book:
|
||||
$(Q)$(BOOTSTRAP) --step doc-book
|
||||
standalone-docs:
|
||||
$(Q)$(BOOTSTRAP) --step doc-standalone
|
||||
91
src/bootstrap/rustc.rs
Normal file
91
src/bootstrap/rustc.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
extern crate bootstrap;
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
let args = env::args_os().skip(1).collect::<Vec<_>>();
|
||||
// Detect whether or not we're a build script depending on whether --target
|
||||
// is passed (a bit janky...)
|
||||
let is_build_script = args.iter()
|
||||
.position(|i| i.to_str() == Some("--target"))
|
||||
.is_none();
|
||||
|
||||
// Build scripts always use the snapshot compiler which is guaranteed to be
|
||||
// able to produce an executable, whereas intermediate compilers may not
|
||||
// have the standard library built yet and may not be able to produce an
|
||||
// executable. Otherwise we just use the standard compiler we're
|
||||
// bootstrapping with.
|
||||
let rustc = if is_build_script {
|
||||
env::var_os("RUSTC_SNAPSHOT").unwrap()
|
||||
} else {
|
||||
env::var_os("RUSTC_REAL").unwrap()
|
||||
};
|
||||
|
||||
let mut cmd = Command::new(rustc);
|
||||
cmd.args(&args)
|
||||
.arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap()));
|
||||
|
||||
if is_build_script {
|
||||
// Build scripts are always built with the snapshot compiler, so we need
|
||||
// to be sure to set up the right path information for the OS dynamic
|
||||
// linker to find the libraries in question.
|
||||
if let Some(p) = env::var_os("RUSTC_SNAPSHOT_LIBDIR") {
|
||||
let mut path = bootstrap::dylib_path();
|
||||
path.insert(0, PathBuf::from(p));
|
||||
cmd.env(bootstrap::dylib_path_var(), env::join_paths(path).unwrap());
|
||||
}
|
||||
} else {
|
||||
cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").unwrap());
|
||||
|
||||
// When we build Rust dylibs they're all intended for intermediate
|
||||
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
|
||||
// linking all deps statically into the dylib.
|
||||
cmd.arg("-Cprefer-dynamic");
|
||||
|
||||
if let Some(s) = env::var_os("MUSL_ROOT") {
|
||||
let mut root = OsString::from("native=");
|
||||
root.push(&s);
|
||||
root.push("/lib");
|
||||
cmd.arg("-L").arg(&root);
|
||||
}
|
||||
if let Ok(s) = env::var("RUSTC_FLAGS") {
|
||||
cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
|
||||
}
|
||||
}
|
||||
|
||||
// Set various options from config.toml to configure how we're building
|
||||
// code.
|
||||
if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) {
|
||||
cmd.arg("-g");
|
||||
}
|
||||
if env::var("RUSTC_RPATH") == Ok("true".to_string()) {
|
||||
cmd.arg("-Crpath");
|
||||
}
|
||||
let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
|
||||
Ok(s) => if s == "true" {"y"} else {"n"},
|
||||
Err(..) => "n",
|
||||
};
|
||||
cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
|
||||
if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") {
|
||||
cmd.arg("-C").arg(format!("codegen-units={}", s));
|
||||
}
|
||||
|
||||
// Actually run the compiler!
|
||||
std::process::exit(match cmd.status() {
|
||||
Ok(s) => s.code().unwrap_or(1),
|
||||
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
|
||||
})
|
||||
}
|
||||
8
src/build_helper/Cargo.toml
Normal file
8
src/build_helper/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "build_helper"
|
||||
version = "0.1.0"
|
||||
authors = ["The Rust Project Developers"]
|
||||
|
||||
[lib]
|
||||
name = "build_helper"
|
||||
path = "lib.rs"
|
||||
68
src/build_helper/lib.rs
Normal file
68
src/build_helper/lib.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
use std::process::{Command, Stdio};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn run(cmd: &mut Command) {
|
||||
println!("running: {:?}", cmd);
|
||||
run_silent(cmd);
|
||||
}
|
||||
|
||||
pub fn run_silent(cmd: &mut Command) {
|
||||
let status = match cmd.status() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!("failed to execute command: {}", e)),
|
||||
};
|
||||
if !status.success() {
|
||||
fail(&format!("command did not execute successfully: {:?}\n\
|
||||
expected success, got: {}", cmd, status));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gnu_target(target: &str) -> String {
|
||||
match target {
|
||||
"i686-pc-windows-msvc" => "i686-pc-win32".to_string(),
|
||||
"x86_64-pc-windows-msvc" => "x86_64-pc-win32".to_string(),
|
||||
"i686-pc-windows-gnu" => "i686-w64-mingw32".to_string(),
|
||||
"x86_64-pc-windows-gnu" => "x86_64-w64-mingw32".to_string(),
|
||||
s => s.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cc2ar(cc: &Path, target: &str) -> PathBuf {
|
||||
if target.contains("musl") || target.contains("msvc") {
|
||||
PathBuf::from("ar")
|
||||
} else {
|
||||
let file = cc.file_name().unwrap().to_str().unwrap();
|
||||
cc.parent().unwrap().join(file.replace("gcc", "ar")
|
||||
.replace("cc", "ar")
|
||||
.replace("clang", "ar"))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(cmd: &mut Command) -> String {
|
||||
let output = match cmd.stderr(Stdio::inherit()).output() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!("failed to execute command: {}", e)),
|
||||
};
|
||||
if !output.status.success() {
|
||||
panic!("command did not execute successfully: {:?}\n\
|
||||
expected success, got: {}", cmd, output.status);
|
||||
}
|
||||
String::from_utf8(output.stdout).unwrap()
|
||||
}
|
||||
|
||||
fn fail(s: &str) -> ! {
|
||||
println!("\n\n{}\n\n", s);
|
||||
std::process::exit(1);
|
||||
}
|
||||
@ -25,6 +25,7 @@ pub enum Mode {
|
||||
DebugInfoLldb,
|
||||
Codegen,
|
||||
Rustdoc,
|
||||
CodegenUnits
|
||||
}
|
||||
|
||||
impl FromStr for Mode {
|
||||
@ -41,6 +42,7 @@ impl FromStr for Mode {
|
||||
"debuginfo-gdb" => Ok(DebugInfoGdb),
|
||||
"codegen" => Ok(Codegen),
|
||||
"rustdoc" => Ok(Rustdoc),
|
||||
"codegen-units" => Ok(CodegenUnits),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
@ -59,6 +61,7 @@ impl fmt::Display for Mode {
|
||||
DebugInfoLldb => "debuginfo-lldb",
|
||||
Codegen => "codegen",
|
||||
Rustdoc => "rustdoc",
|
||||
CodegenUnits => "codegen-units",
|
||||
}, f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,10 +28,12 @@ extern crate log;
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use getopts::{optopt, optflag, reqopt};
|
||||
use common::Config;
|
||||
use common::{Pretty, DebugInfoGdb, DebugInfoLldb};
|
||||
use test::TestPaths;
|
||||
use util::logv;
|
||||
|
||||
pub mod procsrv;
|
||||
@ -267,15 +269,61 @@ pub fn make_tests(config: &Config) -> Vec<test::TestDescAndFn> {
|
||||
debug!("making tests from {:?}",
|
||||
config.src_base.display());
|
||||
let mut tests = Vec::new();
|
||||
let dirs = fs::read_dir(&config.src_base).unwrap();
|
||||
for file in dirs {
|
||||
let file = file.unwrap().path();
|
||||
debug!("inspecting file {:?}", file.display());
|
||||
if is_test(config, &file) {
|
||||
tests.push(make_test(config, &file))
|
||||
collect_tests_from_dir(config,
|
||||
&config.src_base,
|
||||
&config.src_base,
|
||||
&PathBuf::new(),
|
||||
&mut tests)
|
||||
.unwrap();
|
||||
tests
|
||||
}
|
||||
|
||||
fn collect_tests_from_dir(config: &Config,
|
||||
base: &Path,
|
||||
dir: &Path,
|
||||
relative_dir_path: &Path,
|
||||
tests: &mut Vec<test::TestDescAndFn>)
|
||||
-> io::Result<()> {
|
||||
// Ignore directories that contain a file
|
||||
// `compiletest-ignore-dir`.
|
||||
for file in try!(fs::read_dir(dir)) {
|
||||
let file = try!(file);
|
||||
if file.file_name() == *"compiletest-ignore-dir" {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
tests
|
||||
|
||||
let dirs = try!(fs::read_dir(dir));
|
||||
for file in dirs {
|
||||
let file = try!(file);
|
||||
let file_path = file.path();
|
||||
debug!("inspecting file {:?}", file_path.display());
|
||||
if is_test(config, &file_path) {
|
||||
// If we find a test foo/bar.rs, we have to build the
|
||||
// output directory `$build/foo` so we can write
|
||||
// `$build/foo/bar` into it. We do this *now* in this
|
||||
// sequential loop because otherwise, if we do it in the
|
||||
// tests themselves, they race for the privilege of
|
||||
// creating the directories and sometimes fail randomly.
|
||||
let build_dir = config.build_base.join(&relative_dir_path);
|
||||
fs::create_dir_all(&build_dir).unwrap();
|
||||
|
||||
let paths = TestPaths {
|
||||
file: file_path,
|
||||
base: base.to_path_buf(),
|
||||
relative_dir: relative_dir_path.to_path_buf(),
|
||||
};
|
||||
tests.push(make_test(config, &paths))
|
||||
} else if file_path.is_dir() {
|
||||
let relative_file_path = relative_dir_path.join(file.file_name());
|
||||
try!(collect_tests_from_dir(config,
|
||||
base,
|
||||
&file_path,
|
||||
&relative_file_path,
|
||||
tests));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_test(config: &Config, testfile: &Path) -> bool {
|
||||
@ -305,36 +353,33 @@ pub fn is_test(config: &Config, testfile: &Path) -> bool {
|
||||
return valid;
|
||||
}
|
||||
|
||||
pub fn make_test(config: &Config, testfile: &Path) -> test::TestDescAndFn
|
||||
{
|
||||
pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn {
|
||||
test::TestDescAndFn {
|
||||
desc: test::TestDesc {
|
||||
name: make_test_name(config, testfile),
|
||||
ignore: header::is_test_ignored(config, testfile),
|
||||
name: make_test_name(config, testpaths),
|
||||
ignore: header::is_test_ignored(config, &testpaths.file),
|
||||
should_panic: test::ShouldPanic::No,
|
||||
},
|
||||
testfn: make_test_closure(config, &testfile),
|
||||
testfn: make_test_closure(config, testpaths),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_test_name(config: &Config, testfile: &Path) -> test::TestName {
|
||||
|
||||
// Try to elide redundant long paths
|
||||
fn shorten(path: &Path) -> String {
|
||||
let filename = path.file_name().unwrap().to_str();
|
||||
let p = path.parent().unwrap();
|
||||
let dir = p.file_name().unwrap().to_str();
|
||||
format!("{}/{}", dir.unwrap_or(""), filename.unwrap_or(""))
|
||||
}
|
||||
|
||||
test::DynTestName(format!("[{}] {}", config.mode, shorten(testfile)))
|
||||
pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName {
|
||||
// Convert a complete path to something like
|
||||
//
|
||||
// run-pass/foo/bar/baz.rs
|
||||
let path =
|
||||
PathBuf::from(config.mode.to_string())
|
||||
.join(&testpaths.relative_dir)
|
||||
.join(&testpaths.file.file_name().unwrap());
|
||||
test::DynTestName(format!("[{}] {}", config.mode, path.display()))
|
||||
}
|
||||
|
||||
pub fn make_test_closure(config: &Config, testfile: &Path) -> test::TestFn {
|
||||
let config = (*config).clone();
|
||||
let testfile = testfile.to_path_buf();
|
||||
pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn {
|
||||
let config = config.clone();
|
||||
let testpaths = testpaths.clone();
|
||||
test::DynTestFn(Box::new(move || {
|
||||
runtest::run(config, &testfile)
|
||||
runtest::run(config, &testpaths)
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,8 @@ const OS_TABLE: &'static [(&'static str, &'static str)] = &[
|
||||
("openbsd", "openbsd"),
|
||||
("win32", "windows"),
|
||||
("windows", "windows"),
|
||||
("solaris", "solaris"),
|
||||
("emscripten", "emscripten"),
|
||||
];
|
||||
|
||||
const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
|
||||
@ -39,11 +41,11 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
|
||||
("msp430", "msp430"),
|
||||
("powerpc", "powerpc"),
|
||||
("powerpc64", "powerpc64"),
|
||||
("powerpc64le", "powerpc64le"),
|
||||
("s390x", "systemz"),
|
||||
("sparc", "sparc"),
|
||||
("x86_64", "x86_64"),
|
||||
("xcore", "xcore"),
|
||||
("asmjs", "asmjs"),
|
||||
];
|
||||
|
||||
pub fn get_os(triple: &str) -> &'static str {
|
||||
|
||||
@ -80,3 +80,4 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
|
||||
Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
|
||||
Munksgaard's master's thesis. Research for Servo.
|
||||
* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf)
|
||||
* [You can't spell trust without Rust](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf). Alexis Beingessner's master's thesis.
|
||||
|
||||
@ -259,7 +259,7 @@ thread::spawn(move || {
|
||||
```
|
||||
|
||||
First, we call `lock()`, which acquires the mutex's lock. Because this may fail,
|
||||
it returns an `Result<T, E>`, and because this is just an example, we `unwrap()`
|
||||
it returns a `Result<T, E>`, and because this is just an example, we `unwrap()`
|
||||
it to get a reference to the data. Real code would have more robust error handling
|
||||
here. We're then free to mutate it, since we have the lock.
|
||||
|
||||
@ -286,6 +286,8 @@ use std::sync::mpsc;
|
||||
fn main() {
|
||||
let data = Arc::new(Mutex::new(0));
|
||||
|
||||
// `tx` is the "transmitter" or "sender"
|
||||
// `rx` is the "receiver"
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
for _ in 0..10 {
|
||||
|
||||
@ -64,16 +64,16 @@ unsafe {
|
||||
|
||||
[unsafe]: unsafe.html
|
||||
|
||||
Furthermore, any type stored in a `static` must be `Sync`, and may not have
|
||||
Furthermore, any type stored in a `static` must be `Sync`, and must not have
|
||||
a [`Drop`][drop] implementation.
|
||||
|
||||
[drop]: drop.html
|
||||
|
||||
# Initializing
|
||||
|
||||
Both `const` and `static` have requirements for giving them a value. They may
|
||||
only be given a value that’s a constant expression. In other words, you cannot
|
||||
use the result of a function call or anything similarly complex or at runtime.
|
||||
Both `const` and `static` have requirements for giving them a value. They must
|
||||
be given a value that’s a constant expression. In other words, you cannot use
|
||||
the result of a function call or anything similarly complex or at runtime.
|
||||
|
||||
# Which construct should I use?
|
||||
|
||||
|
||||
@ -567,10 +567,11 @@ to it as "sayings". Similarly, the first `use` statement pulls in the
|
||||
`ja_greetings` as opposed to simply `greetings`. This can help to avoid
|
||||
ambiguity when importing similarly-named items from different places.
|
||||
|
||||
The second `use` statement uses a star glob to bring in _all_ symbols from the
|
||||
`sayings::japanese::farewells` module. As you can see we can later refer to
|
||||
The second `use` statement uses a star glob to bring in all public symbols from
|
||||
the `sayings::japanese::farewells` module. As you can see we can later refer to
|
||||
the Japanese `goodbye` function with no module qualifiers. This kind of glob
|
||||
should be used sparingly.
|
||||
should be used sparingly. It’s worth noting that it only imports the public
|
||||
symbols, even if the code doing the globbing is in the same module.
|
||||
|
||||
The third `use` statement bears more explanation. It's using "brace expansion"
|
||||
globbing to compress three `use` statements into one (this sort of syntax
|
||||
|
||||
@ -118,7 +118,7 @@ least. If your function has a non-trivial contract like this, that is
|
||||
detected/enforced by panics, documenting it is very important.
|
||||
|
||||
```rust
|
||||
/// # Failures
|
||||
/// # Errors
|
||||
# fn foo() {}
|
||||
```
|
||||
|
||||
@ -319,7 +319,7 @@ our source code:
|
||||
```text
|
||||
First, we set `x` to five:
|
||||
|
||||
```text
|
||||
```rust
|
||||
let x = 5;
|
||||
# let y = 6;
|
||||
# println!("{}", x + y);
|
||||
@ -327,7 +327,7 @@ our source code:
|
||||
|
||||
Next, we set `y` to six:
|
||||
|
||||
```text
|
||||
```rust
|
||||
# let x = 5;
|
||||
let y = 6;
|
||||
# println!("{}", x + y);
|
||||
@ -335,7 +335,7 @@ our source code:
|
||||
|
||||
Finally, we print the sum of `x` and `y`:
|
||||
|
||||
```text
|
||||
```rust
|
||||
# let x = 5;
|
||||
# let y = 6;
|
||||
println!("{}", x + y);
|
||||
|
||||
@ -265,6 +265,8 @@ fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
|
||||
```
|
||||
|
||||
Indeed, `map` is [defined as a method][2] on `Option<T>` in the standard library.
|
||||
As a method, it has a slightly different signature: methods take `self`, `&self`,
|
||||
or `&mut self` as their first argument.
|
||||
|
||||
Armed with our new combinator, we can rewrite our `extension_explicit` method
|
||||
to get rid of the case analysis:
|
||||
@ -294,6 +296,9 @@ fn unwrap_or<T>(option: Option<T>, default: T) -> T {
|
||||
}
|
||||
```
|
||||
|
||||
Like with `map` above, the standard library implementation is a method instead
|
||||
of a free function.
|
||||
|
||||
The trick here is that the default value must have the same type as the value
|
||||
that might be inside the `Option<T>`. Using it is dead simple in our case:
|
||||
|
||||
@ -351,11 +356,28 @@ fn file_name(file_path: &str) -> Option<&str> {
|
||||
```
|
||||
|
||||
You might think that we could use the `map` combinator to reduce the case
|
||||
analysis, but its type doesn't quite fit. Namely, `map` takes a function that
|
||||
does something only with the inner value. The result of that function is then
|
||||
*always* [rewrapped with `Some`](#code-option-map). Instead, we need something
|
||||
like `map`, but which allows the caller to return another `Option`. Its generic
|
||||
implementation is even simpler than `map`:
|
||||
analysis, but its type doesn't quite fit...
|
||||
|
||||
```rust,ignore
|
||||
fn file_path_ext(file_path: &str) -> Option<&str> {
|
||||
file_name(file_path).map(|x| extension(x)) //Compilation error
|
||||
}
|
||||
```
|
||||
|
||||
The `map` function here wraps the value returned by the `extension` function
|
||||
inside an `Option<_>` and since the `extension` function itself returns an
|
||||
`Option<&str>` the expression `file_name(file_path).map(|x| extension(x))`
|
||||
actually returns an `Option<Option<&str>>`.
|
||||
|
||||
But since `file_path_ext` just returns `Option<&str>` (and not
|
||||
`Option<Option<&str>>`) we get a compilation error.
|
||||
|
||||
The result of the function taken by map as input is *always* [rewrapped with
|
||||
`Some`](#code-option-map). Instead, we need something like `map`, but which
|
||||
allows the caller to return a `Option<_>` directly without wrapping it in
|
||||
another `Option<_>`.
|
||||
|
||||
Its generic implementation is even simpler than `map`:
|
||||
|
||||
```rust
|
||||
fn and_then<F, T, A>(option: Option<T>, f: F) -> Option<A>
|
||||
@ -377,6 +399,10 @@ fn file_path_ext(file_path: &str) -> Option<&str> {
|
||||
}
|
||||
```
|
||||
|
||||
Side note: Since `and_then` essentially works like `map` but returns an
|
||||
`Option<_>` instead of an `Option<Option<_>>` it is known as `flatmap` in some
|
||||
other languages.
|
||||
|
||||
The `Option` type has many other combinators [defined in the standard
|
||||
library][5]. It is a good idea to skim this list and familiarize
|
||||
yourself with what's available—they can often reduce case analysis
|
||||
@ -1512,7 +1538,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
|
||||
|
||||
We're not going to spend a lot of time on setting up a project with
|
||||
Cargo because it is already covered well in [the Cargo
|
||||
section](../book/hello-cargo.html) and [Cargo's documentation][14].
|
||||
section](getting-started.html#hello-cargo) and [Cargo's documentation][14].
|
||||
|
||||
To get started from scratch, run `cargo new --bin city-pop` and make sure your
|
||||
`Cargo.toml` looks something like this:
|
||||
@ -1566,7 +1592,7 @@ fn print_usage(program: &str, opts: Options) {
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let program = args[0].clone();
|
||||
let program = &args[0];
|
||||
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("h", "help", "Show this usage message.");
|
||||
@ -1579,10 +1605,10 @@ fn main() {
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
let data_path = args[1].clone();
|
||||
let city = args[2].clone();
|
||||
let data_path = &args[1];
|
||||
let city = &args[2];
|
||||
|
||||
// Do stuff with information
|
||||
// Do stuff with information
|
||||
}
|
||||
```
|
||||
|
||||
@ -1614,7 +1640,6 @@ sure to add `extern crate csv;` to the top of your file.)
|
||||
|
||||
```rust,ignore
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
// This struct represents the data in each row of the CSV file.
|
||||
// Type based decoding absolves us of a lot of the nitty gritty error
|
||||
@ -1640,7 +1665,7 @@ fn print_usage(program: &str, opts: Options) {
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let program = args[0].clone();
|
||||
let program = &args[0];
|
||||
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("h", "help", "Show this usage message.");
|
||||
@ -1652,25 +1677,24 @@ fn main() {
|
||||
|
||||
if matches.opt_present("h") {
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let data_file = args[1].clone();
|
||||
let data_path = Path::new(&data_file);
|
||||
let city = args[2].clone();
|
||||
let data_path = &args[1];
|
||||
let city: &str = &args[2];
|
||||
|
||||
let file = File::open(data_path).unwrap();
|
||||
let mut rdr = csv::Reader::from_reader(file);
|
||||
let file = File::open(data_path).unwrap();
|
||||
let mut rdr = csv::Reader::from_reader(file);
|
||||
|
||||
for row in rdr.decode::<Row>() {
|
||||
let row = row.unwrap();
|
||||
for row in rdr.decode::<Row>() {
|
||||
let row = row.unwrap();
|
||||
|
||||
if row.city == city {
|
||||
println!("{}, {}: {:?}",
|
||||
row.city, row.country,
|
||||
row.population.expect("population count"));
|
||||
}
|
||||
}
|
||||
if row.city == city {
|
||||
println!("{}, {}: {:?}",
|
||||
row.city, row.country,
|
||||
row.population.expect("population count"));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -1719,6 +1743,8 @@ Note that we opt to handle the possibility of a missing population count by
|
||||
simply ignoring that row.
|
||||
|
||||
```rust,ignore
|
||||
use std::path::Path;
|
||||
|
||||
struct Row {
|
||||
// unchanged
|
||||
}
|
||||
@ -1756,27 +1782,26 @@ fn search<P: AsRef<Path>>(file_path: P, city: &str) -> Vec<PopulationCount> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let program = args[0].clone();
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let program = &args[0];
|
||||
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("h", "help", "Show this usage message.");
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("h", "help", "Show this usage message.");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => { m }
|
||||
Err(e) => { panic!(e.to_string()) }
|
||||
};
|
||||
if matches.opt_present("h") {
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => { m }
|
||||
Err(e) => { panic!(e.to_string()) }
|
||||
};
|
||||
if matches.opt_present("h") {
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
||||
let data_file = args[1].clone();
|
||||
let data_path = Path::new(&data_file);
|
||||
let city = args[2].clone();
|
||||
for pop in search(&data_path, &city) {
|
||||
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
|
||||
}
|
||||
let data_path = &args[1];
|
||||
let city = &args[2];
|
||||
for pop in search(data_path, city) {
|
||||
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
@ -1886,7 +1911,7 @@ First, here's the new usage:
|
||||
|
||||
```rust,ignore
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
println!("{}", opts.usage(&format!("Usage: {} [options] <city>", program)));
|
||||
println!("{}", opts.usage(&format!("Usage: {} [options] <city>", program)));
|
||||
}
|
||||
```
|
||||
The next part is going to be only a little harder:
|
||||
@ -1898,16 +1923,16 @@ opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"
|
||||
opts.optflag("h", "help", "Show this usage message.");
|
||||
...
|
||||
let file = matches.opt_str("f");
|
||||
let data_file = file.as_ref().map(Path::new);
|
||||
let data_file = &file.as_ref().map(Path::new);
|
||||
|
||||
let city = if !matches.free.is_empty() {
|
||||
matches.free[0].clone()
|
||||
&matches.free[0]
|
||||
} else {
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
};
|
||||
|
||||
match search(&data_file, &city) {
|
||||
match search(data_file, city) {
|
||||
Ok(pops) => {
|
||||
for pop in pops {
|
||||
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
|
||||
|
||||
@ -68,7 +68,7 @@ You get this error:
|
||||
|
||||
```text
|
||||
expected one of `!`, `:`, or `@`, found `)`
|
||||
fn print_number(x, y) {
|
||||
fn print_sum(x, y) {
|
||||
```
|
||||
|
||||
This is a deliberate design decision. While full-program inference is possible,
|
||||
|
||||
@ -39,6 +39,7 @@ Specifically they will each satisfy the following requirements:
|
||||
|
||||
| Target | std |rustc|cargo| notes |
|
||||
|-------------------------------|-----|-----|-----|----------------------------|
|
||||
| `i686-pc-windows-msvc` | ✓ | ✓ | ✓ | 32-bit MSVC (Windows 7+) |
|
||||
| `x86_64-pc-windows-msvc` | ✓ | ✓ | ✓ | 64-bit MSVC (Windows 7+) |
|
||||
| `i686-pc-windows-gnu` | ✓ | ✓ | ✓ | 32-bit MinGW (Windows 7+) |
|
||||
| `x86_64-pc-windows-gnu` | ✓ | ✓ | ✓ | 64-bit MinGW (Windows 7+) |
|
||||
@ -62,7 +63,6 @@ these platforms are required to have each of the following:
|
||||
|
||||
| Target | std |rustc|cargo| notes |
|
||||
|-------------------------------|-----|-----|-----|----------------------------|
|
||||
| `i686-pc-windows-msvc` | ✓ | ✓ | ✓ | 32-bit MSVC (Windows 7+) |
|
||||
| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL |
|
||||
| `arm-linux-androideabi` | ✓ | | | ARM Android |
|
||||
| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) |
|
||||
@ -85,6 +85,9 @@ unofficial locations.
|
||||
| `i686-linux-android` | ✓ | | | 32-bit x86 Android |
|
||||
| `aarch64-linux-android` | ✓ | | | ARM64 Android |
|
||||
| `powerpc-unknown-linux-gnu` | ✓ | | | PowerPC Linux (2.6.18+) |
|
||||
| `powerpc64-unknown-linux-gnu` | ✓ | | | PPC64 Linux (2.6.18+) |
|
||||
|`powerpc64le-unknown-linux-gnu`| ✓ | | | PPC64LE Linux (2.6.18+) |
|
||||
|`armv7-unknown-linux-gnueabihf`| ✓ | | | ARMv7 Linux (2.6.18+) |
|
||||
| `i386-apple-ios` | ✓ | | | 32-bit x86 iOS |
|
||||
| `x86_64-apple-ios` | ✓ | | | 64-bit x86 iOS |
|
||||
| `armv7-apple-ios` | ✓ | | | ARM iOS |
|
||||
@ -97,6 +100,7 @@ unofficial locations.
|
||||
| `x86_64-unknown-bitrig` | ✓ | ✓ | | 64-bit Bitrig |
|
||||
| `x86_64-unknown-dragonfly` | ✓ | ✓ | | 64-bit DragonFlyBSD |
|
||||
| `x86_64-rumprun-netbsd` | ✓ | | | 64-bit NetBSD Rump Kernel |
|
||||
| `x86_64-sun-solaris` | ✓ | ✓ | | 64-bit Solaris/SunOS |
|
||||
| `i686-pc-windows-msvc` (XP) | ✓ | | | Windows XP support |
|
||||
| `x86_64-pc-windows-msvc` (XP) | ✓ | | | Windows XP support |
|
||||
|
||||
@ -111,7 +115,7 @@ If we're on Linux or a Mac, all we need to do is open a terminal and type this:
|
||||
$ curl -sSf https://static.rust-lang.org/rustup.sh | sh
|
||||
```
|
||||
|
||||
This will download a script, and stat the installation. If it all goes well,
|
||||
This will download a script, and start the installation. If it all goes well,
|
||||
you’ll see this appear:
|
||||
|
||||
```text
|
||||
@ -167,6 +171,10 @@ variable. If it isn't, run the installer again, select "Change" on the "Change,
|
||||
repair, or remove installation" page and ensure "Add to PATH" is installed on
|
||||
the local hard drive.
|
||||
|
||||
Rust does not do its own linking, and so you’ll need to have a linker
|
||||
installed. Doing so will depend on your specific system, consult its
|
||||
documentation for more details.
|
||||
|
||||
If not, there are a number of places where we can get help. The easiest is
|
||||
[the #rust IRC channel on irc.mozilla.org][irc], which we can access through
|
||||
[Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans
|
||||
@ -511,15 +519,17 @@ programming languages. For complex projects composed of multiple crates, it’s
|
||||
much easier to let Cargo coordinate the build. Using Cargo, you can run `cargo
|
||||
build`, and it should work the right way.
|
||||
|
||||
## Building for Release
|
||||
### Building for Release
|
||||
|
||||
When your project is finally ready for release, you can use `cargo build
|
||||
When your project is ready for release, you can use `cargo build
|
||||
--release` to compile your project with optimizations. These optimizations make
|
||||
your Rust code run faster, but turning them on makes your program take longer
|
||||
to compile. This is why there are two different profiles, one for development,
|
||||
and one for building the final program you’ll give to a user.
|
||||
|
||||
Running this command also causes Cargo to create a new file called
|
||||
### What Is That `Cargo.lock`?
|
||||
|
||||
Running `cargo build` also causes Cargo to create a new file called
|
||||
*Cargo.lock*, which looks like this:
|
||||
|
||||
```toml
|
||||
@ -563,7 +573,7 @@ executable application, as opposed to a library. Executables are often called
|
||||
*binaries* (as in `/usr/bin`, if you’re on a Unix system).
|
||||
|
||||
Cargo has generated two files and one directory for us: a `Cargo.toml` and a
|
||||
*src* directory with a *main.rs* file inside. These should look familliar,
|
||||
*src* directory with a *main.rs* file inside. These should look familiar,
|
||||
they’re exactly what we created by hand, above.
|
||||
|
||||
This output is all you need to get started. First, open `Cargo.toml`. It should
|
||||
@ -602,11 +612,11 @@ This chapter covered the basics that will serve you well through the rest of
|
||||
this book, and the rest of your time with Rust. Now that you’ve got the tools
|
||||
down, we'll cover more about the Rust language itself.
|
||||
|
||||
You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or
|
||||
You have two options: Dive into a project with ‘[Tutorial: Guessing Game][guessinggame]’, or
|
||||
start from the bottom and work your way up with ‘[Syntax and
|
||||
Semantics][syntax]’. More experienced systems programmers will probably prefer
|
||||
‘Learn Rust’, while those from dynamic backgrounds may enjoy either. Different
|
||||
‘Tutorial: Guessing Game’, while those from dynamic backgrounds may enjoy either. Different
|
||||
people learn differently! Choose whatever’s right for you.
|
||||
|
||||
[learnrust]: learn-rust.html
|
||||
[guessinggame]: guessing-game.html
|
||||
[syntax]: syntax-and-semantics.html
|
||||
|
||||
@ -258,7 +258,7 @@ done:
|
||||
io::stdin().read_line(&mut guess).expect("failed to read line");
|
||||
```
|
||||
|
||||
But that gets hard to read. So we’ve split it up, three lines for three method
|
||||
But that gets hard to read. So we’ve split it up, two lines for two method
|
||||
calls. We already talked about `read_line()`, but what about `expect()`? Well,
|
||||
we already mentioned that `read_line()` puts what the user types into the `&mut
|
||||
String` we pass it. But it also returns a value: in this case, an
|
||||
@ -276,10 +276,10 @@ it’s called on, and if it isn’t a successful one, [`panic!`][panic]s with a
|
||||
message you passed it. A `panic!` like this will cause our program to crash,
|
||||
displaying the message.
|
||||
|
||||
[expect]: ../std/option/enum.Option.html#method.expect
|
||||
[expect]: ../std/result/enum.Result.html#method.expect
|
||||
[panic]: error-handling.html
|
||||
|
||||
If we leave off calling these two methods, our program will compile, but
|
||||
If we leave off calling this method, our program will compile, but
|
||||
we’ll get a warning:
|
||||
|
||||
```bash
|
||||
@ -644,7 +644,7 @@ So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
|
||||
Rust doesn’t know how to compare the `guess` and the `secret_number`. They
|
||||
need to be the same type. Ultimately, we want to convert the `String` we
|
||||
read as input into a real number type, for comparison. We can do that
|
||||
with three more lines. Here’s our new program:
|
||||
with two more lines. Here’s our new program:
|
||||
|
||||
```rust,ignore
|
||||
extern crate rand;
|
||||
@ -680,7 +680,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
The new three lines:
|
||||
The new two lines:
|
||||
|
||||
```rust,ignore
|
||||
let guess: u32 = guess.trim().parse()
|
||||
@ -906,16 +906,17 @@ let guess: u32 = match guess.trim().parse() {
|
||||
Err(_) => continue,
|
||||
};
|
||||
```
|
||||
|
||||
This is how you generally move from ‘crash on error’ to ‘actually handle the
|
||||
returned by `parse()` is an `enum` like `Ordering`, but in this case, each
|
||||
variant has some data associated with it: `Ok` is a success, and `Err` is a
|
||||
error’, by switching from `expect()` to a `match` statement. A `Result` is
|
||||
returned by `parse()`, this is an `enum` like `Ordering`, but in this case,
|
||||
each variant has some data associated with it: `Ok` is a success, and `Err` is a
|
||||
failure. Each contains more information: the successfully parsed integer, or an
|
||||
error type. In this case, we `match` on `Ok(num)`, which sets the inner value
|
||||
of the `Ok` to the name `num`, and then we return it on the right-hand
|
||||
side. In the `Err` case, we don’t care what kind of error it is, so we
|
||||
use `_` instead of a name. This ignores the error, and `continue` causes us
|
||||
to go to the next iteration of the `loop`.
|
||||
error type. In this case, we `match` on `Ok(num)`, which sets the name `num` to
|
||||
the unwrapped `Ok` value (ythe integer), and then we return it on the
|
||||
right-hand side. In the `Err` case, we don’t care what kind of error it is, so
|
||||
we just use the catch all `_` instead of a name. This catches everything that
|
||||
isn't `Ok`, and `continue` lets us move to the next iteration of the loop; in
|
||||
effect, this enables us to ignore all errors and continue with our program.
|
||||
|
||||
Now we should be good! Let’s try:
|
||||
|
||||
|
||||
@ -311,10 +311,12 @@ for i in (1..100).filter(|&x| x % 2 == 0) {
|
||||
```
|
||||
|
||||
This will print all of the even numbers between one and a hundred.
|
||||
(Note that because `filter` doesn't consume the elements that are
|
||||
being iterated over, it is passed a reference to each element, and
|
||||
thus the filter predicate uses the `&x` pattern to extract the integer
|
||||
itself.)
|
||||
(Note that, unlike `map`, the closure passed to `filter` is passed a reference
|
||||
to the element instead of the element itself. The filter predicate here uses
|
||||
the `&x` pattern to extract the integer. The filter closure is passed a
|
||||
reference because it returns `true` or `false` instead of the element,
|
||||
so the `filter` implementation must retain ownership to put the elements
|
||||
into the newly constructed iterator.)
|
||||
|
||||
You can chain all three things together: start with an iterator, adapt it
|
||||
a few times, and then consume the result. Check it out:
|
||||
|
||||
@ -39,11 +39,17 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
|
||||
|
||||
p
|
||||
}
|
||||
|
||||
#[lang = "exchange_free"]
|
||||
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
|
||||
libc::free(ptr as *mut libc::c_void)
|
||||
}
|
||||
|
||||
#[lang = "box_free"]
|
||||
unsafe fn box_free<T>(ptr: *mut T) {
|
||||
deallocate(ptr as *mut u8, ::core::mem::size_of::<T>(), ::core::mem::align_of::<T>());
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(argc: isize, argv: *const *const u8) -> isize {
|
||||
let x = box 1;
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
% Learn Rust
|
||||
|
||||
Welcome! This chapter has a few tutorials that teach you Rust through building
|
||||
projects. You’ll get a high-level overview, but we’ll skim over the details.
|
||||
|
||||
If you’d prefer a more ‘from the ground up’-style experience, check
|
||||
out [Syntax and Semantics][ss].
|
||||
|
||||
[ss]: syntax-and-semantics.html
|
||||
@ -125,7 +125,8 @@ Don't forget to add the parentheses around the range.
|
||||
#### On iterators:
|
||||
|
||||
```rust
|
||||
# let lines = "hello\nworld".lines();
|
||||
let lines = "hello\nworld".lines();
|
||||
|
||||
for (linenumber, line) in lines.enumerate() {
|
||||
println!("{}: {}", linenumber, line);
|
||||
}
|
||||
@ -134,10 +135,8 @@ for (linenumber, line) in lines.enumerate() {
|
||||
Outputs:
|
||||
|
||||
```text
|
||||
0: Content of line one
|
||||
1: Content of line two
|
||||
2: Content of line three
|
||||
3: Content of line four
|
||||
0: hello
|
||||
1: world
|
||||
```
|
||||
|
||||
## Ending iteration early
|
||||
@ -195,7 +194,7 @@ for x in 0..10 {
|
||||
You may also encounter situations where you have nested loops and need to
|
||||
specify which one your `break` or `continue` statement is for. Like most
|
||||
other languages, by default a `break` or `continue` will apply to innermost
|
||||
loop. In a situation where you would like to a `break` or `continue` for one
|
||||
loop. In a situation where you would like to `break` or `continue` for one
|
||||
of the outer loops, you can use labels to specify which loop the `break` or
|
||||
`continue` statement applies to. This will only print when both `x` and `y` are
|
||||
odd:
|
||||
|
||||
@ -77,10 +77,11 @@ The compiler currently makes a few assumptions about symbols which are available
|
||||
in the executable to call. Normally these functions are provided by the standard
|
||||
library, but without it you must define your own.
|
||||
|
||||
The first of these two functions, `eh_personality`, is used by the
|
||||
failure mechanisms of the compiler. This is often mapped to GCC's
|
||||
personality function (see the
|
||||
[libstd implementation](../std/rt/unwind/index.html) for more
|
||||
information), but crates which do not trigger a panic can be assured
|
||||
that this function is never called. The second function, `panic_fmt`, is
|
||||
also used by the failure mechanisms of the compiler.
|
||||
The first of these two functions, `eh_personality`, is used by the failure
|
||||
mechanisms of the compiler. This is often mapped to GCC's personality function
|
||||
(see the [libstd implementation][unwind] for more information), but crates
|
||||
which do not trigger a panic can be assured that this function is never
|
||||
called. The second function, `panic_fmt`, is also used by the failure
|
||||
mechanisms of the compiler.
|
||||
|
||||
[unwind]: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/unwind/gcc.rs
|
||||
|
||||
@ -51,10 +51,11 @@ fn foo() {
|
||||
}
|
||||
```
|
||||
|
||||
When `v` comes into scope, a new [vector] is created, and it allocates space on
|
||||
[the heap][heap] for each of its elements. When `v` goes out of scope at the
|
||||
end of `foo()`, Rust will clean up everything related to the vector, even the
|
||||
heap-allocated memory. This happens deterministically, at the end of the scope.
|
||||
When `v` comes into scope, a new [vector] is created on [the stack][stack],
|
||||
and it allocates space on [the heap][heap] for its elements. When `v` goes out
|
||||
of scope at the end of `foo()`, Rust will clean up everything related to the
|
||||
vector, even the heap-allocated memory. This happens deterministically, at the
|
||||
end of the scope.
|
||||
|
||||
We'll cover [vectors] in detail later in this chapter; we only use them
|
||||
here as an example of a type that allocates space on the heap at runtime. They
|
||||
@ -67,6 +68,7 @@ Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will ha
|
||||
[arrays]: primitive-types.html#arrays
|
||||
[vectors]: vectors.html
|
||||
[heap]: the-stack-and-the-heap.html
|
||||
[stack]: the-stack-and-the-heap.html#the-stack
|
||||
[bindings]: variable-bindings.html
|
||||
[generics]: generics.html
|
||||
|
||||
@ -122,21 +124,65 @@ special annotation here, it’s the default thing that Rust does.
|
||||
## The details
|
||||
|
||||
The reason that we cannot use a binding after we’ve moved it is subtle, but
|
||||
important. When we write code like this:
|
||||
important.
|
||||
|
||||
When we write code like this:
|
||||
|
||||
```rust
|
||||
let x = 10;
|
||||
```
|
||||
|
||||
Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit
|
||||
pattern representing the value of 10 to the allocated memory and binds the
|
||||
variable name x to this memory region for future reference.
|
||||
|
||||
Now consider the following code fragment:
|
||||
|
||||
```rust
|
||||
let v = vec![1, 2, 3];
|
||||
|
||||
let v2 = v;
|
||||
let mut v2 = v;
|
||||
```
|
||||
|
||||
The first line allocates memory for the vector object, `v`, and for the data it
|
||||
contains. The vector object is stored on the [stack][sh] and contains a pointer
|
||||
to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`,
|
||||
it creates a copy of that pointer, for `v2`. Which means that there would be two
|
||||
pointers to the content of the vector on the heap. It would violate Rust’s
|
||||
safety guarantees by introducing a data race. Therefore, Rust forbids using `v`
|
||||
after we’ve done the move.
|
||||
The first line allocates memory for the vector object `v` on the stack like
|
||||
it does for `x` above. But in addition to that it also allocates some memory
|
||||
on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address
|
||||
of this heap allocation to an internal pointer, which is part of the vector
|
||||
object placed on the stack (let's call it the data pointer).
|
||||
|
||||
It is worth pointing out (even at the risk of stating the obvious) that the
|
||||
vector object and its data live in separate memory regions instead of being a
|
||||
single contiguous memory allocation (due to reasons we will not go into at
|
||||
this point of time). These two parts of the vector (the one on the stack and
|
||||
one on the heap) must agree with each other at all times with regards to
|
||||
things like the length, capacity etc.
|
||||
|
||||
When we move `v` to `v2`, Rust actually does a bitwise copy of the vector
|
||||
object `v` into the stack allocation represented by `v2`. This shallow copy
|
||||
does not create a copy of the heap allocation containing the actual data.
|
||||
Which means that there would be two pointers to the contents of the vector
|
||||
both pointing to the same memory allocation on the heap. It would violate
|
||||
Rust’s safety guarantees by introducing a data race if one could access both
|
||||
`v` and `v2` at the same time.
|
||||
|
||||
For example if we truncated the vector to just two elements through `v2`:
|
||||
|
||||
```rust
|
||||
# let v = vec![1, 2, 3];
|
||||
# let mut v2 = v;
|
||||
v2.truncate(2);
|
||||
```
|
||||
|
||||
and `v1` were still accessible we'd end up with an invalid vector since `v1`
|
||||
would not know that the heap data has been truncated. Now, the part of the
|
||||
vector `v1` on the stack does not agree with the corresponding part on the
|
||||
heap. `v1` still thinks there are three elements in the vector and will
|
||||
happily let us access the non existent element `v1[2]` but as you might
|
||||
already know this is a recipe for disaster. Especially because it might lead
|
||||
to a segmentation fault or worse allow an unauthorized user to read from
|
||||
memory to which they don't have access.
|
||||
|
||||
This is why Rust forbids using `v` after we’ve done the move.
|
||||
|
||||
[sh]: the-stack-and-the-heap.html
|
||||
|
||||
|
||||
@ -173,7 +173,39 @@ let (x, _, z) = coordinate();
|
||||
Here, we bind the first and last element of the tuple to `x` and `z`, but
|
||||
ignore the middle element.
|
||||
|
||||
Similarly, you can use `..` in a pattern to disregard multiple values.
|
||||
It’s worth noting that using `_` never binds the value in the first place,
|
||||
which means a value may not move:
|
||||
|
||||
```rust
|
||||
let tuple: (u32, String) = (5, String::from("five"));
|
||||
|
||||
// Here, tuple is moved, because the String moved:
|
||||
let (x, _s) = tuple;
|
||||
|
||||
// The next line would give "error: use of partially moved value: `tuple`"
|
||||
// println!("Tuple is: {:?}", tuple);
|
||||
|
||||
// However,
|
||||
|
||||
let tuple = (5, String::from("five"));
|
||||
|
||||
// Here, tuple is _not_ moved, as the String was never moved, and u32 is Copy:
|
||||
let (x, _) = tuple;
|
||||
|
||||
// That means this works:
|
||||
println!("Tuple is: {:?}", tuple);
|
||||
```
|
||||
|
||||
This also means that any temporary variables will be dropped at the end of the
|
||||
statement:
|
||||
|
||||
```rust
|
||||
// Here, the String created will be dropped immediately, as it’s not bound:
|
||||
|
||||
let _ = String::from(" hello ").trim();
|
||||
```
|
||||
|
||||
You can also use `..` in a pattern to disregard multiple values:
|
||||
|
||||
```rust
|
||||
enum OptionalTuple {
|
||||
@ -271,7 +303,7 @@ struct Person {
|
||||
}
|
||||
|
||||
let name = "Steve".to_string();
|
||||
let mut x: Option<Person> = Some(Person { name: Some(name) });
|
||||
let x: Option<Person> = Some(Person { name: Some(name) });
|
||||
match x {
|
||||
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
|
||||
_ => {}
|
||||
|
||||
@ -164,6 +164,9 @@ copying. For example, you might want to reference only one line of a file read
|
||||
into memory. By nature, a slice is not created directly, but from an existing
|
||||
variable binding. Slices have a defined length, can be mutable or immutable.
|
||||
|
||||
Internally, slices are represented as a pointer to the beginning of the data
|
||||
and a length.
|
||||
|
||||
## Slicing syntax
|
||||
|
||||
You can use a combo of `&` and `[]` to create a slice from various things. The
|
||||
|
||||
@ -39,7 +39,7 @@ The second, with a `\`, trims the spaces and the newline:
|
||||
|
||||
```rust
|
||||
let s = "foo\
|
||||
bar";
|
||||
bar";
|
||||
|
||||
assert_eq!("foobar", s);
|
||||
```
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
## Keywords
|
||||
|
||||
* `as`: primitive casting. See [Casting Between Types (`as`)].
|
||||
* `as`: primitive casting, or disambiguating the specific trait containing an item. See [Casting Between Types (`as`)], [Universal Function Call Syntax (Angle-bracket Form)], [Associated Types].
|
||||
* `break`: break out of loop. See [Loops (Ending Iteration Early)].
|
||||
* `const`: constant items and constant raw pointers. See [`const` and `static`], [Raw Pointers].
|
||||
* `continue`: continue to next loop iteration. See [Loops (Ending Iteration Early)].
|
||||
@ -115,8 +115,11 @@
|
||||
* `::path`: path relative to the crate root (*i.e.* an explicitly absolute path). See [Crates and Modules (Re-exporting with `pub use`)].
|
||||
* `self::path`: path relative to the current module (*i.e.* an explicitly relative path). See [Crates and Modules (Re-exporting with `pub use`)].
|
||||
* `super::path`: path relative to the parent of the current module. See [Crates and Modules (Re-exporting with `pub use`)].
|
||||
* `type::ident`: associated constants, functions, and types. See [Associated Types].
|
||||
* `type::ident`, `<type as trait>::ident`: associated constants, functions, and types. See [Associated Types].
|
||||
* `<type>::…`: associated item for a type which cannot be directly named (*e.g.* `<&T>::…`, `<[T]>::…`, *etc.*). See [Associated Types].
|
||||
* `trait::method(…)`: disambiguating a method call by naming the trait which defines it. See [Universal Function Call Syntax].
|
||||
* `type::method(…)`: disambiguating a method call by naming the type for which it's defined. See [Universal Function Call Syntax].
|
||||
* `<type as trait>::method(…)`: disambiguating a method call by naming the trait _and_ type. See [Universal Function Call Syntax (Angle-bracket Form)].
|
||||
|
||||
<!-- Generics -->
|
||||
|
||||
@ -132,7 +135,8 @@
|
||||
<!-- Constraints -->
|
||||
|
||||
* `T: U`: generic parameter `T` constrained to types that implement `U`. See [Traits].
|
||||
* `T: 'a`: generic type `T` must outlive lifetime `'a`.
|
||||
* `T: 'a`: generic type `T` must outlive lifetime `'a`. When we say that a type 'outlives' the lifetime, we mean that it cannot transitively contain any references with lifetimes shorter than `'a`.
|
||||
* `T : 'static`: The generic type `T` contains no borrowed references other than `'static` ones.
|
||||
* `'b: 'a`: generic lifetime `'b` must outlive lifetime `'a`.
|
||||
* `T: ?Sized`: allow generic type parameter to be a dynamically-sized type. See [Unsized Types (`?Sized`)].
|
||||
* `'a + trait`, `trait + trait`: compound type constraint. See [Traits (Multiple Trait Bounds)].
|
||||
@ -234,6 +238,8 @@
|
||||
[Traits (`where` clause)]: traits.html#where-clause
|
||||
[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds
|
||||
[Traits]: traits.html
|
||||
[Universal Function Call Syntax]: ufcs.html
|
||||
[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#angle-bracket-form
|
||||
[Unsafe]: unsafe.html
|
||||
[Unsized Types (`?Sized`)]: unsized-types.html#sized
|
||||
[Variable Bindings]: variable-bindings.html
|
||||
|
||||
@ -24,6 +24,7 @@ Cargo will automatically generate a simple test when you make a new project.
|
||||
Here's the contents of `src/lib.rs`:
|
||||
|
||||
```rust
|
||||
# fn main() {}
|
||||
#[test]
|
||||
fn it_works() {
|
||||
}
|
||||
@ -75,6 +76,7 @@ So why does our do-nothing test pass? Any test which doesn't `panic!` passes,
|
||||
and any test that does `panic!` fails. Let's make our test fail:
|
||||
|
||||
```rust
|
||||
# fn main() {}
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert!(false);
|
||||
@ -145,6 +147,7 @@ This is useful if you want to integrate `cargo test` into other tooling.
|
||||
We can invert our test's failure with another attribute: `should_panic`:
|
||||
|
||||
```rust
|
||||
# fn main() {}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn it_works() {
|
||||
@ -175,6 +178,7 @@ Rust provides another macro, `assert_eq!`, that compares two arguments for
|
||||
equality:
|
||||
|
||||
```rust
|
||||
# fn main() {}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn it_works() {
|
||||
@ -209,6 +213,7 @@ make sure that the failure message contains the provided text. A safer version
|
||||
of the example above would be:
|
||||
|
||||
```rust
|
||||
# fn main() {}
|
||||
#[test]
|
||||
#[should_panic(expected = "assertion failed")]
|
||||
fn it_works() {
|
||||
@ -219,6 +224,7 @@ fn it_works() {
|
||||
That's all there is to the basics! Let's write one 'real' test:
|
||||
|
||||
```rust,ignore
|
||||
# fn main() {}
|
||||
pub fn add_two(a: i32) -> i32 {
|
||||
a + 2
|
||||
}
|
||||
@ -238,6 +244,7 @@ Sometimes a few specific tests can be very time-consuming to execute. These
|
||||
can be disabled by default by using the `ignore` attribute:
|
||||
|
||||
```rust
|
||||
# fn main() {}
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(4, add_two(2));
|
||||
@ -299,6 +306,7 @@ missing the `tests` module. The idiomatic way of writing our example
|
||||
looks like this:
|
||||
|
||||
```rust,ignore
|
||||
# fn main() {}
|
||||
pub fn add_two(a: i32) -> i32 {
|
||||
a + 2
|
||||
}
|
||||
@ -327,6 +335,7 @@ a large module, and so this is a common use of globs. Let's change our
|
||||
`src/lib.rs` to make use of it:
|
||||
|
||||
```rust,ignore
|
||||
# fn main() {}
|
||||
pub fn add_two(a: i32) -> i32 {
|
||||
a + 2
|
||||
}
|
||||
@ -377,6 +386,7 @@ put a `tests/lib.rs` file inside, with this as its contents:
|
||||
```rust,ignore
|
||||
extern crate adder;
|
||||
|
||||
# fn main() {}
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(4, adder::add_two(2));
|
||||
@ -432,6 +442,7 @@ running examples in your documentation (**note:** this only works in library
|
||||
crates, not binary crates). Here's a fleshed-out `src/lib.rs` with examples:
|
||||
|
||||
```rust,ignore
|
||||
# fn main() {}
|
||||
//! The `adder` crate provides functions that add numbers to other numbers.
|
||||
//!
|
||||
//! # Examples
|
||||
|
||||
@ -277,16 +277,22 @@ This will compile without error.
|
||||
This means that even if someone does something bad like add methods to `i32`,
|
||||
it won’t affect you, unless you `use` that trait.
|
||||
|
||||
There’s one more restriction on implementing traits: either the trait, or the
|
||||
type you’re writing the `impl` for, must be defined by you. So, we could
|
||||
implement the `HasArea` type for `i32`, because `HasArea` is in our code. But
|
||||
if we tried to implement `ToString`, a trait provided by Rust, for `i32`, we could
|
||||
not, because neither the trait nor the type are in our code.
|
||||
There’s one more restriction on implementing traits: either the trait
|
||||
or the type you’re implementing it for must be defined by you. Or more
|
||||
precisely, one of them must be defined in the same crate as the `impl`
|
||||
you're writing. For more on Rust's module and package system, see the
|
||||
chapter on [crates and modules][cm].
|
||||
|
||||
So, we could implement the `HasArea` type for `i32`, because we defined
|
||||
`HasArea` in our code. But if we tried to implement `ToString`, a trait
|
||||
provided by Rust, for `i32`, we could not, because neither the trait nor
|
||||
the type are defined in our crate.
|
||||
|
||||
One last thing about traits: generic functions with a trait bound use
|
||||
‘monomorphization’ (mono: one, morph: form), so they are statically dispatched.
|
||||
What’s that mean? Check out the chapter on [trait objects][to] for more details.
|
||||
|
||||
[cm]: crates-and-modules.html
|
||||
[to]: trait-objects.html
|
||||
|
||||
# Multiple trait bounds
|
||||
|
||||
@ -11,7 +11,7 @@ don’t want to use the standard library via an attribute: `#![no_std]`.
|
||||
> For details on binaries without the standard library, see [the nightly
|
||||
> chapter on `#![no_std]`](no-stdlib.html)
|
||||
|
||||
To use `#![no_std]`, add a it to your crate root:
|
||||
To use `#![no_std]`, add it to your crate root:
|
||||
|
||||
```rust
|
||||
#![no_std]
|
||||
@ -25,7 +25,7 @@ Much of the functionality that’s exposed in the standard library is also
|
||||
available via the [`core` crate](../core/). When we’re using the standard
|
||||
library, Rust automatically brings `std` into scope, allowing you to use
|
||||
its features without an explicit import. By the same token, when using
|
||||
`!#[no_std]`, Rust will bring `core` into scope for you, as well as [its
|
||||
`#![no_std]`, Rust will bring `core` into scope for you, as well as [its
|
||||
prelude](../core/prelude/v1/). This means that a lot of code will Just Work:
|
||||
|
||||
```rust
|
||||
|
||||
@ -11,8 +11,8 @@ let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>
|
||||
```
|
||||
|
||||
(Notice that unlike the `println!` macro we’ve used in the past, we use square
|
||||
brackets `[]` with `vec!` macro. Rust allows you to use either in either situation,
|
||||
this is just convention.)
|
||||
brackets `[]` with `vec!` macro. Rust allows you to use either in either
|
||||
situation, this is just convention.)
|
||||
|
||||
There’s an alternate form of `vec!` for repeating an initial value:
|
||||
|
||||
@ -20,6 +20,12 @@ There’s an alternate form of `vec!` for repeating an initial value:
|
||||
let v = vec![0; 10]; // ten zeroes
|
||||
```
|
||||
|
||||
Vectors store their contents as contiguous arrays of `T` on the heap. This means
|
||||
that they must be able to know the size of `T` at compile time (that is, how
|
||||
many bytes are needed to store a `T`?). The size of some things can't be known
|
||||
at compile time. For these you'll have to store a pointer to that thing:
|
||||
thankfully, the [`Box`][box] type works perfectly for this.
|
||||
|
||||
## Accessing elements
|
||||
|
||||
To get the value at a particular index in the vector, we use `[]`s:
|
||||
@ -113,6 +119,7 @@ Vectors have many more useful methods, which you can read about in [their
|
||||
API documentation][vec].
|
||||
|
||||
[vec]: ../std/vec/index.html
|
||||
[box]: ../std/boxed/index.html
|
||||
[generic]: generics.html
|
||||
[panic]: concurrency.html#panics
|
||||
[get]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get
|
||||
|
||||
@ -516,7 +516,7 @@ struct_expr : expr_path '{' ident ':' expr
|
||||
### Block expressions
|
||||
|
||||
```antlr
|
||||
block_expr : '{' [ stmt ';' | item ] *
|
||||
block_expr : '{' [ stmt | item ] *
|
||||
[ expr ] '}' ;
|
||||
```
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ These reprs have no effect on a struct.
|
||||
|
||||
# repr(packed)
|
||||
|
||||
`repr(packed)` forces rust to strip any padding, and only align the type to a
|
||||
`repr(packed)` forces Rust to strip any padding, and only align the type to a
|
||||
byte. This may improve the memory footprint, but will likely have other negative
|
||||
side-effects.
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@ comments (`/** ... */`), are interpreted as a special syntax for `doc`
|
||||
`#[doc="..."]` around the body of the comment, i.e., `/// Foo` turns into
|
||||
`#[doc="Foo"]`.
|
||||
|
||||
Line comments beginning with `//!` and block comments `/*! ... !*/` are
|
||||
Line comments beginning with `//!` and block comments `/*! ... */` are
|
||||
doc comments that apply to the parent of the comment, rather than the item
|
||||
that follows. That is, they are equivalent to writing `#![doc="..."]` around
|
||||
the body of the comment. `//!` comments are usually used to document
|
||||
@ -236,6 +236,8 @@ following forms:
|
||||
* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
|
||||
(`r`), or `U+0074` (`t`), denoting the Unicode values `U+000A` (LF),
|
||||
`U+000D` (CR) or `U+0009` (HT) respectively.
|
||||
* The _null escape_ is the character `U+0030` (`0`) and denotes the Unicode
|
||||
value `U+0000` (NUL).
|
||||
* The _backslash escape_ is the character `U+005C` (`\`) which must be
|
||||
escaped in order to denote *itself*.
|
||||
|
||||
@ -297,6 +299,8 @@ following forms:
|
||||
* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
|
||||
(`r`), or `U+0074` (`t`), denoting the bytes values `0x0A` (ASCII LF),
|
||||
`0x0D` (ASCII CR) or `0x09` (ASCII HT) respectively.
|
||||
* The _null escape_ is the character `U+0030` (`0`) and denotes the byte
|
||||
value `0x00` (ASCII NUL).
|
||||
* The _backslash escape_ is the character `U+005C` (`\`) which must be
|
||||
escaped in order to denote its ASCII encoding `0x5C`.
|
||||
|
||||
@ -841,8 +845,8 @@ extern crate std as ruststd; // linking to 'std' under another name
|
||||
|
||||
A _use declaration_ creates one or more local name bindings synonymous with
|
||||
some other [path](#paths). Usually a `use` declaration is used to shorten the
|
||||
path required to refer to a module item. These declarations may appear at the
|
||||
top of [modules](#modules) and [blocks](grammar.html#block-expressions).
|
||||
path required to refer to a module item. These declarations may appear in
|
||||
[modules](#modules) and [blocks](grammar.html#block-expressions), usually at the top.
|
||||
|
||||
> **Note**: Unlike in many languages,
|
||||
> `use` declarations in Rust do *not* declare linkage dependency with external crates.
|
||||
@ -984,8 +988,8 @@ fn first((value, _): (i32, i32)) -> i32 { value }
|
||||
#### Generic functions
|
||||
|
||||
A _generic function_ allows one or more _parameterized types_ to appear in its
|
||||
signature. Each type parameter must be explicitly declared, in an
|
||||
angle-bracket-enclosed, comma-separated list following the function name.
|
||||
signature. Each type parameter must be explicitly declared in an
|
||||
angle-bracket-enclosed and comma-separated list, following the function name.
|
||||
|
||||
```rust,ignore
|
||||
// foo is generic over A and B
|
||||
@ -1137,7 +1141,6 @@ the list of fields entirely. Such a struct implicitly defines a constant of
|
||||
its type with the same name. For example:
|
||||
|
||||
```
|
||||
# #![feature(braced_empty_structs)]
|
||||
struct Cookie;
|
||||
let c = [Cookie, Cookie {}, Cookie, Cookie {}];
|
||||
```
|
||||
@ -1145,7 +1148,6 @@ let c = [Cookie, Cookie {}, Cookie, Cookie {}];
|
||||
is equivalent to
|
||||
|
||||
```
|
||||
# #![feature(braced_empty_structs)]
|
||||
struct Cookie {}
|
||||
const Cookie: Cookie = Cookie {};
|
||||
let c = [Cookie, Cookie {}, Cookie, Cookie {}];
|
||||
@ -1179,7 +1181,7 @@ Enumeration constructors can have either named or unnamed fields:
|
||||
```rust
|
||||
enum Animal {
|
||||
Dog (String, f64),
|
||||
Cat { name: String, weight: f64 }
|
||||
Cat { name: String, weight: f64 },
|
||||
}
|
||||
|
||||
let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2);
|
||||
@ -1237,12 +1239,12 @@ const STRING: &'static str = "bitstring";
|
||||
|
||||
struct BitsNStrings<'a> {
|
||||
mybits: [u32; 2],
|
||||
mystring: &'a str
|
||||
mystring: &'a str,
|
||||
}
|
||||
|
||||
const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
|
||||
mybits: BITS,
|
||||
mystring: STRING
|
||||
mystring: STRING,
|
||||
};
|
||||
```
|
||||
|
||||
@ -1661,7 +1663,7 @@ struct Foo;
|
||||
|
||||
// Declare a public struct with a private field
|
||||
pub struct Bar {
|
||||
field: i32
|
||||
field: i32,
|
||||
}
|
||||
|
||||
// Declare a public enum with two public variants
|
||||
@ -1764,7 +1766,7 @@ pub mod submodule {
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
For a rust program to pass the privacy checking pass, all paths must be valid
|
||||
For a Rust program to pass the privacy checking pass, all paths must be valid
|
||||
accesses given the two rules above. This includes all use statements,
|
||||
expressions, types, etc.
|
||||
|
||||
@ -2044,7 +2046,7 @@ The following configurations must be defined by the implementation:
|
||||
production. For example, it controls the behavior of the standard library's
|
||||
`debug_assert!` macro.
|
||||
* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, `"x86_64"`
|
||||
`"mips"`, `"powerpc"`, `"powerpc64"`, `"powerpc64le"`, `"arm"`, or `"aarch64"`.
|
||||
`"mips"`, `"powerpc"`, `"powerpc64"`, `"arm"`, or `"aarch64"`.
|
||||
* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or
|
||||
`"big"`.
|
||||
* `target_env = ".."` - An option provided by the compiler by default
|
||||
@ -2095,7 +2097,7 @@ along with their default settings. [Compiler
|
||||
plugins](book/compiler-plugins.html#lint-plugins) can provide additional lint checks.
|
||||
|
||||
```{.ignore}
|
||||
mod m1 {
|
||||
pub mod m1 {
|
||||
// Missing documentation is ignored here
|
||||
#[allow(missing_docs)]
|
||||
pub fn undocumented_one() -> i32 { 1 }
|
||||
@ -2115,9 +2117,9 @@ check on and off:
|
||||
|
||||
```{.ignore}
|
||||
#[warn(missing_docs)]
|
||||
mod m2{
|
||||
pub mod m2{
|
||||
#[allow(missing_docs)]
|
||||
mod nested {
|
||||
pub mod nested {
|
||||
// Missing documentation is ignored here
|
||||
pub fn undocumented_one() -> i32 { 1 }
|
||||
|
||||
@ -2137,7 +2139,7 @@ that lint check:
|
||||
|
||||
```{.ignore}
|
||||
#[forbid(missing_docs)]
|
||||
mod m3 {
|
||||
pub mod m3 {
|
||||
// Attempting to toggle warning signals an error here
|
||||
#[allow(missing_docs)]
|
||||
/// Returns 2.
|
||||
@ -2381,7 +2383,6 @@ The currently implemented features of the reference compiler are:
|
||||
terms of encapsulation).
|
||||
* - `default_type_parameter_fallback` - Allows type parameter defaults to
|
||||
influence type inference.
|
||||
* - `braced_empty_structs` - Allows use of empty structs and enum variants with braces.
|
||||
|
||||
* - `stmt_expr_attributes` - Allows attributes on expressions and
|
||||
non-item statements.
|
||||
@ -3036,7 +3037,7 @@ the case of a `while` loop, the head is the conditional expression controlling
|
||||
the loop. In the case of a `for` loop, the head is the call-expression
|
||||
controlling the loop. If the label is present, then `continue 'foo` returns
|
||||
control to the head of the loop with label `'foo`, which need not be the
|
||||
innermost label enclosing the `break` expression, but must enclose it.
|
||||
innermost label enclosing the `continue` expression, but must enclose it.
|
||||
|
||||
A `continue` expression is only permitted in the body of a loop.
|
||||
|
||||
@ -3212,7 +3213,7 @@ may refer to the variables bound within the pattern they follow.
|
||||
let message = match maybe_digit {
|
||||
Some(x) if x < 10 => process_digit(x),
|
||||
Some(x) => process_other(x),
|
||||
None => panic!()
|
||||
None => panic!(),
|
||||
};
|
||||
```
|
||||
|
||||
@ -3504,7 +3505,7 @@ An example of a `fn` type:
|
||||
|
||||
```
|
||||
fn add(x: i32, y: i32) -> i32 {
|
||||
return x + y;
|
||||
x + y
|
||||
}
|
||||
|
||||
let mut x = add(5,7);
|
||||
@ -3564,8 +3565,9 @@ Each instance of a trait object includes:
|
||||
each method of `SomeTrait` that `T` implements, a pointer to `T`'s
|
||||
implementation (i.e. a function pointer).
|
||||
|
||||
The purpose of trait objects is to permit "late binding" of methods. A call to
|
||||
a method on a trait object is only resolved to a vtable entry at compile time.
|
||||
The purpose of trait objects is to permit "late binding" of methods. Calling a
|
||||
method on a trait object results in virtual dispatch at runtime: that is, a
|
||||
function pointer is loaded from the trait object vtable and invoked indirectly.
|
||||
The actual implementation for each vtable entry can vary on an object-by-object
|
||||
basis.
|
||||
|
||||
@ -4060,7 +4062,7 @@ the guarantee that these issues are never caused by safe code.
|
||||
* Breaking the [pointer aliasing
|
||||
rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
|
||||
with raw pointers (a subset of the rules used by C)
|
||||
* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
|
||||
* `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T`
|
||||
contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
|
||||
guarantees.
|
||||
* Mutating non-mutable data (that is, data reached through a shared reference or
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
% Rustc UX guidelines
|
||||
|
||||
Don't forget the user. Whether human or another program, such as an IDE, a
|
||||
good user experience with the compiler goes a long way into making developer
|
||||
lives better. We don't want users to be baffled by compiler output or
|
||||
@ -70,4 +72,4 @@ understandable compiler scripts.
|
||||
* The `--verbose` flag is for adding verbose information to `rustc` output
|
||||
when not compiling a program. For example, using it with the `--version` flag
|
||||
gives information about the hashes of the code.
|
||||
* Experimental flags and options must be guarded behind the `-Z unstable-options` flag.
|
||||
* Experimental flags and options must be guarded behind the `-Z unstable-options` flag.
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
\usepackage{newunicodechar}
|
||||
\newunicodechar⊥{{$\bot$}}
|
||||
@ -1,5 +1,5 @@
|
||||
<div id="versioninfo">
|
||||
<img src="https://www.rust-lang.org/logos/rust-logo-32x32-blk.png" width="32" height="32" alt><br>
|
||||
<img src="https://www.rust-lang.org/logos/rust-logo-32x32-blk.png" width="32" height="32" alt="Rust logo"><br>
|
||||
<span class="white-sticker"><a href="https://www.rust-lang.org">Rust</a> VERSION</span><br>
|
||||
<a href="https://github.com/rust-lang/rust/commit/STAMP"
|
||||
class="hash white-sticker">SHORT_HASH</a>
|
||||
|
||||
@ -1,117 +0,0 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(rustc_private, rustdoc)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rustdoc;
|
||||
extern crate serialize as rustc_serialize;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::{read_dir, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::error::Error;
|
||||
|
||||
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap};
|
||||
|
||||
use rustdoc::html::markdown::Markdown;
|
||||
use rustc_serialize::json;
|
||||
|
||||
/// Load all the metadata files from `metadata_dir` into an in-memory map.
|
||||
fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<Error>> {
|
||||
let mut all_errors = BTreeMap::new();
|
||||
|
||||
for entry in try!(read_dir(metadata_dir)) {
|
||||
let path = try!(entry).path();
|
||||
|
||||
let mut metadata_str = String::new();
|
||||
try!(File::open(&path).and_then(|mut f| f.read_to_string(&mut metadata_str)));
|
||||
|
||||
let some_errors: ErrorMetadataMap = try!(json::decode(&metadata_str));
|
||||
|
||||
for (err_code, info) in some_errors {
|
||||
all_errors.insert(err_code, info);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(all_errors)
|
||||
}
|
||||
|
||||
/// Output an HTML page for the errors in `err_map` to `output_path`.
|
||||
fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Path) -> Result<(), Box<Error>> {
|
||||
let mut output_file = try!(File::create(output_path));
|
||||
|
||||
try!(write!(&mut output_file,
|
||||
r##"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rust Compiler Error Index</title>
|
||||
<meta charset="utf-8">
|
||||
<!-- Include rust.css after main.css so its rules take priority. -->
|
||||
<link rel="stylesheet" type="text/css" href="main.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="rust.css"/>
|
||||
<style>
|
||||
.error-undescribed {{
|
||||
display: none;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
"##
|
||||
));
|
||||
|
||||
try!(write!(&mut output_file, "<h1>Rust Compiler Error Index</h1>\n"));
|
||||
|
||||
for (err_code, info) in err_map {
|
||||
// Enclose each error in a div so they can be shown/hidden en masse.
|
||||
let desc_desc = match info.description {
|
||||
Some(_) => "error-described",
|
||||
None => "error-undescribed",
|
||||
};
|
||||
let use_desc = match info.use_site {
|
||||
Some(_) => "error-used",
|
||||
None => "error-unused",
|
||||
};
|
||||
try!(write!(&mut output_file, "<div class=\"{} {}\">", desc_desc, use_desc));
|
||||
|
||||
// Error title (with self-link).
|
||||
try!(write!(&mut output_file,
|
||||
"<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
|
||||
err_code));
|
||||
|
||||
// Description rendered as markdown.
|
||||
match info.description {
|
||||
Some(ref desc) => try!(write!(&mut output_file, "{}", Markdown(desc))),
|
||||
None => try!(write!(&mut output_file, "<p>No description.</p>\n")),
|
||||
}
|
||||
|
||||
try!(write!(&mut output_file, "</div>\n"));
|
||||
}
|
||||
|
||||
try!(write!(&mut output_file, "</body>\n</html>"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main_with_result() -> Result<(), Box<Error>> {
|
||||
let build_arch = try!(env::var("CFG_BUILD"));
|
||||
let metadata_dir = get_metadata_dir(&build_arch);
|
||||
let err_map = try!(load_all_errors(&metadata_dir));
|
||||
try!(render_error_page(&err_map, Path::new("doc/error-index.html")));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = main_with_result() {
|
||||
panic!("{}", e.description());
|
||||
}
|
||||
}
|
||||
203
src/error_index_generator/main.rs
Normal file
203
src/error_index_generator/main.rs
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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.
|
||||
|
||||
#![feature(rustc_private, rustdoc)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rustdoc;
|
||||
extern crate serialize as rustc_serialize;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::{read_dir, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::error::Error;
|
||||
|
||||
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};
|
||||
|
||||
use rustdoc::html::markdown::Markdown;
|
||||
use rustc_serialize::json;
|
||||
|
||||
enum OutputFormat {
|
||||
HTML(HTMLFormatter),
|
||||
Markdown(MarkdownFormatter),
|
||||
Unknown(String),
|
||||
}
|
||||
|
||||
impl OutputFormat {
|
||||
fn from(format: &str) -> OutputFormat {
|
||||
match &*format.to_lowercase() {
|
||||
"html" => OutputFormat::HTML(HTMLFormatter),
|
||||
"markdown" => OutputFormat::Markdown(MarkdownFormatter),
|
||||
s => OutputFormat::Unknown(s.to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Formatter {
|
||||
fn header(&self, output: &mut Write) -> Result<(), Box<Error>>;
|
||||
fn title(&self, output: &mut Write) -> Result<(), Box<Error>>;
|
||||
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
|
||||
err_code: &str) -> Result<(), Box<Error>>;
|
||||
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>>;
|
||||
}
|
||||
|
||||
struct HTMLFormatter;
|
||||
struct MarkdownFormatter;
|
||||
|
||||
impl Formatter for HTMLFormatter {
|
||||
fn header(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, r##"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rust Compiler Error Index</title>
|
||||
<meta charset="utf-8">
|
||||
<!-- Include rust.css after main.css so its rules take priority. -->
|
||||
<link rel="stylesheet" type="text/css" href="main.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="rust.css"/>
|
||||
<style>
|
||||
.error-undescribed {{
|
||||
display: none;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
"##));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn title(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, "<h1>Rust Compiler Error Index</h1>\n"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
|
||||
err_code: &str) -> Result<(), Box<Error>> {
|
||||
// Enclose each error in a div so they can be shown/hidden en masse.
|
||||
let desc_desc = match info.description {
|
||||
Some(_) => "error-described",
|
||||
None => "error-undescribed",
|
||||
};
|
||||
let use_desc = match info.use_site {
|
||||
Some(_) => "error-used",
|
||||
None => "error-unused",
|
||||
};
|
||||
try!(write!(output, "<div class=\"{} {}\">", desc_desc, use_desc));
|
||||
|
||||
// Error title (with self-link).
|
||||
try!(write!(output,
|
||||
"<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
|
||||
err_code));
|
||||
|
||||
// Description rendered as markdown.
|
||||
match info.description {
|
||||
Some(ref desc) => try!(write!(output, "{}", Markdown(desc))),
|
||||
None => try!(write!(output, "<p>No description.</p>\n")),
|
||||
}
|
||||
|
||||
try!(write!(output, "</div>\n"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, "</body>\n</html>"));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Formatter for MarkdownFormatter {
|
||||
#[allow(unused_variables)]
|
||||
fn header(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn title(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, "# Rust Compiler Error Index\n"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
|
||||
err_code: &str) -> Result<(), Box<Error>> {
|
||||
Ok(match info.description {
|
||||
Some(ref desc) => try!(write!(output, "## {}\n{}\n", err_code, desc)),
|
||||
None => (),
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Load all the metadata files from `metadata_dir` into an in-memory map.
|
||||
fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<Error>> {
|
||||
let mut all_errors = BTreeMap::new();
|
||||
|
||||
for entry in try!(read_dir(metadata_dir)) {
|
||||
let path = try!(entry).path();
|
||||
|
||||
let mut metadata_str = String::new();
|
||||
try!(File::open(&path).and_then(|mut f| f.read_to_string(&mut metadata_str)));
|
||||
|
||||
let some_errors: ErrorMetadataMap = try!(json::decode(&metadata_str));
|
||||
|
||||
for (err_code, info) in some_errors {
|
||||
all_errors.insert(err_code, info);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(all_errors)
|
||||
}
|
||||
|
||||
/// Output an HTML page for the errors in `err_map` to `output_path`.
|
||||
fn render_error_page<T: Formatter>(err_map: &ErrorMetadataMap, output_path: &Path,
|
||||
formatter: T) -> Result<(), Box<Error>> {
|
||||
let mut output_file = try!(File::create(output_path));
|
||||
|
||||
try!(formatter.header(&mut output_file));
|
||||
try!(formatter.title(&mut output_file));
|
||||
|
||||
for (err_code, info) in err_map {
|
||||
try!(formatter.error_code_block(&mut output_file, info, err_code));
|
||||
}
|
||||
|
||||
formatter.footer(&mut output_file)
|
||||
}
|
||||
|
||||
fn main_with_result(format: OutputFormat) -> Result<(), Box<Error>> {
|
||||
let build_arch = try!(env::var("CFG_BUILD"));
|
||||
let metadata_dir = get_metadata_dir(&build_arch);
|
||||
let err_map = try!(load_all_errors(&metadata_dir));
|
||||
match format {
|
||||
OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
|
||||
OutputFormat::HTML(h) => try!(render_error_page(&err_map,
|
||||
Path::new("doc/error-index.html"),
|
||||
h)),
|
||||
OutputFormat::Markdown(m) => try!(render_error_page(&err_map,
|
||||
Path::new("doc/error-index.md"),
|
||||
m)),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_args() -> OutputFormat {
|
||||
for arg in env::args().skip(1) {
|
||||
return OutputFormat::from(&arg);
|
||||
}
|
||||
OutputFormat::from("html")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = main_with_result(parse_args()) {
|
||||
panic!("{}", e.description());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user