Skip to content

Commit 43cf733

Browse files
committed
Auto merge of #25350 - alexcrichton:msvc, r=brson
Special thanks to @retep998 for the [excellent writeup](rust-lang/rfcs#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::back::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
2 parents c322dbb + cb3071b commit 43cf733

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1832
-1066
lines changed

Makefile.in

-5
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,3 @@ ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \
266266
CFG_INFO := $(info cfg: including ctags rules)
267267
include $(CFG_SRC_DIR)mk/ctags.mk
268268
endif
269-
270-
# Find all of the .d files and include them to add information about
271-
# header file dependencies.
272-
ALL_DEP_FILES := $(ALL_OBJ_FILES:%.o=%.d)
273-
-include $(ALL_DEP_FILES)

configure

+98-10
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ CFG_TARGET=$(to_llvm_triple $CFG_TARGET)
610610
# there's no rpath. This is where the build system itself puts libraries;
611611
# --libdir is used to configure the installation directory.
612612
# FIXME: This needs to parameterized over target triples. Do it in platform.mk
613-
if [ "$CFG_OSTYPE" = "pc-windows-gnu" ]
613+
if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
614614
then
615615
CFG_LIBDIR_RELATIVE=bin
616616
else
@@ -628,7 +628,8 @@ esac
628628

629629
CFG_LIBDIR_RELATIVE=`echo ${CFG_LIBDIR} | cut -c$((${#CFG_PREFIX}+${CAT_INC}))-`
630630

631-
if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] && [ "$CFG_LIBDIR_RELATIVE" != "bin" ]; then
631+
if ( [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ] ) \
632+
&& [ "$CFG_LIBDIR_RELATIVE" != "bin" ]; then
632633
err "libdir on windows should be set to 'bin'"
633634
fi
634635

@@ -817,7 +818,7 @@ then
817818
fi
818819

819820
BIN_SUF=
820-
if [ "$CFG_OSTYPE" = "pc-windows-gnu" ]
821+
if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
821822
then
822823
BIN_SUF=.exe
823824
fi
@@ -1097,6 +1098,65 @@ do
10971098
err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
10981099
fi
10991100
;;
1101+
1102+
x86_64-*-msvc)
1103+
# Currently the build system is not configured to build jemalloc
1104+
# with MSVC, so we omit this optional dependency.
1105+
step_msg "targeting MSVC, disabling jemalloc"
1106+
CFG_DISABLE_JEMALLOC=1
1107+
putvar CFG_DISABLE_JEMALLOC
1108+
1109+
# There are some MSYS python builds which will auto-translate
1110+
# windows-style paths to MSYS-style paths in Python itself.
1111+
# Unfortunately this breaks LLVM's build system as somewhere along
1112+
# the line LLVM prints a path into a file from Python and then CMake
1113+
# later tries to interpret that path. If Python prints a MSYS path
1114+
# and CMake tries to use it as a Windows path, you're gonna have a
1115+
# Bad Time.
1116+
#
1117+
# Consequently here we try to detect when that happens and print an
1118+
# error if it does.
1119+
if $CFG_PYTHON -c 'import sys; print sys.argv[1]' `pwd` | grep '^/'
1120+
then
1121+
err "python is silently translating windows paths to MSYS paths \
1122+
and the build will fail if this python is used.\n\n \
1123+
Either an official python install must be used or an \
1124+
alternative python package in MinGW must be used."
1125+
fi
1126+
1127+
# MSVC requires cmake because that's how we're going to build LLVM
1128+
probe_need CFG_CMAKE cmake
1129+
1130+
# Use the REG program to figure out where VS is installed
1131+
# We need to figure out where cl.exe and link.exe are, so we do some
1132+
# munging and some probing here. We also look for the default
1133+
# INCLUDE and LIB variables for MSVC so we can set those in the
1134+
# build system as well.
1135+
install=$(reg QUERY \
1136+
'HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0' \
1137+
-v InstallDir)
1138+
need_ok "couldn't find visual studio install root"
1139+
CFG_MSVC_ROOT=$(echo "$install" | grep InstallDir | sed 's/.*REG_SZ[ ]*//')
1140+
CFG_MSVC_ROOT=$(dirname "$CFG_MSVC_ROOT")
1141+
CFG_MSVC_ROOT=$(dirname "$CFG_MSVC_ROOT")
1142+
CFG_MSVC_CL="${CFG_MSVC_ROOT}/VC/bin/amd64/cl.exe"
1143+
CFG_MSVC_LIB="${CFG_MSVC_ROOT}/VC/bin/amd64/lib.exe"
1144+
CFG_MSVC_LINK="${CFG_MSVC_ROOT}/VC/bin/amd64/link.exe"
1145+
1146+
vcvarsall="${CFG_MSVC_ROOT}/VC/vcvarsall.bat"
1147+
CFG_MSVC_INCLUDE_PATH=$(cmd /c "\"$vcvarsall\" amd64 && cmd /c echo %INCLUDE%")
1148+
need_ok "failed to learn about MSVC's INCLUDE"
1149+
CFG_MSVC_LIB_PATH=$(cmd /c "\"$vcvarsall\" amd64 && cmd /c echo %LIB%")
1150+
need_ok "failed to learn about MSVC's LIB"
1151+
1152+
putvar CFG_MSVC_ROOT
1153+
putvar CFG_MSVC_CL
1154+
putvar CFG_MSVC_LIB
1155+
putvar CFG_MSVC_LINK
1156+
putvar CFG_MSVC_INCLUDE_PATH
1157+
putvar CFG_MSVC_LIB_PATH
1158+
;;
1159+
11001160
*)
11011161
;;
11021162
esac
@@ -1138,6 +1198,7 @@ do
11381198
do
11391199
make_dir $t/rt/stage$s
11401200
make_dir $t/rt/jemalloc
1201+
make_dir $t/rt/compiler-rt
11411202
for i in \
11421203
isaac sync test \
11431204
arch/i386 arch/x86_64 arch/arm arch/aarch64 arch/mips arch/powerpc
@@ -1301,7 +1362,39 @@ do
13011362
done
13021363
fi
13031364

