Skip to content

Commit b538189

Browse files
committed
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.
1 parent ce8b317 commit b538189

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,37 @@ endif
4545
# instead of `lib.exe` for assembling archives, so we need to inject this custom
4646
# dependency here.
4747
NATIVE_TOOL_DEPS_core_T_x86_64-pc-windows-msvc += llvm-ar.exe
48+
49+
# When working with MSVC on windows, each DLL needs to explicitly declare its
50+
# interface to the outside world through some means. The options for doing so
51+
# include:
52+
#
53+
# 1. A custom attribute on each function itself
54+
# 2. A linker argument saying what to export
55+
# 3. A file which lists all symbols that need to be exported
56+
#
57+
# The Rust compiler takes care (1) for us for all Rust code by annotating all
58+
# public-facing functions with dllexport, but we have a few native dependencies
59+
# which need to cross the DLL boundary. The most important of these dependencies
60+
# is LLVM which is linked into `rustc_llvm.dll` but primarily used from
61+
# `rustc_trans.dll`. This means that many of LLVM's C API functions need to be
62+
# exposed from `rustc_llvm.dll` to be forwarded over the boundary.
63+
#
64+
# Unfortunately, at this time, LLVM does not handle this sort of exportation on
65+
# Windows for us, so we're forced to do it ourselves if we want it (which seems
66+
# like the path of least resistance right now). To do this we generate a `.DEF`
67+
# file [1] which we then custom-pass to the linker when building the rustc_llvm
68+
# crate. This DEF file list all symbols that are exported from
69+
# `src/librustc_llvm/lib.rs` and is generated by a small python script.
70+
#
71+
# Fun times!
72+
#
73+
# [1]: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
74+
RUSTFLAGS_rustc_llvm_T_x86_64-pc-windows-msvc += \
75+
-C link-args="-DEF:x86_64-pc-windows-msvc/rt/rustc_llvm.def"
76+
CUSTOM_DEPS_rustc_llvm_T_x86_64-pc-windows-msvc += \
77+
x86_64-pc-windows-msvc/rt/rustc_llvm.def
78+
79+
x86_64-pc-windows-msvc/rt/rustc_llvm.def: $(S)src/etc/mklldef.py \
80+
$(S)src/librustc_llvm/lib.rs
81+
$(CFG_PYTHON) $^ $@ rustc_llvm-$(CFG_FILENAME_EXTRA)

mk/target.mk

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) := \
3939
$$(foreach dep,$$(NATIVE_DEPS_$(4)_T_$(2)), \
4040
$$(RT_OUTPUT_DIR_$(2))/$$(dep)) \
4141
$$(foreach dep,$$(NATIVE_TOOL_DEPS_$(4)_T_$(2)), \
42-
$$(TBIN$(1)_T_$(3)_H_$(3))/$$(dep))
42+
$$(TBIN$(1)_T_$(3)_H_$(3))/$$(dep)) \
43+
$$(CUSTOM_DEPS_$(4)_T_$(2))
4344
endef
4445

4546
$(foreach host,$(CFG_HOST), \
@@ -92,6 +93,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
9293
$$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \
9394
$$(LLVM_STDCPP_RUSTFLAGS_$(2)) \
9495
$$(RUSTFLAGS_$(4)) \
96+
$$(RUSTFLAGS_$(4)_T_$(2)) \
9597
--out-dir $$(@D) \
9698
-C extra-filename=-$$(CFG_FILENAME_EXTRA) \
9799
$$<

src/etc/mklldef.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
# file at the top-level directory of this distribution and at
3+
# http://rust-lang.org/COPYRIGHT.
4+
#
5+
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
# option. This file may not be copied, modified, or distributed
9+
# except according to those terms.
10+
11+
import sys
12+
13+
input_file = sys.argv[1]
14+
output_file = sys.argv[2]
15+
name = sys.argv[3]
16+
17+
with open(input_file, 'r') as f:
18+
with open(output_file, 'w') as g:
19+
print >> g, 'LIBRARY ' + name
20+
print >> g, 'EXPORTS'
21+
for x in f:
22+
x = str(x)
23+
if not x.startswith(' pub fn LLVM'): continue
24+
name = x[11:x.find('(')]
25+
print >> g, ' ' + name

0 commit comments

Comments
 (0)