mk: Hardcode the bootstrap key for each release
Starting with the 1.10.0 release we would like to bootstrap all compilers from
the previous stable release. For example the 1.10.0 compiler should bootstrap
from the literal 1.9.0 release artifacts. To do this, however, we need a way to
enable unstable features temporarily in a stable compiler (as the released
compiler is stable), but it turns out we already have a way to do that!
At compile time the configure script selects a `CFG_BOOTSTRAP_KEY` variable
value and then exports it into the makefiles. If the `RUSTC_BOOTSTRAP_KEY`
environment variable is set to this value, then the compiler is allowed to
"cheat" and use unstable features.
This method of choosing the bootstrap key, however, is problematic for the
intention of bootstrapping from the previous release. Each time a 1.9.0 compiler
is created, a new bootstrap key will be selected. That means that the 1.10.0
compiler will only compile from *our* literal release artifacts. Instead
distributions would like to bootstrap from their own compilers, so instead we
simply hardcode the bootstrap key for each release.
This patch uses the same `CFG_FILENAME_EXTRA` value (a hash of the release
string) as the bootstrap key. Consequently all 1.9.0 compilers, no matter where
they are compiled, will have the same bootstrap key. Additionally we won't need
to keep updating this as it'll be based on the release number anyway.
Once the 1.9.0 beta has been created, we can update the 1.10.0 nightly sources
(the `master` branch at that time) to bootstrap from that release using this
hard-coded bootstrap key. We will likely just hardcode into the makefiles what
the previous bootstrap key was and we'll change that whenever the stage0
compiler is updated.
Starting with the 1.10.0 release we would like to bootstrap all compilers from
the previous stable release. For example the 1.10.0 compiler should bootstrap
from the literal 1.9.0 release artifacts. To do this, however, we need a way to
enable unstable features temporarily in a stable compiler (as the released
compiler is stable), but it turns out we already have a way to do that!
At compile time the configure script selects a `CFG_BOOTSTRAP_KEY` variable
value and then exports it into the makefiles. If the `RUSTC_BOOTSTRAP_KEY`
environment variable is set to this value, then the compiler is allowed to
"cheat" and use unstable features.
This method of choosing the bootstrap key, however, is problematic for the
intention of bootstrapping from the previous release. Each time a 1.9.0 compiler
is created, a new bootstrap key will be selected. That means that the 1.10.0
compiler will only compile from *our* literal release artifacts. Instead
distributions would like to bootstrap from their own compilers, so instead we
simply hardcode the bootstrap key for each release.
This patch uses the same `CFG_FILENAME_EXTRA` value (a hash of the release
string) as the bootstrap key. Consequently all 1.9.0 compilers, no matter where
they are compiled, will have the same bootstrap key. Additionally we won't need
to keep updating this as it'll be based on the release number anyway.
Once the 1.9.0 beta has been created, we can update the 1.10.0 nightly sources
(the `master` branch at that time) to bootstrap from that release using this
hard-coded bootstrap key. We will likely just hardcode into the makefiles what
the previous bootstrap key was and we'll change that whenever the stage0
compiler is updated.
Our `codegen` test suite requires the LLVM `FileCheck` utility but unfortunately
this isn't always available in all custom LLVM roots (e.g. those specified via
`--llvm-root`). This commit adds a `./configure` option called
`--disable-codegen-tests` which will manually disable running these tests. In
the case that this option is passed we can forgo the need for the `FileCheck`
executable. Note that we still require `FileCheck` by default as we will attempt
to run these tests.
Closes#28667
Detect the triple in the configure script for probing MSVC shenanigans and also
be sure to use `llvm-config` from the build host and not the target when
configuring compiler-rt.
Rust 1.7.0 and newer appears to require LLVM 3.6.0 or newer when
building against a version that's out of the tree with the --llvm-root
flag.
Signed-off-by: Doug Goldstein <cardoe@cardoe.com>
The `--disable-jemalloc` configure option has a failure mode where it will
create a distribution that is not compatible with other compilers. For example
the nightly for Linux will assume that it will link to jemalloc by default as
an allocator for executable crates. If, however, a standard library is used
which was built via `./configure --disable-jemalloc` then this will fail
because the jemalloc crate wasn't built.
While this seems somewhat reasonable as a niche situation, the same mechanism is
used for disabling jemalloc for platforms that just don't support it. For
example if the rumprun target is compiled then the sibiling Linux target *also*
doesn't have jemalloc. This is currently a problem for our cross-build nightlies
which build many targets. If rumprun is also built, it will disable jemalloc for
all targets, which isn't desired.
This commit moves the platform-specific disabling of jemalloc as hardcoded logic
into the makefiles that is scoped per-platform. This way when configuring
multiple targets **without the `--disable-jemalloc` option specified** all
targets will get jemalloc as they should.
In other words, enforce what was documented in #30626 (and also stop blaming it on LLVM, we have at least one Python script of our own).
Also, there is no Python later than 2.7 and there never will be.
This commit adds a `--enable-rustbuild` option to the configure script which
will copy a different `Makefile.in` into place to intercept all `make`
invocations.
Currently this makefile only has one target, but it's expected to be filled out
quite a bit over time!
Backtraces, and the compilation of libbacktrace for asmjs, are disabled.
This port doesn't use jemalloc so, like pnacl, it disables jemalloc *for all targets*
in the configure file.
It disables stack protection.
This target covers MIPS devices that run the trunk version of OpenWRT.
The x86_64-unknown-linux-musl target always links statically to C libraries. For
the mips(el)-unknown-linux-musl target, we opt for dynamic linking (like most of
other targets do) to keep binary size down.
As for the C compiler flags used in the build system, we use the same flags used
for the mips(el)-unknown-linux-gnu target.
r? @alexcrichton
This target covers MIPS devices that run the trunk version of OpenWRT.
The x86_64-unknown-linux-musl target always links statically to C libraries. For
the mips(el)-unknown-linux-musl target, we opt for dynamic linking (like most of
other targets do) to keep binary size down.
As for the C compiler flags used in the build system, we use the same flags used
for the mips(el)-unknown-linux-gnu target.
The purpose of the translation item collector is to find all monomorphic instances of functions, methods and statics that need to be translated into LLVM IR in order to compile the current crate.
So far these instances have been discovered lazily during the trans path. For incremental compilation we want to know the set of these instances in advance, and that is what the trans::collect module provides.
In the future, incremental and regular translation will be driven by the collector implemented here.
We've been seeing a lot of timeouts in tests on the bots and investigation ended
pointing to jemalloc/jemalloc#315 as the culprit. Unfortunately it looks like
that doesn't seem to have a fix on the way soon, so let's temporarily downgrade
back to the previous version of jemalloc we were using (where #30434 was the
most recent upgrade)
We've been seeing a lot of timeouts in tests on the bots and investigation ended
pointing to jemalloc/jemalloc#315 as the culprit. Unfortunately it looks like
that doesn't seem to have a fix on the way soon, so let's temporarily downgrade
back to the previous version of jemalloc we were using (where #30434 was the
most recent upgrade)
This mixes in additional information into the hash that is
passed to -C extra-filename. It can be used to further distinguish
the standard libraries if they must be installed next to each
other.
Closes#29559
On some weird setup where $SHELL is a relative path (can happen under GNU
Screen,) `file -L "$BIN_TO_PROBE"` fails and $CFG_CPUTYPE is wrongly set to
i686. We should not only check its string value but also permission on
filesystem.
This commit changes our distribution and in-tree sources to pass the `-C rpath`
flag by default during compiles. This means that from-source builds, including
our release channels, will have this option enabled as well. Motivated
by #29941, this change means that the compiler should be usable as-is on all
platforms just after extraction or installation. This experience is already true
on Windows but on Unixes you still need to set up LD_LIBRARY_PATH or the
equivalent, which can often be unfortunate.
This option was originally turned off by default for Linux distributions who
tend to take care of these sorts of details themselves, so it is expected that
all those builds of Rust will want to pass `--disable-rpath` to the configure
script to preserve that behavior.
Closes#29941
On some weird setup where $SHELL is a relative path (can happen under GNU
Screen,) `file -L "$BIN_TO_PROBE"` fails and $CFG_CPUTYPE is wrongly set to
i686. We should not only check its string value but also permission on
filesystem.
This handles cases when the LLVM used isn't configured will the 'usual'
targets. Also, cases where LLVM is shared are also handled (ie with
`LD_LIBRARY_PATH` etc).
This commit changes our distribution and in-tree sources to pass the `-C rpath`
flag by default during compiles. This means that from-source builds, including
our release channels, will have this option enabled as well. Motivated
by #29941, this change means that the compiler should be usable as-is on all
platforms just after extraction or installation. This experience is already true
on Windows but on Unixes you still need to set up LD_LIBRARY_PATH or the
equivalent, which can often be unfortunate.
This option was originally turned off by default for Linux distributions who
tend to take care of these sorts of details themselves, so it is expected that
all those builds of Rust will want to pass `--disable-rpath` to the configure
script to preserve that behavior.
Closes#29941
The Rust build scripts do work if the source directory contains spaces. I tried to make it work with spaces. I managed to get the Rust's and LLVM's configure scripts to work with spaces in the path, but I could not figure out how to get the Rust makefiles working.
So for now, this PR updates Rust's `configure` to abort if the source path contains spaces. I also added a note about spaces in the source path to the README.
I think this should close#18477 for now.
Debian wants to build all binaries with particular hardening flags.
The Rust makefiles are inconsistent in which architectures they
correctly include CFLAGS/etc from the enivoronment (see mk/cfg/*).
This patch adds LDFLAGS, and then unconditionally prepends
CFLAGS/LDFLAGS/etc to the build commands.
Part of #28710
Landing pads during stage0 are now enabled by defaullt. Since this has its downsides and upsides either way, I made it possible to change the option through configure.
For most parts, rumprun currently looks like NetBSD, as they share the same
libc and drivers. However, being a unikernel, rumprun does not support
process management, signals or virtual memory, so related functions
might fail at runtime. Stack guards are disabled exactly for this reason.
Code for rumprun is always cross-compiled, it uses always static
linking and needs a custom linker.
it makes rustc compatible with gcc installation that are using
`--program-transform-name' configure flag (on OpenBSD for example).
- detects at configure the name of stdc++ library on the system
- use the detected name in llvm makefile (with enable-static-stdcpp),
and pass it to mklldeps.py
- generate mklldeps.rs using this detected name
note that CFG_STDCPP_NAME is about stdc++ name, not about libc++. If
using libc++, the default name will be `stdc++', but it won't be used
when linking.
Redirect stdout on the python bogosity detector. This is printing
pwd to the terminal currently.
Reformat the bogus python/cmake messages so they format correctly.
echo does not always escape newlines (it doesn't here), and multiline
strings don't whitespace munch.
r? @alexcrichton
Redirect stdout on the python bogosity detector. This is printing
pwd to the terminal currently.
Reformat the bogus python/cmake messages so they format correctly.
echo does not always escape newlines (it doesn't here), and multiline
strings don't whitespace munch.
under OpenBSD, it could be have present multiples versions of gcc compiler:
- gcc-4.2 (with patchs) : c/c++ compiler present in `/usr/bin`. It is unusable to build recent LLVM (so rustc too).
- gcc/g++ -4.9 : c/c++ compiler, installed as third-party with "ports" mechanism. The compiler is installed in `/usr/local` as `egcc` (and `eg++`).
this PR adds probing for `egcc` for `CFG_GCC`, if the first probed `gcc` is too old. It will set `CC` and `CXX` too, in order to pass the variables to LLVM configure if builded.
please note this PR is a first step in order to build rustc under OpenBSD with unpatched tree.
r? @alexcrichton
cc @brson @dhuseby
Visual Studio 2015, recently released, includes the Universal CRT, a different
flavor than was provided before. The binaries and header files for this library
are included in new locations not previously known about by gcc-rs, and this
commit adds support for the necessary probing to find these.
Unfortunately there are no prior examples of this probing to be found in
frameworks like CMake or clang, so this is done is a bit of a sketchy method
today. It assumes that the installation is in a relatively standard format and
then blindly looks for the location of the UCRT. I'd love to switch this over to
using registry keys for probing, but I was currently unable to find such keys.
This should enable the compiler to work outside VS 2015 dev tools prompts.
Adds support to the configure script for detecting Visual Studio 2015 being
installed and builds LLVM/uses cl with that compiler. The compiler will
automatically use this MSVC linker anyway because it's the highest version.
This has travis build LLVM and rustc up to stage1, but not run any tests. It seems wasteful to have the ultimate might of travis running on every PR just to check for whitespace errors. This is a pure subset of the bootstrap, so it shouldn't ever spuriously break.
`make tidy` still runs first, so we still get \"fast errors\" on bad style. However once make tidy passes, the build will simply keep running to try to make rustc. `tidy` takes ~3 mins to complete, so if your build runs longer you can be confident we've gone on to build LLVM/rustc. In principle this is configured to use ccache (it shows up in the build logs as uploaded/downloaded), but I found no actual performance changes in using it.
Maybe someone at @travis-ci knows what's up with that.
For reference, here is a successful build with ccache enabled: https://travis-ci.org/Gankro/rust/builds/70821237
and one without: https://travis-ci.org/Gankro/rust/builds/70812814
Builds seem to take about 41mins regardless.
r? @alexcrichton
Tidy is still run first for failing fast on the easy stuff.
To accomplish this we have travis actually persist ccache across builds. This
has LLVM built within 6 minutes, and all of stage1 built within 18.
Caching should work on fresh PRs (cache acquired from the master branch).
Because all we persist is ccache, there is minimal danger of persisting corrupt
build state.
I had to mangle `configure` a bit to make --enable-ccache work when custom
compilers are provide via CC and CXX.
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.
I've configured with the parameters suggested by @brson in #18670 and
confirmed that it works on Gentoo Linux amd64.
Fixes#18670.
Signed-off-by: OGINO Masanori <masanori.ogino@gmail.com>
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>
```
Bug fixes for configure on FreeBSD:
- Don't ban using gcc; newer versions can be installed and other checks should enforce its suitability.
- Don't force Rust to link itself with /usr/local/lib{,gcc4[46]}, which causes builds to fail if Rust is already installed. I've not been able to find an use case where this is actually necessary.
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
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.
Currently, there are two conditional blocks that exist to check for "clang or gcc"
On line 866:
```
if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
then
err "either clang or gcc is required"
fi
```
and on line 1019:
```
if [ -z "$CC" -a -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
then
err "either clang or gcc is required"
fi
```
Given the order of the clauses, this results in the "either clang or gcc is required" error from the earlier block, (even) when CC is set.
The expected behaviour is to honour user-flags, in this case CC.
Aside from removing all hand-holdy compiler checks in favour of actual compiler *feature* checks, this change removes the redundant former block in favour of the latter block, which appears designed to allow the expected behaviour.
The `run` function passed its argument to `msg` via `"$@"`, but `msg`
only printed its first argument. I think the intention was for `msg` to
print all its arguments. (If not, `run` should only `msg "$1"`.)
Took me a moment to figure out that the appropriate response to
"need program file" was to install the program named "file", not
to think "If I didn't need the program file, why would I be
compiling things?".
the "-c" option of head isn't a posix option, and it isn't supported
under openbsd.
prefer the use of cut -c 1-8 (which is posix) to extract the first 8
chars.
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 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.
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