1304-
if [ ${do_reconfigure} -ne 0 ]
1365+
use_cmake=0
1366+
case "$t" in
1367+
(*-msvc)
1368+
use_cmake=1
1369+
;;
1370+
esac
1371+
1372+
if [ ${do_reconfigure} -ne 0 ] && [ ${use_cmake} -ne 0 ]
1373+
then
1374+
msg "configuring LLVM for $t with cmake"
1375+
1376+
CMAKE_ARGS="-DLLVM_INCLUDE_TESTS=OFF"
1377+
if [ ! -z "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then
1378+
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug"
1379+
else
1380+
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release"
1381+
fi
1382+
if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ]
1383+
then
1384+
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=OFF"
1385+
else
1386+
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON"
1387+
fi
1388+
1389+
msg "configuring LLVM with:"
1390+
msg "$CMAKE_ARGS"
1391+
(cd $LLVM_BUILD_DIR && "$CFG_CMAKE" $CFG_LLVM_SRC_DIR \
1392+
-G "Visual Studio 12 2013 Win64" \
1393+
$CMAKE_ARGS)
1394+
need_ok "LLVM cmake configure failed"
1395+
fi
1396+
1397+
if [ ${do_reconfigure} -ne 0 ] && [ ${use_cmake} -eq 0 ]
13051398
then
13061399
# LLVM's configure doesn't recognize the new Windows triples yet
13071400
gnu_t=$(to_gnu_triple $t)
@@ -1325,7 +1418,7 @@ do
13251418
# (llvm's configure tries to find pthread first, so we have to disable it explicitly.)
13261419
# Also note that pthreads works badly on mingw-w64 systems: #8996
13271420
case "$CFG_BUILD" in
1328-
(*-windows-*)
1421+
(*-windows-gnu)
13291422
LLVM_OPTS="$LLVM_OPTS --disable-pthreads"
13301423
;;
13311424
esac
@@ -1509,11 +1602,6 @@ do
15091602
putvar $CFG_LLVM_INST_DIR
15101603
done
15111604

1512-
# Munge any paths that appear in config.mk back to posix-y
1513-
cp config.tmp config.tmp.bak
1514-
sed -e 's@ \([a-zA-Z]\):[/\\]@ /\1/@g;' <config.tmp.bak >config.tmp
1515-
rm -f config.tmp.bak
1516-
15171605
msg
15181606
copy_if_changed ${CFG_SRC_DIR}Makefile.in ./Makefile
15191607
move_if_changed config.tmp config.mk

mk/cfg/aarch64-apple-ios.mk

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
55
CFG_IOS_SDK_aarch64-apple-ios := $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null)
66
CFG_IOS_SDK_FLAGS_aarch64-apple-ios := -target aarch64-apple-darwin -isysroot $(CFG_IOS_SDK_aarch64-apple-ios) -mios-version-min=7.0 -arch arm64
77
CC_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
8+
LINK_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
89
CXX_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
910
CPP_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
1011
AR_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos ar)

mk/cfg/aarch64-linux-android.mk

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# aarch64-linux-android configuration
22
# CROSS_PREFIX_aarch64-linux-android-
33
CC_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-gcc
4+
LINK_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-gcc
45
CXX_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-g++
56
CPP_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-gcc -E
67
AR_aarch64-linux-android=$(CFG_ANDROID_CROSS_PATH)/bin/aarch64-linux-android-ar

