As there’s no C++ runtime any more there’s really no point in having anything but Rust tags being made.
I’ve also taken the liberty of excluding the compiler parts of this in the `librust%,,` pattern substitution. Whether or not this is “correct” will depend on whether you want tags for the compiler or for general use. For myself, I want it for general use.
I’m not sure how much people use the tags files anyway. I definitely do, but with Racer existing the tags files aren’t quite so necessary.
I've been baking this out of tree for long enough. This is currently about ~2/5ths the size of TRPL. Time to get it in tree so it can be more widely maintained and scrutinized. I've preserved the whole gruesome history including various rewrites. I can definitely squash these a fair amount if desired. Some random people submitted minor fixes though, so they're mixed in.
Edit: forgot to link to rendered http://cglab.ca/~abeinges/blah/turpl/_book/
Edit2:
To streamline the review process, I'm going to break this into sections that need official "domain expert" approval:
# Summary
* [ ] references.md -- very important, needs work
* [x] Meet Safe and Unsafe: reviewed by @aturon
* [x] Data Layout: reviewed by @arielb1
* [x] Ownership: reviewed by @aturon ( and sorta @nikomatsakis ) -- significantly updated, may need re-r
* [x] Coversions: reviewed by @nrc
* [x] Uninitialized Memory: reviewed by @pnkfelix
* [x] Ownership-Oriented Resource Management: reviewed by @aturon
* [x] Unwinding: reviewed by @alexcrichton
* [x] Concurrency: reviewed by @aturon
* [x] Implementing Vec: r? @huonw
As there’s no C++ runtime any more there’s really no point in having
anything but Rust tags being made.
I’ve also taken the liberty of excluding the compiler parts of this in
the `librust%,,` pattern substitution. Whether or not this is “correct”
will depend on whether you want tags for the compiler or for general
use. For myself, I want it for general use.
I’m not sure how much people use the tags files anyway. I definitely do,
but with Racer existing the tags files aren’t quite so necessary.
This commit moves the IR files in the distribution, rust_try.ll,
rust_try_msvc_64.ll, and rust_try_msvc_32.ll into the compiler from the main
distribution. There's a few reasons for this change:
* LLVM changes its IR syntax from time to time, so it's very difficult to
have these files build across many LLVM versions simultaneously. We'll likely
want to retain this ability for quite some time into the future.
* The implementation of these files is closely tied to the compiler and runtime
itself, so it makes sense to fold it into a location which can do more
platform-specific checks for various implementation details (such as MSVC 32
vs 64-bit).
* This removes LLVM as a build-time dependency of the standard library. This may
end up becoming very useful if we move towards building the standard library
with Cargo.
In the immediate future, however, this commit should restore compatibility with
LLVM 3.5 and 3.6.
We have previously always relied upon an external tool, `ar`, to modify archives
that the compiler produces (staticlibs, rlibs, etc). This approach, however, has
a number of downsides:
* Spawning a process is relatively expensive for small compilations
* Encoding arguments across process boundaries often incurs unnecessary overhead
or lossiness. For example `ar` has a tough time dealing with files that have
the same name in archives, and the compiler copies many files around to ensure
they can be passed to `ar` in a reasonable fashion.
* Most `ar` programs found do **not** have the ability to target arbitrary
platforms, so this is an extra tool which needs to be found/specified when
cross compiling.
The LLVM project has had a tool called `llvm-ar` for quite some time now, but it
wasn't available in the standard LLVM libraries (it was just a standalone
program). Recently, however, in LLVM 3.7, this functionality has been moved to a
library and is now accessible by consumers of LLVM via the `writeArchive`
function.
This commit migrates our archive bindings to no longer invoke `ar` by default
but instead make a library call to LLVM to do various operations. This solves
all of the downsides listed above:
* Archive management is now much faster, for example creating a "hello world"
staticlib is now 6x faster (50ms => 8ms). Linking dynamic libraries also
recently started requiring modification of rlibs, and linking a hello world
dynamic library is now 2x faster.
* The compiler is now one step closer to "hassle free" cross compilation because
no external tool is needed for managing archives, LLVM does the right thing!
This commit does not remove support for calling a system `ar` utility currently.
We will continue to maintain compatibility with LLVM 3.5 and 3.6 looking forward
(so the system LLVM can be used wherever possible), and in these cases we must
shell out to a system utility. All nightly builds of Rust, however, will stop
needing a system `ar`.
This PR was originally going to be a "let's start running tests on MSVC" PR, but it didn't quite get to that point. It instead gets us ~80% of the way there! The steps taken in this PR are:
* Landing pads are turned on by default for 64-bit MSVC. The LLVM support is "good enough" with the caveat the destructor glue is now marked noinline. This was recommended [on the associated bug](https://llvm.org/bugs/show_bug.cgi?id=23884) as a stopgap until LLVM has a better representation for exception handling in MSVC. The consequence of this is that MSVC will have a bit of a perf hit, but there are possible routes we can take if this workaround sticks around for too long.
* The linker (`link.exe`) is now looked up in the Windows Registry if it's not otherwise available in the environment. This improves using the compiler outside of a VS shell (e.g. in a MSYS shell or in a vanilla cmd.exe shell). This also makes cross compiles via Cargo "just work" when crossing between 32 and 64 bit!
* TLS destructors were fixed to start running on MSVC (they previously weren't running at all)
* A few assorted `run-pass` tests were fixed.
* The dependency on the `rust_builtin` library was removed entirely for MSVC to try to prevent any `cl.exe` compiled objects get into the standard library. This should help us later remove any dependence on the CRT by the standard library.
* I re-added `rust_try_msvc_32.ll` for 32-bit MSVC and ensured that landing pads were turned off by default there as well.
Despite landing pads being enabled, there are still *many* failing tests on MSVC. The two major classes I've identified so far are:
* Spurious aborts. It appears that when optimizations are enabled that landing pads aren't always lined up properly, and sometimes an exception being thrown can't find the catch block down the stack, causing the program to abort. I've been working to reduce this test case but haven't been met with great success just yet.
* Parallel codegen does not work on MSVC. Our current strategy is to take the N object files emitted by the N codegen threads and use `ld -r` to assemble them into *one* object file. The MSVC linker, however, does not have this ability, and this will need to be rearchitected to work on MSVC.
I will fix parallel codegen in a future PR, and I'll also be watching LLVM closely to see if the aborts... disappear!
This commit alters the compiler to no longer "just run link.exe" but instead
probe the system's registry to find where the linker is located. The default
library search path (normally found through LIB) is also found through the
registry. This also brings us in line with the default behavior of Clang, and
much of the logic of where to look for information is copied over from Clang as
well. Finally, this commit removes the makefile logic for updating the
environment variables for the compiler, except for stage0 where it's still
necessary.
The motivation for this change is rooted in two positions:
* Not having to set up these environment variables is much less hassle both for
the bootstrap and for running the compiler itself. This means that the
compiler can be run outside of VS shells and be run inside of cmd.exe or a
MSYS shell.
* When dealing with cross compilation, there's not actually a set of environment
variables that can be set for the compiler. This means, for example, if a
Cargo compilation is targeting 32-bit from 64-bit you can't actually set up
one set of environment variables. Having the compiler deal with the logic
instead is generally much more convenient!
This commit modifies the configure script and our makefiles to support building
32-bit MSVC targets. The MSVC toolchain is now parameterized over whether it can
produce a 32-bit or 64-bit binary. The configure script was updated to export
more variables at configure time, and the makefiles were rejiggered to
selectively reexport the relevant environment variables for the applicable
targets they're going to run for.
Now that LLVM has been updated, the only remaining roadblock to implementing
unwinding for MSVC is to fill out the runtime support in `std::rt::unwind::seh`.
This commit does precisely that, fixing up some other bits and pieces along the
way:
* The `seh` unwinding module now uses `RaiseException` to initiate a panic.
* The `rust_try.ll` file was rewritten for MSVC (as it's quite different) and is
located at `rust_try_msvc_64.ll`, only included on MSVC builds for now.
* The personality function for all landing pads generated by LLVM is hard-wired
to `__C_specific_handler` instead of the standard `rust_eh_personality` lang
item. This is required to get LLVM to emit SEH unwinding information instead
of DWARF unwinding information. This also means that on MSVC the
`rust_eh_personality` function is entirely unused (but is defined as it's a
lang item).
More details about how panicking works on SEH can be found in the
`rust_try_msvc_64.ll` or `seh.rs` files, but I'm always open to adding more
comments!
A key aspect of this PR is missing, however, which is that **unwinding is still
turned off by default for MSVC**. There is a [bug in llvm][llvm-bug] which
causes optimizations to inline enough landing pads that LLVM chokes. If the
compiler is optimized at `-O1` (where inlining isn't enabled) then it can
bootstrap with unwinding enabled, but when optimized at `-O2` (inlining is
enabled) then it hits a fatal LLVM error.
[llvm-bug]: https://llvm.org/bugs/show_bug.cgi?id=23884
In #26252 support was added to have prettier paths printed out on failure by not
passing the full path to the source file to the compiler, but instead just a
small relative path. To preserve this relative path across configurations, the
`SREL` variable was used for reconfiguring, but if `SREL` is empty then it will
attempt to run the command `configure` which is distinct from running
`./configure` (e.g. doesn't run the local script).
This commit modifies the `SREL` value to re-run the configure script by setting
it to `./` in the case where `SREL` is empty.
In #26252 support was added to have prettier paths printed out on failure by not
passing the full path to the source file to the compiler, but instead just a
small relative path. To preserve this relative path across configurations, the
`SREL` variable was used for reconfiguring, but if `SREL` is empty then it will
attempt to run the command `configure` which is distinct from running
`./configure` (e.g. doesn't run the local script).
This commit modifies the `SREL` value to re-run the configure script by setting
it to `./` in the case where `SREL` is empty.
musl only creates rlib files for stdlib linking so we need to ignore the `CFG_LIB_GLOB_` setting, otherwise we an error:
```
$ make --debug VERBOSE=1 dist-tar-bins
[...]
Successfully remade target file `prepare-target-x86_64-unknown-linux-gnu-host-x86_64-unknown-linux-gnu-2-dir-x86_64-unknown-linux-gnu'.
File `prepare-target-x86_64-unknown-linux-musl-host-x86_64-unknown-linux-gnu-2-dir-x86_64-unknown-linux-gnu' does not exist.
Must remake target `prepare-target-x86_64-unknown-linux-musl-host-x86_64-unknown-linux-gnu-2-dir-x86_64-unknown-linux-gnu'.
umask 022 && mkdir -p tmp/dist/rustc-1.2.0-dev-x86_64-unknown-linux-gnu-image/lib/rustlib/x86_64-unknown-linux-musl/lib
umask 022 && mkdir -p tmp/dist/rustc-1.2.0-dev-x86_64-unknown-linux-gnu-image/lib/rustlib/x86_64-unknown-linux-gnu/bin
LIB_NAME="liblibc-d8ace771.rlib"; MATCHES=""; if [ -n "$MATCHES" ]; then echo "warning: one or libraries matching Rust library 'liblibc-*.rlib'" && echo " (other than '$LIB_NAME' itself) alre
ady present" && echo " at destination tmp/dist/rustc-1.2.0-dev-x86_64-unknown-linux-gnu-image/lib/rustlib/x86_64-unknown-linux-musl/lib:" && echo $MATCHES ; fi
install -m644 `ls -drt1 x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-musl/lib/liblibc-*.rlib` tmp/dist/rustc-1.2.0-dev-x86_64-unknown-linux-gnu-image/lib/rustlib/x86_64-unk
nown-linux-musl/lib/
LIB_NAME=""; MATCHES=""; if [ -n "$MATCHES" ]; then echo "warning: one or libraries matching Rust library 'libstd-*.so'" && echo " (other than '$LIB_NAME' itself) already present" && echo
" at destination tmp/dist/rustc-1.2.0-dev-x86_64-unknown-linux-gnu-image/lib/rustlib/x86_64-unknown-linux-musl/lib:" && echo $MATCHES ; fi
install -m644 `ls -drt1 x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-musl/lib/libstd-*.so` tmp/dist/rustc-1.2.0-dev-x86_64-unknown-linux-gnu-image/lib/rustlib/x86_64-unknow
n-linux-musl/lib/
ls: cannot access x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-musl/lib/libstd-*.so: No such file or directory
install: missing destination file operand after ‘tmp/dist/rustc-1.2.0-dev-x86_64-unknown-linux-gnu-image/lib/rustlib/x86_64-unknown-linux-musl/lib/’
Try 'install --help' for more information.
make: *** [prepare-target-x86_64-unknown-linux-musl-host-x86_64-unknown-linux-gnu-2-dir-x86_64-unknown-linux-gnu] Error 1
```
`CFG_INSTALL_ONLY_RLIB_` is provided for this reason and fixes `make install` and `make dist`.
mk: Build crates with relative source file paths
The path we pass to rustc will be visible in panic messages and
backtraces: they will be user visible!
Avoid junk in these paths by passing relative paths to rustc.
For most advanced users, `libcore` or `libstd` in the path will be
a clue to the location -- inside our code, not theirs.
Store both the relative path to the source as well as the absolute.
Use the relative path where it matters, compiling the main crates,
instead of changing all of the build process to cope with relative
paths.
Example output after this patch:
```
$ ./testunwrap
thread '<main>' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:362
$ RUST_BACKTRACE=1 ./testunwrap
thread '<main>' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:362
stack backtrace:
1: 0x7ff59c1e9956 - sys::backtrace::write::h67a542fd2b201576des
at ../src/libstd/sys/unix/backtrace.rs:158
2: 0x7ff59c1ed5b6 - panicking::on_panic::h3d21c41cdd5c12d41Xw
at ../src/libstd/panicking.rs:58
3: 0x7ff59c1e7b6e - rt::unwind::begin_unwind_inner::h9f3a5440cebb8baeLDw
at ../src/libstd/rt/unwind/mod.rs:273
4: 0x7ff59c1e7f84 - rt::unwind::begin_unwind_fmt::h4fe8a903e0c296b0RCw
at ../src/libstd/rt/unwind/mod.rs:212
5: 0x7ff59c1eced7 - rust_begin_unwind
6: 0x7ff59c22c11a - panicking::panic_fmt::h00b0cd49c98a9220i5B
at ../src/libcore/panicking.rs:64
7: 0x7ff59c22b9e0 - panicking::panic::hf549420c0ee03339P3B
at ../src/libcore/panicking.rs:45
8: 0x7ff59c1e621d - option::Option<T>::unwrap::h501963526474862829
9: 0x7ff59c1e61b1 - main::hb5c91ce92347d1e6eaa
10: 0x7ff59c1f1c18 - rust_try_inner
11: 0x7ff59c1f1c05 - rust_try
12: 0x7ff59c1ef374 - rt::lang_start::h7e51e19c6677cffe5Sw
at ../src/libstd/rt/unwind/mod.rs:147
at ../src/libstd/rt/unwind/mod.rs:130
at ../src/libstd/rt/mod.rs:128
13: 0x7ff59c1e628e - main
14: 0x7ff59b3f6b44 - __libc_start_main
15: 0x7ff59c1e6078 - <unknown>
16: 0x0 - <unknown>
```
The path we pass to rustc will be visible in panic messages and
backtraces: they will be user visible!
Avoid junk in these paths by passing relative paths to rustc.
For most advanced users, `libcore` or `libstd` in the path will be
a clue to the location -- inside our code, not theirs.
Store both the relative path to the source as well as the absolute.
Use the relative path where it matters, compiling the main crates,
instead of changing all of the build process to cope with relative
paths.
Example output after this patch:
```
$ ./testunwrap
thread '<main>' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:362
$ RUST_BACKTRACE=1 ./testunwrap
thread '<main>' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:362
stack backtrace:
1: 0x7ff59c1e9956 - sys::backtrace::write::h67a542fd2b201576des
at ../src/libstd/sys/unix/backtrace.rs:158
2: 0x7ff59c1ed5b6 - panicking::on_panic::h3d21c41cdd5c12d41Xw
at ../src/libstd/panicking.rs:58
3: 0x7ff59c1e7b6e - rt::unwind::begin_unwind_inner::h9f3a5440cebb8baeLDw
at ../src/libstd/rt/unwind/mod.rs:273
4: 0x7ff59c1e7f84 - rt::unwind::begin_unwind_fmt::h4fe8a903e0c296b0RCw
at ../src/libstd/rt/unwind/mod.rs:212
5: 0x7ff59c1eced7 - rust_begin_unwind
6: 0x7ff59c22c11a - panicking::panic_fmt::h00b0cd49c98a9220i5B
at ../src/libcore/panicking.rs:64
7: 0x7ff59c22b9e0 - panicking::panic::hf549420c0ee03339P3B
at ../src/libcore/panicking.rs:45
8: 0x7ff59c1e621d - option::Option<T>::unwrap::h501963526474862829
9: 0x7ff59c1e61b1 - main::hb5c91ce92347d1e6eaa
10: 0x7ff59c1f1c18 - rust_try_inner
11: 0x7ff59c1f1c05 - rust_try
12: 0x7ff59c1ef374 - rt::lang_start::h7e51e19c6677cffe5Sw
at ../src/libstd/rt/unwind/mod.rs:147
at ../src/libstd/rt/unwind/mod.rs:130
at ../src/libstd/rt/mod.rs:128
13: 0x7ff59c1e628e - main
14: 0x7ff59b3f6b44 - __libc_start_main
15: 0x7ff59c1e6078 - <unknown>
16: 0x0 - <unknown>
```
Right now the distribution tarball for MSVC only includes the *.dll files for
the supporting libraries, but not the corresponding *.lib files which allow
actually linking to the dll. This means that the current MSVC nightlies cannot
produce dynamically linked binaries as the *.lib files are not available to link
against.
This commit modifies the `LIB_GLOB` used to copy the files around to include the
`lib` variant of the `dll`.
On MSVC there are two ways that the CRT can be linked, either statically or
dynamically. Each object file produced by the compiler is compiled against
msvcrt (a dll) or libcmt (a static library). When the linker is dealing with
more than one object file, it requires that all object files link to the same
CRT, or else the linker will spit out some errors.
For now, compile code with `-MD` as it seems to appear more often in C libraries
so we'll stick with the same trend.
On MSVC there are two ways that the CRT can be linked, either statically or
dynamically. Each object file produced by the compiler is compiled against
msvcrt (a dll) or libcmt (a static library). When the linker is dealing with
more than one object file, it requires that all object files link to the same
CRT, or else the linker will spit out some errors.
For now, compile code with `-MD` as it seems to appear more often in C libraries
so we'll stick with the same trend.
GDB and LLDB pretty printers have some common functionality and also access some common information, such as the layout of standard library types. So far, this information has been duplicated in the two pretty printing python modules. This PR introduces a common module used by both debuggers.
This PR also implements proper rendering of `String` and `&str` values in LLDB.
Now that MSVC support has landed in the most recent nightlies we can now have
MSVC bootstrap itself without going through a GNU compiler first. Unfortunately,
however, the bootstrap currently fails due to the compiler not being able to
find the llvm-ar.exe tool during the stage0 libcore compile. The compiler cannot
find this tool because it's looking inside a directory that does not exist:
$SYSROOT/rustlib/x86_64-pc-windows-gnu/bin
The `gnu` on this triple is because the bootstrap compiler's host architecture
is GNU. The build system, however, only arranges for the llvm-ar.exe tool to be
available in this location:
$SYSROOT/rustlib/x86_64-pc-windows-msvc/bin
To resolve this discrepancy, the build system has been modified to understand
triples that are bootstrapped from another triple, and in this case copy the
native tools to the right location.
This commit adds a ./configure option called `--disable-elf-tls` which disables
ELF based TLS (that which is communicated to LLVM) on platforms which already
support it. OSX 10.6 does not support this form of TLS, and some users of Rust
need to target 10.6 and are unable to do so due to the usage of TLS. The
standard library will continue to use ELF based TLS on OSX by default (as the
officially supported platform is 10.7+), but this adds an option to compile the
standard library in a way that is compatible with 10.6.
Closes#25342
GDB and LLDB pretty printers have some common functionality
and also access some common information, such as the layout of
standard library types. So far, this information has been
duplicated in the two pretty printing python modules. This
commit introduces a common module used by both debuggers.
This commit adds a ./configure option called `--disable-elf-tls` which disables
ELF based TLS (that which is communicated to LLVM) on platforms which already
support it. OSX 10.6 does not support this form of TLS, and some users of Rust
need to target 10.6 and are unable to do so due to the usage of TLS. The
standard library will continue to use ELF based TLS on OSX by default (as the
officially supported platform is 10.7+), but this adds an option to compile the
standard library in a way that is compatible with 10.6.
Now that MSVC support has landed in the most recent nightlies we can now have
MSVC bootstrap itself without going through a GNU compiler first. Unfortunately,
however, the bootstrap currently fails due to the compiler not being able to
find the llvm-ar.exe tool during the stage0 libcore compile. The compiler cannot
find this tool because it's looking inside a directory that does not exist:
$SYSROOT/rustlib/x86_64-pc-windows-gnu/bin
The `gnu` on this triple is because the bootstrap compiler's host architecture
is GNU. The build system, however, only arranges for the llvm-ar.exe tool to be
available in this location:
$SYSROOT/rustlib/x86_64-pc-windows-msvc/bin
To resolve this discrepancy, the build system has been modified to understand
triples that are bootstrapped from another triple, and in this case copy the
native tools to the right location.
The changes scaled back in 4cc025d8 were a little too aggressive and broke a
bunch of cross compilations by not defining the `LINK_$(1)` variable for all
targets. This commit ensures that the variable is defined for all targets by
defaulting it to the normal compiler if it's not already defined (it's only
defined specially for MSVC).
Closes#25723Closes#25802
The current codegen tests only compare IR line counts between similar
rust and C programs, the latter getting compiled with clang. That looked
like a good idea back then, but actually things like lifetime intrinsics
mean that less IR isn't always better, so the metric isn't really
helpful.
Instead, we can start doing tests that check specific aspects of the
generated IR, like attributes or metadata. To do that, we can use LLVM's
FileCheck tool which has a number of useful features for such tests.
To start off, I created some tests for a few things that were recently
added and/or broken.
The changes scaled back in 4cc025d8 were a little too aggressive and broke a
bunch of cross compilations by not defining the `LINK_$(1)` variable for all
targets. This commit ensures that the variable is defined for all targets by
defaulting it to the normal compiler if it's not already defined (it's only
defined specially for MSVC).
Closes#25723
The recent MSVC patch made the build system pass explicit linkers to
rustc, but did not set that up for anything other than MSVC.
This is blocking nightlies.
The install target depends on compiler-docs but 'all' does not.
This means that running 'make && make install' will run additional
doc builds and tests during installation, which hides bugs in
the build.
For now this just unconditionally stops building compiler docs.
The install target depends on compiler-docs but 'all' does not.
This means that running 'make && make install' will run additional
doc builds and tests during installation, which hides bugs in
the build.
For now this just unconditionally stops building compiler docs.
Special thanks to @retep998 for the [excellent writeup](https://github.com/rust-lang/rfcs/issues/1061) of tasks to be done and @ricky26 for initially blazing the trail here!
# MSVC Support
This goal of this series of commits is to add MSVC support to the Rust compiler
and build system, allowing it more easily interoperate with Visual Studio
installations and native libraries compiled outside of MinGW.
The tl;dr; of this change is that there is a new target of the compiler,
`x86_64-pc-windows-msvc`, which will not interact with the MinGW toolchain at
all and will instead use `link.exe` to assemble output artifacts.
## Why try to use MSVC?
With today's Rust distribution, when you install a compiler on Windows you also
install `gcc.exe` and a number of supporting libraries by default (this can be
opted out of). This allows installations to remain independent of MinGW
installations, but it still generally requires native code to be linked with
MinGW instead of MSVC. Some more background can also be found in #1768 about the
incompatibilities between MinGW and MSVC.
Overall the current installation strategy is quite nice so long as you don't
interact with native code, but once you do the usage of a MinGW-based `gcc.exe`
starts to get quite painful.
Relying on a nonstandard Windows toolchain has also been a long-standing "code
smell" of Rust and has been slated for remedy for quite some time now. Using a
standard toolchain is a great motivational factor for improving the
interoperability of Rust code with the native system.
## What does it mean to use MSVC?
"Using MSVC" can be a bit of a nebulous concept, but this PR defines it as:
* The build system for Rust will build as much code as possible with the MSVC
compiler, `cl.exe`.
* The build system will use native MSVC tools for managing archives.
* The compiler will link all output with `link.exe` instead of `gcc.exe`.
None of these are currently implemented today, but all are required for the
compiler to fluently interoperate with MSVC.
## How does this all work?
At the highest level, this PR adds a new target triple to the Rust compiler:
x86_64-pc-windows-msvc
All logic for using MSVC or not is scoped within this triple and code can
conditionally build for MSVC or MinGW via:
#[cfg(target_env = "msvc")]
It is expected that auto builders will be set up for MSVC-based compiles in
addition to the existing MinGW-based compiles, and we will likely soon start
shipping MSVC nightlies where `x86_64-pc-windows-msvc` is the host target triple
of the compiler.
# Summary of changes
Here I'll explain at a high level what many of the changes made were targeted
at, but many more details can be found in the commits themselves. Many thanks to
@retep998 for the excellent writeup in rust-lang/rfcs#1061 and @rick26 for a lot
of the initial proof-of-concept work!
## Build system changes
As is probably expected, a large chunk of this PR is changes to Rust's build
system to build with MSVC. At a high level **it is an explicit non goal** to
enable building outside of a MinGW shell, instead all Makefile infrastructure we
have today is retrofitted with support to use MSVC instead of the standard MSVC
toolchain. Some of the high-level changes are:
* The configure script now detects when MSVC is being targeted and adds a number
of additional requirements about the build environment:
* The `--msvc-root` option must be specified or `cl.exe` must be in PATH to
discover where MSVC is installed. The compiler in use is also required to
target x86_64.
* Once the MSVC root is known, the INCLUDE/LIB environment variables are
scraped so they can be reexported by the build system.
* CMake is required to build LLVM with MSVC (and LLVM is also configured with
CMake instead of the normal configure script).
* jemalloc is currently unconditionally disabled for MSVC targets as jemalloc
isn't a hard requirement and I don't know how to build it with MSVC.
* Invocations of a C and/or C++ compiler are now abstracted behind macros to
appropriately call the underlying compiler with the correct format of
arguments, for example there is now a macro for "assemble an archive from
objects" instead of hard-coded invocations of `$(AR) crus liboutput.a ...`
* The output filenames for standard libraries such as morestack/compiler-rt are
now "more correct" on windows as they are shipped as `foo.lib` instead of
`libfoo.a`.
* Rust targets can now depend on native tools provided by LLVM, and as you'll
see in the commits the entire MSVC target depends on `llvm-ar.exe`.
* Support for custom arbitrary makefile dependencies of Rust targets has been
added. The MSVC target for `rustc_llvm` currently requires a custom `.DEF`
file to be passed to the linker to get further linkages to complete.
## Compiler changes
The modifications made to the compiler have so far largely been minor tweaks
here and there, mostly just adding a layer of abstraction over whether MSVC or a
GNU-like linker is being used. At a high-level these changes are:
* The section name for metadata storage in dynamic libraries is called `.rustc`
for MSVC-based platorms as section names cannot contain more than 8
characters.
* The implementation of `rustc_back::Archive` was refactored, but the
functionality has remained the same.
* Targets can now specify the default `ar` utility to use, and for MSVC this
defaults to `llvm-ar.exe`
* The building of the linker command in `rustc_trans:🔙:link` has been
abstracted behind a trait for the same code path to be used between GNU and
MSVC linkers.
## Standard library changes
Only a few small changes were required to the stadnard library itself, and only
for minor differences between the C runtime of msvcrt.dll and MinGW's libc.a
* Some function names for floating point functions have leading underscores, and
some are not present at all.
* Linkage to the `advapi32` library for crypto-related functions is now
explicit.
* Some small bits of C code here and there were fixed for compatibility with
MSVC's cl.exe compiler.
# Future Work
This commit is not yet a 100% complete port to using MSVC as there are still
some key components missing as well as some unimplemented optimizations. This PR
is already getting large enough that I wanted to draw the line here, but here's
a list of what is not implemented in this PR, on purpose:
## Unwinding
The revision of our LLVM submodule [does not seem to implement][llvm] does not
support lowering SEH exception handling on the Windows MSVC targets, so
unwinding support is not currently implemented for the standard library (it's
lowered to an abort).
[llvm]: https://github.com/rust-lang/llvm/blob/rust-llvm-2015-02-19/lib/CodeGen/Passes.cpp#L454-L461
It looks like, however, that upstream LLVM has quite a bit more support for SEH
unwinding and landing pads than the current revision we have, so adding support
will likely just involve updating LLVM and then adding some shims of our own
here and there.
## dllimport and dllexport
An interesting part of Windows which MSVC forces our hand on (and apparently
MinGW didn't) is the usage of `dllimport` and `dllexport` attributes in LLVM IR
as well as native dependencies (in C these correspond to
`__declspec(dllimport)`).
Whenever a dynamic library is built by MSVC it must have its public interface
specified by functions tagged with `dllexport` or otherwise they're not
available to be linked against. This poses a few problems for the compiler, some
of which are somewhat fundamental, but this commit alters the compiler to attach
the `dllexport` attribute to all LLVM functions that are reachable (e.g. they're
already tagged with external linkage). This is suboptimal for a few reasons:
* If an object file will never be included in a dynamic library, there's no need
to attach the dllexport attribute. Most object files in Rust are not destined
to become part of a dll as binaries are statically linked by default.
* If the compiler is emitting both an rlib and a dylib, the same source object
file is currently used but with MSVC this may be less feasible. The compiler
may be able to get around this, but it may involve some invasive changes to
deal with this.
The flipside of this situation is that whenever you link to a dll and you import
a function from it, the import should be tagged with `dllimport`. At this time,
however, the compiler does not emit `dllimport` for any declarations other than
constants (where it is required), which is again suboptimal for even more
reasons!
* Calling a function imported from another dll without using `dllimport` causes
the linker/compiler to have extra overhead (one `jmp` instruction on x86) when
calling the function.
* The same object file may be used in different circumstances, so a function may
be imported from a dll if the object is linked into a dll, but it may be
just linked against if linked into an rlib.
* The compiler has no knowledge about whether native functions should be tagged
dllimport or not.
For now the compiler takes the perf hit (I do not have any numbers to this
effect) by marking very little as `dllimport` and praying the linker will take
care of everything. Fixing this problem will likely require adding a few
attributes to Rust itself (feature gated at the start) and then strongly
recommending static linkage on Windows! This may also involve shipping a
statically linked compiler on Windows instead of a dynamically linked compiler,
but these sorts of changes are pretty invasive and aren't part of this PR.
## CI integration
Thankfully we don't need to set up a new snapshot bot for the changes made here as our snapshots are freestanding already, we should be able to use the same snapshot to bootstrap both MinGW and MSVC compilers (once a new snapshot is made from these changes).
I plan on setting up a new suite of auto bots which are testing MSVC configurations for now as well, for now they'll just be bootstrapping and not running tests, but once unwinding is implemented they'll start running all tests as well and we'll eventually start gating on them as well.
---
I'd love as many eyes on this as we've got as this was one of my first interactions with MSVC and Visual Studio, so there may be glaring holes that I'm missing here and there!
cc @retep998, @ricky26, @vadimcn, @klutzy
r? @brson
This commit updates the `dist` target for MSVC to not build the mingw components
and to also ensure that the `llvm-ar.exe` binary is ferried along into the right
location for installs.
Windows needs explicit exports of functions from DLLs but LLVM does not mention
any of its symbols as being export-able from a DLL. The compiler, however,
relies on being able to use LLVM symbols across DLL boundaries so we need to
force many of LLVM's symbols to be exported from `rustc_llvm.dll`. This commit
adds support for generation of a `rustc_llvm.def` file which is passed along to
the linker when generating `rustc_llvm.dll` which should keep all these symbols
exportable and usable.
The compiler will require that `llvm-ar.exe` be available for MSVC-targeting
builds (more comments on this soon), so this commit adds support for targets to
depend on LLVM tools. The `core` library for MSVC depends on `llvm-ar.exe` which
will be copied into place for the target before the compiler starts to run.
Note that these targets all depend on `llvm-config.exe` to ensure that they're
built before they're attempted to be copied.
This commit updates the rustllvm.mk file with the necessary flags and such to
build rustllvm.lib with cl.exe instead of gcc. Some comments can be found in the
commit itself.
It looks like compiler-rt has a cmake build sytem inside its source, but I have
been unable to figure out how to use it and actually build the right library.
For now this commit hard-wires MSVC-targeting builds of libcompiler-rt to
continue using `make` as the primary bulid system, but some frobbing of the
flags are necessary to ensure that the right compiler is used.
Currently the MSVC compilers don't have any cross prefixes and we're only able
to make an MSVC compiler with a cross compile, so just avoid this logic on msvc
for now.
We have a number of support C/C++ files in Rust that we link into the standard
library and other various locations, and these all need to be built with cl.exe
instead of gcc.exe when targeting MSVC. This commit adds helper macros for this
functionality to use different sets of programs/flags/invocations on MSVC than
on GNU-like platforms.
This commit modifies the makefiles to enable building LLVM with cmake and Visual
Studio to generate an LLVM that targets MSVC. Rust's configure script requires
cmake to be installed when targeting MSVC and will configure LLVM with cmake
instead of the normal `./configure` script LLVM provides. The build will then
run cmake to execute the build instead of the normal `make`.
Currently `make clean-llvm` isn't supported on MSVC as I can't figure out how to
run a "clean" target for the Visual Studio files.
This commit starts to add MSVC support to the ./configure script to enable the
build system to detect and build an MSVC target with the cl.exe compiler and
toolchain. The primary change here is a large sanity check when an MSVC target
is requested (and currently only `x86_64-pc-windows-msvc` is recognized).
When building an MSVC target, the configure script either requires the
`--msvc-root` argument or for `cl.exe` to be in `PATH`. It also requires that if
in the path `cl.exe` is the 64-bit version of the compiler.
Once detected the configure script will run the `vcvarsall.bat` script provided
by Visual Studio to learn about the `INCLUDE` and `LIB` variables needed by the
`cl.exe` compiler to run (the default include/lib paths for the
compiler/linker). These variables are then reexported when running `make` to
ensure that our own compiles are running the same toolchain.
The purpose of this detection and environment variable scraping is to avoid
requiring the build itself to be run inside of a `cmd.exe` shell but rather
allow it to run in the currently expected MinGW/MSYS shell.
We use a script called `mklldeps.py` to run `llvm-config` to generate a list
of LLVM libraries and native dependencies needed by LLVM, but all cross-compiled
LLVM builds were using the *host triple's* `llvm-config` instead of the
*target's* `llvm-config`. This commit alters this to require the right
`llvmdeps.rs` to be generated which will run the correct `llvm-config`.
Previously libmorestack.a and libcompiler-rt.a were installed, but link.exe
looks for morestack.lib and compiler-rt.lib by default, so we need to install
these with the correct name
The code takes a prefix of the MD5 hash of the version string.
Since the hash command differs across GNU and BSD platforms, we scan for
the right one in the configure script.
Closes#25007
The code takes a prefix of the MD5 hash of the version string.
Since the hash command differs across GNU and BSD platforms, we scan for
the right one in the configure script.
Closes#25007
Then, decouple the question of whether the compiler/stdlib carry
debuginfo (which is controlled via `--enable-debuginfo` and implied by
`--enable-debug`) from the question of whether the tests carry
debuginfo (which now no longer is implied by `--enable-debug` nor
`--enable-debuginfo`, and is off by default).
These commits build on [some great work on reddit](http://www.reddit.com/r/rust/comments/33boew/weekend_experiment_link_rust_programs_against/) for adding MUSL support to the compiler. This goal of this PR is to enable a `--target x86_64-unknown-linux-musl` argument to the compiler to work A-OK. The outcome here is that there are 0 compile-time dependencies for a MUSL-targeting build *except for a linker*. Currently this also assumes that MUSL is being used for statically linked binaries so there is no support for dynamically linked binaries with MUSL.
MUSL support largely just entailed munging around with the linker and where libs are located, and the major highlights are:
* The entirety of `libc.a` is included in `liblibc.rlib` (statically included as an archive).
* The entirety of `libunwind.a` is included in `libstd.rlib` (like with liblibc).
* The target specification for MUSL passes a number of ... flavorful options! Each option is documented in the relevant commit.
* The entire test suite currently passes with MUSL as a target, except for:
* Dynamic linking tests are all ignored as it's not supported with MUSL
* Stack overflow detection is not working MUSL yet (I'm not sure why)
* There is a language change included in this PR to add a `target_env` `#[cfg]` directive. This is used to conditionally build code for only MUSL (or for linux distros not MUSL). I highly suspect that this will also be used by Windows to target MSVC instead of a MinGW-based toolchain.
To build a compiler targeting MUSL you need to follow these steps:
1. Clone the current MUSL repo from `git://git.musl-libc.org/musl`. Build this as usual and install it.
2. Clone and build LLVM's [libcxxabi](http://libcxxabi.llvm.org/) library. Only the `libunwind.a` artifact is needed. I have tried using upstream libunwind's source repo but I have not gotten unwinding to work with it unfortunately. Move `libunwind.a` adjacent to MUSL's `libc.a`
3. Configure a Rust checkout with `--target=x86_64-unknown-linux-musl --musl-root=$MUSL_ROOT` where `MUSL_ROOT` is where you installed MUSL in step 1.
I hope to improve building a copy of libunwind as it's still a little sketchy and difficult to do today, but other than that everything should "just work"! This PR is not intended to include 100% comprehensive support for MUSL, as future modifications will probably be necessary.
There were a few test cases to fix:
* Dynamic libraries are not supported with MUSL right now, so all of those
related test which force or require dylibs are ignored.
* Looks like the default stack for MUSL is smaller than glibc, so a few stack
allocations in benchmarks were boxed up (shouldn't have a perf impact).
* Some small linkage tweaks here and there
* Out-of-stack detection does not currently work with MUSL
This commit adds support to the makefiles, configuration script, and build
system to understand MUSL. This is broken up into a few parts:
* Any target of the form `*-musl` requires the `--musl-root` option to
`./configure` which will indicate the root of the MUSL installation. It is
also expected that there is a libunwind build inside of that installation
built against that MUSL.
* Objects from MUSL are copied into the build tree for Rust to be statically
linked into the appropriate Rust library.
* Objects for binary startup and shutdown are included in each Rust installation
by default for MUSL. This requires MUSL to only be installed on the machine
compiling rust. Only a linker will be necessary for compiling against MUSL on
a target machine.
Eventually a MUSL and/or libunwind build may be integrated by default into the
build but for now they are just always assumed to exist externally.
In most places in mk/tests.mk, it's positioned after rpass-full and
before cfail-full (because rfail comes before cfail). The order of tests
seems a little inconsistent, but reordering everywhere would obscure this
commit.
This required fixing the `pretty-rpass-full` tests to have the same `$$(CSREQ$(1)_T_$(2)_H_$(3))` dependencies as the `rpass-full` and `cfail-full` tests. It also required fixing the `run-make/simd-ffi` test to use unique names for its output files.
The current code attempts to define the
PRETTY_DEPS$(1)_H_$(3)_pretty-rpass-full variable, which does not work,
because $(1) and $(3) are not inside a function. Moreover, there is a test
(run-pass-fulldeps/compiler-calls.rs) that uses rustc_driver, which is not
an indirect dependency of librustc or libsyntax. Listing all the
dependencies will be hard to maintain, but there's a better way to do
this...
As with the rpass-full and cfail-full tests, add dependencies using the
$$(CSREQ$(1)_T_$(3)_H_$(3)) variable, which includes the complete set of
host and target crates, built for a particular stage and host. We use
T_$(3), not T_$(2), because we only build LLVM for host triples (not
target triples), so we can only build rustc_llvm for host triples. The
fulldeps tests that use plugins need host rustc crates, whereas fulldeps
tests that link against rustc and run should be skipped for
cross-compilation (such as Android).
Fixes#22021
Instead of rustc-1.0.0-beta-$triple.tar.gz, betas will be named
rustc-beta-$triple.tar.gz. This will give betas a stable download
URL, prevent old artifacts from accumulating in the dist server's
root directory, and not require the website to be updated every
beta.
As a tradeoff, it will be harder to download previous betas because
they will need to be located in the archives.
This patch
1. renames libunicode to librustc_unicode,
2. deprecates several pieces of libunicode (see below), and
3. removes references to deprecated functions from
librustc_driver and libsyntax. This may change pretty-printed
output from these modules in cases involving wide or combining
characters used in filenames, identifiers, etc.
The following functions are marked deprecated:
1. char.width() and str.width():
--> use unicode-width crate
2. str.graphemes() and str.grapheme_indices():
--> use unicode-segmentation crate
3. str.nfd_chars(), str.nfkd_chars(), str.nfc_chars(), str.nfkc_chars(),
char.compose(), char.decompose_canonical(), char.decompose_compatible(),
char.canonical_combining_class():
--> use unicode-normalization crate
This patch
1. renames libunicode to librustc_unicode,
2. deprecates several pieces of libunicode (see below), and
3. removes references to deprecated functions from
librustc_driver and libsyntax. This may change pretty-printed
output from these modules in cases involving wide or combining
characters used in filenames, identifiers, etc.
The following functions are marked deprecated:
1. char.width() and str.width():
--> use unicode-width crate
2. str.graphemes() and str.grapheme_indices():
--> use unicode-segmentation crate
3. str.nfd_chars(), str.nfkd_chars(), str.nfc_chars(), str.nfkc_chars(),
char.compose(), char.decompose_canonical(), char.decompose_compatible(),
char.canonical_combining_class():
--> use unicode-normalization crate