Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed May 19, 2015
1 parent ce8b317 commit b538189
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
34 changes: 34 additions & 0 deletions mk/cfg/x86_64-pc-windows-msvc.mk
Expand Up @@ -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)
4 changes: 3 additions & 1 deletion mk/target.mk
Expand Up @@ -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), \
Expand Down Expand Up @@ -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) \
$$<
Expand Down
25 changes: 25 additions & 0 deletions 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

0 comments on commit b538189

Please sign in to comment.