mk/cfg/aarch64-unknown-linux-gnu.mk

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# aarch64-unknown-linux-gnu configuration
22
CROSS_PREFIX_aarch64-unknown-linux-gnu=aarch64-linux-gnu-
33
CC_aarch64-unknown-linux-gnu=gcc
4+
LINK_aarch64-unknown-linux-gnu=gcc
45
CXX_aarch64-unknown-linux-gnu=g++
56
CPP_aarch64-unknown-linux-gnu=gcc -E
67
AR_aarch64-unknown-linux-gnu=ar

mk/cfg/arm-linux-androideabi.mk

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# arm-linux-androideabi configuration
2+
LINK_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-gcc
23
CC_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-gcc
34
CXX_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-g++
45
CPP_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-gcc -E

mk/cfg/x86_64-pc-windows-gnu.mk

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# x86_64-pc-windows-gnu configuration
22
CROSS_PREFIX_x86_64-pc-windows-gnu=x86_64-w64-mingw32-
33
CC_x86_64-pc-windows-gnu=gcc
4+
LINK_x86_64-pc-windows-gnu=gcc
45
CXX_x86_64-pc-windows-gnu=g++
56
CPP_x86_64-pc-windows-gnu=gcc -E
67
AR_x86_64-pc-windows-gnu=ar

mk/cfg/x86_64-pc-windows-msvc.mk

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# x86_64-pc-windows-msvc configuration
2+
CC_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
3+
LINK_x86_64-pc-windows-msvc="$(CFG_MSVC_LINK)" -nologo
4+
CXX_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
5+
CPP_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
6+
AR_x86_64-pc-windows-msvc="$(CFG_MSVC_LIB)" -nologo
7+
CFG_LIB_NAME_x86_64-pc-windows-msvc=$(1).dll
8+
CFG_STATIC_LIB_NAME_x86_64-pc-windows-msvc=$(1).lib
9+
CFG_LIB_GLOB_x86_64-pc-windows-msvc=$(1)-*.dll
10+
CFG_LIB_DSYM_GLOB_x86_64-pc-windows-msvc=$(1)-*.dylib.dSYM
11+
CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-msvc :=
12+
CFG_GCCISH_CFLAGS_x86_64-pc-windows-msvc :=
13+
CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-msvc :=
14+
CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-msvc :=
15+
CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-msvc :=
16+
CFG_LLC_FLAGS_x86_64-pc-windows-msvc :=
17+
CFG_INSTALL_NAME_x86_64-pc-windows-msvc =
18+
CFG_EXE_SUFFIX_x86_64-pc-windows-msvc := .exe
19+
CFG_WINDOWSY_x86_64-pc-windows-msvc := 1
20+
CFG_UNIXY_x86_64-pc-windows-msvc :=
21+
CFG_LDPATH_x86_64-pc-windows-msvc :=
22+
CFG_RUN_x86_64-pc-windows-msvc=$(2)
23+
CFG_RUN_TARG_x86_64-pc-windows-msvc=$(call CFG_RUN_x86_64-pc-windows-msvc,,$(2))
24+
CFG_GNU_TRIPLE_x86_64-pc-windows-msvc := x86_64-pc-win32
25+
26+
# These two environment variables are scraped by the `./configure` script and
27+
# are necessary for `cl.exe` to find standard headers (the INCLUDE variable) and
28+
# for `link.exe` to find standard libraries (the LIB variable).
29+
ifdef CFG_MSVC_INCLUDE_PATH
30+
export INCLUDE := $(CFG_MSVC_INCLUDE_PATH)
31+
endif
32+
ifdef CFG_MSVC_LIB_PATH
33+
export LIB := $(CFG_MSVC_LIB_PATH)
34+
endif
35+
36+
# Unfortunately `link.exe` is also a program in `/usr/bin` on MinGW installs,
37+
# but it's not the one that we want. As a result we make sure that our detected
38+
# `link.exe` shows up in PATH first.
39+
ifdef CFG_MSVC_LINK
40+
export PATH := $(CFG_MSVC_ROOT)/VC/bin/amd64:$(PATH)
41+
endif
42+
43+
# There are more comments about this available in the target specification for
44+
# Windows MSVC in the compiler, but the gist of it is that we use `llvm-ar.exe`
45+
# instead of `lib.exe` for assembling archives, so we need to inject this custom
46+
# dependency here.
47+
NATIVE_TOOL_DEPS_core_T_x86_64-pc-windows-msvc += llvm-ar.exe
48+
INSTALLED_BINS_x86_64-pc-windows-msvc += llvm-ar.exe
49+
50+
# When working with MSVC on windows, each DLL needs to explicitly declare its
51+
# interface to the outside world through some means. The options for doing so
52+
# include:
53+
#
54+
# 1. A custom attribute on each function itself
55+
# 2. A linker argument saying what to export
56+
# 3. A file which lists all symbols that need to be exported
57+
#
58+
# The Rust compiler takes care (1) for us for all Rust code by annotating all
59+
# public-facing functions with dllexport, but we have a few native dependencies
60+
# which need to cross the DLL boundary. The most important of these dependencies
61+
# is LLVM which is linked into `rustc_llvm.dll` but primarily used from
62+
# `rustc_trans.dll`. This means that many of LLVM's C API functions need to be
63+
# exposed from `rustc_llvm.dll` to be forwarded over the boundary.
64+
#
65+
# Unfortunately, at this time, LLVM does not handle this sort of exportation on
66+
# Windows for us, so we're forced to do it ourselves if we want it (which seems
67+
# like the path of least resistance right now). To do this we generate a `.DEF`
68+
# file [1] which we then custom-pass to the linker when building the rustc_llvm
69+
# crate. This DEF file list all symbols that are exported from
70+
# `src/librustc_llvm/lib.rs` and is generated by a small python script.
71+
#
72+
# Fun times!
73+
#
74+
# [1]: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
75+
RUSTFLAGS_rustc_llvm_T_x86_64-pc-windows-msvc += \
76+
-C link-args="-DEF:x86_64-pc-windows-msvc/rt/rustc_llvm.def"
77+
CUSTOM_DEPS_rustc_llvm_T_x86_64-pc-windows-msvc += \
78+
x86_64-pc-windows-msvc/rt/rustc_llvm.def
79+
80+
x86_64-pc-windows-msvc/rt/rustc_llvm.def: $(S)src/etc/mklldef.py \
81+
$(S)src/librustc_llvm/lib.rs
82+
$(CFG_PYTHON) $^ $@ rustc_llvm-$(CFG_FILENAME_EXTRA)

