mirror of https://github.com/rust-lang/rust.git
auto merge of #10528 : alexcrichton/rust/static-linking-v2, r=pcwalton
In this series of commits, I've implemented static linking for rust. The scheme I implemented was the same as my [mailing list post](https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html). The commits have more details to the nitty gritty of what went on. I've rebased this on top of my native mutex pull request (#10479), but I imagine that it will land before this lands, I just wanted to pre-emptively get all the rebase conflicts out of the way (becuase this is reorganizing building librustrt as well). Some contentious points I want to make sure are all good: * I've added more "compiler chooses a default" behavior than I would like, I want to make sure that this is all very clearly outlined in the code, and if not I would like to remove behavior or make it clearer. * I want to make sure that the new "fancy suite" tests are ok (using make/python instead of another rust crate) If we do indeed pursue this, I would be more than willing to write up a document describing how linking in rust works. I believe that this behavior should be very understandable, and the compiler should never hinder someone just because linking is a little fuzzy.
This commit is contained in:
commit
4252a24ae1
63
Makefile.in
63
Makefile.in
|
@ -130,6 +130,14 @@ ifndef DEBUG_BORROWS
|
|||
RUSTFLAGS_STAGE2 += -Z no-debug-borrows
|
||||
endif
|
||||
|
||||
# The executables crated during this compilation process have no need to include
|
||||
# static copies of libstd and libextra. We also generate dynamic versions of all
|
||||
# libraries, so in the interest of space, prefer dynamic linking throughout the
|
||||
# compilation process.
|
||||
RUSTFLAGS_STAGE1 += -Z prefer-dynamic
|
||||
RUSTFLAGS_STAGE2 += -Z prefer-dynamic
|
||||
RUSTFLAGS_STAGE3 += -Z prefer-dynamic
|
||||
|
||||
# platform-specific auto-configuration
|
||||
include $(CFG_SRC_DIR)mk/platform.mk
|
||||
|
||||
|
@ -214,7 +222,7 @@ GENERATED :=
|
|||
|
||||
define DEF_LIBS
|
||||
|
||||
CFG_RUNTIME_$(1) :=$(call CFG_LIB_NAME_$(1),rustrt)
|
||||
CFG_RUNTIME_$(1) :=$(call CFG_STATIC_LIB_NAME_$(1),rustrt)
|
||||
CFG_RUSTLLVM_$(1) :=$(call CFG_LIB_NAME_$(1),rustllvm)
|
||||
CFG_STDLIB_$(1) :=$(call CFG_LIB_NAME_$(1),std)
|
||||
CFG_EXTRALIB_$(1) :=$(call CFG_LIB_NAME_$(1),extra)
|
||||
|
@ -239,6 +247,10 @@ LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg)
|
|||
LIBRUSTDOC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc)
|
||||
LIBRUSTUV_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustuv)
|
||||
|
||||
EXTRALIB_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,extra)
|
||||
STDLIB_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,std)
|
||||
LIBRUSTUV_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,rustuv)
|
||||
|
||||
endef
|
||||
|
||||
# $(1) is the path for directory to match against
|
||||
|
@ -392,42 +404,25 @@ TBIN$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/bin
|
|||
TLIB$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/$$(CFG_LIBDIR)
|
||||
|
||||
# The name of the standard and extra libraries used by rustc
|
||||
ifdef CFG_DISABLE_SHAREDSTD
|
||||
HSTDLIB_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/libstd.rlib
|
||||
TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/libstd.rlib
|
||||
HSTDLIB_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_STDLIB_$(3))
|
||||
TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2))
|
||||
|
||||
HEXTRALIB_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/libextra.rlib
|
||||
TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/libextra.rlib
|
||||
HEXTRALIB_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_EXTRALIB_$(3))
|
||||
TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2))
|
||||
|
||||
HLIBRUSTC_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/librustc.rlib
|
||||
TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/librustc.rlib
|
||||
else
|
||||
HSTDLIB_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_STDLIB_$(3))
|
||||
TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2))
|
||||
HLIBRUSTC_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTC_$(3))
|
||||
TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2))
|
||||
|
||||
HEXTRALIB_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_EXTRALIB_$(3))
|
||||
TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2))
|
||||
|
||||
HLIBRUSTC_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTC_$(3))
|
||||
TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2))
|
||||
|
||||
HLIBRUSTUV_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTUV_$(3))
|
||||
TLIBRUSTUV_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2))
|
||||
endif
|
||||
HLIBRUSTUV_DEFAULT$(1)_H_$(3) = \
|
||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTUV_$(3))
|
||||
TLIBRUSTUV_DEFAULT$(1)_T_$(2)_H_$(3) = \
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2))
|
||||
|
||||
# Preqrequisites for using the stageN compiler
|
||||
HSREQ$(1)_H_$(3) = \
|
||||
|
|
|
@ -364,7 +364,6 @@ fi
|
|||
BOOL_OPTIONS=""
|
||||
VAL_OPTIONS=""
|
||||
|
||||
opt sharedstd 1 "build libstd as a shared library"
|
||||
opt valgrind 0 "run tests with valgrind (memcheck by default)"
|
||||
opt helgrind 0 "run tests with helgrind instead of memcheck"
|
||||
opt docs 1 "build documentation"
|
||||
|
|
12
doc/rust.md
12
doc/rust.md
|
@ -1507,19 +1507,15 @@ an `abi` string, as shown here:
|
|||
extern "stdcall" { }
|
||||
~~~~
|
||||
|
||||
The `link_name` attribute allows the name of the library to be specified.
|
||||
The `link` attribute allows the name of the library to be specified. When
|
||||
specified the compiler will attempt to link against the native library of the
|
||||
specified name.
|
||||
|
||||
~~~~ {.xfail-test}
|
||||
#[link_name = "crypto"]
|
||||
#[link(name = "crypto")]
|
||||
extern { }
|
||||
~~~~
|
||||
|
||||
The `nolink` attribute tells the Rust compiler
|
||||
not to do any linking for the external block.
|
||||
This is particularly useful for creating external blocks for libc,
|
||||
which tends to not follow standard library naming conventions
|
||||
and is linked to all Rust programs anyway.
|
||||
|
||||
The type of a function
|
||||
declared in an extern block
|
||||
is `extern "abi" fn(A1, ..., An) -> R`,
|
||||
|
|
10
mk/clean.mk
10
mk/clean.mk
|
@ -59,6 +59,7 @@ clean-generic-$(2)-$(1):
|
|||
$(Q)find $(1)/rustllvm \
|
||||
$(1)/rt \
|
||||
$(1)/test \
|
||||
$(1)/stage* \
|
||||
-name '*.[odasS]' -o \
|
||||
-name '*.so' -o \
|
||||
-name '*.dylib' -o \
|
||||
|
@ -91,13 +92,16 @@ clean$(1)_H_$(2):
|
|||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTC_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBSYNTAX_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(STDLIB_GLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(STDLIB_RGLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_GLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_RGLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTUV_GLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTUV_RGLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTC_GLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTPKG_GLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOC_GLOB_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUSTLLVM_$(2))
|
||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/libstd.rlib
|
||||
|
||||
endef
|
||||
|
||||
|
@ -122,14 +126,16 @@ clean$(1)_T_$(2)_H_$(3):
|
|||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(STDLIB_GLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(STDLIB_RGLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_GLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_RGLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTUV_GLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTUV_RGLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTC_GLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTPKG_GLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOC_GLOB_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(2))
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libstd.rlib
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/librun_pass_stage* # For unix
|
||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/run_pass_stage* # For windows
|
||||
|
|
35
mk/host.mk
35
mk/host.mk
|
@ -50,7 +50,7 @@ $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)): \
|
|||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(4)),$$(notdir $$@))
|
||||
$$(Q)cp $$< $$@
|
||||
$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTC_GLOB_$(4)) \
|
||||
$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTC_DSYM_GLOB_$(4))) \
|
||||
$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTC_DSYM_GLOB_$(4))) \
|
||||
$$(HLIB$(2)_H_$(4))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(4)),$$(notdir $$@))
|
||||
|
||||
|
@ -82,6 +82,7 @@ $$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)): \
|
|||
| $$(HLIB$(2)_H_$(4))/
|
||||
@$$(call E, cp: $$@)
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(4)),$$(notdir $$@))
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(4)),$$(notdir $$@))
|
||||
$$(Q)cp $$< $$@
|
||||
# Subtle: We do not let the shell expand $$(STDLIB_DSYM_GLOB) directly rather
|
||||
# we use Make's $$(wildcard) facility. The reason is that, on mac, when using
|
||||
|
@ -91,9 +92,11 @@ $$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)): \
|
|||
# Make instead expands the glob to nothing, which gives us the correct behavior.
|
||||
# (Copy .dsym file if it exists, but do nothing otherwise)
|
||||
$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_GLOB_$(4)) \
|
||||
$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_RGLOB_$(4))) \
|
||||
$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_DSYM_GLOB_$(4))) \
|
||||
$$(HLIB$(2)_H_$(4))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(4)),$$(notdir $$@))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(4)),$$(notdir $$@))
|
||||
|
||||
$$(HLIB$(2)_H_$(4))/$(CFG_EXTRALIB_$(4)): \
|
||||
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \
|
||||
|
@ -102,11 +105,14 @@ $$(HLIB$(2)_H_$(4))/$(CFG_EXTRALIB_$(4)): \
|
|||
| $$(HLIB$(2)_H_$(4))/
|
||||
@$$(call E, cp: $$@)
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(4)),$$(notdir $$@))
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(4)),$$(notdir $$@))
|
||||
$$(Q)cp $$< $$@
|
||||
$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_GLOB_$(4)) \
|
||||
$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_RGLOB_$(4))) \
|
||||
$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_DSYM_GLOB_$(4))) \
|
||||
$$(HLIB$(2)_H_$(4))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(4)),$$(notdir $$@))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(4)),$$(notdir $$@))
|
||||
|
||||
$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTUV_$(4)): \
|
||||
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTUV_$(4)) \
|
||||
|
@ -115,35 +121,14 @@ $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTUV_$(4)): \
|
|||
| $$(HLIB$(2)_H_$(4))/
|
||||
@$$(call E, cp: $$@)
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(4)),$$(notdir $$@))
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(4)),$$(notdir $$@))
|
||||
$$(Q)cp $$< $$@
|
||||
$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTUV_GLOB_$(4)) \
|
||||
$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTUV_RGLOB_$(4))) \
|
||||
$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTUV_DSYM_GLOB_$(4))) \
|
||||
$$(HLIB$(2)_H_$(4))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(4)),$$(notdir $$@))
|
||||
|
||||
$$(HLIB$(2)_H_$(4))/libstd.rlib: \
|
||||
$$(TLIB$(1)_T_$(4)_H_$(3))/libstd.rlib \
|
||||
$$(HLIB$(2)_H_$(4))/$$(CFG_RUNTIME_$(4)) \
|
||||
| $$(HLIB$(2)_H_$(4))/
|
||||
@$$(call E, cp: $$@)
|
||||
$$(Q)cp $$< $$@
|
||||
|
||||
$$(HLIB$(2)_H_$(4))/libextra.rlib: \
|
||||
$$(TLIB$(1)_T_$(4)_H_$(3))/libextra.rlib \
|
||||
$$(HLIB$(2)_H_$(4))/libstd.rlib \
|
||||
$$(HLIB$(2)_H_$(4))/$$(CFG_RUNTIME_$(4)) \
|
||||
| $$(HLIB$(2)_H_$(4))/
|
||||
@$$(call E, cp: $$@)
|
||||
$$(Q)cp $$< $$@
|
||||
|
||||
$$(HLIB$(2)_H_$(4))/librustc.rlib: \
|
||||
$$(TLIB$(1)_T_$(4)_H_$(3))/librustc.rlib \
|
||||
$$(HLIB$(2)_H_$(4))/libstd.rlib \
|
||||
$$(HLIB$(2)_H_$(4))/libextra.rlib \
|
||||
$$(HLIB$(2)_H_$(4))/$$(CFG_RUNTIME_$(4)) \
|
||||
| $$(HLIB$(2)_H_$(4))/
|
||||
@$$(call E, cp: $$@)
|
||||
$$(Q)cp $$< $$@
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(4)),$$(notdir $$@))
|
||||
|
||||
$$(HLIB$(2)_H_$(4))/$(CFG_RUSTLLVM_$(4)): \
|
||||
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_RUSTLLVM_$(4)) \
|
||||
|
|
|
@ -88,7 +88,6 @@ install-target-$(1)-host-$(2): LIB_SOURCE_DIR=$$(TL$(1)$(2))
|
|||
install-target-$(1)-host-$(2): LIB_DESTIN_DIR=$$(PTL$(1)$(2))
|
||||
install-target-$(1)-host-$(2): $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2))
|
||||
$$(Q)$$(call MK_INSTALL_DIR,$$(PTL$(1)$(2)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(CFG_RUNTIME_$(1)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(STDLIB_GLOB_$(1)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(EXTRALIB_GLOB_$(1)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTUV_GLOB_$(1)))
|
||||
|
@ -101,7 +100,6 @@ install-target-$(1)-host-$(2): LIB_SOURCE_DIR=$$(TL$(1)$(2))
|
|||
install-target-$(1)-host-$(2): LIB_DESTIN_DIR=$$(PTL$(1)$(2))
|
||||
install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2))
|
||||
$$(Q)$$(call MK_INSTALL_DIR,$$(PTL$(1)$(2)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(CFG_RUNTIME_$(1)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(CFG_RUSTLLVM_$(1)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(STDLIB_GLOB_$(1)))
|
||||
$$(Q)$$(call INSTALL_LIB,$$(EXTRALIB_GLOB_$(1)))
|
||||
|
@ -144,13 +142,15 @@ install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_)_H_$(CFG_BUILD_))
|
|||
$(Q)$(call INSTALL,$(HB2),$(PHB),rustpkg$(X_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc$(X_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(STDLIB_GLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(STDLIB_RGLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(EXTRALIB_GLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(EXTRALIB_RGLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(LIBRUSTUV_GLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(LIBRUSTUV_RGLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(LIBRUSTC_GLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(LIBSYNTAX_GLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL_LIB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUNTIME_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUSTLLVM_$(CFG_BUILD)))
|
||||
$(Q)$(call INSTALL,$(S)/man,$(CFG_MANDIR)/man1,rustc.1)
|
||||
$(Q)$(call INSTALL,$(S)/man,$(CFG_MANDIR)/man1,rustdoc.1)
|
||||
|
@ -167,11 +167,13 @@ uninstall:
|
|||
$(Q)rm -f $(PHB)/rustpkg$(X_$(CFG_BUILD))
|
||||
$(Q)rm -f $(PHB)/rustdoc$(X_$(CFG_BUILD))
|
||||
$(Q)rm -f $(PHL)/$(CFG_RUSTLLVM_$(CFG_BUILD))
|
||||
$(Q)rm -f $(PHL)/$(CFG_RUNTIME_$(CFG_BUILD))
|
||||
$(Q)for i in \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(STDLIB_GLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(STDLIB_RGLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(EXTRALIB_GLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(EXTRALIB_RGLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTUV_GLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTUV_RGLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTC_GLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(LIBSYNTAX_GLOB_$(CFG_BUILD))) \
|
||||
$(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD))) \
|
||||
|
@ -232,7 +234,6 @@ endif
|
|||
define INSTALL_RUNTIME_TARGET_N
|
||||
install-runtime-target-$(1)-host-$(2): $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2))
|
||||
$(Q)$(call ADB_SHELL,mkdir,$(CFG_RUNTIME_PUSH_DIR))
|
||||
$(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(CFG_RUNTIME_$(1)),$(CFG_RUNTIME_PUSH_DIR))
|
||||
$(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(STDLIB_GLOB_$(1)),$(CFG_RUNTIME_PUSH_DIR))
|
||||
$(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(EXTRALIB_GLOB_$(1)),$(CFG_RUNTIME_PUSH_DIR))
|
||||
$(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(LIBRUSTUV_GLOB_$(1)),$(CFG_RUNTIME_PUSH_DIR))
|
||||
|
@ -241,7 +242,6 @@ endef
|
|||
define INSTALL_RUNTIME_TARGET_CLEANUP_N
|
||||
install-runtime-target-$(1)-cleanup:
|
||||
$(Q)$(call ADB,remount)
|
||||
$(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(CFG_RUNTIME_$(1)))
|
||||
$(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(STDLIB_GLOB_$(1)))
|
||||
$(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(EXTRALIB_GLOB_$(1)))
|
||||
$(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(LIBRUSTUV_GLOB_$(1)))
|
||||
|
|
|
@ -138,6 +138,7 @@ endif
|
|||
endif
|
||||
endif
|
||||
|
||||
CFG_RLIB_GLOB=lib$(1)-*.rlib
|
||||
|
||||
# x86_64-unknown-linux-gnu configuration
|
||||
CC_x86_64-unknown-linux-gnu=$(CC)
|
||||
|
|
6
mk/rt.mk
6
mk/rt.mk
|
@ -121,11 +121,9 @@ $$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJS_
|
|||
@$$(call E, link: $$@)
|
||||
$$(Q)$(AR_$(1)) rcs $$@ $$^
|
||||
|
||||
$$(RT_BUILD_DIR_$(1)_$(2))/$(CFG_RUNTIME_$(1)): $$(RUNTIME_OBJS_$(1)_$(2)) $$(MKFILE_DEPS) \
|
||||
$$(RUNTIME_DEF_$(1)_$(2))
|
||||
$$(RT_BUILD_DIR_$(1)_$(2))/$(CFG_RUNTIME_$(1)): $$(RUNTIME_OBJS_$(1)_$(2)) $$(MKFILE_DEPS)
|
||||
@$$(call E, link: $$@)
|
||||
$$(Q)$$(call CFG_LINK_CXX_$(1),$$@, $$(RUNTIME_OBJS_$(1)_$(2)) \
|
||||
$$(CFG_LIBUV_LINK_FLAGS_$(1)),$$(RUNTIME_DEF_$(1)_$(2)),$$(CFG_RUNTIME_$(1)))
|
||||
$$(Q)$(AR_$(1)) rcs $$@ $$(RUNTIME_OBJS_$(1)_$(2))
|
||||
|
||||
# These could go in rt.mk or rustllvm.mk, they're needed for both.
|
||||
|
||||
|
|
|
@ -60,8 +60,10 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)): \
|
|||
| $$(TLIB$(1)_T_$(2)_H_$(3))/
|
||||
@$$(call E, compile_and_link: $$@)
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(2)),$$(notdir $$@))
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(2)),$$(notdir $$@))
|
||||
$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(2)),$$(notdir $$@))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(2)),$$(notdir $$@))
|
||||
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)): \
|
||||
$$(EXTRALIB_CRATE) $$(EXTRALIB_INPUTS) \
|
||||
|
@ -70,8 +72,10 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)): \
|
|||
| $$(TLIB$(1)_T_$(2)_H_$(3))/
|
||||
@$$(call E, compile_and_link: $$@)
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(2)),$$(notdir $$@))
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(2)),$$(notdir $$@))
|
||||
$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(2)),$$(notdir $$@))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(2)),$$(notdir $$@))
|
||||
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2)): \
|
||||
$$(LIBRUSTUV_CRATE) $$(LIBRUSTUV_INPUTS) \
|
||||
|
@ -82,11 +86,13 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2)): \
|
|||
| $$(TLIB$(1)_T_$(2)_H_$(3))/
|
||||
@$$(call E, compile_and_link: $$@)
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(2)),$$(notdir $$@))
|
||||
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(2)),$$(notdir $$@))
|
||||
$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
|
||||
-L $$(UV_SUPPORT_DIR_$(2)) \
|
||||
-L $$(dir $$(LIBUV_LIB_$(2))) \
|
||||
--out-dir $$(@D) $$< && touch $$@
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(2)),$$(notdir $$@))
|
||||
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(2)),$$(notdir $$@))
|
||||
|
||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(3)): \
|
||||
$$(LIBSYNTAX_CRATE) $$(LIBSYNTAX_INPUTS) \
|
||||
|
|
44
mk/tests.mk
44
mk/tests.mk
|
@ -193,7 +193,7 @@ check-lite: cleantestlibs cleantmptestlogs \
|
|||
check-stage2-std check-stage2-extra check-stage2-rpass \
|
||||
check-stage2-rustuv \
|
||||
check-stage2-rustpkg \
|
||||
check-stage2-rfail check-stage2-cfail
|
||||
check-stage2-rfail check-stage2-cfail check-stage2-rmake
|
||||
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
|
||||
|
||||
.PHONY: cleantmptestlogs cleantestlibs
|
||||
|
@ -284,7 +284,8 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
|
|||
check-stage$(1)-T-$(2)-H-$(3)-rfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
|
||||
|
@ -584,6 +585,10 @@ TEST_SREQ$(1)_T_$(2)_H_$(3) = \
|
|||
# remove directive, if present, from CFG_RUSTC_FLAGS (issue #7898).
|
||||
CTEST_RUSTC_FLAGS := $$(subst --cfg ndebug,,$$(CFG_RUSTC_FLAGS))
|
||||
|
||||
# There's no need our entire test suite to take up gigabytes of space on disk
|
||||
# including copies of libstd/libextra all over the place
|
||||
CTEST_RUSTC_FLAGS := $$(CTEST_RUSTC_FLAGS) -Z prefer-dynamic
|
||||
|
||||
# The tests can not be optimized while the rest of the compiler is optimized, so
|
||||
# filter out the optimization (if any) from rustc and then figure out if we need
|
||||
# to be optimized
|
||||
|
@ -766,6 +771,7 @@ TEST_GROUPS = \
|
|||
cfail \
|
||||
bench \
|
||||
perf \
|
||||
rmake \
|
||||
debuginfo \
|
||||
codegen \
|
||||
doc \
|
||||
|
@ -896,3 +902,37 @@ endef
|
|||
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
$(eval $(call DEF_CHECK_FAST_FOR_H,$(host))))
|
||||
|
||||
RMAKE_TESTS := $(shell ls -d $(S)src/test/run-make/*/)
|
||||
RMAKE_TESTS := $(RMAKE_TESTS:$(S)src/test/run-make/%/=%)
|
||||
|
||||
define DEF_RMAKE_FOR_T_H
|
||||
# $(1) the stage
|
||||
# $(2) target triple
|
||||
# $(3) host triple
|
||||
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec: \
|
||||
$$(call TEST_OK_FILE,$(1),$(2),$(3),rmake)
|
||||
|
||||
$$(call TEST_OK_FILE,$(1),$(2),$(3),rmake): \
|
||||
$$(RMAKE_TESTS:%=$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok)
|
||||
@touch $$@
|
||||
|
||||
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
$(S)src/test/run-make/%/Makefile \
|
||||
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3))
|
||||
@rm -rf $(3)/test/run-make/$$*
|
||||
@mkdir -p $(3)/test/run-make/$$*
|
||||
@echo maketest: $$*
|
||||
$$(Q)python $(S)src/etc/maketest.py $$(dir $$<) \
|
||||
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
|
||||
$(3)/test/run-make/$$* \
|
||||
"$$(CC_$(3)) $$(CFG_GCCISH_CFLAGS_$(3))"
|
||||
@touch $$@
|
||||
|
||||
endef
|
||||
|
||||
$(foreach stage,$(STAGES), \
|
||||
$(foreach target,$(CFG_TARGET), \
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
$(eval $(call DEF_RMAKE_FOR_T_H,$(stage),$(target),$(host))))))
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# xfail-license
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.putenv('RUSTC', os.path.abspath(sys.argv[2]))
|
||||
os.putenv('TMPDIR', os.path.abspath(sys.argv[3]))
|
||||
os.putenv('CC', sys.argv[4])
|
||||
|
||||
proc = subprocess.Popen(['make', '-C', sys.argv[1]],
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE)
|
||||
out, err = proc.communicate()
|
||||
i = proc.wait()
|
||||
|
||||
if i != 0:
|
||||
|
||||
print '----- ' + sys.argv[1] + """ --------------------
|
||||
------ stdout ---------------------------------------------
|
||||
""" + out + """
|
||||
------ stderr ---------------------------------------------
|
||||
""" + err + """
|
||||
------ ---------------------------------------------
|
||||
"""
|
||||
sys.exit(i)
|
||||
|
|
@ -31,7 +31,6 @@ snapshot_files = {
|
|||
"lib/librustc-*.so",
|
||||
"lib/libsyntax-*.so",
|
||||
"lib/librustuv-*.so",
|
||||
"lib/librustrt.so",
|
||||
"lib/librustllvm.so"],
|
||||
"macos": ["bin/rustc",
|
||||
"lib/libstd-*.dylib",
|
||||
|
@ -39,7 +38,6 @@ snapshot_files = {
|
|||
"lib/librustc-*.dylib",
|
||||
"lib/libsyntax-*.dylib",
|
||||
"lib/librustuv-*.dylib",
|
||||
"lib/librustrt.dylib",
|
||||
"lib/librustllvm.dylib"],
|
||||
"winnt": ["bin/rustc.exe",
|
||||
"bin/std-*.dll",
|
||||
|
@ -47,7 +45,6 @@ snapshot_files = {
|
|||
"bin/rustc-*.dll",
|
||||
"bin/syntax-*.dll",
|
||||
"bin/rustuv-*.dll",
|
||||
"bin/rustrt.dll",
|
||||
"bin/rustllvm.dll"],
|
||||
"freebsd": ["bin/rustc",
|
||||
"lib/libstd-*.so",
|
||||
|
@ -55,7 +52,6 @@ snapshot_files = {
|
|||
"lib/librustc-*.so",
|
||||
"lib/libsyntax-*.so",
|
||||
"lib/librustuv-*.so",
|
||||
"lib/librustrt.so",
|
||||
"lib/librustllvm.so"]
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use std::vec;
|
|||
pub mod rustrt {
|
||||
use std::libc::{c_int, c_void, size_t};
|
||||
|
||||
#[link_name = "rustrt"]
|
||||
#[link(name = "rustrt")]
|
||||
extern {
|
||||
pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void,
|
||||
src_buf_len: size_t,
|
||||
|
|
|
@ -32,12 +32,15 @@ Rust extras are part of the standard Rust distribution.
|
|||
|
||||
#[comment = "Rust extras"];
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
#[crate_type = "lib"]; // NOTE: remove after stage0 snapshot
|
||||
#[crate_type = "rlib"];
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
#[feature(macro_rules, globs, managed_boxes)];
|
||||
|
||||
#[deny(non_camel_case_types)];
|
||||
#[deny(missing_doc)];
|
||||
#[allow(attribute_usage)]; // NOTE: remove after the next snapshot
|
||||
|
||||
use std::str::{StrSlice, OwnedStr};
|
||||
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
//! A helper class for dealing with static archives
|
||||
|
||||
use driver::session::Session;
|
||||
use metadata::filesearch;
|
||||
|
||||
use std::io::fs;
|
||||
use std::os;
|
||||
use std::run::{ProcessOptions, Process, ProcessOutput};
|
||||
use std::str;
|
||||
use extra::tempfile::TempDir;
|
||||
use syntax::abi;
|
||||
|
||||
pub struct Archive {
|
||||
priv sess: Session,
|
||||
priv dst: Path,
|
||||
}
|
||||
|
||||
fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
|
||||
paths: &[&Path]) -> ProcessOutput {
|
||||
let ar = sess.opts.ar.clone().unwrap_or_else(|| ~"ar");
|
||||
let mut args = ~[args.to_owned()];
|
||||
let mut paths = paths.iter().map(|p| p.as_str().unwrap().to_owned());
|
||||
args.extend(&mut paths);
|
||||
let mut opts = ProcessOptions::new();
|
||||
opts.dir = cwd;
|
||||
debug!("{} {}", ar, args.connect(" "));
|
||||
match cwd {
|
||||
Some(p) => { debug!("inside {}", p.display()); }
|
||||
None => {}
|
||||
}
|
||||
let o = Process::new(ar, args.as_slice(), opts).finish_with_output();
|
||||
if !o.status.success() {
|
||||
sess.err(format!("{} failed with: {}", ar, o.status));
|
||||
sess.note(format!("stdout ---\n{}", str::from_utf8(o.output)));
|
||||
sess.note(format!("stderr ---\n{}", str::from_utf8(o.error)));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
o
|
||||
}
|
||||
|
||||
impl Archive {
|
||||
/// Initializes a new static archive with the given object file
|
||||
pub fn create<'a>(sess: Session, dst: &'a Path,
|
||||
initial_object: &'a Path) -> Archive {
|
||||
run_ar(sess, "crus", None, [dst, initial_object]);
|
||||
Archive { sess: sess, dst: dst.clone() }
|
||||
}
|
||||
|
||||
/// Opens an existing static archive
|
||||
pub fn open(sess: Session, dst: Path) -> Archive {
|
||||
assert!(dst.exists());
|
||||
Archive { sess: sess, dst: dst }
|
||||
}
|
||||
|
||||
/// Read a file in the archive
|
||||
pub fn read(&self, file: &str) -> ~[u8] {
|
||||
// Apparently if "ar p" is used on windows, it generates a corrupt file
|
||||
// which has bad headers and LLVM will immediately choke on it
|
||||
if cfg!(windows) && cfg!(windows) { // FIXME(#10734) double-and
|
||||
let loc = TempDir::new("rsar").unwrap();
|
||||
let archive = os::make_absolute(&self.dst);
|
||||
run_ar(self.sess, "x", Some(loc.path()), [&archive,
|
||||
&Path::init(file)]);
|
||||
fs::File::open(&loc.path().join(file)).read_to_end()
|
||||
} else {
|
||||
run_ar(self.sess, "p", None, [&self.dst, &Path::init(file)]).output
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds all of the contents of a native library to this archive. This will
|
||||
/// search in the relevant locations for a library named `name`.
|
||||
pub fn add_native_library(&mut self, name: &str) {
|
||||
let location = self.find_library(name);
|
||||
self.add_archive(&location, name);
|
||||
}
|
||||
|
||||
/// Adds all of the contents of the rlib at the specified path to this
|
||||
/// archive.
|
||||
pub fn add_rlib(&mut self, rlib: &Path) {
|
||||
let name = rlib.filename_str().unwrap().split('-').next().unwrap();
|
||||
self.add_archive(rlib, name);
|
||||
}
|
||||
|
||||
fn add_archive(&mut self, archive: &Path, name: &str) {
|
||||
let loc = TempDir::new("rsar").unwrap();
|
||||
|
||||
// First, extract the contents of the archive to a temporary directory
|
||||
let archive = os::make_absolute(archive);
|
||||
run_ar(self.sess, "x", Some(loc.path()), [&archive]);
|
||||
|
||||
// Next, we must rename all of the inputs to "guaranteed unique names".
|
||||
// The reason for this is that archives are keyed off the name of the
|
||||
// files, so if two files have the same name they will override one
|
||||
// another in the archive (bad).
|
||||
let files = fs::readdir(loc.path());
|
||||
let mut inputs = ~[];
|
||||
for file in files.iter() {
|
||||
let filename = file.filename_str().unwrap();
|
||||
let filename = format!("r-{}-{}", name, filename);
|
||||
let new_filename = file.with_filename(filename);
|
||||
fs::rename(file, &new_filename);
|
||||
inputs.push(new_filename);
|
||||
}
|
||||
|
||||
// Finally, add all the renamed files to this archive
|
||||
let mut args = ~[&self.dst];
|
||||
args.extend(&mut inputs.iter());
|
||||
run_ar(self.sess, "r", None, args.as_slice());
|
||||
}
|
||||
|
||||
fn find_library(&self, name: &str) -> Path {
|
||||
let (prefix, ext) = match self.sess.targ_cfg.os {
|
||||
abi::OsWin32 => ("", "lib"), _ => ("lib", "a"),
|
||||
};
|
||||
let libname = format!("{}{}.{}", prefix, name, ext);
|
||||
|
||||
let mut rustpath = filesearch::rust_path();
|
||||
rustpath.push(self.sess.filesearch.get_target_lib_path());
|
||||
let path = self.sess.opts.addl_lib_search_paths.iter();
|
||||
for path in path.chain(rustpath.iter()) {
|
||||
debug!("looking for {} inside {}", name, path.display());
|
||||
let test = path.join(libname.clone());
|
||||
if test.exists() { return test }
|
||||
}
|
||||
self.sess.fatal(format!("could not find native static library `{}`, \
|
||||
perhaps an -L flag is missing?", name));
|
||||
}
|
||||
}
|
|
@ -63,6 +63,6 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
|||
|
||||
target_triple: target_triple,
|
||||
|
||||
cc_args: ~[~"-marm"]
|
||||
cc_args: ~[~"-marm"],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
use back::archive::Archive;
|
||||
use back::rpath;
|
||||
use driver::session::Session;
|
||||
use driver::session;
|
||||
|
@ -16,7 +17,7 @@ use lib::llvm::llvm;
|
|||
use lib::llvm::ModuleRef;
|
||||
use lib;
|
||||
use metadata::common::LinkMeta;
|
||||
use metadata::{encoder, cstore, filesearch};
|
||||
use metadata::{encoder, cstore, filesearch, csearch};
|
||||
use middle::trans::context::CrateContext;
|
||||
use middle::trans::common::gensym_name;
|
||||
use middle::ty;
|
||||
|
@ -30,7 +31,6 @@ use std::os::consts::{macos, freebsd, linux, android, win32};
|
|||
use std::ptr;
|
||||
use std::run;
|
||||
use std::str;
|
||||
use std::vec;
|
||||
use std::io::fs;
|
||||
use syntax::abi;
|
||||
use syntax::ast;
|
||||
|
@ -88,7 +88,6 @@ pub mod jit {
|
|||
use driver::session::Session;
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{ModuleRef, ContextRef, ExecutionEngineRef};
|
||||
use metadata::cstore;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::cast;
|
||||
|
@ -125,19 +124,6 @@ pub mod jit {
|
|||
// core linked into rustc. We don't want that,
|
||||
// incase the user wants to use an older extra library.
|
||||
|
||||
let cstore = sess.cstore;
|
||||
let r = cstore::get_used_crate_files(cstore);
|
||||
for cratepath in r.iter() {
|
||||
debug!("linking: {}", cratepath.display());
|
||||
|
||||
cratepath.with_c_str(|buf_t| {
|
||||
if !llvm::LLVMRustLoadCrate(manager, buf_t) {
|
||||
llvm_err(sess, ~"Could not link");
|
||||
}
|
||||
debug!("linked: {}", cratepath.display());
|
||||
})
|
||||
}
|
||||
|
||||
// We custom-build a JIT execution engine via some rust wrappers
|
||||
// first. This wrappers takes ownership of the module passed in.
|
||||
let ee = llvm::LLVMRustBuildJIT(manager, m, stacks);
|
||||
|
@ -368,20 +354,20 @@ pub mod write {
|
|||
}
|
||||
|
||||
pub fn run_assembler(sess: Session, assembly: &Path, object: &Path) {
|
||||
let cc_prog = super::get_cc_prog(sess);
|
||||
let cc = super::get_cc_prog(sess);
|
||||
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let cc_args = ~[
|
||||
let args = [
|
||||
~"-c",
|
||||
~"-o", object.as_str().unwrap().to_owned(),
|
||||
assembly.as_str().unwrap().to_owned()];
|
||||
|
||||
let prog = run::process_output(cc_prog, cc_args);
|
||||
debug!("{} {}", cc, args.connect(" "));
|
||||
let prog = run::process_output(cc, args);
|
||||
|
||||
if !prog.status.success() {
|
||||
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
|
||||
sess.note(format!("{} arguments: {}",
|
||||
cc_prog, cc_args.connect(" ")));
|
||||
sess.err(format!("linking with `{}` failed: {}", cc, prog.status));
|
||||
sess.note(format!("{} arguments: {}", cc, args.connect(" ")));
|
||||
sess.note(str::from_utf8(prog.error + prog.output));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
|
@ -876,90 +862,71 @@ pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str
|
|||
mangle(ccx.sess, path, None, None)
|
||||
}
|
||||
|
||||
|
||||
pub fn output_dll_filename(os: abi::Os, lm: LinkMeta) -> ~str {
|
||||
let (dll_prefix, dll_suffix) = match os {
|
||||
abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
|
||||
abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
|
||||
abi::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
|
||||
abi::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
|
||||
abi::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
|
||||
};
|
||||
format!("{}{}-{}-{}{}", dll_prefix, lm.name, lm.extras_hash, lm.vers, dll_suffix)
|
||||
pub fn output_lib_filename(lm: LinkMeta) -> ~str {
|
||||
format!("{}-{}-{}", lm.name, lm.extras_hash, lm.vers)
|
||||
}
|
||||
|
||||
pub fn get_cc_prog(sess: Session) -> ~str {
|
||||
match sess.opts.linker {
|
||||
Some(ref linker) => return linker.to_owned(),
|
||||
None => {}
|
||||
}
|
||||
|
||||
// In the future, FreeBSD will use clang as default compiler.
|
||||
// It would be flexible to use cc (system's default C compiler)
|
||||
// instead of hard-coded gcc.
|
||||
// For win32, there is no cc command, so we add a condition to make it use g++.
|
||||
// We use g++ rather than gcc because it automatically adds linker options required
|
||||
// for generation of dll modules that correctly register stack unwind tables.
|
||||
match sess.opts.linker {
|
||||
Some(ref linker) => linker.to_str(),
|
||||
None => match sess.targ_cfg.os {
|
||||
abi::OsAndroid =>
|
||||
match &sess.opts.android_cross_path {
|
||||
&Some(ref path) => {
|
||||
format!("{}/bin/arm-linux-androideabi-gcc", *path)
|
||||
}
|
||||
&None => {
|
||||
sess.fatal("need Android NDK path for linking \
|
||||
(--android-cross-path)")
|
||||
}
|
||||
},
|
||||
abi::OsWin32 => ~"g++",
|
||||
_ => ~"cc"
|
||||
}
|
||||
// For win32, there is no cc command, so we add a condition to make it use
|
||||
// g++. We use g++ rather than gcc because it automatically adds linker
|
||||
// options required for generation of dll modules that correctly register
|
||||
// stack unwind tables.
|
||||
match sess.targ_cfg.os {
|
||||
abi::OsAndroid => match sess.opts.android_cross_path {
|
||||
Some(ref path) => format!("{}/bin/arm-linux-androideabi-gcc", *path),
|
||||
None => {
|
||||
sess.fatal("need Android NDK path for linking \
|
||||
(--android-cross-path)")
|
||||
}
|
||||
},
|
||||
abi::OsWin32 => ~"g++",
|
||||
_ => ~"cc",
|
||||
}
|
||||
}
|
||||
|
||||
// If the user wants an exe generated we need to invoke
|
||||
// cc to link the object file with some libs
|
||||
/// Perform the linkage portion of the compilation phase. This will generate all
|
||||
/// of the requested outputs for this compilation session.
|
||||
pub fn link_binary(sess: Session,
|
||||
crate_types: &[~str],
|
||||
obj_filename: &Path,
|
||||
out_filename: &Path,
|
||||
lm: LinkMeta) {
|
||||
|
||||
let cc_prog = get_cc_prog(sess);
|
||||
// The invocations of cc share some flags across platforms
|
||||
|
||||
let output = if *sess.building_library {
|
||||
let long_libname = output_dll_filename(sess.targ_cfg.os, lm);
|
||||
debug!("link_meta.name: {}", lm.name);
|
||||
debug!("long_libname: {}", long_libname);
|
||||
debug!("out_filename: {}", out_filename.display());
|
||||
let out_dirname = out_filename.dir_path();
|
||||
debug!("dirname(out_filename): {}", out_dirname.display());
|
||||
|
||||
out_filename.with_filename(long_libname)
|
||||
let outputs = if sess.opts.test {
|
||||
// If we're generating a test executable, then ignore all other output
|
||||
// styles at all other locations
|
||||
~[session::OutputExecutable]
|
||||
} else {
|
||||
out_filename.clone()
|
||||
// Always generate whatever was specified on the command line, but also
|
||||
// look at what was in the crate file itself for generating output
|
||||
// formats.
|
||||
let mut outputs = sess.opts.outputs.clone();
|
||||
for ty in crate_types.iter() {
|
||||
if "bin" == *ty {
|
||||
outputs.push(session::OutputExecutable);
|
||||
} else if "dylib" == *ty || "lib" == *ty {
|
||||
outputs.push(session::OutputDylib);
|
||||
} else if "rlib" == *ty {
|
||||
outputs.push(session::OutputRlib);
|
||||
} else if "staticlib" == *ty {
|
||||
outputs.push(session::OutputStaticlib);
|
||||
}
|
||||
}
|
||||
if outputs.len() == 0 {
|
||||
outputs.push(session::OutputExecutable);
|
||||
}
|
||||
outputs
|
||||
};
|
||||
|
||||
debug!("output: {}", output.display());
|
||||
let cc_args = link_args(sess, obj_filename, out_filename, lm);
|
||||
debug!("{} link args: {}", cc_prog, cc_args.connect(" "));
|
||||
if (sess.opts.debugging_opts & session::print_link_args) != 0 {
|
||||
println!("{} link args: {}", cc_prog, cc_args.connect(" "));
|
||||
}
|
||||
|
||||
// We run 'cc' here
|
||||
let prog = run::process_output(cc_prog, cc_args);
|
||||
|
||||
if !prog.status.success() {
|
||||
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
|
||||
sess.note(format!("{} arguments: {}",
|
||||
cc_prog, cc_args.connect(" ")));
|
||||
sess.note(str::from_utf8(prog.error + prog.output));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
|
||||
// On OSX, debuggers needs this utility to get run to do some munging of the
|
||||
// symbols
|
||||
if sess.targ_cfg.os == abi::OsMacos && sess.opts.debuginfo {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
run::process_status("dsymutil", [output.as_str().unwrap().to_owned()]);
|
||||
for output in outputs.move_iter() {
|
||||
link_binary_output(sess, output, obj_filename, out_filename, lm);
|
||||
}
|
||||
|
||||
// Remove the temporary object file if we aren't saving temps
|
||||
|
@ -971,34 +938,36 @@ pub fn link_binary(sess: Session,
|
|||
fn is_writeable(p: &Path) -> bool {
|
||||
use std::io;
|
||||
|
||||
!p.exists() ||
|
||||
(match io::result(|| p.stat()) {
|
||||
Err(..) => false,
|
||||
Ok(m) => m.perm & io::UserWrite == io::UserWrite
|
||||
})
|
||||
match io::result(|| p.stat()) {
|
||||
Err(..) => true,
|
||||
Ok(m) => m.perm & io::UserWrite == io::UserWrite
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link_args(sess: Session,
|
||||
obj_filename: &Path,
|
||||
out_filename: &Path,
|
||||
lm:LinkMeta) -> ~[~str] {
|
||||
|
||||
// Converts a library file-stem into a cc -l argument
|
||||
fn unlib(config: @session::config, stem: ~str) -> ~str {
|
||||
if stem.starts_with("lib") &&
|
||||
config.os != abi::OsWin32 {
|
||||
stem.slice(3, stem.len()).to_owned()
|
||||
} else {
|
||||
stem
|
||||
fn link_binary_output(sess: Session,
|
||||
output: session::OutputStyle,
|
||||
obj_filename: &Path,
|
||||
out_filename: &Path,
|
||||
lm: LinkMeta) {
|
||||
let libname = output_lib_filename(lm);
|
||||
let out_filename = match output {
|
||||
session::OutputRlib => {
|
||||
out_filename.with_filename(format!("lib{}.rlib", libname))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let output = if *sess.building_library {
|
||||
let long_libname = output_dll_filename(sess.targ_cfg.os, lm);
|
||||
out_filename.with_filename(long_libname)
|
||||
} else {
|
||||
out_filename.clone()
|
||||
session::OutputDylib => {
|
||||
let (prefix, suffix) = match sess.targ_cfg.os {
|
||||
abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
|
||||
abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
|
||||
abi::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
|
||||
abi::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
|
||||
abi::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
|
||||
};
|
||||
out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix))
|
||||
}
|
||||
session::OutputStaticlib => {
|
||||
out_filename.with_filename(format!("lib{}.a", libname))
|
||||
}
|
||||
session::OutputExecutable => out_filename.clone(),
|
||||
};
|
||||
|
||||
// Make sure the output and obj_filename are both writeable.
|
||||
|
@ -1006,61 +975,282 @@ pub fn link_args(sess: Session,
|
|||
// however, the Linux linker will happily overwrite a read-only file.
|
||||
// We should be consistent.
|
||||
let obj_is_writeable = is_writeable(obj_filename);
|
||||
let out_is_writeable = is_writeable(&output);
|
||||
let out_is_writeable = is_writeable(&out_filename);
|
||||
if !out_is_writeable {
|
||||
sess.fatal(format!("Output file {} is not writeable -- check its permissions.",
|
||||
output.display()));
|
||||
out_filename.display()));
|
||||
}
|
||||
else if !obj_is_writeable {
|
||||
sess.fatal(format!("Object file {} is not writeable -- check its permissions.",
|
||||
obj_filename.display()));
|
||||
}
|
||||
|
||||
match output {
|
||||
session::OutputRlib => {
|
||||
link_rlib(sess, obj_filename, &out_filename);
|
||||
}
|
||||
session::OutputStaticlib => {
|
||||
link_staticlib(sess, obj_filename, &out_filename);
|
||||
}
|
||||
session::OutputExecutable => {
|
||||
link_natively(sess, false, obj_filename, &out_filename);
|
||||
}
|
||||
session::OutputDylib => {
|
||||
link_natively(sess, true, obj_filename, &out_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create an 'rlib'
|
||||
//
|
||||
// An rlib in its current incarnation is essentially a renamed .a file. The
|
||||
// rlib primarily contains the object file of the crate, but it also contains
|
||||
// all of the object files from native libraries. This is done by unzipping
|
||||
// native libraries and inserting all of the contents into this archive.
|
||||
fn link_rlib(sess: Session, obj_filename: &Path,
|
||||
out_filename: &Path) -> Archive {
|
||||
let mut a = Archive::create(sess, out_filename, obj_filename);
|
||||
for &(ref l, kind) in cstore::get_used_libraries(sess.cstore).iter() {
|
||||
match kind {
|
||||
cstore::NativeStatic => {
|
||||
a.add_native_library(l.as_slice());
|
||||
}
|
||||
cstore::NativeUnknown => {}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// Create a static archive
|
||||
//
|
||||
// This is essentially the same thing as an rlib, but it also involves adding
|
||||
// all of the upstream crates' objects into the the archive. This will slurp in
|
||||
// all of the native libraries of upstream dependencies as well.
|
||||
//
|
||||
// Additionally, there's no way for us to link dynamic libraries, so we warn
|
||||
// about all dynamic library dependencies that they're not linked in.
|
||||
fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) {
|
||||
let mut a = link_rlib(sess, obj_filename, out_filename);
|
||||
a.add_native_library("morestack");
|
||||
|
||||
let crates = cstore::get_used_crates(sess.cstore, cstore::RequireStatic);
|
||||
for &(cnum, ref path) in crates.iter() {
|
||||
let p = match *path {
|
||||
Some(ref p) => p.clone(), None => {
|
||||
sess.err(format!("could not find rlib for: `{}`",
|
||||
cstore::get_crate_data(sess.cstore, cnum).name));
|
||||
continue
|
||||
}
|
||||
};
|
||||
a.add_rlib(&p);
|
||||
let native_libs = csearch::get_native_libraries(sess.cstore, cnum);
|
||||
for lib in native_libs.iter() {
|
||||
sess.warn(format!("unlinked native library: {}", *lib));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a dynamic library or executable
|
||||
//
|
||||
// This will invoke the system linker/cc to create the resulting file. This
|
||||
// links to all upstream files as well.
|
||||
fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
|
||||
out_filename: &Path) {
|
||||
// The invocations of cc share some flags across platforms
|
||||
let cc_prog = get_cc_prog(sess);
|
||||
let mut cc_args = sess.targ_cfg.target_strs.cc_args.clone();
|
||||
cc_args.push_all_move(link_args(sess, dylib, obj_filename, out_filename));
|
||||
if (sess.opts.debugging_opts & session::print_link_args) != 0 {
|
||||
println!("{} link args: {}", cc_prog, cc_args.connect(" "));
|
||||
}
|
||||
|
||||
// May have not found libraries in the right formats.
|
||||
sess.abort_if_errors();
|
||||
|
||||
// Invoke the system linker
|
||||
debug!("{} {}", cc_prog, cc_args.connect(" "));
|
||||
let prog = run::process_output(cc_prog, cc_args);
|
||||
|
||||
if !prog.status.success() {
|
||||
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
|
||||
sess.note(format!("{} arguments: {}", cc_prog, cc_args.connect(" ")));
|
||||
sess.note(str::from_utf8(prog.error + prog.output));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
|
||||
|
||||
// On OSX, debuggers need this utility to get run to do some munging of
|
||||
// the symbols
|
||||
if sess.targ_cfg.os == abi::OsMacos && sess.opts.debuginfo {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
run::process_status("dsymutil",
|
||||
[out_filename.as_str().unwrap().to_owned()]);
|
||||
}
|
||||
}
|
||||
|
||||
fn link_args(sess: Session,
|
||||
dylib: bool,
|
||||
obj_filename: &Path,
|
||||
out_filename: &Path) -> ~[~str] {
|
||||
|
||||
// The default library location, we need this to find the runtime.
|
||||
// The location of crates will be determined as needed.
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let lib_path = sess.filesearch.get_target_lib_path();
|
||||
let stage: ~str = ~"-L" + lib_path.as_str().unwrap();
|
||||
|
||||
let mut args = vec::append(~[stage], sess.targ_cfg.target_strs.cc_args);
|
||||
let mut args = ~[stage];
|
||||
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
args.push_all([
|
||||
~"-o", output.as_str().unwrap().to_owned(),
|
||||
~"-o", out_filename.as_str().unwrap().to_owned(),
|
||||
obj_filename.as_str().unwrap().to_owned()]);
|
||||
|
||||
let lib_cmd = match sess.targ_cfg.os {
|
||||
abi::OsMacos => ~"-dynamiclib",
|
||||
_ => ~"-shared"
|
||||
};
|
||||
if sess.targ_cfg.os == abi::OsLinux {
|
||||
// GNU-style linkers will use this to omit linking to libraries which
|
||||
// don't actually fulfill any relocations, but only for libraries which
|
||||
// follow this flag. Thus, use it before specifing libraries to link to.
|
||||
args.push(~"-Wl,--as-needed");
|
||||
|
||||
// # Crate linking
|
||||
|
||||
let cstore = sess.cstore;
|
||||
let r = cstore::get_used_crate_files(cstore);
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
for cratepath in r.iter() {
|
||||
if cratepath.extension_str() == Some("rlib") {
|
||||
args.push(cratepath.as_str().unwrap().to_owned());
|
||||
continue;
|
||||
// GNU-style linkers support optimization with -O. --gc-sections
|
||||
// removes metadata and potentially other useful things, so don't
|
||||
// include it. GNU ld doesn't need a numeric argument, but other linkers
|
||||
// do.
|
||||
if sess.opts.optimize == session::Default ||
|
||||
sess.opts.optimize == session::Aggressive {
|
||||
args.push(~"-Wl,-O1");
|
||||
}
|
||||
let dir = cratepath.dirname_str().unwrap();
|
||||
if !dir.is_empty() { args.push("-L" + dir); }
|
||||
let libarg = unlib(sess.targ_cfg, cratepath.filestem_str().unwrap().to_owned());
|
||||
args.push("-l" + libarg);
|
||||
}
|
||||
|
||||
let ula = cstore::get_used_link_args(cstore);
|
||||
for arg in ula.iter() { args.push(arg.to_owned()); }
|
||||
add_upstream_rust_crates(&mut args, sess, dylib);
|
||||
add_local_native_libraries(&mut args, sess);
|
||||
|
||||
// # Extern library linking
|
||||
// # Telling the linker what we're doing
|
||||
|
||||
// User-supplied library search paths (-L on the cammand line) These are
|
||||
// the same paths used to find Rust crates, so some of them may have been
|
||||
// added already by the previous crate linking code. This only allows them
|
||||
// to be found at compile time so it is still entirely up to outside
|
||||
// forces to make sure that library can be found at runtime.
|
||||
if dylib {
|
||||
// On mac we need to tell the linker to let this library be rpathed
|
||||
if sess.targ_cfg.os == abi::OsMacos {
|
||||
args.push(~"-dynamiclib");
|
||||
args.push(~"-Wl,-dylib");
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
args.push(~"-Wl,-install_name,@rpath/" +
|
||||
out_filename.filename_str().unwrap());
|
||||
} else {
|
||||
args.push(~"-shared")
|
||||
}
|
||||
}
|
||||
|
||||
if sess.targ_cfg.os == abi::OsFreebsd {
|
||||
args.push_all([~"-L/usr/local/lib",
|
||||
~"-L/usr/local/lib/gcc46",
|
||||
~"-L/usr/local/lib/gcc44"]);
|
||||
}
|
||||
|
||||
// Stack growth requires statically linking a __morestack function
|
||||
args.push(~"-lmorestack");
|
||||
|
||||
// FIXME (#2397): At some point we want to rpath our guesses as to
|
||||
// where extern libraries might live, based on the
|
||||
// addl_lib_search_paths
|
||||
args.push_all(rpath::get_rpath_flags(sess, out_filename));
|
||||
|
||||
// Finally add all the linker arguments provided on the command line along
|
||||
// with any #[link_args] attributes found inside the crate
|
||||
args.push_all(sess.opts.linker_args);
|
||||
for arg in cstore::get_used_link_args(sess.cstore).iter() {
|
||||
args.push(arg.clone());
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
// # Rust Crate linking
|
||||
//
|
||||
// Rust crates are not considered at all when creating an rlib output. All
|
||||
// dependencies will be linked when producing the final output (instead of
|
||||
// the intermediate rlib version)
|
||||
fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session,
|
||||
dylib: bool) {
|
||||
// Converts a library file-stem into a cc -l argument
|
||||
fn unlib(config: @session::config, stem: &str) -> ~str {
|
||||
if stem.starts_with("lib") &&
|
||||
config.os != abi::OsWin32 {
|
||||
stem.slice(3, stem.len()).to_owned()
|
||||
} else {
|
||||
stem.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
let cstore = sess.cstore;
|
||||
if !dylib && !sess.prefer_dynamic() {
|
||||
// With an executable, things get a little interesting. As a limitation
|
||||
// of the current implementation, we require that everything must be
|
||||
// static, or everything must be dynamic. The reasons for this are a
|
||||
// little subtle, but as with the above two cases, the goal is to
|
||||
// prevent duplicate copies of the same library showing up. For example,
|
||||
// a static immediate dependency might show up as an upstream dynamic
|
||||
// dependency and we currently have no way of knowing that. We know that
|
||||
// all dynamic libaries require dynamic dependencies (see above), so
|
||||
// it's satisfactory to include either all static libraries or all
|
||||
// dynamic libraries.
|
||||
let crates = cstore::get_used_crates(cstore,
|
||||
cstore::RequireStatic);
|
||||
if crates.iter().all(|&(_, ref p)| p.is_some()) {
|
||||
for &(cnum, ref path) in crates.iter() {
|
||||
let cratepath = path.clone().unwrap();
|
||||
|
||||
// If we're linking to the static version of the crate, then
|
||||
// we're mostly good to go. The caveat here is that we need to
|
||||
// pull in the static crate's native dependencies.
|
||||
args.push(cratepath.as_str().unwrap().to_owned());
|
||||
|
||||
let libs = csearch::get_native_libraries(sess.cstore, cnum);
|
||||
for lib in libs.iter() {
|
||||
args.push("-l" + *lib);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a fallback of three different cases of linking:
|
||||
//
|
||||
// * When creating a dynamic library, all inputs are required to be dynamic
|
||||
// as well
|
||||
// * If an executable is created with a preference on dynamic linking, then
|
||||
// this case is the fallback
|
||||
// * If an executable is being created, and one of the inputs is missing as
|
||||
// a static library, then this is the fallback case.
|
||||
let crates = cstore::get_used_crates(cstore, cstore::RequireDynamic);
|
||||
for &(cnum, ref path) in crates.iter() {
|
||||
let cratepath = match *path {
|
||||
Some(ref p) => p.clone(),
|
||||
None => {
|
||||
sess.err(format!("could not find dynamic library for: `{}`",
|
||||
cstore::get_crate_data(sess.cstore, cnum).name));
|
||||
return
|
||||
}
|
||||
};
|
||||
// Just need to tell the linker about where the library lives and what
|
||||
// its name is
|
||||
let dir = cratepath.dirname_str().unwrap();
|
||||
if !dir.is_empty() { args.push("-L" + dir); }
|
||||
let libarg = unlib(sess.targ_cfg, cratepath.filestem_str().unwrap());
|
||||
args.push("-l" + libarg);
|
||||
}
|
||||
}
|
||||
|
||||
// # Native library linking
|
||||
//
|
||||
// User-supplied library search paths (-L on the cammand line) These are
|
||||
// the same paths used to find Rust crates, so some of them may have been
|
||||
// added already by the previous crate linking code. This only allows them
|
||||
// to be found at compile time so it is still entirely up to outside
|
||||
// forces to make sure that library can be found at runtime.
|
||||
//
|
||||
// Also note that the native libraries linked here are only the ones located
|
||||
// in the current crate. Upstream crates with native library dependencies
|
||||
// may have their native library pulled in above.
|
||||
fn add_local_native_libraries(args: &mut ~[~str], sess: Session) {
|
||||
for path in sess.opts.addl_lib_search_paths.iter() {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
args.push("-L" + path.as_str().unwrap().to_owned());
|
||||
|
@ -1072,73 +1262,7 @@ pub fn link_args(sess: Session,
|
|||
args.push("-L" + path.as_str().unwrap().to_owned());
|
||||
}
|
||||
|
||||
if sess.targ_cfg.os == abi::OsLinux {
|
||||
// GNU-style linkers will use this to omit linking to libraries which don't actually fulfill
|
||||
// any relocations, but only for libraries which follow this flag. Thus, use it before
|
||||
// specifing libraries to link to.
|
||||
args.push(~"-Wl,--as-needed");
|
||||
for &(ref l, _) in cstore::get_used_libraries(sess.cstore).iter() {
|
||||
args.push(~"-l" + *l);
|
||||
}
|
||||
|
||||
// The names of the extern libraries
|
||||
let used_libs = cstore::get_used_libraries(cstore);
|
||||
for l in used_libs.iter() { args.push(~"-l" + *l); }
|
||||
|
||||
if *sess.building_library {
|
||||
args.push(lib_cmd);
|
||||
|
||||
// On mac we need to tell the linker to let this library
|
||||
// be rpathed
|
||||
if sess.targ_cfg.os == abi::OsMacos {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
args.push("-Wl,-install_name,@rpath/"
|
||||
+ output.filename_str().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
// On linux librt and libdl are an indirect dependencies via rustrt,
|
||||
// and binutils 2.22+ won't add them automatically
|
||||
if sess.targ_cfg.os == abi::OsLinux {
|
||||
// GNU-style linkers supports optimization with -O. --gc-sections removes metadata and
|
||||
// potentially other useful things, so don't include it. GNU ld doesn't need a numeric
|
||||
// argument, but other linkers do.
|
||||
if sess.opts.optimize == session::Default || sess.opts.optimize == session::Aggressive {
|
||||
args.push(~"-Wl,-O1");
|
||||
}
|
||||
|
||||
args.push_all([~"-lrt", ~"-ldl"]);
|
||||
|
||||
// LLVM implements the `frem` instruction as a call to `fmod`,
|
||||
// which lives in libm. Similar to above, on some linuxes we
|
||||
// have to be explicit about linking to it. See #2510
|
||||
args.push(~"-lm");
|
||||
}
|
||||
else if sess.targ_cfg.os == abi::OsAndroid {
|
||||
args.push_all([~"-ldl", ~"-llog", ~"-lsupc++", ~"-lgnustl_shared"]);
|
||||
args.push(~"-lm");
|
||||
}
|
||||
|
||||
if sess.targ_cfg.os == abi::OsFreebsd {
|
||||
args.push_all([~"-pthread", ~"-lrt",
|
||||
~"-L/usr/local/lib", ~"-lexecinfo",
|
||||
~"-L/usr/local/lib/gcc46",
|
||||
~"-L/usr/local/lib/gcc44", ~"-lstdc++",
|
||||
~"-Wl,-z,origin",
|
||||
~"-Wl,-rpath,/usr/local/lib/gcc46",
|
||||
~"-Wl,-rpath,/usr/local/lib/gcc44"]);
|
||||
}
|
||||
|
||||
// Stack growth requires statically linking a __morestack function
|
||||
args.push(~"-lmorestack");
|
||||
|
||||
// Always want the runtime linked in
|
||||
args.push(~"-lrustrt");
|
||||
|
||||
// FIXME (#2397): At some point we want to rpath our guesses as to where
|
||||
// extern libraries might live, based on the addl_lib_search_paths
|
||||
args.push_all(rpath::get_rpath_flags(sess, &output));
|
||||
|
||||
// Finally add all the linker arguments provided on the command line
|
||||
args.push_all(sess.opts.linker_args);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,6 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
|||
|
||||
target_triple: target_triple,
|
||||
|
||||
cc_args: ~[]
|
||||
cc_args: ~[],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@ fn not_win32(os: abi::Os) -> bool {
|
|||
os != abi::OsWin32
|
||||
}
|
||||
|
||||
pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
|
||||
-> ~[~str] {
|
||||
pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] {
|
||||
let os = sess.targ_cfg.os;
|
||||
|
||||
// No rpath on windows
|
||||
|
@ -30,18 +29,28 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
|
|||
return ~[];
|
||||
}
|
||||
|
||||
let mut flags = ~[];
|
||||
|
||||
if sess.targ_cfg.os == abi::OsFreebsd {
|
||||
flags.push_all([~"-Wl,-rpath,/usr/local/lib/gcc46",
|
||||
~"-Wl,-rpath,/usr/local/lib/gcc44",
|
||||
~"-Wl,-z,origin"]);
|
||||
}
|
||||
|
||||
debug!("preparing the RPATH!");
|
||||
|
||||
let sysroot = sess.filesearch.sysroot();
|
||||
let output = out_filename;
|
||||
let libs = cstore::get_used_crate_files(sess.cstore);
|
||||
let libs = cstore::get_used_crates(sess.cstore, cstore::RequireDynamic);
|
||||
let libs = libs.move_iter().filter_map(|(_, l)| l.map(|p| p.clone())).collect();
|
||||
// We don't currently rpath extern libraries, but we know
|
||||
// where rustrt is and we know every rust program needs it
|
||||
let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));
|
||||
|
||||
let rpaths = get_rpaths(os, sysroot, output, libs,
|
||||
sess.opts.target_triple);
|
||||
rpaths_to_flags(rpaths)
|
||||
flags.push_all(rpaths_to_flags(rpaths));
|
||||
flags
|
||||
}
|
||||
|
||||
fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path {
|
||||
|
@ -52,8 +61,11 @@ fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path {
|
|||
}
|
||||
|
||||
pub fn rpaths_to_flags(rpaths: &[~str]) -> ~[~str] {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
rpaths.iter().map(|rpath| format!("-Wl,-rpath,{}",*rpath)).collect()
|
||||
let mut ret = ~[];
|
||||
for rpath in rpaths.iter() {
|
||||
ret.push("-Wl,-rpath," + *rpath);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
fn get_rpaths(os: abi::Os,
|
||||
|
|
|
@ -14,5 +14,5 @@ pub struct t {
|
|||
meta_sect_name: ~str,
|
||||
data_layout: ~str,
|
||||
target_triple: ~str,
|
||||
cc_args: ~[~str]
|
||||
cc_args: ~[~str],
|
||||
}
|
||||
|
|
|
@ -46,6 +46,6 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
|||
|
||||
target_triple: target_triple,
|
||||
|
||||
cc_args: ~[~"-m32"]
|
||||
cc_args: ~[~"-m32"],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -54,6 +54,6 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
|||
|
||||
target_triple: target_triple,
|
||||
|
||||
cc_args: ~[~"-m64"]
|
||||
cc_args: ~[~"-m64"],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
use back::link;
|
||||
use back::{arm, x86, x86_64, mips};
|
||||
use driver::session::{Aggressive};
|
||||
use driver::session::{Aggressive, OutputExecutable};
|
||||
use driver::session::{Session, Session_, No, Less, Default};
|
||||
use driver::session;
|
||||
use front;
|
||||
|
@ -164,8 +164,11 @@ pub fn phase_2_configure_and_expand(sess: Session,
|
|||
mut crate: ast::Crate) -> ast::Crate {
|
||||
let time_passes = sess.time_passes();
|
||||
|
||||
*sess.building_library = session::building_library(sess.opts.crate_type,
|
||||
&crate, sess.opts.test);
|
||||
*sess.building_library = session::building_library(sess.opts, &crate);
|
||||
let want_exe = sess.opts.outputs.iter().any(|&o| o == OutputExecutable);
|
||||
if *sess.building_library && want_exe {
|
||||
sess.err("cannot build both a library and an executable");
|
||||
}
|
||||
|
||||
time(time_passes, "gated feature checking", (), |_|
|
||||
front::feature_gate::check_crate(sess, &crate));
|
||||
|
@ -225,10 +228,8 @@ pub fn phase_3_run_analysis_passes(sess: Session,
|
|||
syntax::ast_map::map_crate(sess.diagnostic(), crate));
|
||||
|
||||
time(time_passes, "external crate/lib resolution", (), |_|
|
||||
creader::read_crates(sess.diagnostic(), crate, sess.cstore,
|
||||
sess.filesearch,
|
||||
creader::read_crates(sess, crate,
|
||||
session::sess_os_to_meta_os(sess.targ_cfg.os),
|
||||
sess.opts.is_static,
|
||||
token::get_ident_interner()));
|
||||
|
||||
let lang_items = time(time_passes, "language item collection", (), |_|
|
||||
|
@ -330,7 +331,8 @@ pub fn phase_3_run_analysis_passes(sess: Session,
|
|||
pub struct CrateTranslation {
|
||||
context: ContextRef,
|
||||
module: ModuleRef,
|
||||
link: LinkMeta
|
||||
link: LinkMeta,
|
||||
crate_types: ~[~str],
|
||||
}
|
||||
|
||||
/// Run the translation phase to LLVM, after which the AST and analysis can
|
||||
|
@ -390,6 +392,7 @@ pub fn phase_6_link_output(sess: Session,
|
|||
outputs: &OutputFilenames) {
|
||||
time(sess.time_passes(), "linking", (), |_|
|
||||
link::link_binary(sess,
|
||||
trans.crate_types,
|
||||
&outputs.obj_filename,
|
||||
&outputs.out_filename,
|
||||
trans.link));
|
||||
|
@ -417,11 +420,6 @@ pub fn stop_after_phase_5(sess: Session) -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
if sess.opts.is_static && *sess.building_library {
|
||||
debug!("building static library, returning early from compile_input");
|
||||
return true;
|
||||
}
|
||||
|
||||
if sess.opts.jit {
|
||||
debug!("running JIT, returning early from compile_input");
|
||||
return true;
|
||||
|
@ -652,13 +650,21 @@ pub fn build_session_options(binary: @str,
|
|||
matches: &getopts::Matches,
|
||||
demitter: @diagnostic::Emitter)
|
||||
-> @session::options {
|
||||
let crate_type = if matches.opt_present("lib") {
|
||||
session::lib_crate
|
||||
} else if matches.opt_present("bin") {
|
||||
session::bin_crate
|
||||
} else {
|
||||
session::unknown_crate
|
||||
};
|
||||
let mut outputs = ~[];
|
||||
if matches.opt_present("rlib") {
|
||||
outputs.push(session::OutputRlib)
|
||||
}
|
||||
if matches.opt_present("staticlib") {
|
||||
outputs.push(session::OutputStaticlib)
|
||||
}
|
||||
// dynamic libraries are the "compiler blesssed" default library
|
||||
if matches.opt_present("dylib") || matches.opt_present("lib") {
|
||||
outputs.push(session::OutputDylib)
|
||||
}
|
||||
if matches.opt_present("bin") {
|
||||
outputs.push(session::OutputExecutable)
|
||||
}
|
||||
|
||||
let parse_only = matches.opt_present("parse-only");
|
||||
let no_trans = matches.opt_present("no-trans");
|
||||
|
||||
|
@ -750,11 +756,10 @@ pub fn build_session_options(binary: @str,
|
|||
let debuginfo = debugging_opts & session::debug_info != 0 ||
|
||||
extra_debuginfo;
|
||||
|
||||
let statik = debugging_opts & session::statik != 0;
|
||||
|
||||
let addl_lib_search_paths = matches.opt_strs("L").map(|s| {
|
||||
Path::init(s.as_slice())
|
||||
Path::init(s.as_slice())
|
||||
}).move_iter().collect();
|
||||
let ar = matches.opt_str("ar");
|
||||
let linker = matches.opt_str("linker");
|
||||
let linker_args = matches.opt_strs("link-args").flat_map( |a| {
|
||||
a.split(' ').map(|arg| arg.to_owned()).collect()
|
||||
|
@ -782,8 +787,7 @@ pub fn build_session_options(binary: @str,
|
|||
};
|
||||
|
||||
let sopts = @session::options {
|
||||
crate_type: crate_type,
|
||||
is_static: statik,
|
||||
outputs: outputs,
|
||||
gc: gc,
|
||||
optimize: opt_level,
|
||||
custom_passes: custom_passes,
|
||||
|
@ -795,6 +799,7 @@ pub fn build_session_options(binary: @str,
|
|||
jit: jit,
|
||||
output_type: output_type,
|
||||
addl_lib_search_paths: @mut addl_lib_search_paths,
|
||||
ar: ar,
|
||||
linker: linker,
|
||||
linker_args: linker_args,
|
||||
maybe_sysroot: sysroot_opt,
|
||||
|
@ -871,7 +876,6 @@ pub fn parse_pretty(sess: Session, name: &str) -> PpMode {
|
|||
// rustc command line options
|
||||
pub fn optgroups() -> ~[getopts::groups::OptGroup] {
|
||||
~[
|
||||
optflag("", "bin", "Compile an executable crate (default)"),
|
||||
optflag("c", "", "Compile and assemble, but do not link"),
|
||||
optmulti("", "cfg", "Configure the compilation
|
||||
environment", "SPEC"),
|
||||
|
@ -881,8 +885,13 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
|
|||
optflag("h", "help","Display this message"),
|
||||
optmulti("L", "", "Add a directory to the library search path",
|
||||
"PATH"),
|
||||
optflag("", "lib", "Compile a library crate"),
|
||||
optflag("", "bin", "Compile an executable crate (default)"),
|
||||
optflag("", "lib", "Compile a rust library crate using the compiler's default"),
|
||||
optflag("", "rlib", "Compile a rust library crate as an rlib file"),
|
||||
optflag("", "staticlib", "Compile a static library crate"),
|
||||
optflag("", "dylib", "Compile a dynamic library crate"),
|
||||
optopt("", "linker", "Program to use for linking instead of the default.", "LINKER"),
|
||||
optopt("", "ar", "Program to use for managing archives instead of the default.", "AR"),
|
||||
optmulti("", "link-args", "FLAGS is a space-separated list of flags
|
||||
passed to the linker", "FLAGS"),
|
||||
optflag("", "ls", "List the symbols defined by a library crate"),
|
||||
|
@ -957,19 +966,16 @@ pub fn build_output_filenames(input: &input,
|
|||
let obj_path;
|
||||
let out_path;
|
||||
let sopts = sess.opts;
|
||||
let stop_after_codegen =
|
||||
sopts.output_type != link::output_type_exe ||
|
||||
sopts.is_static && *sess.building_library;
|
||||
let stop_after_codegen = sopts.output_type != link::output_type_exe;
|
||||
|
||||
let obj_suffix =
|
||||
match sopts.output_type {
|
||||
link::output_type_none => ~"none",
|
||||
link::output_type_bitcode => ~"bc",
|
||||
link::output_type_assembly => ~"s",
|
||||
link::output_type_llvm_assembly => ~"ll",
|
||||
// Object and exe output both use the '.o' extension here
|
||||
link::output_type_object | link::output_type_exe => ~"o"
|
||||
};
|
||||
let obj_suffix = match sopts.output_type {
|
||||
link::output_type_none => ~"none",
|
||||
link::output_type_bitcode => ~"bc",
|
||||
link::output_type_assembly => ~"s",
|
||||
link::output_type_llvm_assembly => ~"ll",
|
||||
// Object and exe output both use the '.o' extension here
|
||||
link::output_type_object | link::output_type_exe => ~"o"
|
||||
};
|
||||
|
||||
match *ofile {
|
||||
None => {
|
||||
|
@ -1047,6 +1053,7 @@ pub fn early_error(emitter: @diagnostic::Emitter, msg: &str) -> ! {
|
|||
|
||||
pub fn list_metadata(sess: Session, path: &Path, out: @mut io::Writer) {
|
||||
metadata::loader::list_file_metadata(
|
||||
sess,
|
||||
token::get_ident_interner(),
|
||||
session::sess_os_to_meta_os(sess.targ_cfg.os), path, out);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ use back::link;
|
|||
use back::target_strs;
|
||||
use back;
|
||||
use driver::driver::host_triple;
|
||||
use driver::session;
|
||||
use metadata::filesearch;
|
||||
use metadata;
|
||||
use middle::lint;
|
||||
|
@ -30,13 +29,6 @@ use syntax;
|
|||
|
||||
use std::hashmap::{HashMap,HashSet};
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum crate_type {
|
||||
bin_crate,
|
||||
lib_crate,
|
||||
unknown_crate,
|
||||
}
|
||||
|
||||
pub struct config {
|
||||
os: abi::Os,
|
||||
arch: abi::Architecture,
|
||||
|
@ -66,16 +58,16 @@ pub static gc: uint = 1 << 17;
|
|||
pub static jit: uint = 1 << 18;
|
||||
pub static debug_info: uint = 1 << 19;
|
||||
pub static extra_debug_info: uint = 1 << 20;
|
||||
pub static statik: uint = 1 << 21;
|
||||
pub static print_link_args: uint = 1 << 22;
|
||||
pub static no_debug_borrows: uint = 1 << 23;
|
||||
pub static lint_llvm: uint = 1 << 24;
|
||||
pub static print_llvm_passes: uint = 1 << 25;
|
||||
pub static no_vectorize_loops: uint = 1 << 26;
|
||||
pub static no_vectorize_slp: uint = 1 << 27;
|
||||
pub static no_prepopulate_passes: uint = 1 << 28;
|
||||
pub static use_softfp: uint = 1 << 29;
|
||||
pub static gen_crate_map: uint = 1 << 30;
|
||||
pub static print_link_args: uint = 1 << 21;
|
||||
pub static no_debug_borrows: uint = 1 << 22;
|
||||
pub static lint_llvm: uint = 1 << 23;
|
||||
pub static print_llvm_passes: uint = 1 << 24;
|
||||
pub static no_vectorize_loops: uint = 1 << 25;
|
||||
pub static no_vectorize_slp: uint = 1 << 26;
|
||||
pub static no_prepopulate_passes: uint = 1 << 27;
|
||||
pub static use_softfp: uint = 1 << 28;
|
||||
pub static gen_crate_map: uint = 1 << 29;
|
||||
pub static prefer_dynamic: uint = 1 << 30;
|
||||
|
||||
pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] {
|
||||
~[("verbose", "in general, enable more debug printouts", verbose),
|
||||
|
@ -107,7 +99,6 @@ pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] {
|
|||
("extra-debug-info", "Extra debugging info (experimental)",
|
||||
extra_debug_info),
|
||||
("debug-info", "Produce debug info (experimental)", debug_info),
|
||||
("static", "Use or produce static libraries or binaries (experimental)", statik),
|
||||
("no-debug-borrows",
|
||||
"do not show where borrow checks fail",
|
||||
no_debug_borrows),
|
||||
|
@ -129,6 +120,7 @@ pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] {
|
|||
no_vectorize_slp),
|
||||
("soft-float", "Generate software floating point library calls", use_softfp),
|
||||
("gen-crate-map", "Force generation of a toplevel crate map", gen_crate_map),
|
||||
("prefer-dynamic", "Prefer dynamic linking to static linking", prefer_dynamic),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -144,8 +136,8 @@ pub enum OptLevel {
|
|||
pub struct options {
|
||||
// The crate config requested for the session, which may be combined
|
||||
// with additional crate configurations during the compile process
|
||||
crate_type: crate_type,
|
||||
is_static: bool,
|
||||
outputs: ~[OutputStyle],
|
||||
|
||||
gc: bool,
|
||||
optimize: OptLevel,
|
||||
custom_passes: ~[~str],
|
||||
|
@ -159,6 +151,7 @@ pub struct options {
|
|||
addl_lib_search_paths: @mut HashSet<Path>, // This is mutable for rustpkg, which
|
||||
// updates search paths based on the
|
||||
// parsed code
|
||||
ar: Option<~str>,
|
||||
linker: Option<~str>,
|
||||
linker_args: ~[~str],
|
||||
maybe_sysroot: Option<@Path>,
|
||||
|
@ -194,6 +187,14 @@ pub enum EntryFnType {
|
|||
EntryNone,
|
||||
}
|
||||
|
||||
#[deriving(Eq, Clone)]
|
||||
pub enum OutputStyle {
|
||||
OutputExecutable,
|
||||
OutputDylib,
|
||||
OutputRlib,
|
||||
OutputStaticlib,
|
||||
}
|
||||
|
||||
pub struct Session_ {
|
||||
targ_cfg: @config,
|
||||
opts: @options,
|
||||
|
@ -337,6 +338,9 @@ impl Session_ {
|
|||
pub fn gen_crate_map(&self) -> bool {
|
||||
self.debugging_opt(gen_crate_map)
|
||||
}
|
||||
pub fn prefer_dynamic(&self) -> bool {
|
||||
self.debugging_opt(prefer_dynamic)
|
||||
}
|
||||
|
||||
// pointless function, now...
|
||||
pub fn str_of(&self, id: ast::Ident) -> @str {
|
||||
|
@ -357,8 +361,7 @@ impl Session_ {
|
|||
/// Some reasonable defaults
|
||||
pub fn basic_options() -> @options {
|
||||
@options {
|
||||
crate_type: session::lib_crate,
|
||||
is_static: false,
|
||||
outputs: ~[],
|
||||
gc: false,
|
||||
optimize: No,
|
||||
custom_passes: ~[],
|
||||
|
@ -370,6 +373,7 @@ pub fn basic_options() -> @options {
|
|||
jit: false,
|
||||
output_type: link::output_type_exe,
|
||||
addl_lib_search_paths: @mut HashSet::new(),
|
||||
ar: None,
|
||||
linker: None,
|
||||
linker_args: ~[],
|
||||
maybe_sysroot: None,
|
||||
|
@ -391,24 +395,17 @@ pub fn expect<T:Clone>(sess: Session, opt: Option<T>, msg: || -> ~str) -> T {
|
|||
diagnostic::expect(sess.diagnostic(), opt, msg)
|
||||
}
|
||||
|
||||
pub fn building_library(req_crate_type: crate_type,
|
||||
crate: &ast::Crate,
|
||||
testing: bool) -> bool {
|
||||
match req_crate_type {
|
||||
bin_crate => false,
|
||||
lib_crate => true,
|
||||
unknown_crate => {
|
||||
if testing {
|
||||
false
|
||||
} else {
|
||||
match syntax::attr::first_attr_value_str_by_name(
|
||||
crate.attrs,
|
||||
"crate_type") {
|
||||
Some(s) => "lib" == s,
|
||||
_ => false
|
||||
}
|
||||
pub fn building_library(options: &options, crate: &ast::Crate) -> bool {
|
||||
for output in options.outputs.iter() {
|
||||
match *output {
|
||||
OutputExecutable => {}
|
||||
OutputStaticlib | OutputDylib | OutputRlib => return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if options.test { return false }
|
||||
match syntax::attr::first_attr_value_str_by_name(crate.attrs, "crate_type") {
|
||||
Some(s) => "lib" == s || "rlib" == s || "dylib" == s || "staticlib" == s,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,75 +420,3 @@ pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
|
|||
abi::OsFreebsd => loader::OsFreebsd
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use driver::session::{bin_crate, building_library, lib_crate};
|
||||
use driver::session::{unknown_crate};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::codemap;
|
||||
|
||||
fn make_crate_type_attr(t: @str) -> ast::Attribute {
|
||||
attr::mk_attr(attr::mk_name_value_item_str(@"crate_type", t))
|
||||
}
|
||||
|
||||
fn make_crate(with_bin: bool, with_lib: bool) -> @ast::Crate {
|
||||
let mut attrs = ~[];
|
||||
if with_bin {
|
||||
attrs.push(make_crate_type_attr(@"bin"));
|
||||
}
|
||||
if with_lib {
|
||||
attrs.push(make_crate_type_attr(@"lib"));
|
||||
}
|
||||
@ast::Crate {
|
||||
module: ast::_mod { view_items: ~[], items: ~[] },
|
||||
attrs: attrs,
|
||||
config: ~[],
|
||||
span: codemap::dummy_sp(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bin_crate_type_attr_results_in_bin_output() {
|
||||
let crate = make_crate(true, false);
|
||||
assert!(!building_library(unknown_crate, crate, false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lib_crate_type_attr_results_in_lib_output() {
|
||||
let crate = make_crate(false, true);
|
||||
assert!(building_library(unknown_crate, crate, false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bin_option_overrides_lib_crate_type() {
|
||||
let crate = make_crate(false, true);
|
||||
assert!(!building_library(bin_crate, crate, false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lib_option_overrides_bin_crate_type() {
|
||||
let crate = make_crate(true, false);
|
||||
assert!(building_library(lib_crate, crate, false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bin_crate_type_is_default() {
|
||||
let crate = make_crate(false, false);
|
||||
assert!(!building_library(unknown_crate, crate, false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_option_overrides_lib_crate_type() {
|
||||
let crate = make_crate(false, true);
|
||||
assert!(!building_library(unknown_crate, crate, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_option_does_not_override_requested_lib_type() {
|
||||
let crate = make_crate(false, false);
|
||||
assert!(building_library(lib_crate, crate, true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
use middle::lint;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::visit;
|
||||
|
@ -41,6 +42,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
|
|||
("managed_boxes", Active),
|
||||
("non_ascii_idents", Active),
|
||||
("thread_local", Active),
|
||||
("link_args", Active),
|
||||
|
||||
// These are used to test this portion of the compiler, they don't actually
|
||||
// mean anything
|
||||
|
@ -111,7 +113,8 @@ impl Visitor<()> for Context {
|
|||
|
||||
fn visit_item(&mut self, i: @ast::item, _:()) {
|
||||
for attr in i.attrs.iter() {
|
||||
if "thread_local" == attr.name() {
|
||||
if "thread_local" == attr.name() &&
|
||||
cfg!(stage0, remove_this_on_next_snapshot) { // NOTE: snap rem
|
||||
self.gate_feature("thread_local", i.span,
|
||||
"`#[thread_local]` is an experimental feature, and does not \
|
||||
currently handle destructors. There is no corresponding \
|
||||
|
@ -132,6 +135,16 @@ impl Visitor<()> for Context {
|
|||
}
|
||||
}
|
||||
|
||||
ast::item_foreign_mod(..) => {
|
||||
if attr::contains_name(i.attrs, "link_args") &&
|
||||
cfg!(stage0, remove_this_on_next_snapshot) { // NOTE: snap
|
||||
self.gate_feature("link_args", i.span,
|
||||
"the `link_args` attribute is not portable \
|
||||
across platforms, it is recommended to \
|
||||
use `#[link(name = \"foo\")]` instead")
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
#[comment = "The Rust compiler"];
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
#[crate_type = "lib"]; // NOTE: remove after stage0 snapshot
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
|
||||
#[allow(attribute_usage)]; // NOTE: remove after the next snapshot
|
||||
|
||||
extern mod extra;
|
||||
extern mod syntax;
|
||||
|
@ -87,6 +89,7 @@ pub mod front {
|
|||
}
|
||||
|
||||
pub mod back {
|
||||
pub mod archive;
|
||||
pub mod link;
|
||||
pub mod abi;
|
||||
pub mod upcall;
|
||||
|
|
|
@ -14,7 +14,6 @@ use std::c_str::ToCStr;
|
|||
use std::hashmap::HashMap;
|
||||
use std::libc::{c_uint, c_ushort, c_void, free};
|
||||
use std::str::raw::from_c_str;
|
||||
use std::option;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
|
@ -304,9 +303,16 @@ pub mod llvm {
|
|||
use super::{ValueRef, TargetMachineRef, FileType};
|
||||
use super::{CodeGenModel, RelocMode, CodeGenOptLevel};
|
||||
use super::debuginfo::*;
|
||||
use std::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong};
|
||||
use std::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong,
|
||||
size_t};
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[link_args = "-lrustllvm"]
|
||||
extern {}
|
||||
#[cfg(not(stage0))] // if you're deleting this, put this on the block below
|
||||
#[link(name = "rustllvm")]
|
||||
extern {}
|
||||
|
||||
extern {
|
||||
/* Create and destroy contexts. */
|
||||
pub fn LLVMContextCreate() -> ContextRef;
|
||||
|
@ -1426,6 +1432,16 @@ pub mod llvm {
|
|||
LLVMDisposeMemoryBuffer() to get rid of it. */
|
||||
pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *c_char)
|
||||
-> MemoryBufferRef;
|
||||
/** Borrows the contents of the memory buffer (doesn't copy it) */
|
||||
pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *c_char,
|
||||
InputDataLength: size_t,
|
||||
BufferName: *c_char,
|
||||
RequiresNull: Bool)
|
||||
-> MemoryBufferRef;
|
||||
pub fn LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: *c_char,
|
||||
InputDataLength: size_t,
|
||||
BufferName: *c_char)
|
||||
-> MemoryBufferRef;
|
||||
|
||||
/** Returns a string describing the last error caused by an LLVMRust*
|
||||
call. */
|
||||
|
@ -1901,38 +1917,32 @@ pub fn mk_pass_manager() -> PassManager {
|
|||
|
||||
/* Memory-managed interface to object files. */
|
||||
|
||||
pub struct object_file_res {
|
||||
ObjectFile: ObjectFileRef,
|
||||
pub struct ObjectFile {
|
||||
llof: ObjectFileRef,
|
||||
}
|
||||
|
||||
impl Drop for object_file_res {
|
||||
fn drop(&mut self) {
|
||||
impl ObjectFile {
|
||||
// This will take ownership of llmb
|
||||
pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
|
||||
unsafe {
|
||||
llvm::LLVMDisposeObjectFile(self.ObjectFile);
|
||||
let llof = llvm::LLVMCreateObjectFile(llmb);
|
||||
if llof as int == 0 {
|
||||
llvm::LLVMDisposeMemoryBuffer(llmb);
|
||||
return None
|
||||
}
|
||||
|
||||
Some(ObjectFile {
|
||||
llof: llof,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn object_file_res(ObjFile: ObjectFileRef) -> object_file_res {
|
||||
object_file_res {
|
||||
ObjectFile: ObjFile
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ObjectFile {
|
||||
llof: ObjectFileRef,
|
||||
dtor: @object_file_res
|
||||
}
|
||||
|
||||
pub fn mk_object_file(llmb: MemoryBufferRef) -> Option<ObjectFile> {
|
||||
unsafe {
|
||||
let llof = llvm::LLVMCreateObjectFile(llmb);
|
||||
if llof as int == 0 { return option::None::<ObjectFile>; }
|
||||
|
||||
option::Some(ObjectFile {
|
||||
llof: llof,
|
||||
dtor: @object_file_res(llof)
|
||||
})
|
||||
impl Drop for ObjectFile {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
llvm::LLVMDisposeObjectFile(self.llof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,6 +197,8 @@ pub static tag_region_param_def: uint = 0x100;
|
|||
pub static tag_region_param_def_ident: uint = 0x101;
|
||||
pub static tag_region_param_def_def_id: uint = 0x102;
|
||||
|
||||
pub static tag_native_libraries: uint = 0x103;
|
||||
pub static tag_native_libraries_lib: uint = 0x104;
|
||||
|
||||
pub struct LinkMeta {
|
||||
name: @str,
|
||||
|
|
|
@ -10,10 +10,9 @@
|
|||
|
||||
//! Validates all used crates and extern libraries and loads their metadata
|
||||
|
||||
|
||||
use driver::session::Session;
|
||||
use metadata::cstore;
|
||||
use metadata::decoder;
|
||||
use metadata::filesearch::FileSearch;
|
||||
use metadata::loader;
|
||||
|
||||
use std::hashmap::HashMap;
|
||||
|
@ -29,19 +28,13 @@ use syntax::visit;
|
|||
|
||||
// Traverses an AST, reading all the information about use'd crates and extern
|
||||
// libraries necessary for later resolving, typechecking, linking, etc.
|
||||
pub fn read_crates(diag: @mut span_handler,
|
||||
pub fn read_crates(sess: Session,
|
||||
crate: &ast::Crate,
|
||||
cstore: @mut cstore::CStore,
|
||||
filesearch: @FileSearch,
|
||||
os: loader::Os,
|
||||
statik: bool,
|
||||
intr: @ident_interner) {
|
||||
let e = @mut Env {
|
||||
diag: diag,
|
||||
filesearch: filesearch,
|
||||
cstore: cstore,
|
||||
sess: sess,
|
||||
os: os,
|
||||
statik: statik,
|
||||
crate_cache: @mut ~[],
|
||||
next_crate_num: 1,
|
||||
intr: intr
|
||||
|
@ -50,7 +43,7 @@ pub fn read_crates(diag: @mut span_handler,
|
|||
visit_crate(e, crate);
|
||||
visit::walk_crate(&mut v, crate, ());
|
||||
dump_crates(*e.crate_cache);
|
||||
warn_if_multiple_versions(e, diag, *e.crate_cache);
|
||||
warn_if_multiple_versions(e, sess.diagnostic(), *e.crate_cache);
|
||||
}
|
||||
|
||||
struct ReadCrateVisitor { e:@mut Env }
|
||||
|
@ -113,18 +106,15 @@ fn warn_if_multiple_versions(e: @mut Env,
|
|||
}
|
||||
|
||||
struct Env {
|
||||
diag: @mut span_handler,
|
||||
filesearch: @FileSearch,
|
||||
cstore: @mut cstore::CStore,
|
||||
sess: Session,
|
||||
os: loader::Os,
|
||||
statik: bool,
|
||||
crate_cache: @mut ~[cache_entry],
|
||||
next_crate_num: ast::CrateNum,
|
||||
intr: @ident_interner
|
||||
}
|
||||
|
||||
fn visit_crate(e: &Env, c: &ast::Crate) {
|
||||
let cstore = e.cstore;
|
||||
let cstore = e.sess.cstore;
|
||||
|
||||
for a in c.attrs.iter().filter(|m| "link_args" == m.name()) {
|
||||
match a.value_str() {
|
||||
|
@ -146,7 +136,7 @@ fn visit_view_item(e: @mut Env, i: &ast::view_item) {
|
|||
let p_path = Path::init(p);
|
||||
match p_path.filestem_str() {
|
||||
None|Some("") =>
|
||||
e.diag.span_bug(i.span, "Bad package path in `extern mod` item"),
|
||||
e.sess.span_bug(i.span, "Bad package path in `extern mod` item"),
|
||||
Some(s) =>
|
||||
vec::append(
|
||||
~[attr::mk_name_value_item_str(@"package_id", p),
|
||||
|
@ -162,7 +152,7 @@ fn visit_view_item(e: @mut Env, i: &ast::view_item) {
|
|||
meta_items,
|
||||
@"",
|
||||
i.span);
|
||||
cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum);
|
||||
cstore::add_extern_mod_stmt_cnum(e.sess.cstore, id, cnum);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
@ -170,60 +160,62 @@ fn visit_view_item(e: @mut Env, i: &ast::view_item) {
|
|||
|
||||
fn visit_item(e: &Env, i: @ast::item) {
|
||||
match i.node {
|
||||
ast::item_foreign_mod(ref fm) => {
|
||||
if fm.abis.is_rust() || fm.abis.is_intrinsic() {
|
||||
return;
|
||||
}
|
||||
ast::item_foreign_mod(ref fm) => {
|
||||
if fm.abis.is_rust() || fm.abis.is_intrinsic() {
|
||||
return;
|
||||
}
|
||||
|
||||
let cstore = e.cstore;
|
||||
let link_args = i.attrs.iter()
|
||||
.filter_map(|at| if "link_args" == at.name() {Some(at)} else {None})
|
||||
.collect::<~[&ast::Attribute]>();
|
||||
|
||||
// XXX: two whom it may concern, this was the old logic applied to the
|
||||
// ast's extern mod blocks which had names (we used to allow
|
||||
// "extern mod foo"). This code was never run for anonymous blocks,
|
||||
// and we now only have anonymous blocks. We're still in the midst
|
||||
// of figuring out what the exact operations we'd like to support
|
||||
// when linking external modules, but I wanted to leave this logic
|
||||
// here for the time beging to refer back to it
|
||||
|
||||
//let mut already_added = false;
|
||||
//let link_name = i.attrs.iter()
|
||||
// .find(|at| "link_name" == at.name())
|
||||
// .and_then(|at| at.value_str());
|
||||
|
||||
//let foreign_name = match link_name {
|
||||
// Some(nn) => {
|
||||
// if nn.is_empty() {
|
||||
// e.diag.span_fatal(
|
||||
// i.span,
|
||||
// "empty #[link_name] not allowed; use \
|
||||
// #[nolink].");
|
||||
// }
|
||||
// nn
|
||||
// }
|
||||
// None => token::ident_to_str(&i.ident)
|
||||
// };
|
||||
//if !attr::contains_name(i.attrs, "nolink") {
|
||||
// already_added =
|
||||
// !cstore::add_used_library(cstore, foreign_name);
|
||||
//}
|
||||
//if !link_args.is_empty() && already_added {
|
||||
// e.diag.span_fatal(i.span, ~"library '" + foreign_name +
|
||||
// "' already added: can't specify link_args.");
|
||||
//}
|
||||
|
||||
for m in link_args.iter() {
|
||||
match m.value_str() {
|
||||
Some(linkarg) => {
|
||||
cstore::add_used_link_args(cstore, linkarg);
|
||||
// First, add all of the custom link_args attributes
|
||||
let cstore = e.sess.cstore;
|
||||
let link_args = i.attrs.iter()
|
||||
.filter_map(|at| if "link_args" == at.name() {Some(at)} else {None})
|
||||
.to_owned_vec();
|
||||
for m in link_args.iter() {
|
||||
match m.value_str() {
|
||||
Some(linkarg) => {
|
||||
cstore::add_used_link_args(cstore, linkarg);
|
||||
}
|
||||
None => { /* fallthrough */ }
|
||||
}
|
||||
}
|
||||
|
||||
// Next, process all of the #[link(..)]-style arguments
|
||||
let cstore = e.sess.cstore;
|
||||
let link_args = i.attrs.iter()
|
||||
.filter_map(|at| if "link" == at.name() {Some(at)} else {None})
|
||||
.to_owned_vec();
|
||||
for m in link_args.iter() {
|
||||
match m.meta_item_list() {
|
||||
Some(items) => {
|
||||
let kind = items.iter().find(|k| {
|
||||
"kind" == k.name()
|
||||
}).and_then(|a| a.value_str());
|
||||
let kind = match kind {
|
||||
Some(k) if "static" == k => cstore::NativeStatic,
|
||||
Some(k) => {
|
||||
e.sess.span_fatal(i.span,
|
||||
format!("unknown kind: `{}`", k));
|
||||
}
|
||||
None => cstore::NativeUnknown
|
||||
};
|
||||
let n = items.iter().find(|n| {
|
||||
"name" == n.name()
|
||||
}).and_then(|a| a.value_str());
|
||||
let n = match n {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
e.sess.span_fatal(i.span,
|
||||
"#[link(...)] specified without \
|
||||
`name = \"foo\"`");
|
||||
}
|
||||
};
|
||||
cstore::add_used_library(cstore, n.to_owned(), kind);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
None => { /* fallthrough */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,24 +255,21 @@ fn resolve_crate(e: @mut Env,
|
|||
match existing_match(e, metas, hash) {
|
||||
None => {
|
||||
let load_ctxt = loader::Context {
|
||||
diag: e.diag,
|
||||
filesearch: e.filesearch,
|
||||
sess: e.sess,
|
||||
span: span,
|
||||
ident: ident,
|
||||
metas: metas,
|
||||
hash: hash,
|
||||
os: e.os,
|
||||
is_static: e.statik,
|
||||
intr: e.intr
|
||||
};
|
||||
let (lident, ldata) = loader::load_library_crate(&load_ctxt);
|
||||
let loader::Library {
|
||||
dylib, rlib, metadata
|
||||
} = load_ctxt.load_library_crate();
|
||||
|
||||
let cfilename = Path::init(lident);
|
||||
let cdata = ldata;
|
||||
|
||||
let attrs = decoder::get_crate_attributes(cdata);
|
||||
let attrs = decoder::get_crate_attributes(metadata);
|
||||
let linkage_metas = attr::find_linkage_metas(attrs);
|
||||
let hash = decoder::get_crate_hash(cdata);
|
||||
let hash = decoder::get_crate_hash(metadata);
|
||||
|
||||
// Claim this crate number and cache it
|
||||
let cnum = e.next_crate_num;
|
||||
|
@ -293,7 +282,7 @@ fn resolve_crate(e: @mut Env,
|
|||
e.next_crate_num += 1;
|
||||
|
||||
// Now resolve the crates referenced by this crate
|
||||
let cnum_map = resolve_crate_deps(e, cdata);
|
||||
let cnum_map = resolve_crate_deps(e, metadata);
|
||||
|
||||
let cname =
|
||||
match attr::last_meta_item_value_str_by_name(load_ctxt.metas,
|
||||
|
@ -303,14 +292,18 @@ fn resolve_crate(e: @mut Env,
|
|||
};
|
||||
let cmeta = @cstore::crate_metadata {
|
||||
name: cname,
|
||||
data: cdata,
|
||||
data: metadata,
|
||||
cnum_map: cnum_map,
|
||||
cnum: cnum
|
||||
};
|
||||
|
||||
let cstore = e.cstore;
|
||||
let cstore = e.sess.cstore;
|
||||
cstore::set_crate_data(cstore, cnum, cmeta);
|
||||
cstore::add_used_crate_file(cstore, &cfilename);
|
||||
cstore::add_used_crate_source(cstore, cstore::CrateSource {
|
||||
dylib: dylib,
|
||||
rlib: rlib,
|
||||
cnum: cnum,
|
||||
});
|
||||
return cnum;
|
||||
}
|
||||
Some(cnum) => {
|
||||
|
|
|
@ -262,6 +262,12 @@ pub fn get_item_visibility(cstore: @mut cstore::CStore,
|
|||
decoder::get_item_visibility(cdata, def_id.node)
|
||||
}
|
||||
|
||||
pub fn get_native_libraries(cstore: @mut cstore::CStore,
|
||||
crate_num: ast::CrateNum) -> ~[~str] {
|
||||
let cdata = cstore::get_crate_data(cstore, crate_num);
|
||||
decoder::get_native_libraries(cdata)
|
||||
}
|
||||
|
||||
pub fn each_impl(cstore: @mut cstore::CStore,
|
||||
crate_num: ast::CrateNum,
|
||||
callback: |ast::DefId|) {
|
||||
|
|
|
@ -34,12 +34,33 @@ pub struct crate_metadata {
|
|||
cnum: ast::CrateNum
|
||||
}
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum LinkagePreference {
|
||||
RequireDynamic,
|
||||
RequireStatic,
|
||||
}
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum NativeLibaryKind {
|
||||
NativeStatic,
|
||||
NativeUnknown,
|
||||
}
|
||||
|
||||
// Where a crate came from on the local filesystem. One of these two options
|
||||
// must be non-None.
|
||||
#[deriving(Eq)]
|
||||
pub struct CrateSource {
|
||||
dylib: Option<Path>,
|
||||
rlib: Option<Path>,
|
||||
cnum: ast::CrateNum,
|
||||
}
|
||||
|
||||
pub struct CStore {
|
||||
priv metas: HashMap <ast::CrateNum, @crate_metadata>,
|
||||
priv extern_mod_crate_map: extern_mod_crate_map,
|
||||
priv used_crate_files: ~[Path],
|
||||
priv used_libraries: ~[@str],
|
||||
priv used_link_args: ~[@str],
|
||||
priv used_crate_sources: ~[CrateSource],
|
||||
priv used_libraries: ~[(~str, NativeLibaryKind)],
|
||||
priv used_link_args: ~[~str],
|
||||
intr: @ident_interner
|
||||
}
|
||||
|
||||
|
@ -50,7 +71,7 @@ pub fn mk_cstore(intr: @ident_interner) -> CStore {
|
|||
return CStore {
|
||||
metas: HashMap::new(),
|
||||
extern_mod_crate_map: HashMap::new(),
|
||||
used_crate_files: ~[],
|
||||
used_crate_sources: ~[],
|
||||
used_libraries: ~[],
|
||||
used_link_args: ~[],
|
||||
intr: intr
|
||||
|
@ -88,39 +109,50 @@ pub fn iter_crate_data(cstore: &CStore, i: |ast::CrateNum, @crate_metadata|) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_used_crate_file(cstore: &mut CStore, lib: &Path) {
|
||||
if !cstore.used_crate_files.contains(lib) {
|
||||
cstore.used_crate_files.push((*lib).clone());
|
||||
pub fn add_used_crate_source(cstore: &mut CStore, src: CrateSource) {
|
||||
if !cstore.used_crate_sources.contains(&src) {
|
||||
cstore.used_crate_sources.push(src);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_used_crate_files(cstore: &CStore) -> ~[Path] {
|
||||
// XXX(pcwalton): Bad copy.
|
||||
return cstore.used_crate_files.clone();
|
||||
pub fn get_used_crate_sources<'a>(cstore: &'a CStore) -> &'a [CrateSource] {
|
||||
cstore.used_crate_sources.as_slice()
|
||||
}
|
||||
|
||||
pub fn add_used_library(cstore: &mut CStore, lib: @str) -> bool {
|
||||
pub fn get_used_crates(cstore: &CStore, prefer: LinkagePreference)
|
||||
-> ~[(ast::CrateNum, Option<Path>)]
|
||||
{
|
||||
let mut ret = ~[];
|
||||
for src in cstore.used_crate_sources.iter() {
|
||||
ret.push((src.cnum, match prefer {
|
||||
RequireDynamic => src.dylib.clone(),
|
||||
RequireStatic => src.rlib.clone(),
|
||||
}));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
pub fn add_used_library(cstore: &mut CStore,
|
||||
lib: ~str, kind: NativeLibaryKind) -> bool {
|
||||
assert!(!lib.is_empty());
|
||||
|
||||
if cstore.used_libraries.iter().any(|x| x == &lib) { return false; }
|
||||
cstore.used_libraries.push(lib);
|
||||
if cstore.used_libraries.iter().any(|&(ref x, _)| x == &lib) { return false; }
|
||||
cstore.used_libraries.push((lib, kind));
|
||||
true
|
||||
}
|
||||
|
||||
pub fn get_used_libraries<'a>(cstore: &'a CStore) -> &'a [@str] {
|
||||
let slice: &'a [@str] = cstore.used_libraries;
|
||||
slice
|
||||
pub fn get_used_libraries<'a>(cstore: &'a CStore) -> &'a [(~str, NativeLibaryKind)] {
|
||||
cstore.used_libraries.as_slice()
|
||||
}
|
||||
|
||||
pub fn add_used_link_args(cstore: &mut CStore, args: &str) {
|
||||
for s in args.split(' ') {
|
||||
cstore.used_link_args.push(s.to_managed());
|
||||
cstore.used_link_args.push(s.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_used_link_args<'a>(cstore: &'a CStore) -> &'a [@str] {
|
||||
let slice: &'a [@str] = cstore.used_link_args;
|
||||
slice
|
||||
pub fn get_used_link_args<'a>(cstore: &'a CStore) -> &'a [~str] {
|
||||
cstore.used_link_args.as_slice()
|
||||
}
|
||||
|
||||
pub fn add_extern_mod_stmt_cnum(cstore: &mut CStore,
|
||||
|
|
|
@ -1529,3 +1529,13 @@ pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: ty::ctxt)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_native_libraries(cdata: Cmd) -> ~[~str] {
|
||||
let libraries = reader::get_doc(reader::Doc(cdata.data), tag_native_libraries);
|
||||
let mut result = ~[];
|
||||
reader::tagged_docs(libraries, tag_native_libraries_lib, |lib_doc| {
|
||||
result.push(lib_doc.as_str());
|
||||
true
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ struct Stats {
|
|||
attr_bytes: u64,
|
||||
dep_bytes: u64,
|
||||
lang_item_bytes: u64,
|
||||
native_lib_bytes: u64,
|
||||
impl_bytes: u64,
|
||||
misc_bytes: u64,
|
||||
item_bytes: u64,
|
||||
|
@ -1633,6 +1634,23 @@ fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
|
|||
ebml_w.end_tag(); // tag_lang_items
|
||||
}
|
||||
|
||||
fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
|
||||
ebml_w.start_tag(tag_native_libraries);
|
||||
|
||||
for &(ref lib, kind) in cstore::get_used_libraries(ecx.cstore).iter() {
|
||||
match kind {
|
||||
cstore::NativeStatic => {} // these libraries are not propagated
|
||||
cstore::NativeUnknown => {
|
||||
ebml_w.start_tag(tag_native_libraries_lib);
|
||||
ebml_w.writer.write(lib.as_bytes());
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
struct ImplVisitor<'self> {
|
||||
ecx: &'self EncodeContext<'self>,
|
||||
ebml_w: &'self mut writer::Encoder,
|
||||
|
@ -1750,6 +1768,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
|
|||
attr_bytes: 0,
|
||||
dep_bytes: 0,
|
||||
lang_item_bytes: 0,
|
||||
native_lib_bytes: 0,
|
||||
impl_bytes: 0,
|
||||
misc_bytes: 0,
|
||||
item_bytes: 0,
|
||||
|
@ -1806,6 +1825,11 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
|
|||
encode_lang_items(&ecx, &mut ebml_w);
|
||||
ecx.stats.lang_item_bytes = wr.tell() - i;
|
||||
|
||||
// Encode the native libraries used
|
||||
i = wr.tell();
|
||||
encode_native_libraries(&ecx, &mut ebml_w);
|
||||
ecx.stats.native_lib_bytes = wr.tell() - i;
|
||||
|
||||
// Encode the def IDs of impls, for coherence checking.
|
||||
i = wr.tell();
|
||||
encode_impls(&ecx, crate, &mut ebml_w);
|
||||
|
@ -1842,6 +1866,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
|
|||
println!(" attribute bytes: {}", ecx.stats.attr_bytes);
|
||||
println!(" dep bytes: {}", ecx.stats.dep_bytes);
|
||||
println!(" lang item bytes: {}", ecx.stats.lang_item_bytes);
|
||||
println!(" native bytes: {}", ecx.stats.native_lib_bytes);
|
||||
println!(" impl bytes: {}", ecx.stats.impl_bytes);
|
||||
println!(" misc bytes: {}", ecx.stats.misc_bytes);
|
||||
println!(" item bytes: {}", ecx.stats.item_bytes);
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
|
||||
//! Finds crate binaries and loads their metadata
|
||||
|
||||
|
||||
use lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
|
||||
use back::archive::Archive;
|
||||
use driver::session::Session;
|
||||
use lib::llvm::{False, llvm, ObjectFile, mk_section_iter};
|
||||
use metadata::decoder;
|
||||
use metadata::encoder;
|
||||
use metadata::filesearch::{FileSearch, FileMatch, FileMatches, FileDoesntMatch};
|
||||
use metadata::filesearch::{FileMatches, FileDoesntMatch};
|
||||
use metadata::filesearch;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::diagnostic::span_handler;
|
||||
|
@ -26,6 +27,7 @@ use syntax::attr::AttrMetaMethods;
|
|||
use std::c_str::ToCStr;
|
||||
use std::cast;
|
||||
use std::io;
|
||||
use std::libc;
|
||||
use std::num;
|
||||
use std::option;
|
||||
use std::os::consts::{macos, freebsd, linux, android, win32};
|
||||
|
@ -43,103 +45,176 @@ pub enum Os {
|
|||
}
|
||||
|
||||
pub struct Context {
|
||||
diag: @mut span_handler,
|
||||
filesearch: @FileSearch,
|
||||
sess: Session,
|
||||
span: Span,
|
||||
ident: @str,
|
||||
metas: ~[@ast::MetaItem],
|
||||
hash: @str,
|
||||
os: Os,
|
||||
is_static: bool,
|
||||
intr: @ident_interner
|
||||
}
|
||||
|
||||
pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) {
|
||||
match find_library_crate(cx) {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
cx.diag.span_fatal(cx.span,
|
||||
format!("can't find crate for `{}`",
|
||||
cx.ident));
|
||||
}
|
||||
pub struct Library {
|
||||
dylib: Option<Path>,
|
||||
rlib: Option<Path>,
|
||||
metadata: @~[u8],
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn load_library_crate(&self) -> Library {
|
||||
match self.find_library_crate() {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
self.sess.span_fatal(self.span,
|
||||
format!("can't find crate for `{}`",
|
||||
self.ident));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_library_crate(cx: &Context) -> Option<(~str, @~[u8])> {
|
||||
attr::require_unique_names(cx.diag, cx.metas);
|
||||
find_library_crate_aux(cx, libname(cx), cx.filesearch)
|
||||
}
|
||||
fn find_library_crate(&self) -> Option<Library> {
|
||||
attr::require_unique_names(self.sess.diagnostic(), self.metas);
|
||||
let filesearch = self.sess.filesearch;
|
||||
let crate_name = crate_name_from_metas(self.metas);
|
||||
let (dyprefix, dysuffix) = self.dylibname();
|
||||
|
||||
fn libname(cx: &Context) -> (~str, ~str) {
|
||||
if cx.is_static { return (~"lib", ~".rlib"); }
|
||||
let (dll_prefix, dll_suffix) = match cx.os {
|
||||
OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
|
||||
OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
|
||||
OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
|
||||
OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
|
||||
OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
|
||||
};
|
||||
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
|
||||
let dylib_prefix = format!("{}{}-", dyprefix, crate_name);
|
||||
let rlib_prefix = format!("lib{}-", crate_name);
|
||||
|
||||
(dll_prefix.to_owned(), dll_suffix.to_owned())
|
||||
}
|
||||
let mut matches = ~[];
|
||||
filesearch::search(filesearch, |path| {
|
||||
match path.filename_str() {
|
||||
None => FileDoesntMatch,
|
||||
Some(file) => {
|
||||
let (candidate, existing) = if file.starts_with(rlib_prefix) &&
|
||||
file.ends_with(".rlib") {
|
||||
debug!("{} is an rlib candidate", path.display());
|
||||
(true, self.add_existing_rlib(matches, path, file))
|
||||
} else if file.starts_with(dylib_prefix) &&
|
||||
file.ends_with(dysuffix) {
|
||||
debug!("{} is a dylib candidate", path.display());
|
||||
(true, self.add_existing_dylib(matches, path, file))
|
||||
} else {
|
||||
(false, false)
|
||||
};
|
||||
|
||||
fn find_library_crate_aux(
|
||||
cx: &Context,
|
||||
(prefix, suffix): (~str, ~str),
|
||||
filesearch: @filesearch::FileSearch
|
||||
) -> Option<(~str, @~[u8])> {
|
||||
let crate_name = crate_name_from_metas(cx.metas);
|
||||
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
|
||||
let prefix = format!("{}{}-", prefix, crate_name);
|
||||
let mut matches = ~[];
|
||||
filesearch::search(filesearch, |path| -> FileMatch {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let path_str = path.filename_str();
|
||||
match path_str {
|
||||
None => FileDoesntMatch,
|
||||
Some(path_str) =>
|
||||
if path_str.starts_with(prefix) && path_str.ends_with(suffix) {
|
||||
debug!("{} is a candidate", path.display());
|
||||
match get_metadata_section(cx.os, path) {
|
||||
Some(cvec) =>
|
||||
if !crate_matches(cvec, cx.metas, cx.hash) {
|
||||
debug!("skipping {}, metadata doesn't match",
|
||||
path.display());
|
||||
FileDoesntMatch
|
||||
} else {
|
||||
debug!("found {} with matching metadata", path.display());
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
matches.push((path.as_str().unwrap().to_owned(), cvec));
|
||||
FileMatches
|
||||
},
|
||||
_ => {
|
||||
debug!("could not load metadata for {}", path.display());
|
||||
FileDoesntMatch
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
FileDoesntMatch
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
match matches.len() {
|
||||
0 => None,
|
||||
1 => Some(matches[0]),
|
||||
_ => {
|
||||
cx.diag.span_err(
|
||||
cx.span, format!("multiple matching crates for `{}`", crate_name));
|
||||
cx.diag.handler().note("candidates:");
|
||||
for pair in matches.iter() {
|
||||
let ident = pair.first();
|
||||
let data = pair.second();
|
||||
cx.diag.handler().note(format!("path: {}", ident));
|
||||
let attrs = decoder::get_crate_attributes(data);
|
||||
note_linkage_attrs(cx.intr, cx.diag, attrs);
|
||||
if candidate && existing {
|
||||
FileMatches
|
||||
} else if candidate {
|
||||
match get_metadata_section(self.sess, self.os, path,
|
||||
crate_name) {
|
||||
Some(cvec) =>
|
||||
if crate_matches(cvec, self.metas, self.hash) {
|
||||
debug!("found {} with matching metadata",
|
||||
path.display());
|
||||
let (rlib, dylib) = if file.ends_with(".rlib") {
|
||||
(Some(path.clone()), None)
|
||||
} else {
|
||||
(None, Some(path.clone()))
|
||||
};
|
||||
matches.push(Library {
|
||||
rlib: rlib,
|
||||
dylib: dylib,
|
||||
metadata: cvec,
|
||||
});
|
||||
FileMatches
|
||||
} else {
|
||||
debug!("skipping {}, metadata doesn't match",
|
||||
path.display());
|
||||
FileDoesntMatch
|
||||
},
|
||||
_ => {
|
||||
debug!("could not load metadata for {}",
|
||||
path.display());
|
||||
FileDoesntMatch
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FileDoesntMatch
|
||||
}
|
||||
}
|
||||
cx.diag.handler().abort_if_errors();
|
||||
}
|
||||
});
|
||||
|
||||
match matches.len() {
|
||||
0 => None,
|
||||
1 => Some(matches[0]),
|
||||
_ => {
|
||||
self.sess.span_err(self.span,
|
||||
format!("multiple matching crates for `{}`", crate_name));
|
||||
self.sess.note("candidates:");
|
||||
for lib in matches.iter() {
|
||||
match lib.dylib {
|
||||
Some(ref p) => {
|
||||
self.sess.note(format!("path: {}", p.display()));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
match lib.rlib {
|
||||
Some(ref p) => {
|
||||
self.sess.note(format!("path: {}", p.display()));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
let attrs = decoder::get_crate_attributes(lib.metadata);
|
||||
note_linkage_attrs(self.intr, self.sess.diagnostic(), attrs);
|
||||
}
|
||||
self.sess.abort_if_errors();
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_existing_rlib(&self, libs: &mut [Library],
|
||||
path: &Path, file: &str) -> bool {
|
||||
let (prefix, suffix) = self.dylibname();
|
||||
let file = file.slice_from(3); // chop off 'lib'
|
||||
let file = file.slice_to(file.len() - 5); // chop off '.rlib'
|
||||
let file = format!("{}{}{}", prefix, file, suffix);
|
||||
|
||||
for lib in libs.mut_iter() {
|
||||
match lib.dylib {
|
||||
Some(ref p) if p.filename_str() == Some(file.as_slice()) => {
|
||||
assert!(lib.rlib.is_none()); // XXX: legit compiler error
|
||||
lib.rlib = Some(path.clone());
|
||||
return true;
|
||||
}
|
||||
Some(..) | None => {}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn add_existing_dylib(&self, libs: &mut [Library],
|
||||
path: &Path, file: &str) -> bool {
|
||||
let (prefix, suffix) = self.dylibname();
|
||||
let file = file.slice_from(prefix.len());
|
||||
let file = file.slice_to(file.len() - suffix.len());
|
||||
let file = format!("lib{}.rlib", file);
|
||||
|
||||
for lib in libs.mut_iter() {
|
||||
match lib.rlib {
|
||||
Some(ref p) if p.filename_str() == Some(file.as_slice()) => {
|
||||
assert!(lib.dylib.is_none()); // XXX: legit compiler error
|
||||
lib.dylib = Some(path.clone());
|
||||
return true;
|
||||
}
|
||||
Some(..) | None => {}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the corresponding (prefix, suffix) that files need to have for
|
||||
// dynamic libraries
|
||||
fn dylibname(&self) -> (&'static str, &'static str) {
|
||||
match self.os {
|
||||
OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
|
||||
OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
|
||||
OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
|
||||
OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
|
||||
OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,16 +271,26 @@ pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
|
|||
local_metas.iter().all(|needed| attr::contains(extern_metas, *needed))
|
||||
}
|
||||
|
||||
fn get_metadata_section(os: Os,
|
||||
filename: &Path) -> Option<@~[u8]> {
|
||||
fn get_metadata_section(sess: Session, os: Os, filename: &Path,
|
||||
crate_name: &str) -> Option<@~[u8]> {
|
||||
unsafe {
|
||||
let mb = filename.with_c_str(|buf| {
|
||||
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
|
||||
});
|
||||
if mb as int == 0 { return option::None::<@~[u8]>; }
|
||||
let of = match mk_object_file(mb) {
|
||||
option::Some(of) => of,
|
||||
_ => return option::None::<@~[u8]>
|
||||
let mb = if filename.filename_str().unwrap().ends_with(".rlib") {
|
||||
let archive = Archive::open(sess, filename.clone());
|
||||
let contents = archive.read(crate_name + ".o");
|
||||
let ptr = vec::raw::to_ptr(contents);
|
||||
crate_name.with_c_str(|name| {
|
||||
llvm::LLVMCreateMemoryBufferWithMemoryRangeCopy(
|
||||
ptr as *i8, contents.len() as libc::size_t, name)
|
||||
})
|
||||
} else {
|
||||
filename.with_c_str(|buf| {
|
||||
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
|
||||
})
|
||||
};
|
||||
if mb as int == 0 { return None }
|
||||
let of = match ObjectFile::new(mb) {
|
||||
Some(of) => of,
|
||||
_ => return None
|
||||
};
|
||||
let si = mk_section_iter(of.llof);
|
||||
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
|
||||
|
@ -266,11 +351,17 @@ pub fn read_meta_section_name(os: Os) -> &'static str {
|
|||
}
|
||||
|
||||
// A diagnostic function for dumping crate metadata to an output stream
|
||||
pub fn list_file_metadata(intr: @ident_interner,
|
||||
pub fn list_file_metadata(sess: Session,
|
||||
intr: @ident_interner,
|
||||
os: Os,
|
||||
path: &Path,
|
||||
out: @mut io::Writer) {
|
||||
match get_metadata_section(os, path) {
|
||||
// guess the crate name from the pathname
|
||||
let crate_name = path.filename_str().unwrap();
|
||||
let crate_name = if crate_name.starts_with("lib") {
|
||||
crate_name.slice_from(3) } else { crate_name };
|
||||
let crate_name = crate_name.split('-').next().unwrap();
|
||||
match get_metadata_section(sess, os, path, crate_name) {
|
||||
option::Some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
|
||||
option::None => {
|
||||
write!(out, "could not find metadata in {}.\n", path.display())
|
||||
|
|
|
@ -808,7 +808,7 @@ fn check_heap_item(cx: &Context, it: &ast::item) {
|
|||
}
|
||||
|
||||
static crate_attrs: &'static [&'static str] = &[
|
||||
"crate_type", "link", "feature", "no_uv", "no_main", "no_std",
|
||||
"crate_type", "feature", "no_uv", "no_main", "no_std",
|
||||
"desc", "comment", "license", "copyright", // not used in rustc now
|
||||
];
|
||||
|
||||
|
@ -830,7 +830,7 @@ static other_attrs: &'static [&'static str] = &[
|
|||
"deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability
|
||||
"crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze",
|
||||
"no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag",
|
||||
"packed", "simd", "repr", "deriving", "unsafe_destructor",
|
||||
"packed", "simd", "repr", "deriving", "unsafe_destructor", "link",
|
||||
|
||||
//mod-level
|
||||
"path", "link_name", "link_args", "nolink", "macro_escape", "no_implicit_prelude",
|
||||
|
|
|
@ -77,14 +77,14 @@ use extra::time;
|
|||
use extra::sort;
|
||||
use syntax::ast::Name;
|
||||
use syntax::ast_map::{path, path_elt_to_str, path_name, path_pretty_name};
|
||||
use syntax::ast_util::{local_def};
|
||||
use syntax::ast_util::{local_def, is_local};
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
use syntax::parse::token::{special_idents};
|
||||
use syntax::print::pprust::stmt_to_str;
|
||||
use syntax::{ast, ast_util, codemap, ast_map};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic, OsWin32, OsAndroid};
|
||||
use syntax::visit;
|
||||
use syntax::visit::Visitor;
|
||||
|
@ -2996,7 +2996,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
|
|||
return map;
|
||||
}
|
||||
|
||||
pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
|
||||
pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) {
|
||||
let mut subcrates: ~[ValueRef] = ~[];
|
||||
let mut i = 1;
|
||||
let cstore = ccx.sess.cstore;
|
||||
|
@ -3014,19 +3014,20 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
|
|||
subcrates.push(p2i(ccx, cr));
|
||||
i += 1;
|
||||
}
|
||||
let event_loop_factory = if !*ccx.sess.building_library {
|
||||
match ccx.tcx.lang_items.event_loop_factory() {
|
||||
Some(did) => unsafe {
|
||||
let event_loop_factory = match ccx.tcx.lang_items.event_loop_factory() {
|
||||
Some(did) => unsafe {
|
||||
if is_local(did) {
|
||||
llvm::LLVMConstPointerCast(get_item_val(ccx, did.node),
|
||||
ccx.int_type.ptr_to().to_ref())
|
||||
} else {
|
||||
let name = csearch::get_symbol(ccx.sess.cstore, did);
|
||||
let global = name.with_c_str(|buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
|
||||
});
|
||||
global
|
||||
},
|
||||
None => C_null(ccx.int_type.ptr_to())
|
||||
}
|
||||
} else {
|
||||
C_null(ccx.int_type.ptr_to())
|
||||
}
|
||||
},
|
||||
None => C_null(ccx.int_type.ptr_to())
|
||||
};
|
||||
unsafe {
|
||||
let maptype = Type::array(&ccx.int_type, subcrates.len() as u64);
|
||||
|
@ -3106,18 +3107,6 @@ pub fn write_metadata(cx: &CrateContext, crate: &ast::Crate) {
|
|||
}
|
||||
}
|
||||
|
||||
// Writes the current ABI version into the crate.
|
||||
pub fn write_abi_version(ccx: &mut CrateContext) {
|
||||
unsafe {
|
||||
let llval = C_uint(ccx, abi::abi_version);
|
||||
let llglobal = "rust_abi_version".with_c_str(|buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
|
||||
});
|
||||
llvm::LLVMSetInitializer(llglobal, llval);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, True);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trans_crate(sess: session::Session,
|
||||
crate: ast::Crate,
|
||||
analysis: &CrateAnalysis,
|
||||
|
@ -3177,7 +3166,6 @@ pub fn trans_crate(sess: session::Session,
|
|||
}
|
||||
|
||||
glue::emit_tydescs(ccx);
|
||||
write_abi_version(ccx);
|
||||
if ccx.sess.opts.debuginfo {
|
||||
debuginfo::finalize(ccx);
|
||||
}
|
||||
|
@ -3217,10 +3205,18 @@ pub fn trans_crate(sess: session::Session,
|
|||
let llcx = ccx.llcx;
|
||||
let link_meta = ccx.link_meta;
|
||||
let llmod = ccx.llmod;
|
||||
let crate_types = crate.attrs.iter().filter_map(|a| {
|
||||
if "crate_type" == a.name() {
|
||||
a.value_str()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).map(|a| a.to_owned()).collect();
|
||||
|
||||
return CrateTranslation {
|
||||
context: llcx,
|
||||
module: llmod,
|
||||
link: link_meta
|
||||
link: link_meta,
|
||||
crate_types: crate_types,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ struct buf {
|
|||
}
|
||||
|
||||
// sundown FFI
|
||||
#[link_args = "-lsundown"]
|
||||
#[link(name = "sundown", kind = "static")]
|
||||
extern {
|
||||
fn sdhtml_renderer(callbacks: *sd_callbacks,
|
||||
options_ptr: *html_renderopt,
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
#[desc = "rustdoc, the Rust documentation extractor"];
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
#[crate_type = "lib"]; // NOTE: remove after stage0 snapshot
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
#[feature(globs, struct_variant, managed_boxes)];
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
url = "https://github.com/mozilla/rust/tree/master/src/librustpkg")];
|
||||
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
#[crate_type = "lib"]; // NOTE: remove after stage0 snapshot
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
#[feature(globs, managed_boxes)];
|
||||
|
||||
|
@ -114,7 +115,7 @@ impl<'self> PkgScript<'self> {
|
|||
let options = @session::options {
|
||||
binary: binary,
|
||||
maybe_sysroot: Some(@sysroot),
|
||||
crate_type: session::bin_crate,
|
||||
outputs: ~[session::OutputExecutable],
|
||||
.. (*session::basic_options()).clone()
|
||||
};
|
||||
let input = driver::file_input(script.clone());
|
||||
|
|
|
@ -36,6 +36,7 @@ use path_util::{target_executable_in_workspace, target_test_in_workspace,
|
|||
chmod_read_only, platform_library_name};
|
||||
use rustc::back::link::get_cc_prog;
|
||||
use rustc::metadata::filesearch::rust_path;
|
||||
use rustc::driver::session;
|
||||
use rustc::driver::driver::{build_session, build_session_options, host_triple, optgroups};
|
||||
use syntax::diagnostic;
|
||||
use target::*;
|
||||
|
@ -1829,10 +1830,11 @@ fn test_linker_build() {
|
|||
@diagnostic::Emitter);
|
||||
let test_sys = test_sysroot();
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let cc = get_cc_prog(sess);
|
||||
command_line_test([test_sys.as_str().unwrap().to_owned(),
|
||||
~"install",
|
||||
~"--linker",
|
||||
get_cc_prog(sess),
|
||||
cc,
|
||||
~"foo"],
|
||||
workspace);
|
||||
assert_executable_exists(workspace, "foo");
|
||||
|
|
|
@ -25,7 +25,6 @@ use syntax::visit::Visitor;
|
|||
use syntax::util::small_vector::SmallVector;
|
||||
use rustc::back::link::output_type_exe;
|
||||
use rustc::back::link;
|
||||
use rustc::driver::session::{lib_crate, bin_crate};
|
||||
use context::{in_target, StopBefore, Link, Assemble, BuildContext};
|
||||
use package_id::PkgId;
|
||||
use package_source::PkgSrc;
|
||||
|
@ -195,8 +194,8 @@ pub fn compile_input(context: &BuildContext,
|
|||
debug!("compile_input's sysroot = {}", csysroot.display());
|
||||
|
||||
let crate_type = match what {
|
||||
Lib => lib_crate,
|
||||
Test | Bench | Main => bin_crate
|
||||
Lib => session::OutputDylib,
|
||||
Test | Bench | Main => session::OutputExecutable,
|
||||
};
|
||||
let matches = getopts(debug_flags()
|
||||
+ match what {
|
||||
|
@ -239,7 +238,7 @@ pub fn compile_input(context: &BuildContext,
|
|||
debug!("Output type = {:?}", output_type);
|
||||
|
||||
let options = @session::options {
|
||||
crate_type: crate_type,
|
||||
outputs: ~[crate_type],
|
||||
optimize: opt,
|
||||
test: what == Test || what == Bench,
|
||||
maybe_sysroot: Some(sysroot_to_use),
|
||||
|
|
|
@ -41,9 +41,12 @@ via `close` and `delete` methods.
|
|||
url = "https://github.com/mozilla/rust/tree/master/src/librustuv")];
|
||||
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
#[crate_type = "lib"]; // NOTE: remove after stage0 snapshot
|
||||
#[crate_type = "rlib"];
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
#[feature(macro_rules, globs)];
|
||||
#[allow(attribute_usage)]; // NOTE: remove after the next snapshot
|
||||
|
||||
use std::cast::transmute;
|
||||
use std::cast;
|
||||
|
|
|
@ -524,8 +524,13 @@ pub unsafe fn guess_handle(handle: c_int) -> c_int {
|
|||
// second copies of everything. We obviously don't want this, so instead of
|
||||
// dying horribly during testing, we allow all of the test rustuv's references
|
||||
// to get resolved to the original rustuv crate.
|
||||
#[link_args = "-luv_support -luv"]
|
||||
#[cfg(not(test))]
|
||||
#[cfg(not(test), not(stage0))]
|
||||
#[link(name = "uv_support", kind = "static")]
|
||||
#[link(name = "uv", kind = "static")]
|
||||
extern {}
|
||||
|
||||
#[cfg(not(test), stage0)]
|
||||
#[link_args = "-luv -luv_support"]
|
||||
extern {}
|
||||
|
||||
extern {
|
||||
|
@ -717,12 +722,26 @@ extern {
|
|||
pub fn uv_signal_stop(handle: *uv_signal_t) -> c_int;
|
||||
}
|
||||
|
||||
// libuv requires various system libraries to successfully link on some
|
||||
// platforms
|
||||
#[cfg(target_os = "linux")]
|
||||
// various platform libraries required by libuv
|
||||
#[cfg(not(stage0), not(target_os = "android"))]
|
||||
#[link(name = "pthread")]
|
||||
extern {}
|
||||
#[cfg(stage0)]
|
||||
#[link_args = "-lpthread"]
|
||||
extern {}
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
#[cfg(target_os = "win32", not(stage0))]
|
||||
#[link(name = "ws2_32")]
|
||||
#[link(name = "psapi")]
|
||||
#[link(name = "iphlpapi")]
|
||||
extern {}
|
||||
#[cfg(target_os = "win32", stage0)]
|
||||
#[link_args = "-lws2_32 -lpsapi -liphlpapi"]
|
||||
extern {}
|
||||
|
||||
#[cfg(target_os = "freebsd", not(stage0))]
|
||||
#[link(name = "kvm")]
|
||||
extern {}
|
||||
#[cfg(target_os = "freebsd", stage0)]
|
||||
#[link_args = "-lkvm"]
|
||||
extern {}
|
||||
|
|
|
@ -51,7 +51,9 @@
|
|||
|
||||
#[comment = "The Rust standard library"];
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
#[crate_type = "lib"]; // NOTE: remove after stage0 snapshot
|
||||
#[crate_type = "rlib"];
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
|
@ -64,6 +66,7 @@
|
|||
|
||||
#[deny(non_camel_case_types)];
|
||||
#[deny(missing_doc)];
|
||||
#[allow(attribute_usage)]; // NOTE: remove after the next snapshot
|
||||
|
||||
// When testing libstd, bring in libuv as the I/O backend so tests can print
|
||||
// things and all of the std::io tests have an I/O interface to run on top
|
||||
|
@ -79,15 +82,7 @@
|
|||
#[cfg(test)] pub use ops = realstd::ops;
|
||||
#[cfg(test)] pub use cmp = realstd::cmp;
|
||||
|
||||
// On Linux, link to the runtime with -lrt.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[doc(hidden)]
|
||||
pub mod linkhack {
|
||||
#[link_args="-lrustrt -lrt"]
|
||||
#[link_args = "-lpthread"]
|
||||
extern {
|
||||
}
|
||||
}
|
||||
mod rtdeps;
|
||||
|
||||
/* The Prelude. */
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
//! This module contains the linkage attributes to all runtime dependencies of
|
||||
//! the stndard library This varies per-platform, but these libraries are
|
||||
//! necessary for running libstd.
|
||||
|
||||
// All platforms need to link to rustrt
|
||||
#[link(name = "rustrt", kind = "static")]
|
||||
extern {}
|
||||
|
||||
// LLVM implements the `frem` instruction as a call to `fmod`, which lives in
|
||||
// libm. Hence, we must explicitly link to it.
|
||||
//
|
||||
// On linux librt and libdl are indirect dependencies via rustrt,
|
||||
// and binutils 2.22+ won't add them automatically
|
||||
#[cfg(target_os = "linux")]
|
||||
#[link(name = "rt")]
|
||||
#[link(name = "dl")]
|
||||
#[link(name = "m")]
|
||||
#[link(name = "pthread")]
|
||||
#[link(name = "stdc++")]
|
||||
extern {}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[link(name = "dl")]
|
||||
#[link(name = "log")]
|
||||
#[link(name = "supc++")]
|
||||
#[link(name = "gnustl_shared")]
|
||||
#[link(name = "m")]
|
||||
extern {}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[link(name = "execinfo")]
|
||||
#[link(name = "rt")]
|
||||
#[link(name = "stdc++")]
|
||||
#[link(name = "pthread")]
|
||||
extern {}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[link(name = "pthread")]
|
||||
#[link(name = "stdc++")]
|
||||
extern {}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[link_args = "-lstdc++"]
|
||||
extern {}
|
|
@ -19,7 +19,8 @@
|
|||
uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")];
|
||||
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
#[crate_type = "lib"]; // NOTE: remove after stage0 snapshot
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
#[feature(macro_rules, globs, managed_boxes)];
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
rust_dbg_abi_1
|
||||
rust_dbg_abi_2
|
||||
rust_dbg_static_mut
|
||||
rust_dbg_static_mut_check_four
|
||||
rust_get_time
|
||||
rust_tzset
|
||||
rust_gmtime
|
||||
rust_localtime
|
||||
rust_timegm
|
||||
rust_mktime
|
||||
rust_precise_time_ns
|
||||
rust_list_dir_val
|
||||
rust_list_dir_wfd_size
|
||||
rust_list_dir_wfd_fp_buf
|
||||
rust_unset_sigprocmask
|
||||
rust_env_pairs
|
||||
rust_win32_rand_acquire
|
||||
rust_win32_rand_gen
|
||||
rust_win32_rand_release
|
||||
upcall_rust_personality
|
||||
upcall_reset_stack_limit
|
||||
rust_dbg_call
|
||||
rust_dbg_do_nothing
|
||||
tdefl_compress_mem_to_heap
|
||||
tinfl_decompress_mem_to_heap
|
||||
rust_swap_registers
|
||||
rust_readdir
|
||||
rust_opendir
|
||||
rust_dbg_extern_identity_u32
|
||||
rust_dbg_extern_identity_u64
|
||||
rust_dbg_extern_identity_TwoU8s
|
||||
rust_dbg_extern_identity_TwoU16s
|
||||
rust_dbg_extern_identity_TwoU32s
|
||||
rust_dbg_extern_identity_TwoU64s
|
||||
rust_dbg_extern_identity_TwoDoubles
|
||||
rust_dbg_extern_return_TwoU8s
|
||||
rust_dbg_extern_return_TwoU16s
|
||||
rust_dbg_extern_return_TwoU32s
|
||||
rust_dbg_extern_return_TwoU64s
|
||||
rust_dbg_extern_identity_double
|
||||
rust_dbg_extern_identity_u8
|
||||
rust_try
|
||||
rust_begin_unwind
|
||||
rust_valgrind_stack_register
|
||||
rust_valgrind_stack_deregister
|
||||
rust_running_on_valgrind
|
||||
rust_get_num_cpus
|
||||
rust_get_test_int
|
||||
rust_pthread_mutex_t_size
|
||||
rust_pthread_cond_t_size
|
||||
rust_crit_section_size
|
|
@ -630,3 +630,5 @@ LLVMAddReturnAttribute
|
|||
LLVMRemoveReturnAttribute
|
||||
LLVMTypeToString
|
||||
LLVMAddColdAttribute
|
||||
LLVMCreateMemoryBufferWithMemoryRange
|
||||
LLVMCreateMemoryBufferWithMemoryRangeCopy
|
||||
|
|
|
@ -8,14 +8,13 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[link_name = "rustrt"];
|
||||
#[link(name = "anonexternmod",
|
||||
vers = "0.1")];
|
||||
#[link(name = "anonexternmod", vers = "0.1")];
|
||||
|
||||
#[crate_type = "lib"];
|
||||
|
||||
use std::libc;
|
||||
|
||||
extern {
|
||||
#[link(name = "rustrt")]
|
||||
pub fn rust_get_test_int() -> libc::intptr_t;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ use std::libc;
|
|||
pub mod rustrt {
|
||||
use std::libc;
|
||||
|
||||
#[link(name = "rustrt")]
|
||||
extern {
|
||||
pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
|
||||
data: libc::uintptr_t)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
pub mod rustrt {
|
||||
use std::libc;
|
||||
|
||||
#[link(name = "rustrt")]
|
||||
extern {
|
||||
fn rust_get_test_int() -> libc::intptr_t;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) lib.rs -Z gen-crate-map
|
||||
ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
|
||||
$(CC) main.c -o $(call RUN,main) -lboot -Wl,-rpath,$(TMPDIR)
|
||||
$(call RUN,main)
|
||||
rm $(call DYLIB,boot)
|
||||
$(call FAIL,main)
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
#[link(package_id = "boot", name = "boot", vers = "0.1")];
|
||||
#[crate_type = "lib"];
|
||||
|
||||
extern mod rustuv; // pull in uvio
|
||||
|
||||
use std::rt;
|
||||
|
||||
#[no_mangle] // this needs to get called from C
|
||||
pub extern "C" fn foo(argc: int, argv: **u8) -> int {
|
||||
do rt::start(argc, argv) {
|
||||
do spawn {
|
||||
println!("hello");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// this is the rust entry point that we're going to call.
|
||||
int foo(int argc, char *argv[]);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return foo(argc, argv);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
-include ../tools.mk
|
||||
|
||||
# This hits an assertion in the linker on older versions of osx apparently
|
||||
ifeq ($(shell uname),Darwin)
|
||||
all:
|
||||
echo ignored
|
||||
else
|
||||
all: $(call DYLIB,cfoo)
|
||||
$(RUSTC) foo.rs
|
||||
$(RUSTC) bar.rs
|
||||
$(call RUN,bar)
|
||||
rm $(TMPDIR)/$(call DYLIB_GLOB,cfoo)
|
||||
$(call FAIL,bar)
|
||||
endif
|
|
@ -0,0 +1,5 @@
|
|||
extern mod foo;
|
||||
|
||||
fn main() {
|
||||
foo::rsfoo();
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int foo() { return 0; }
|
|
@ -0,0 +1,10 @@
|
|||
#[crate_type = "dylib"];
|
||||
|
||||
#[link(name = "cfoo")]
|
||||
extern {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
pub fn rsfoo() {
|
||||
unsafe { foo() }
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
-include ../tools.mk
|
||||
|
||||
# This hits an assertion in the linker on older versions of osx apparently
|
||||
ifeq ($(shell uname),Darwin)
|
||||
all:
|
||||
echo ignored
|
||||
else
|
||||
all: $(call DYLIB,cfoo)
|
||||
$(RUSTC) foo.rs
|
||||
$(RUSTC) bar.rs
|
||||
LD_LIBRARY_PATH=$(TMPDIR) $(call RUN,bar)
|
||||
rm $(TMPDIR)/$(call DYLIB_GLOB,cfoo)
|
||||
$(call FAIL,bar)
|
||||
endif
|
|
@ -0,0 +1,5 @@
|
|||
extern mod foo;
|
||||
|
||||
fn main() {
|
||||
foo::rsfoo();
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int foo() { return 0; }
|
|
@ -0,0 +1,10 @@
|
|||
#[crate_type = "rlib"];
|
||||
|
||||
#[link(name = "cfoo")]
|
||||
extern {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
pub fn rsfoo() {
|
||||
unsafe { foo() }
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) foo.rs
|
||||
ln -s $(call DYLIB,foo-*) $(call DYLIB,foo)
|
||||
$(CC) bar.c -lfoo -o $(call RUN,bar) -Wl,-rpath,$(TMPDIR)
|
||||
$(call RUN,bar)
|
||||
rm $(call DYLIB,foo)
|
||||
$(call FAIL,bar)
|
|
@ -0,0 +1,6 @@
|
|||
void foo();
|
||||
|
||||
int main() {
|
||||
foo();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "dylib"];
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn foo() {}
|
|
@ -0,0 +1,13 @@
|
|||
-include ../tools.mk
|
||||
|
||||
ifneq ($(shell uname),Darwin)
|
||||
EXTRAFLAGS := -lm -lrt -ldl -lpthread
|
||||
endif
|
||||
|
||||
all:
|
||||
$(RUSTC) foo.rs -Z gen-crate-map
|
||||
ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
|
||||
$(CC) bar.c -lfoo -o $(call RUN,bar) $(EXTRAFLAGS) -lstdc++
|
||||
$(call RUN,bar)
|
||||
rm $(call STATICLIB,foo*)
|
||||
$(call RUN,bar)
|
|
@ -0,0 +1,6 @@
|
|||
void foo();
|
||||
|
||||
int main() {
|
||||
foo();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "staticlib"];
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn foo() {}
|
|
@ -0,0 +1,9 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all: $(call STATICLIB,cfoo)
|
||||
$(RUSTC) foo.rs
|
||||
$(RUSTC) bar.rs
|
||||
rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo)
|
||||
$(call RUN,bar)
|
||||
rm $(TMPDIR)/$(call DYLIB_GLOB,foo)
|
||||
$(call FAIL,bar)
|
|
@ -0,0 +1,5 @@
|
|||
extern mod foo;
|
||||
|
||||
fn main() {
|
||||
foo::rsfoo();
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int foo() { return 0; }
|
|
@ -0,0 +1,10 @@
|
|||
#[crate_type = "dylib"];
|
||||
|
||||
#[link(name = "cfoo")]
|
||||
extern {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
pub fn rsfoo() {
|
||||
unsafe { foo() }
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all: $(call STATICLIB,cfoo)
|
||||
$(RUSTC) foo.rs
|
||||
$(RUSTC) bar.rs
|
||||
rm $(TMPDIR)/$(call RLIB_GLOB,foo)
|
||||
rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo)
|
||||
$(call RUN,bar)
|
|
@ -0,0 +1,5 @@
|
|||
extern mod foo;
|
||||
|
||||
fn main() {
|
||||
foo::rsfoo();
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int foo() { return 0; }
|
|
@ -0,0 +1,10 @@
|
|||
#[crate_type = "rlib"];
|
||||
|
||||
#[link(name = "cfoo")]
|
||||
extern {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
pub fn rsfoo() {
|
||||
unsafe { foo() }
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) m1.rs
|
||||
$(RUSTC) m2.rs
|
||||
$(RUSTC) m3.rs
|
||||
$(RUSTC) m4.rs
|
||||
$(call RUN,m4)
|
||||
rm $(TMPDIR)/$(call DYLIB_GLOB,m1)
|
||||
rm $(TMPDIR)/$(call DYLIB_GLOB,m2)
|
||||
rm $(TMPDIR)/$(call DYLIB_GLOB,m3)
|
||||
$(call FAIL,m4)
|
|
@ -0,0 +1,2 @@
|
|||
#[crate_type = "dylib"];
|
||||
pub fn m1() {}
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "dylib"];
|
||||
extern mod m1;
|
||||
|
||||
pub fn m2() { m1::m1() }
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "dylib"];
|
||||
extern mod m2;
|
||||
|
||||
pub fn m3() { m2::m2() }
|
|
@ -0,0 +1,3 @@
|
|||
extern mod m3;
|
||||
|
||||
fn main() { m3::m3() }
|
|
@ -0,0 +1,7 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) both.rs
|
||||
$(RUSTC) dylib.rs -Z prefer-dynamic
|
||||
$(RUSTC) prog.rs
|
||||
$(call RUN,prog)
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "rlib"];
|
||||
#[crate_type = "dylib"];
|
||||
|
||||
pub static foo: int = 4;
|
|
@ -0,0 +1,6 @@
|
|||
#[crate_type = "dylib"];
|
||||
extern mod both;
|
||||
|
||||
use std::cast;
|
||||
|
||||
pub fn addr() -> uint { unsafe { cast::transmute(&both::foo) } }
|
|
@ -0,0 +1,9 @@
|
|||
extern mod dylib;
|
||||
extern mod both;
|
||||
|
||||
use std::cast;
|
||||
|
||||
fn main() {
|
||||
assert_eq!(unsafe { cast::transmute::<&int, uint>(&both::foo) },
|
||||
dylib::addr());
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) rlib.rs
|
||||
$(RUSTC) dylib.rs && exit 1 || exit 0
|
||||
$(RUSTC) rlib.rs --dylib
|
||||
$(RUSTC) dylib.rs
|
||||
rm $(call DYLIB,rlib-*)
|
||||
$(RUSTC) prog.rs && exit 1 || exit 0
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "dylib"];
|
||||
extern mod rlib;
|
||||
|
||||
pub fn dylib() { rlib::rlib() }
|
|
@ -0,0 +1,7 @@
|
|||
extern mod dylib;
|
||||
extern mod rlib;
|
||||
|
||||
fn main() {
|
||||
dylib::dylib();
|
||||
rlib::rlib();
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
#[crate_type = "rlib"];
|
||||
pub fn rlib() {}
|
|
@ -0,0 +1,8 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) bar.rs --dylib --rlib
|
||||
$(RUSTC) foo.rs -Z prefer-dynamic
|
||||
$(call RUN,foo)
|
||||
rm $(TMPDIR)/*bar*
|
||||
$(call FAILS,foo)
|
|
@ -0,0 +1 @@
|
|||
pub fn bar() {}
|
|
@ -0,0 +1,5 @@
|
|||
extern mod bar;
|
||||
|
||||
fn main() {
|
||||
bar::bar();
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) bar.rs --dylib --rlib
|
||||
ls $(TMPDIR)/$(call RLIB_GLOB,bar)
|
||||
$(RUSTC) foo.rs
|
||||
rm $(TMPDIR)/*bar*
|
||||
$(call RUN,foo)
|
|
@ -0,0 +1 @@
|
|||
pub fn bar() {}
|
|
@ -0,0 +1,5 @@
|
|||
extern mod bar;
|
||||
|
||||
fn main() {
|
||||
bar::bar();
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) m1.rs
|
||||
$(RUSTC) m2.rs
|
||||
$(RUSTC) m3.rs
|
||||
$(RUSTC) m4.rs
|
||||
$(call RUN,m4)
|
||||
rm $(TMPDIR)/*lib
|
||||
$(call RUN,m4)
|
|
@ -0,0 +1,2 @@
|
|||
#[crate_type = "rlib"];
|
||||
pub fn m1() {}
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "rlib"];
|
||||
extern mod m1;
|
||||
|
||||
pub fn m2() { m1::m1() }
|
|
@ -0,0 +1,4 @@
|
|||
#[crate_type = "rlib"];
|
||||
extern mod m2;
|
||||
|
||||
pub fn m3() { m2::m2() }
|
|
@ -0,0 +1,3 @@
|
|||
extern mod m3;
|
||||
|
||||
fn main() { m3::m3() }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue