about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-05-11 15:49:30 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-05-19 10:53:07 -0700
commitb538189ba0abb77658c7b082d2d541daaaa7f80a (patch)
tree10bfbb144628df7710c2c196000818fcf01cabc8
parentce8b317558a83021b7ea0f40c5719995e234da03 (diff)
downloadrust-b538189ba0abb77658c7b082d2d541daaaa7f80a.tar.gz
rust-b538189ba0abb77658c7b082d2d541daaaa7f80a.zip
mk: Generate a .def file for rustc_llvm on MSVC
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.
-rw-r--r--mk/cfg/x86_64-pc-windows-msvc.mk34
-rw-r--r--mk/target.mk4
-rw-r--r--src/etc/mklldef.py25
3 files changed, 62 insertions, 1 deletions
diff --git a/mk/cfg/x86_64-pc-windows-msvc.mk b/mk/cfg/x86_64-pc-windows-msvc.mk
index 209c53f0452..1a1f059945a 100644
--- a/mk/cfg/x86_64-pc-windows-msvc.mk
+++ b/mk/cfg/x86_64-pc-windows-msvc.mk
@@ -45,3 +45,37 @@ endif
 # instead of `lib.exe` for assembling archives, so we need to inject this custom
 # dependency here.
 NATIVE_TOOL_DEPS_core_T_x86_64-pc-windows-msvc += llvm-ar.exe
+
+# When working with MSVC on windows, each DLL needs to explicitly declare its
+# interface to the outside world through some means. The options for doing so
+# include:
+#
+# 1. A custom attribute on each function itself
+# 2. A linker argument saying what to export
+# 3. A file which lists all symbols that need to be exported
+#
+# The Rust compiler takes care (1) for us for all Rust code by annotating all
+# public-facing functions with dllexport, but we have a few native dependencies
+# which need to cross the DLL boundary. The most important of these dependencies
+# is LLVM which is linked into `rustc_llvm.dll` but primarily used from
+# `rustc_trans.dll`. This means that many of LLVM's C API functions need to be
+# exposed from `rustc_llvm.dll` to be forwarded over the boundary.
+#
+# Unfortunately, at this time, LLVM does not handle this sort of exportation on
+# Windows for us, so we're forced to do it ourselves if we want it (which seems
+# like the path of least resistance right now). To do this we generate a `.DEF`
+# file [1] which we then custom-pass to the linker when building the rustc_llvm
+# crate. This DEF file list all symbols that are exported from
+# `src/librustc_llvm/lib.rs` and is generated by a small python script.
+#
+# Fun times!
+#
+# [1]: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
+RUSTFLAGS_rustc_llvm_T_x86_64-pc-windows-msvc += \
+	-C link-args="-DEF:x86_64-pc-windows-msvc/rt/rustc_llvm.def"
+CUSTOM_DEPS_rustc_llvm_T_x86_64-pc-windows-msvc += \
+	x86_64-pc-windows-msvc/rt/rustc_llvm.def
+
+x86_64-pc-windows-msvc/rt/rustc_llvm.def: $(S)src/etc/mklldef.py \
+			$(S)src/librustc_llvm/lib.rs
+	$(CFG_PYTHON) $^ $@ rustc_llvm-$(CFG_FILENAME_EXTRA)
diff --git a/mk/target.mk b/mk/target.mk
index 4359eec8447..c8efb8e86d6 100644
--- a/mk/target.mk
+++ b/mk/target.mk
@@ -39,7 +39,8 @@ CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) := \
 		$$(foreach dep,$$(NATIVE_DEPS_$(4)_T_$(2)), \
 		  $$(RT_OUTPUT_DIR_$(2))/$$(dep)) \
 		$$(foreach dep,$$(NATIVE_TOOL_DEPS_$(4)_T_$(2)), \
-		  $$(TBIN$(1)_T_$(3)_H_$(3))/$$(dep))
+		  $$(TBIN$(1)_T_$(3)_H_$(3))/$$(dep)) \
+		$$(CUSTOM_DEPS_$(4)_T_$(2))
 endef
 
 $(foreach host,$(CFG_HOST), \
@@ -92,6 +93,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
 		$$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \
 		$$(LLVM_STDCPP_RUSTFLAGS_$(2)) \
 		$$(RUSTFLAGS_$(4)) \
+		$$(RUSTFLAGS_$(4)_T_$(2)) \
 		--out-dir $$(@D) \
 		-C extra-filename=-$$(CFG_FILENAME_EXTRA) \
 		$$<
diff --git a/src/etc/mklldef.py b/src/etc/mklldef.py
new file mode 100644
index 00000000000..d2f8ee469a4
--- /dev/null
+++ b/src/etc/mklldef.py
@@ -0,0 +1,25 @@
+# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+import sys
+
+input_file = sys.argv[1]
+output_file = sys.argv[2]
+name = sys.argv[3]
+
+with open(input_file, 'r') as f:
+    with open(output_file, 'w') as g:
+        print >> g, 'LIBRARY ' + name
+        print >> g, 'EXPORTS'
+        for x in f:
+            x = str(x)
+            if not x.startswith('    pub fn LLVM'): continue
+            name = x[11:x.find('(')]
+            print >> g, '  ' + name