mk/clean.mk

-13
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,3 @@ $(foreach host, $(CFG_HOST), \
118118
$(eval $(foreach target, $(CFG_TARGET), \
119119
$(eval $(foreach stage, 0 1 2 3, \
120120
$(eval $(call CLEAN_TARGET_STAGE_N,$(stage),$(target),$(host))))))))
121-
122-
define DEF_CLEAN_LLVM_HOST
123-
ifeq ($(CFG_LLVM_ROOT),)
124-
clean-llvm$(1):
125-
$$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) clean
126-
else
127-
clean-llvm$(1): ;
128-
129-
endif
130-
endef
131-
132-
$(foreach host, $(CFG_HOST), \
133-
$(eval $(call DEF_CLEAN_LLVM_HOST,$(host))))

mk/crates.mk

-3
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,6 @@ ONLY_RLIB_rustc_bitflags := 1
125125
# Documented-by-default crates
126126
DOC_CRATES := std alloc collections core libc rustc_unicode
127127

128-
# Installed objects/libraries by default
129-
INSTALLED_OBJECTS := libmorestack.a libcompiler-rt.a
130-
131128
################################################################################
132129
# You should not need to edit below this line
133130
################################################################################

mk/dist.mk

+10-1
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,11 @@ dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1) prepare-overlay-$(1)
144144
@$(call E, build: $$@)
145145
# Copy essential gcc components into installer
146146
ifdef CFG_WINDOWSY_$(1)
147+
ifeq ($$(findstring gnu,$(1)),gnu)
147148
$$(Q)rm -Rf tmp/dist/win-rust-gcc-$(1)
148149
$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image tmp/dist/win-rust-gcc-$(1) $(1)
149150
$$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
151+
endif
150152
endif
151153
$$(Q)$$(S)src/rust-installer/gen-installer.sh \
152154
--product-name=Rust \
@@ -213,7 +215,14 @@ endif
213215
dist-install-dirs: $(foreach host,$(CFG_HOST),dist-install-dir-$(host))
214216

215217
ifdef CFG_WINDOWSY_$(CFG_BUILD)
216-
MAYBE_MINGW_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(MINGW_PKG_NAME)-$(host).tar.gz)
218+
define BUILD_MINGW_TARBALL
219+
ifeq ($$(findstring gnu,$(1)),gnu)
220+
MAYBE_MINGW_TARBALLS += dist/$(MINGW_PKG_NAME)-$(1).tar.gz
221+
endif
222+
endef
223+
224+
$(foreach host,$(CFG_HOST),\
225+
$(eval $(call BUILD_MINGW_TARBALL,$(host))))
217226
endif
218227

219228
ifeq ($(CFG_DISABLE_DOCS),)

0 commit comments

Comments
 (0)