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
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)
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
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
-
- 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
-
- 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))
-
- 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
+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))/$(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))
# Preqrequisites for using the stageN compiler
HSREQ$(1)_H_$(3) = \
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"
valopt datadir "${CFG_PREFIX}/share" "install data"
valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
-valopt libdir "${CFG_PREFIX}/lib" "install libraries"
+valopt libdir "${CFG_PREFIX}/lib" "install libraries"
# Validate Options
step_msg "validating $CFG_SELF args"
CFG_MANDIR=${CFG_MANDIR%/}
CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
-CFG_SUPPORTED_TARGET="$(grep ^CC_*=* $CFG_SRC_DIR/mk/platform.mk | sed -e 's/^CC_//' -e 's/\([^=]*\).*/\1/' | xargs)"
+CFG_SUPPORTED_TARGET="$(grep ^CC_*=* ${CFG_SRC_DIR}mk/platform.mk | sed -e 's/^CC_//' -e 's/\([^=]*\).*/\1/' | xargs)"
# copy host-triples to target-triples so that hosts are a subset of targets
V_TEMP=""
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`,
$(Q)find $(1)/rustllvm \
$(1)/rt \
$(1)/test \
+ $(1)/stage* \
-name '*.[odasS]' -o \
-name '*.so' -o \
-name '*.dylib' -o \
$(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
$(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
$$(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 $$@))
| $$(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
# 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)) \
| $$(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)) \
| $$(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)) \
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)))
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)))
$(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)
$(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))) \
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))
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)))
else
# This is just a rough approximation of LLVM deps
-LLVM_DEPS_SRC=$(call rwildcard,$(CFG_LLVM_SRC_DIR)/lib,*cpp *hpp)
-LLVM_DEPS_INC=$(call rwildcard,$(CFG_LLVM_SRC_DIR)/include,*cpp *hpp)
+LLVM_DEPS_SRC=$(call rwildcard,$(CFG_LLVM_SRC_DIR)lib,*cpp *hpp)
+LLVM_DEPS_INC=$(call rwildcard,$(CFG_LLVM_SRC_DIR)include,*cpp *hpp)
LLVM_DEPS=$(LLVM_DEPS_SRC) $(LLVM_DEPS_INC)
endif
endif
endif
+CFG_RLIB_GLOB=lib$(1)-*.rlib
# x86_64-unknown-linux-gnu configuration
CC_x86_64-unknown-linux-gnu=$(CC)
@$$(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.
| $$(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) \
| $$(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) \
| $$(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) \
endif
ifdef CFG_WINDOWSY_$(1)
- CFG_TESTLIB_$(1)=$$(CFG_BUILD_DIR)/$$(2)/$$(strip \
+ CFG_TESTLIB_$(1)=$$(CFG_BUILD_DIR)$$(2)/$$(strip \
$$(if $$(findstring stage0,$$(1)), \
stage0/$$(CFG_LIBDIR), \
$$(if $$(findstring stage1,$$(1)), \
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
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 \
# 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
cfail \
bench \
perf \
+ rmake \
debuginfo \
codegen \
doc \
$(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))))))
--- /dev/null
+# 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)
+
"lib/librustc-*.so",
"lib/libsyntax-*.so",
"lib/librustuv-*.so",
- "lib/librustrt.so",
"lib/librustllvm.so"],
"macos": ["bin/rustc",
"lib/libstd-*.dylib",
"lib/librustc-*.dylib",
"lib/libsyntax-*.dylib",
"lib/librustuv-*.dylib",
- "lib/librustrt.dylib",
"lib/librustllvm.dylib"],
"winnt": ["bin/rustc.exe",
"bin/std-*.dll",
"bin/rustc-*.dll",
"bin/syntax-*.dll",
"bin/rustuv-*.dll",
- "bin/rustrt.dll",
"bin/rustllvm.dll"],
"freebsd": ["bin/rustc",
"lib/libstd-*.so",
"lib/librustc-*.so",
"lib/libsyntax-*.so",
"lib/librustuv-*.so",
- "lib/librustrt.so",
"lib/librustllvm.so"]
}
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,
/// The column number at which the error occurred
priv col: uint,
/// A message describing the type of the error
- priv msg: @~str,
+ priv msg: ~str,
}
fn escape_str(s: &str) -> ~str {
}
/// A structure for implementing serialization to JSON.
-pub struct Encoder {
- priv wr: @mut io::Writer,
+pub struct Encoder<'self> {
+ priv wr: &'self mut io::Writer,
}
-/// Creates a new JSON encoder whose output will be written to the writer
-/// specified.
-pub fn Encoder(wr: @mut io::Writer) -> Encoder {
- Encoder { wr: wr }
+impl<'self> Encoder<'self> {
+ /// Creates a new JSON encoder whose output will be written to the writer
+ /// specified.
+ pub fn init<'a>(wr: &'a mut io::Writer) -> Encoder<'a> {
+ Encoder { wr: wr }
+ }
}
-impl serialize::Encoder for Encoder {
+impl<'self> serialize::Encoder for Encoder<'self> {
fn emit_nil(&mut self) { write!(self.wr, "null") }
fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
write!(self.wr, "{}", escape_str(v))
}
- fn emit_enum(&mut self, _name: &str, f: |&mut Encoder|) { f(self) }
+ fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'self>|) { f(self) }
fn emit_enum_variant(&mut self,
name: &str,
_id: uint,
cnt: uint,
- f: |&mut Encoder|) {
+ f: |&mut Encoder<'self>|) {
// enums are encoded as strings or objects
// Bunny => "Bunny"
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
}
}
- fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder|) {
+ fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder<'self>|) {
if idx != 0 {
write!(self.wr, ",");
}
name: &str,
id: uint,
cnt: uint,
- f: |&mut Encoder|) {
+ f: |&mut Encoder<'self>|) {
self.emit_enum_variant(name, id, cnt, f)
}
fn emit_enum_struct_variant_field(&mut self,
_: &str,
idx: uint,
- f: |&mut Encoder|) {
+ f: |&mut Encoder<'self>|) {
self.emit_enum_variant_arg(idx, f)
}
- fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder|) {
+ fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder<'self>|) {
write!(self.wr, r"\{");
f(self);
write!(self.wr, r"\}");
fn emit_struct_field(&mut self,
name: &str,
idx: uint,
- f: |&mut Encoder|) {
+ f: |&mut Encoder<'self>|) {
if idx != 0 { write!(self.wr, ",") }
write!(self.wr, "{}:", escape_str(name));
f(self);
}
- fn emit_tuple(&mut self, len: uint, f: |&mut Encoder|) {
+ fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'self>|) {
self.emit_seq(len, f)
}
- fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder|) {
+ fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'self>|) {
self.emit_seq_elt(idx, f)
}
fn emit_tuple_struct(&mut self,
_name: &str,
len: uint,
- f: |&mut Encoder|) {
+ f: |&mut Encoder<'self>|) {
self.emit_seq(len, f)
}
- fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder|) {
+ fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder<'self>|) {
self.emit_seq_elt(idx, f)
}
- fn emit_option(&mut self, f: |&mut Encoder|) { f(self); }
+ fn emit_option(&mut self, f: |&mut Encoder<'self>|) { f(self); }
fn emit_option_none(&mut self) { self.emit_nil(); }
- fn emit_option_some(&mut self, f: |&mut Encoder|) { f(self); }
+ fn emit_option_some(&mut self, f: |&mut Encoder<'self>|) { f(self); }
- fn emit_seq(&mut self, _len: uint, f: |&mut Encoder|) {
+ fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'self>|) {
write!(self.wr, "[");
f(self);
write!(self.wr, "]");
}
- fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder|) {
+ fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'self>|) {
if idx != 0 {
write!(self.wr, ",");
}
f(self)
}
- fn emit_map(&mut self, _len: uint, f: |&mut Encoder|) {
+ fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'self>|) {
write!(self.wr, r"\{");
f(self);
write!(self.wr, r"\}");
}
- fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder|) {
+ fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'self>|) {
if idx != 0 { write!(self.wr, ",") }
f(self)
}
- fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder|) {
+ fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'self>|) {
write!(self.wr, ":");
f(self)
}
/// Another encoder for JSON, but prints out human-readable JSON instead of
/// compact data
-pub struct PrettyEncoder {
- priv wr: @mut io::Writer,
+pub struct PrettyEncoder<'self> {
+ priv wr: &'self mut io::Writer,
priv indent: uint,
}
-/// Creates a new encoder whose output will be written to the specified writer
-pub fn PrettyEncoder(wr: @mut io::Writer) -> PrettyEncoder {
- PrettyEncoder {
- wr: wr,
- indent: 0,
+impl<'self> PrettyEncoder<'self> {
+ /// Creates a new encoder whose output will be written to the specified writer
+ pub fn init<'a>(wr: &'a mut io::Writer) -> PrettyEncoder<'a> {
+ PrettyEncoder {
+ wr: wr,
+ indent: 0,
+ }
}
}
-impl serialize::Encoder for PrettyEncoder {
+impl<'self> serialize::Encoder for PrettyEncoder<'self> {
fn emit_nil(&mut self) { write!(self.wr, "null") }
fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
fn emit_str(&mut self, v: &str) { write!(self.wr, "{}", escape_str(v)); }
- fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder|) {
+ fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder<'self>|) {
f(self)
}
name: &str,
_: uint,
cnt: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
if cnt == 0 {
write!(self.wr, "{}", escape_str(name));
} else {
fn emit_enum_variant_arg(&mut self,
idx: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
if idx != 0 {
write!(self.wr, ",\n");
}
name: &str,
id: uint,
cnt: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
self.emit_enum_variant(name, id, cnt, f)
}
fn emit_enum_struct_variant_field(&mut self,
_: &str,
idx: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
self.emit_enum_variant_arg(idx, f)
}
fn emit_struct(&mut self,
_: &str,
len: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
if len == 0 {
write!(self.wr, "\\{\\}");
} else {
fn emit_struct_field(&mut self,
name: &str,
idx: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
if idx == 0 {
write!(self.wr, "\n");
} else {
f(self);
}
- fn emit_tuple(&mut self, len: uint, f: |&mut PrettyEncoder|) {
+ fn emit_tuple(&mut self, len: uint, f: |&mut PrettyEncoder<'self>|) {
self.emit_seq(len, f)
}
- fn emit_tuple_arg(&mut self, idx: uint, f: |&mut PrettyEncoder|) {
+ fn emit_tuple_arg(&mut self, idx: uint, f: |&mut PrettyEncoder<'self>|) {
self.emit_seq_elt(idx, f)
}
fn emit_tuple_struct(&mut self,
_: &str,
len: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
self.emit_seq(len, f)
}
fn emit_tuple_struct_arg(&mut self,
idx: uint,
- f: |&mut PrettyEncoder|) {
+ f: |&mut PrettyEncoder<'self>|) {
self.emit_seq_elt(idx, f)
}
- fn emit_option(&mut self, f: |&mut PrettyEncoder|) { f(self); }
+ fn emit_option(&mut self, f: |&mut PrettyEncoder<'self>|) { f(self); }
fn emit_option_none(&mut self) { self.emit_nil(); }
- fn emit_option_some(&mut self, f: |&mut PrettyEncoder|) { f(self); }
+ fn emit_option_some(&mut self, f: |&mut PrettyEncoder<'self>|) { f(self); }
- fn emit_seq(&mut self, len: uint, f: |&mut PrettyEncoder|) {
+ fn emit_seq(&mut self, len: uint, f: |&mut PrettyEncoder<'self>|) {
if len == 0 {
write!(self.wr, "[]");
} else {
}
}
- fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder|) {
+ fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder<'self>|) {
if idx == 0 {
write!(self.wr, "\n");
} else {
f(self)
}
- fn emit_map(&mut self, len: uint, f: |&mut PrettyEncoder|) {
+ fn emit_map(&mut self, len: uint, f: |&mut PrettyEncoder<'self>|) {
if len == 0 {
write!(self.wr, "\\{\\}");
} else {
}
}
- fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder|) {
+ fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'self>|) {
if idx == 0 {
write!(self.wr, "\n");
} else {
f(self);
}
- fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder|) {
+ fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'self>|) {
write!(self.wr, ": ");
f(self);
}
impl Json{
/// Encodes a json value into a io::writer. Uses a single line.
- pub fn to_writer(&self, wr: @mut io::Writer) {
- let mut encoder = Encoder(wr);
+ pub fn to_writer(&self, wr: &mut io::Writer) {
+ let mut encoder = Encoder::init(wr);
self.encode(&mut encoder)
}
/// Encodes a json value into a io::writer.
/// Pretty-prints in a more readable format.
- pub fn to_pretty_writer(&self, wr: @mut io::Writer) {
- let mut encoder = PrettyEncoder(wr);
+ pub fn to_pretty_writer(&self, wr: &mut io::Writer) {
+ let mut encoder = PrettyEncoder::init(wr);
self.encode(&mut encoder)
}
/// Encodes a json value into a string
pub fn to_pretty_str(&self) -> ~str {
- let s = @mut MemWriter::new();
- self.to_pretty_writer(s as @mut io::Writer);
- str::from_utf8(s.inner_ref().as_slice())
+ let mut s = MemWriter::new();
+ self.to_pretty_writer(&mut s as &mut io::Writer);
+ str::from_utf8_owned(s.inner())
}
}
pub struct Parser<T> {
- priv rdr: ~T,
+ priv rdr: T,
priv ch: char,
priv line: uint,
priv col: uint,
}
-/// Decode a json value from an Iterator<char>
-pub fn Parser<T : Iterator<char>>(rdr: ~T) -> Parser<T> {
- let mut p = Parser {
- rdr: rdr,
- ch: '\x00',
- line: 1,
- col: 0,
- };
- p.bump();
- p
+impl<T: Iterator<char>> Parser<T> {
+ /// Decode a json value from an Iterator<char>
+ pub fn init(rdr: T) -> Parser<T> {
+ let mut p = Parser {
+ rdr: rdr,
+ ch: '\x00',
+ line: 1,
+ col: 0,
+ };
+ p.bump();
+ p
+ }
}
impl<T: Iterator<char>> Parser<T> {
}
fn error<T>(&self, msg: ~str) -> Result<T, Error> {
- Err(Error { line: self.line, col: self.col, msg: @msg })
+ Err(Error { line: self.line, col: self.col, msg: msg })
}
fn parse_value(&mut self) -> Result<Json, Error> {
/// Decodes a json value from an `&mut io::Reader`
pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, Error> {
- let s = str::from_utf8(rdr.read_to_end());
- let mut parser = Parser(~s.chars());
+ let s = str::from_utf8_owned(rdr.read_to_end());
+ let mut parser = Parser::init(s.chars());
parser.parse()
}
/// Decodes a json value from a string
pub fn from_str(s: &str) -> Result<Json, Error> {
- let mut parser = Parser(~s.chars());
+ let mut parser = Parser::init(s.chars());
parser.parse()
}
priv stack: ~[Json],
}
-/// Creates a new decoder instance for decoding the specified JSON value.
-pub fn Decoder(json: Json) -> Decoder {
- Decoder {
- stack: ~[json]
+impl Decoder {
+ /// Creates a new decoder instance for decoding the specified JSON value.
+ pub fn init(json: Json) -> Decoder {
+ Decoder {
+ stack: ~[json]
+ }
}
}
fn to_json(&self) -> Json { (*self).clone() }
}
-impl ToJson for @Json {
- fn to_json(&self) -> Json { (**self).to_json() }
-}
-
impl ToJson for int {
fn to_json(&self) -> Json { Number(*self as f64) }
}
fn to_json(&self) -> Json { String((*self).clone()) }
}
-impl ToJson for @~str {
- fn to_json(&self) -> Json { String((**self).clone()) }
-}
-
impl<A:ToJson,B:ToJson> ToJson for (A, B) {
fn to_json(&self) -> Json {
match *self {
impl to_str::ToStr for Json {
/// Encodes a json value into a string
fn to_str(&self) -> ~str {
- let s = @mut MemWriter::new();
- self.to_writer(s as @mut io::Writer);
- str::from_utf8(s.inner_ref().as_slice())
+ let mut s = MemWriter::new();
+ self.to_writer(&mut s as &mut io::Writer);
+ str::from_utf8_owned(s.inner())
}
}
impl to_str::ToStr for Error {
fn to_str(&self) -> ~str {
- format!("{}:{}: {}", self.line, self.col, *self.msg)
+ format!("{}:{}: {}", self.line, self.col, self.msg)
}
}
assert_eq!(a.clone(), from_str(a.to_pretty_str()).unwrap());
}
- fn with_str_writer(f: |@mut io::Writer|) -> ~str {
+ fn with_str_writer(f: |&mut io::Writer|) -> ~str {
use std::io::mem::MemWriter;
use std::io::Decorator;
use std::str;
- let m = @mut MemWriter::new();
- f(m as @mut io::Writer);
- str::from_utf8(*m.inner_ref())
+ let mut m = MemWriter::new();
+ f(&mut m as &mut io::Writer);
+ str::from_utf8_owned(m.inner())
}
#[test]
let animal = Dog;
assert_eq!(
with_str_writer(|wr| {
- let mut encoder = Encoder(wr);
+ let mut encoder = Encoder::init(wr);
animal.encode(&mut encoder);
}),
~"\"Dog\""
);
assert_eq!(
with_str_writer(|wr| {
- let mut encoder = PrettyEncoder(wr);
+ let mut encoder = PrettyEncoder::init(wr);
animal.encode(&mut encoder);
}),
~"\"Dog\""
let animal = Frog(~"Henry", 349);
assert_eq!(
with_str_writer(|wr| {
- let mut encoder = Encoder(wr);
+ let mut encoder = Encoder::init(wr);
animal.encode(&mut encoder);
}),
~"{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"
);
assert_eq!(
with_str_writer(|wr| {
- let mut encoder = PrettyEncoder(wr);
+ let mut encoder = PrettyEncoder::init(wr);
animal.encode(&mut encoder);
}),
~"\
fn test_write_some() {
let value = Some(~"jodhpurs");
let s = with_str_writer(|wr| {
- let mut encoder = Encoder(wr);
+ let mut encoder = Encoder::init(wr);
value.encode(&mut encoder);
});
assert_eq!(s, ~"\"jodhpurs\"");
let value = Some(~"jodhpurs");
let s = with_str_writer(|wr| {
- let mut encoder = PrettyEncoder(wr);
+ let mut encoder = PrettyEncoder::init(wr);
value.encode(&mut encoder);
});
assert_eq!(s, ~"\"jodhpurs\"");
fn test_write_none() {
let value: Option<~str> = None;
let s = with_str_writer(|wr| {
- let mut encoder = Encoder(wr);
+ let mut encoder = Encoder::init(wr);
value.encode(&mut encoder);
});
assert_eq!(s, ~"null");
let s = with_str_writer(|wr| {
- let mut encoder = Encoder(wr);
+ let mut encoder = Encoder::init(wr);
value.encode(&mut encoder);
});
assert_eq!(s, ~"null");
#[test]
fn test_trailing_characters() {
assert_eq!(from_str("nulla"),
- Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"}));
+ Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
assert_eq!(from_str("truea"),
- Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"}));
+ Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
assert_eq!(from_str("falsea"),
- Err(Error {line: 1u, col: 6u, msg: @~"trailing characters"}));
+ Err(Error {line: 1u, col: 6u, msg: ~"trailing characters"}));
assert_eq!(from_str("1a"),
- Err(Error {line: 1u, col: 2u, msg: @~"trailing characters"}));
+ Err(Error {line: 1u, col: 2u, msg: ~"trailing characters"}));
assert_eq!(from_str("[]a"),
- Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"}));
+ Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
assert_eq!(from_str("{}a"),
- Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"}));
+ Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
}
#[test]
fn test_read_identifiers() {
assert_eq!(from_str("n"),
- Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
assert_eq!(from_str("nul"),
- Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
assert_eq!(from_str("t"),
- Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
assert_eq!(from_str("truz"),
- Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
assert_eq!(from_str("f"),
- Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
assert_eq!(from_str("faz"),
- Err(Error {line: 1u, col: 3u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 3u, msg: ~"invalid syntax"}));
assert_eq!(from_str("null"), Ok(Null));
assert_eq!(from_str("true"), Ok(Boolean(true)));
#[test]
fn test_decode_identifiers() {
- let mut decoder = Decoder(from_str("null").unwrap());
+ let mut decoder = Decoder::init(from_str("null").unwrap());
let v: () = Decodable::decode(&mut decoder);
assert_eq!(v, ());
- let mut decoder = Decoder(from_str("true").unwrap());
+ let mut decoder = Decoder::init(from_str("true").unwrap());
let v: bool = Decodable::decode(&mut decoder);
assert_eq!(v, true);
- let mut decoder = Decoder(from_str("false").unwrap());
+ let mut decoder = Decoder::init(from_str("false").unwrap());
let v: bool = Decodable::decode(&mut decoder);
assert_eq!(v, false);
}
#[test]
fn test_read_number() {
assert_eq!(from_str("+"),
- Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
assert_eq!(from_str("."),
- Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
assert_eq!(from_str("-"),
- Err(Error {line: 1u, col: 2u, msg: @~"invalid number"}));
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
assert_eq!(from_str("00"),
- Err(Error {line: 1u, col: 2u, msg: @~"invalid number"}));
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
assert_eq!(from_str("1."),
- Err(Error {line: 1u, col: 3u, msg: @~"invalid number"}));
+ Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
assert_eq!(from_str("1e"),
- Err(Error {line: 1u, col: 3u, msg: @~"invalid number"}));
+ Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
assert_eq!(from_str("1e+"),
- Err(Error {line: 1u, col: 4u, msg: @~"invalid number"}));
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid number"}));
assert_eq!(from_str("3"), Ok(Number(3.0)));
assert_eq!(from_str("3.1"), Ok(Number(3.1)));
#[test]
fn test_decode_numbers() {
- let mut decoder = Decoder(from_str("3").unwrap());
+ let mut decoder = Decoder::init(from_str("3").unwrap());
let v: f64 = Decodable::decode(&mut decoder);
assert_eq!(v, 3.0);
- let mut decoder = Decoder(from_str("3.1").unwrap());
+ let mut decoder = Decoder::init(from_str("3.1").unwrap());
let v: f64 = Decodable::decode(&mut decoder);
assert_eq!(v, 3.1);
- let mut decoder = Decoder(from_str("-1.2").unwrap());
+ let mut decoder = Decoder::init(from_str("-1.2").unwrap());
let v: f64 = Decodable::decode(&mut decoder);
assert_eq!(v, -1.2);
- let mut decoder = Decoder(from_str("0.4").unwrap());
+ let mut decoder = Decoder::init(from_str("0.4").unwrap());
let v: f64 = Decodable::decode(&mut decoder);
assert_eq!(v, 0.4);
- let mut decoder = Decoder(from_str("0.4e5").unwrap());
+ let mut decoder = Decoder::init(from_str("0.4e5").unwrap());
let v: f64 = Decodable::decode(&mut decoder);
assert_eq!(v, 0.4e5);
- let mut decoder = Decoder(from_str("0.4e15").unwrap());
+ let mut decoder = Decoder::init(from_str("0.4e15").unwrap());
let v: f64 = Decodable::decode(&mut decoder);
assert_eq!(v, 0.4e15);
- let mut decoder = Decoder(from_str("0.4e-01").unwrap());
+ let mut decoder = Decoder::init(from_str("0.4e-01").unwrap());
let v: f64 = Decodable::decode(&mut decoder);
assert_eq!(v, 0.4e-01);
}
#[test]
fn test_read_str() {
assert_eq!(from_str("\""),
- Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string"
+ Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing string"
}));
assert_eq!(from_str("\"lol"),
- Err(Error {line: 1u, col: 5u, msg: @~"EOF while parsing string"
+ Err(Error {line: 1u, col: 5u, msg: ~"EOF while parsing string"
}));
assert_eq!(from_str("\"\""), Ok(String(~"")));
#[test]
fn test_decode_str() {
- let mut decoder = Decoder(from_str("\"\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"");
- let mut decoder = Decoder(from_str("\"foo\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"foo\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"foo");
- let mut decoder = Decoder(from_str("\"\\\"\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\\\"\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"\"");
- let mut decoder = Decoder(from_str("\"\\b\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\\b\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"\x08");
- let mut decoder = Decoder(from_str("\"\\n\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\\n\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"\n");
- let mut decoder = Decoder(from_str("\"\\r\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\\r\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"\r");
- let mut decoder = Decoder(from_str("\"\\t\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\\t\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"\t");
- let mut decoder = Decoder(from_str("\"\\u12ab\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\\u12ab\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"\u12ab");
- let mut decoder = Decoder(from_str("\"\\uAB12\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"\\uAB12\"").unwrap());
let v: ~str = Decodable::decode(&mut decoder);
assert_eq!(v, ~"\uAB12");
}
#[test]
fn test_read_list() {
assert_eq!(from_str("["),
- Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing value"}));
+ Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing value"}));
assert_eq!(from_str("[1"),
- Err(Error {line: 1u, col: 3u, msg: @~"EOF while parsing list"}));
+ Err(Error {line: 1u, col: 3u, msg: ~"EOF while parsing list"}));
assert_eq!(from_str("[1,"),
- Err(Error {line: 1u, col: 4u, msg: @~"EOF while parsing value"}));
+ Err(Error {line: 1u, col: 4u, msg: ~"EOF while parsing value"}));
assert_eq!(from_str("[1,]"),
- Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"}));
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
assert_eq!(from_str("[6 7]"),
- Err(Error {line: 1u, col: 4u, msg: @~"expected `,` or `]`"}));
+ Err(Error {line: 1u, col: 4u, msg: ~"expected `,` or `]`"}));
assert_eq!(from_str("[]"), Ok(List(~[])));
assert_eq!(from_str("[ ]"), Ok(List(~[])));
#[test]
fn test_decode_list() {
- let mut decoder = Decoder(from_str("[]").unwrap());
+ let mut decoder = Decoder::init(from_str("[]").unwrap());
let v: ~[()] = Decodable::decode(&mut decoder);
assert_eq!(v, ~[]);
- let mut decoder = Decoder(from_str("[null]").unwrap());
+ let mut decoder = Decoder::init(from_str("[null]").unwrap());
let v: ~[()] = Decodable::decode(&mut decoder);
assert_eq!(v, ~[()]);
- let mut decoder = Decoder(from_str("[true]").unwrap());
+ let mut decoder = Decoder::init(from_str("[true]").unwrap());
let v: ~[bool] = Decodable::decode(&mut decoder);
assert_eq!(v, ~[true]);
- let mut decoder = Decoder(from_str("[true]").unwrap());
+ let mut decoder = Decoder::init(from_str("[true]").unwrap());
let v: ~[bool] = Decodable::decode(&mut decoder);
assert_eq!(v, ~[true]);
- let mut decoder = Decoder(from_str("[3, 1]").unwrap());
+ let mut decoder = Decoder::init(from_str("[3, 1]").unwrap());
let v: ~[int] = Decodable::decode(&mut decoder);
assert_eq!(v, ~[3, 1]);
- let mut decoder = Decoder(from_str("[[3], [1, 2]]").unwrap());
+ let mut decoder = Decoder::init(from_str("[[3], [1, 2]]").unwrap());
let v: ~[~[uint]] = Decodable::decode(&mut decoder);
assert_eq!(v, ~[~[3], ~[1, 2]]);
}
Err(Error {
line: 1u,
col: 2u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
assert_eq!(from_str("{ "),
Err(Error {
line: 1u,
col: 3u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
assert_eq!(from_str("{1"),
Err(Error {
line: 1u,
col: 2u,
- msg: @~"key must be a string"}));
+ msg: ~"key must be a string"}));
assert_eq!(from_str("{ \"a\""),
Err(Error {
line: 1u,
col: 6u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
assert_eq!(from_str("{\"a\""),
Err(Error {
line: 1u,
col: 5u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
assert_eq!(from_str("{\"a\" "),
Err(Error {
line: 1u,
col: 6u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
assert_eq!(from_str("{\"a\" 1"),
- Err(Error {line: 1u, col: 6u, msg: @~"expected `:`"}));
+ Err(Error {line: 1u, col: 6u, msg: ~"expected `:`"}));
assert_eq!(from_str("{\"a\":"),
- Err(Error {line: 1u, col: 6u, msg: @~"EOF while parsing value"}));
+ Err(Error {line: 1u, col: 6u, msg: ~"EOF while parsing value"}));
assert_eq!(from_str("{\"a\":1"),
Err(Error {
line: 1u,
col: 7u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
assert_eq!(from_str("{\"a\":1 1"),
- Err(Error {line: 1u, col: 8u, msg: @~"expected `,` or `}`"}));
+ Err(Error {line: 1u, col: 8u, msg: ~"expected `,` or `}`"}));
assert_eq!(from_str("{\"a\":1,"),
Err(Error {
line: 1u,
col: 8u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
assert_eq!(from_str("{}").unwrap(), mk_object([]));
assert_eq!(from_str("{\"a\": 3}").unwrap(),
{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
]
}";
- let mut decoder = Decoder(from_str(s).unwrap());
+ let mut decoder = Decoder::init(from_str(s).unwrap());
let v: Outer = Decodable::decode(&mut decoder);
assert_eq!(
v,
#[test]
fn test_decode_option() {
- let mut decoder = Decoder(from_str("null").unwrap());
+ let mut decoder = Decoder::init(from_str("null").unwrap());
let value: Option<~str> = Decodable::decode(&mut decoder);
assert_eq!(value, None);
- let mut decoder = Decoder(from_str("\"jodhpurs\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"jodhpurs\"").unwrap());
let value: Option<~str> = Decodable::decode(&mut decoder);
assert_eq!(value, Some(~"jodhpurs"));
}
#[test]
fn test_decode_enum() {
- let mut decoder = Decoder(from_str("\"Dog\"").unwrap());
+ let mut decoder = Decoder::init(from_str("\"Dog\"").unwrap());
let value: Animal = Decodable::decode(&mut decoder);
assert_eq!(value, Dog);
- let mut decoder =
- Decoder(from_str("{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}").unwrap());
+ let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}";
+ let mut decoder = Decoder::init(from_str(s).unwrap());
let value: Animal = Decodable::decode(&mut decoder);
assert_eq!(value, Frog(~"Henry", 349));
}
#[test]
fn test_decode_map() {
let s = ~"{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\"fields\":[\"Henry\", 349]}}";
- let mut decoder = Decoder(from_str(s).unwrap());
+ let mut decoder = Decoder::init(from_str(s).unwrap());
let mut map: TreeMap<~str, Animal> = Decodable::decode(&mut decoder);
assert_eq!(map.pop(&~"a"), Some(Dog));
Err(Error {
line: 3u,
col: 8u,
- msg: @~"EOF while parsing object"}));
+ msg: ~"EOF while parsing object"}));
}
#[deriving(Decodable)]
match from_str(to_parse) {
Err(e) => Some(e.to_str()),
Ok(json) => {
- let _: T = Decodable::decode(&mut Decoder(json));
+ let _: T = Decodable::decode(&mut Decoder::init(json));
None
}
}
#[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};
/// Load MetricDiff from a file.
pub fn load(p: &Path) -> MetricMap {
assert!(p.exists());
- let f = @mut File::open(p) as @mut io::Reader;
- let mut decoder = json::Decoder(json::from_reader(f).unwrap());
+ let mut f = File::open(p);
+ let value = json::from_reader(&mut f as &mut io::Reader).unwrap();
+ let mut decoder = json::Decoder::init(value);
MetricMap(Decodable::decode(&mut decoder))
}
Err(e) => fail!("Couldn't parse workcache database (from file {}): {}",
self.db_filename.display(), e.to_str()),
Ok(r) => {
- let mut decoder = json::Decoder(r);
+ let mut decoder = json::Decoder::init(r);
self.db_cache = Decodable::decode(&mut decoder);
}
}
WorkFromTask(&'self Prep<'self>, PortOne<(Exec, T)>),
}
-fn json_encode<T:Encodable<json::Encoder>>(t: &T) -> ~str {
- let writer = @mut MemWriter::new();
- let mut encoder = json::Encoder(writer as @mut io::Writer);
+fn json_encode<'self, T:Encodable<json::Encoder<'self>>>(t: &T) -> ~str {
+ let mut writer = MemWriter::new();
+ let mut encoder = json::Encoder::init(&mut writer as &mut io::Writer);
t.encode(&mut encoder);
str::from_utf8(writer.inner_ref().as_slice())
}
fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
debug!("json decoding: {}", s);
let j = json::from_str(s).unwrap();
- let mut decoder = json::Decoder(j);
+ let mut decoder = json::Decoder::init(j);
Decodable::decode(&mut decoder)
}
return true;
}
- pub fn exec<T:Send +
- Encodable<json::Encoder> +
+ pub fn exec<'self, T:Send +
+ Encodable<json::Encoder<'self>> +
Decodable<json::Decoder>>(
&'self self, blk: proc(&mut Exec) -> T) -> T {
self.exec_work(blk).unwrap()
}
- fn exec_work<T:Send +
- Encodable<json::Encoder> +
+ fn exec_work<'self, T:Send +
+ Encodable<json::Encoder<'self>> +
Decodable<json::Decoder>>( // FIXME(#5121)
&'self self, blk: proc(&mut Exec) -> T) -> Work<'self, T> {
let mut bo = Some(blk);
}
impl<'self, T:Send +
- Encodable<json::Encoder> +
+ Encodable<json::Encoder<'self>> +
Decodable<json::Decoder>>
Work<'self, T> { // FIXME(#5121)
--- /dev/null
+// 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));
+ }
+}
target_triple: target_triple,
- cc_args: ~[~"-marm"]
+ cc_args: ~[~"-marm"],
};
}
// except according to those terms.
+use back::archive::Archive;
use back::rpath;
use driver::session::Session;
use driver::session;
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;
use std::ptr;
use std::run;
use std::str;
-use std::vec;
use std::io::fs;
use syntax::abi;
use syntax::ast;
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;
// 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);
}
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();
}
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
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.
// 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()));
}
- // 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);
-
- // FIXME (#9639): This needs to handle non-utf8 paths
- args.push_all([
- ~"-o", output.as_str().unwrap().to_owned(),
- obj_filename.as_str().unwrap().to_owned()]);
-
- let lib_cmd = match sess.targ_cfg.os {
- abi::OsMacos => ~"-dynamiclib",
- _ => ~"-shared"
- };
+ 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);
+ }
+ }
+}
- // # Crate linking
+// 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;
+}
- 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;
+// 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));
}
- 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()); }
+// 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(" "));
+ }
- // # Extern library linking
+ // May have not found libraries in the right formats.
+ sess.abort_if_errors();
- // 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.
+ // Invoke the system linker
+ debug!("{} {}", cc_prog, cc_args.connect(" "));
+ let prog = run::process_output(cc_prog, cc_args);
- 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());
+ 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();
}
- let rustpath = filesearch::rust_path();
- for path in rustpath.iter() {
+
+ // 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
- args.push("-L" + path.as_str().unwrap().to_owned());
+ run::process_status("dsymutil",
+ [out_filename.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");
- }
+fn link_args(sess: Session,
+ dylib: bool,
+ obj_filename: &Path,
+ out_filename: &Path) -> ~[~str] {
- // The names of the extern libraries
- let used_libs = cstore::get_used_libraries(cstore);
- for l in used_libs.iter() { args.push(~"-l" + *l); }
+ // 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();
- if *sess.building_library {
- args.push(lib_cmd);
+ let mut args = ~[stage];
- // 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());
- }
- }
+ // FIXME (#9639): This needs to handle non-utf8 paths
+ args.push_all([
+ ~"-o", out_filename.as_str().unwrap().to_owned(),
+ obj_filename.as_str().unwrap().to_owned()]);
- // 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 {
+ // 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");
+
+ // 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");
}
+ }
- args.push_all([~"-lrt", ~"-ldl"]);
+ add_upstream_rust_crates(&mut args, sess, dylib);
+ add_local_native_libraries(&mut args, sess);
- // 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");
+ // # Telling the linker what we're doing
+
+ 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([~"-pthread", ~"-lrt",
- ~"-L/usr/local/lib", ~"-lexecinfo",
+ args.push_all([~"-L/usr/local/lib",
~"-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"]);
+ ~"-L/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, out_filename));
- // 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
+ // 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());
+ }
+
+ let rustpath = filesearch::rust_path();
+ for path in rustpath.iter() {
+ // FIXME (#9639): This needs to handle non-utf8 paths
+ args.push("-L" + path.as_str().unwrap().to_owned());
+ }
+
+ for &(ref l, _) in cstore::get_used_libraries(sess.cstore).iter() {
+ args.push(~"-l" + *l);
+ }
+}
target_triple: target_triple,
- cc_args: ~[]
+ cc_args: ~[],
};
}
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
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 {
}
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,
meta_sect_name: ~str,
data_layout: ~str,
target_triple: ~str,
- cc_args: ~[~str]
+ cc_args: ~[~str],
}
target_triple: target_triple,
- cc_args: ~[~"-m32"]
+ cc_args: ~[~"-m32"],
};
}
target_triple: target_triple,
- cc_args: ~[~"-m64"]
+ cc_args: ~[~"-m64"],
};
}
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;
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));
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", (), |_|
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
outputs: &OutputFilenames) {
time(sess.time_passes(), "linking", (), |_|
link::link_binary(sess,
+ trans.crate_types,
&outputs.obj_filename,
&outputs.out_filename,
trans.link));
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;
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");
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()
};
let sopts = @session::options {
- crate_type: crate_type,
- is_static: statik,
+ outputs: outputs,
gc: gc,
optimize: opt_level,
custom_passes: custom_passes,
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,
// 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"),
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"),
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 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 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"
+ };
match *ofile {
None => {
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);
}
use back::target_strs;
use back;
use driver::driver::host_triple;
-use driver::session;
use metadata::filesearch;
use metadata;
use middle::lint;
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,
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),
("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),
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),
]
}
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],
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>,
EntryNone,
}
+#[deriving(Eq, Clone)]
+pub enum OutputStyle {
+ OutputExecutable,
+ OutputDylib,
+ OutputRlib,
+ OutputStaticlib,
+}
+
pub struct Session_ {
targ_cfg: @config,
opts: @options,
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 {
/// Some reasonable defaults
pub fn basic_options() -> @options {
@options {
- crate_type: session::lib_crate,
- is_static: false,
+ outputs: ~[],
gc: false,
optimize: No,
custom_passes: ~[],
jit: false,
output_type: link::output_type_exe,
addl_lib_search_paths: @mut HashSet::new(),
+ ar: None,
linker: None,
linker_args: ~[],
maybe_sysroot: None,
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
}
}
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));
- }
-}
use middle::lint;
use syntax::ast;
+use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::Span;
use syntax::visit;
("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
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 \
}
}
+ 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")
+ }
+ }
+
_ => {}
}
#[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;
}
pub mod back {
+ pub mod archive;
pub mod link;
pub mod abi;
pub mod upcall;
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;
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;
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. */
/* 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);
+ }
}
}
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,
//! 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;
// 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
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 }
}
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() {
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),
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);
}
_ => ()
}
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;
- }
-
- 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());
+ ast::item_foreign_mod(ref fm) => {
+ if fm.abis.is_rust() || fm.abis.is_intrinsic() {
+ return;
+ }
- //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.");
- //}
+ // 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 */ }
+ }
+ }
- for m in link_args.iter() {
- match m.value_str() {
- Some(linkarg) => {
- cstore::add_used_link_args(cstore, linkarg);
+ // 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 */ }
}
}
- }
- _ => { }
+ _ => { }
}
}
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;
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,
};
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) => {
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|) {
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
}
return CStore {
metas: HashMap::new(),
extern_mod_crate_map: HashMap::new(),
- used_crate_files: ~[],
+ used_crate_sources: ~[],
used_libraries: ~[],
used_link_args: ~[],
intr: intr
}
}
-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 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) -> bool {
+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,
}
}
+
+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;
+}
attr_bytes: u64,
dep_bytes: u64,
lang_item_bytes: u64,
+ native_lib_bytes: u64,
impl_bytes: u64,
misc_bytes: u64,
item_bytes: u64,
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,
attr_bytes: 0,
dep_bytes: 0,
lang_item_bytes: 0,
+ native_lib_bytes: 0,
impl_bytes: 0,
misc_bytes: 0,
item_bytes: 0,
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);
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);
//! 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;
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};
}
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],
}
-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)
-}
+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 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),
- };
+ 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();
- (dll_prefix.to_owned(), dll_suffix.to_owned())
-}
+ // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
+ let dylib_prefix = format!("{}{}-", dyprefix, crate_name);
+ let rlib_prefix = format!("lib{}-", crate_name);
-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
- }
- }
- });
+ 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)
+ };
+
+ 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
+ }
+ }
+ }
+ });
- 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);
+ 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);
}
- cx.diag.handler().abort_if_errors();
+ 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),
}
}
}
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 {
}
// 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())
OpaqueStructLangItem, // 38
EventLoopFactoryLangItem, // 39
+
+ TypeIdLangItem, // 40
}
pub struct LanguageItems {
- items: [Option<ast::DefId>, ..40]
+ items: [Option<ast::DefId>, ..41]
}
impl LanguageItems {
pub fn new() -> LanguageItems {
LanguageItems {
- items: [ None, ..40 ]
+ items: [ None, ..41 ]
}
}
39 => "event_loop_factory",
+ 40 => "type_id",
+
_ => "???"
}
}
pub fn event_loop_factory(&self) -> Option<ast::DefId> {
self.items[EventLoopFactoryLangItem as uint]
}
+ pub fn type_id(&self) -> Option<ast::DefId> {
+ self.items[TypeIdLangItem as uint]
+ }
}
struct LanguageItemCollector {
item_refs.insert("ty_visitor", TyVisitorTraitLangItem as uint);
item_refs.insert("opaque", OpaqueStructLangItem as uint);
item_refs.insert("event_loop_factory", EventLoopFactoryLangItem as uint);
+ item_refs.insert("type_id", TypeIdLangItem as uint);
LanguageItemCollector {
session: session,
}
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
];
"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",
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;
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;
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);
}
}
-// 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,
}
glue::emit_tydescs(ccx);
- write_abi_version(ccx);
if ccx.sess.opts.debuginfo {
debuginfo::finalize(ccx);
}
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,
};
}
return with_scope(bcx, thn.info(), "if_true_then", |bcx| {
let bcx_out = trans_block(bcx, thn, dest);
debuginfo::clear_source_location(bcx.fcx);
- trans_block_cleanups(bcx_out, block_cleanups(bcx))
+ bcx_out
})
} else {
let mut trans = TransItemVisitor { ccx: bcx.fcx.ccx } ;
elexpr.info(),
"if_false_then",
|bcx| {
- let bcx_out = trans_if_else(bcx, elexpr, dest);
+ let bcx_out = trans_if_else(bcx, elexpr, dest, false);
debuginfo::clear_source_location(bcx.fcx);
- trans_block_cleanups(bcx_out, block_cleanups(bcx))
+ bcx_out
})
}
// if false { .. }
let (else_bcx_in, next_bcx) = match els {
Some(elexpr) => {
let else_bcx_in = scope_block(bcx, elexpr.info(), "else");
- let else_bcx_out = trans_if_else(else_bcx_in, elexpr, dest);
+ let else_bcx_out = trans_if_else(else_bcx_in, elexpr, dest, true);
(else_bcx_in, join_blocks(bcx, [then_bcx_out, else_bcx_out]))
}
_ => {
// trans `else [ if { .. } ... | { .. } ]`
fn trans_if_else(else_bcx_in: @mut Block, elexpr: @ast::Expr,
- dest: expr::Dest) -> @mut Block {
+ dest: expr::Dest, cleanup: bool) -> @mut Block {
let else_bcx_out = match elexpr.node {
ast::ExprIf(_, _, _) => {
let elseif_blk = ast_util::block_from_expr(elexpr);
// would be nice to have a constraint on ifs
_ => else_bcx_in.tcx().sess.bug("strange alternative in if")
};
- debuginfo::clear_source_location(else_bcx_in.fcx);
- trans_block_cleanups(else_bcx_out, block_cleanups(else_bcx_in))
+ if cleanup {
+ debuginfo::clear_source_location(else_bcx_in.fcx);
+ trans_block_cleanups(else_bcx_out, block_cleanups(else_bcx_in))
+ } else {
+ else_bcx_out
+ }
}
}
use back::{link};
-use std::libc::c_uint;
-use lib::llvm::{ValueRef, CallConv, StructRetAttribute};
use lib::llvm::llvm;
+use lib::llvm::{ValueRef, CallConv, StructRetAttribute};
use lib;
-use middle::trans::machine;
-use middle::trans::base;
use middle::trans::base::push_ctxt;
-use middle::trans::cabi;
+use middle::trans::base;
use middle::trans::build::*;
use middle::trans::builder::noname;
+use middle::trans::cabi;
use middle::trans::common::*;
+use middle::trans::machine;
+use middle::trans::type_::Type;
use middle::trans::type_of::*;
use middle::trans::type_of;
-use middle::ty;
use middle::ty::FnSig;
-
-use std::uint;
+use middle::ty;
+use std::cmp;
+use std::libc::c_uint;
use std::vec;
+use syntax::abi::{Cdecl, Aapcs, C, AbiSet, Win64};
+use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, System};
use syntax::codemap::Span;
+use syntax::parse::token::special_idents;
use syntax::{ast};
use syntax::{attr, ast_map};
-use syntax::parse::token::special_idents;
-use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, System,
- Cdecl, Aapcs, C, AbiSet, Win64};
use util::ppaux::{Repr, UserString};
-use middle::trans::type_::Type;
///////////////////////////////////////////////////////////////////////////
// Type definitions
let llrust_size = machine::llsize_of_store(ccx, llrust_ret_ty);
let llforeign_align = machine::llalign_of_min(ccx, llforeign_ret_ty);
let llrust_align = machine::llalign_of_min(ccx, llrust_ret_ty);
- let llalign = uint::min(llforeign_align, llrust_align);
+ let llalign = cmp::min(llforeign_align, llrust_align);
debug!("llrust_size={:?}", llrust_size);
base::call_memcpy(bcx, llretptr_i8, llscratch_i8,
C_uint(ccx, llrust_size), llalign as u32);
"type_id" => {
let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
ccx.link_meta.extras_hash);
- Ret(bcx, C_i64(hash as i64))
+ // NB: This needs to be kept in lockstep with the TypeId struct in
+ // libstd/unstable/intrinsics.rs
+ let val = C_named_struct(type_of::type_of(ccx, output_type), [C_u64(hash)]);
+ match bcx.fcx.llretptr {
+ Some(ptr) => {
+ Store(bcx, val, ptr);
+ RetVoid(bcx);
+ },
+ None => Ret(bcx, val)
+ }
}
"init" => {
let tp_ty = substs.tys[0];
use middle::typeck::{lookup_def_ccx};
use middle::typeck::no_params;
use middle::typeck::{require_same_types, method_map, vtable_map};
+use middle::lang_items::TypeIdLangItem;
use util::common::{block_query, indenter, loop_query};
use util::ppaux::UserString;
use util::ppaux;
});
(1u, ~[], td_ptr)
}
- "type_id" => (1u, ~[], ty::mk_u64()),
+ "type_id" => {
+ let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
+ match langid {
+ Ok(did) => (1u, ~[], ty::mk_struct(ccx.tcx, did, substs {
+ self_ty: None,
+ tps: ~[],
+ regions: ty::NonerasedRegions(opt_vec::Empty)
+ }) ),
+ Err(msg) => { tcx.sess.span_fatal(it.span, msg); }
+ }
+ },
"visit_tydesc" => {
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
Ok(t) => t,
}
// sundown FFI
-#[link_args = "-lsundown"]
+#[link(name = "sundown", kind = "static")]
extern {
fn sdhtml_renderer(callbacks: *sd_callbacks,
options_ptr: *html_renderopt,
#[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)];
}
let crate = match obj.pop(&~"crate") {
Some(json) => {
- let mut d = json::Decoder(json);
+ let mut d = json::Decoder::init(json);
Decodable::decode(&mut d)
}
None => return Err(~"malformed json"),
// FIXME #8335: yuck, Rust -> str -> JSON round trip! No way to .encode
// straight to the Rust JSON representation.
let crate_json_str = {
- let w = @mut MemWriter::new();
- crate.encode(&mut json::Encoder(w as @mut io::Writer));
- str::from_utf8(*w.inner_ref())
+ let mut w = MemWriter::new();
+ {
+ let mut encoder = json::Encoder::init(&mut w as &mut io::Writer);
+ crate.encode(&mut encoder);
+ }
+ str::from_utf8_owned(w.inner())
};
let crate_json = match json::from_str(crate_json_str) {
Ok(j) => j,
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)];
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());
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::*;
@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");
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;
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 {
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),
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;
// 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 {
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 {}
//! of any type.
use cast::transmute;
+#[cfg(stage0)]
use cmp::Eq;
use option::{Option, Some, None};
+#[cfg(stage0)]
use to_bytes::{IterBytes, Cb};
use to_str::ToStr;
use unstable::intrinsics;
use util::Void;
+#[cfg(not(stage0))]
+use unstable::intrinsics::TypeId;
///////////////////////////////////////////////////////////////////////////////
// TypeId
///////////////////////////////////////////////////////////////////////////////
/// `TypeId` represents a globally unique identifier for a type
+#[cfg(stage0)]
pub struct TypeId {
priv t: u64,
}
+#[cfg(stage0)]
impl TypeId {
/// Returns the `TypeId` of the type this generic function has been instantiated with
#[inline]
}
}
+#[cfg(stage0)]
impl Eq for TypeId {
#[inline]
fn eq(&self, &other: &TypeId) -> bool {
}
}
+#[cfg(stage0)]
impl IterBytes for TypeId {
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
self.t.iter_bytes(lsb0, f)
static TEST: &'static str = "Test";
- #[test]
- fn type_id() {
- let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
- TypeId::of::<Test>());
- let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
- TypeId::of::<Test>());
-
- assert!(a != b);
- assert!(a != c);
- assert!(b != c);
-
- assert_eq!(a, d);
- assert_eq!(b, e);
- assert_eq!(c, f);
- }
-
- #[test]
- fn type_id_hash() {
- let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>());
-
- assert_eq!(a.hash(), b.hash());
- }
-
#[test]
fn any_as_void_ptr() {
let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
// case where the maximum length will matter.
let char_len = s.char_len();
if char_len >= max {
- let nchars = ::uint::min(max, char_len);
+ let nchars = ::cmp::min(max, char_len);
self.buf.write(s.slice_chars(0, nchars).as_bytes());
return
}
f.pad_integral(local.slice_to(buf.len()), "0x", true);
}
-// FIXME(#4375) shouldn't need an inner module
macro_rules! integer(($signed:ident, $unsigned:ident) => {
- mod $signed {
- use super::*;
-
- // Signed is special because it actuall emits the negative sign,
- // nothing else should do that, however.
- impl Signed for $signed {
- fn fmt(c: &$signed, f: &mut Formatter) {
- ::$unsigned::to_str_bytes(c.abs() as $unsigned, 10, |buf| {
- f.pad_integral(buf, "", *c >= 0);
- })
- }
+ // Signed is special because it actuall emits the negative sign,
+ // nothing else should do that, however.
+ impl Signed for $signed {
+ fn fmt(c: &$signed, f: &mut Formatter) {
+ ::$unsigned::to_str_bytes(c.abs() as $unsigned, 10, |buf| {
+ f.pad_integral(buf, "", *c >= 0);
+ })
}
- int_base!($signed, $unsigned, 2, Binary, "0b")
- int_base!($signed, $unsigned, 8, Octal, "0o")
- int_base!($signed, $unsigned, 16, LowerHex, "0x")
- upper_hex!($signed, $unsigned)
-
- int_base!($unsigned, $unsigned, 2, Binary, "0b")
- int_base!($unsigned, $unsigned, 8, Octal, "0o")
- int_base!($unsigned, $unsigned, 10, Unsigned, "")
- int_base!($unsigned, $unsigned, 16, LowerHex, "0x")
- upper_hex!($unsigned, $unsigned)
}
+ int_base!($signed, $unsigned, 2, Binary, "0b")
+ int_base!($signed, $unsigned, 8, Octal, "0o")
+ int_base!($signed, $unsigned, 16, LowerHex, "0x")
+ upper_hex!($signed, $unsigned)
+
+ int_base!($unsigned, $unsigned, 2, Binary, "0b")
+ int_base!($unsigned, $unsigned, 8, Octal, "0o")
+ int_base!($unsigned, $unsigned, 10, Unsigned, "")
+ int_base!($unsigned, $unsigned, 16, LowerHex, "0x")
+ upper_hex!($unsigned, $unsigned)
})
integer!(int, uint)
pub fn new(inner: W) -> BufferedWriter<W> {
BufferedWriter::with_capacity(DEFAULT_CAPACITY, inner)
}
+
+ fn flush_buf(&mut self) {
+ if self.pos != 0 {
+ self.inner.write(self.buf.slice_to(self.pos));
+ self.pos = 0;
+ }
+ }
}
impl<W: Writer> Writer for BufferedWriter<W> {
fn write(&mut self, buf: &[u8]) {
if self.pos + buf.len() > self.buf.len() {
- self.flush();
+ self.flush_buf();
}
if buf.len() > self.buf.len() {
}
fn flush(&mut self) {
- if self.pos != 0 {
- self.inner.write(self.buf.slice_to(self.pos));
- self.pos = 0;
- }
+ self.flush_buf();
self.inner.flush();
}
}
impl<W: Writer> Decorator<W> for BufferedWriter<W> {
- fn inner(self) -> W { self.inner }
+ fn inner(mut self) -> W { self.flush_buf(); self.inner }
fn inner_ref<'a>(&'a self) -> &'a W { &self.inner }
fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { &mut self.inner }
}
impl<W: Writer> Writer for LineBufferedWriter<W> {
fn write(&mut self, buf: &[u8]) {
- match buf.iter().position(|&b| b == '\n' as u8) {
+ match buf.iter().rposition(|&b| b == '\n' as u8) {
Some(i) => {
self.inner.write(buf.slice_to(i + 1));
self.inner.flush();
writer.inner_ref().inner_ref().as_slice());
}
+ #[test]
+ fn test_buffered_writer_inner_flushes() {
+ let mut w = BufferedWriter::with_capacity(3, MemWriter::new());
+ w.write([0, 1]);
+ assert_eq!([], w.inner_ref().inner_ref().as_slice());
+ let w = w.inner();
+ assert_eq!([0, 1], w.inner_ref().as_slice());
+ }
+
// This is just here to make sure that we don't infinite loop in the
// newtype struct autoderef weirdness
#[test]
assert_eq!(*writer.inner_ref().inner_ref(), ~[]);
writer.flush();
assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1]);
- writer.write([0, '\n' as u8, 1]);
- assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1, 0, '\n' as u8]);
+ writer.write([0, '\n' as u8, 1, '\n' as u8, 2]);
+ assert_eq!(*writer.inner_ref().inner_ref(),
+ ~[0, 1, 0, '\n' as u8, 1, '\n' as u8]);
writer.flush();
- assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1, 0, '\n' as u8, 1]);
+ assert_eq!(*writer.inner_ref().inner_ref(),
+ ~[0, 1, 0, '\n' as u8, 1, '\n' as u8, 2]);
+ writer.write([3, '\n' as u8]);
+ assert_eq!(*writer.inner_ref().inner_ref(),
+ ~[0, 1, 0, '\n' as u8, 1, '\n' as u8, 2, 3, '\n' as u8]);
}
#[bench]
}
impl MemWriter {
+ /// Create a new `MemWriter`.
pub fn new() -> MemWriter {
- MemWriter { buf: vec::with_capacity(128), pos: 0 }
+ MemWriter::with_capacity(128)
+ }
+ /// Create a new `MemWriter`, allocating at least `n` bytes for
+ /// the internal buffer.
+ pub fn with_capacity(n: uint) -> MemWriter {
+ MemWriter { buf: vec::with_capacity(n), pos: 0 }
}
}
#[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",
#[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
#[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. */
//! Operations and constants for `f32`
#[allow(missing_doc)];
+use prelude::*;
+
+use cmath::c_float_utils;
use default::Default;
-use libc::c_int;
-use num::{Zero, One, strconv};
+use libc::{c_float, c_int};
use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal};
+use num::{Zero, One, strconv};
use num;
-use prelude::*;
use to_str;
+use unstable::intrinsics;
pub use cmath::c_float_targ_consts::*;
-use self::delegated::*;
-
macro_rules! delegate(
(
$(
) -> $rv:ty = $bound_name:path
),*
) => (
- // An inner module is required to get the #[inline] attribute on the
- // functions.
- mod delegated {
- use cmath::c_float_utils;
- use libc::{c_float, c_int};
- use unstable::intrinsics;
-
- $(
- #[inline]
- pub fn $name($( $arg : $arg_ty ),*) -> $rv {
- unsafe {
- $bound_name($( $arg ),*)
- }
+ $(
+ #[inline]
+ pub fn $name($( $arg : $arg_ty ),*) -> $rv {
+ unsafe {
+ $bound_name($( $arg ),*)
}
- )*
- }
+ }
+ )*
)
)
#[allow(missing_doc)];
+use prelude::*;
+
+use cmath::c_double_utils;
use default::Default;
-use libc::c_int;
-use num::{Zero, One, strconv};
+use libc::{c_double, c_int};
use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal};
+use num::{Zero, One, strconv};
use num;
-use prelude::*;
use to_str;
+use unstable::intrinsics;
pub use cmath::c_double_targ_consts::*;
pub use cmp::{min, max};
-use self::delegated::*;
-
macro_rules! delegate(
(
$(
) -> $rv:ty = $bound_name:path
),*
) => (
- // An inner module is required to get the #[inline] attribute on the
- // functions.
- mod delegated {
- use cmath::c_double_utils;
- use libc::{c_double, c_int};
- use unstable::intrinsics;
-
- $(
- #[inline]
- pub fn $name($( $arg : $arg_ty ),*) -> $rv {
- unsafe {
- $bound_name($( $arg ),*)
- }
+ $(
+ #[inline]
+ pub fn $name($( $arg : $arg_ty ),*) -> $rv {
+ unsafe {
+ $bound_name($( $arg ),*)
}
- )*
- }
+ }
+ )*
)
)
//! Operations and constants for `i16`
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
int_module!(i16, 16)
impl BitCount for i16 {
//! Operations and constants for `i32`
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
int_module!(i32, 32)
impl BitCount for i32 {
//! Operations and constants for `i64`
-use num::{BitCount, CheckedAdd, CheckedSub};
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
#[cfg(target_word_size = "64")]
use num::CheckedMul;
+use num::{BitCount, CheckedAdd, CheckedSub};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
int_module!(i64, 64)
impl BitCount for i64 {
//! Operations and constants for `i8`
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
int_module!(i8, 8)
impl BitCount for i8 {
#[allow(non_uppercase_statics)];
+use prelude::*;
+
+use default::Default;
use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
-#[cfg(target_word_size = "32")] pub static bits: uint = 32;
-#[cfg(target_word_size = "64")] pub static bits: uint = 64;
-
-int_module!(int, super::bits)
+#[cfg(target_word_size = "32")] int_module!(int, 32)
+#[cfg(target_word_size = "64")] int_module!(int, 64)
#[cfg(target_word_size = "32")]
impl BitCount for int {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME(#4375): this shouldn't have to be a nested module named 'generated'
-
#[macro_escape];
#[doc(hidden)];
-macro_rules! int_module (($T:ty, $bits:expr) => (mod generated {
-
-#[allow(non_uppercase_statics)];
-
-use default::Default;
-use num::{ToStrRadix, FromStrRadix};
-use num::{CheckedDiv, Zero, One, strconv};
-use prelude::*;
-use str;
-
-pub use cmp::{min, max};
+macro_rules! int_module (($T:ty, $bits:expr) => (
pub static bits : uint = $bits;
pub static bytes : uint = ($bits / 8);
}
}
-}))
+))
//! Operations and constants for `u16`
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
+use num::BitCount;
use num::{CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
uint_module!(u16, i16, 16)
impl CheckedAdd for u16 {
//! Operations and constants for `u32`
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
+use num::BitCount;
use num::{CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
uint_module!(u32, i32, 32)
impl CheckedAdd for u32 {
//! Operations and constants for `u64`
-use num::{CheckedAdd, CheckedSub};
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
+use num::BitCount;
#[cfg(target_word_size = "64")]
use num::CheckedMul;
+use num::{CheckedAdd, CheckedSub};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
uint_module!(u64, i64, 64)
impl CheckedAdd for u64 {
//! Operations and constants for `u8`
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
+use num::BitCount;
use num::{CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-pub use self::generated::*;
-
uint_module!(u8, i8, 8)
impl CheckedAdd for u8 {
//! Operations and constants for `uint`
-use num;
+#[allow(non_uppercase_statics)];
+
+use prelude::*;
+
+use default::Default;
+use mem;
+use num::BitCount;
use num::{CheckedAdd, CheckedSub, CheckedMul};
+use num::{CheckedDiv, Zero, One, strconv};
+use num::{ToStrRadix, FromStrRadix};
+use num;
use option::{Option, Some, None};
+use str;
use unstable::intrinsics;
-use mem;
-
-pub use self::generated::*;
uint_module!(uint, int, ::int::bits)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME(#4375): this shouldn't have to be a nested module named 'generated'
-
#[macro_escape];
#[doc(hidden)];
-macro_rules! uint_module (($T:ty, $T_SIGNED:ty, $bits:expr) => (mod generated {
-
-#[allow(non_uppercase_statics)];
-
-use default::Default;
-use num::BitCount;
-use num::{ToStrRadix, FromStrRadix};
-use num::{CheckedDiv, Zero, One, strconv};
-use prelude::*;
-use str;
-
-pub use cmp::{min, max};
+macro_rules! uint_module (($T:ty, $T_SIGNED:ty, $bits:expr) => (
pub static bits : uint = $bits;
pub static bytes : uint = ($bits / 8);
}
}
-}))
+))
use io::buffered::LineBufferedWriter;
use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map};
use str::StrSlice;
-use u32;
use vec::ImmutableVector;
#[cfg(test)] use cast::transmute;
let position = log_level_names.iter().position(|&name| name == level);
match position {
Some(position) => {
- log_level = Some(u32::min(MAX_LOG_LEVEL, (position + 1) as u32))
+ log_level = Some(::cmp::min(MAX_LOG_LEVEL, (position + 1) as u32))
},
_ => {
log_level = None;
--- /dev/null
+// 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 {}
#[allow(missing_doc)];
use clone::Clone;
-
-pub use self::inner::*;
+#[cfg(not(test))] use cmp::*;
+#[cfg(not(test))] use default::Default;
+#[cfg(not(test))] use num::Zero;
/// Method extensions to pairs where both types satisfy the `Clone` bound
pub trait CopyableTuple<T, U> {
})+
}
)+) => {
- pub mod inner {
- use clone::Clone;
- #[cfg(not(test))] use cmp::*;
- #[cfg(not(test))] use default::Default;
- #[cfg(not(test))] use num::Zero;
-
- $(
- pub trait $move_trait<$($T),+> {
- $(fn $get_fn(self) -> $T;)+
- }
+ $(
+ pub trait $move_trait<$($T),+> {
+ $(fn $get_fn(self) -> $T;)+
+ }
- impl<$($T),+> $move_trait<$($T),+> for ($($T,)+) {
- $(
- #[inline]
- fn $get_fn(self) -> $T {
- let $move_pattern = self;
- $ret
- }
- )+
- }
-
- pub trait $immutable_trait<$($T),+> {
- $(fn $get_ref_fn<'a>(&'a self) -> &'a $T;)+
- }
+ impl<$($T),+> $move_trait<$($T),+> for ($($T,)+) {
+ $(
+ #[inline]
+ fn $get_fn(self) -> $T {
+ let $move_pattern = self;
+ $ret
+ }
+ )+
+ }
- impl<$($T),+> $immutable_trait<$($T),+> for ($($T,)+) {
- $(
- #[inline]
- fn $get_ref_fn<'a>(&'a self) -> &'a $T {
- let $ref_pattern = *self;
- $ret
- }
- )+
- }
+ pub trait $immutable_trait<$($T),+> {
+ $(fn $get_ref_fn<'a>(&'a self) -> &'a $T;)+
+ }
- impl<$($T:Clone),+> Clone for ($($T,)+) {
- fn clone(&self) -> ($($T,)+) {
- ($(self.$get_ref_fn().clone(),)+)
+ impl<$($T),+> $immutable_trait<$($T),+> for ($($T,)+) {
+ $(
+ #[inline]
+ fn $get_ref_fn<'a>(&'a self) -> &'a $T {
+ let $ref_pattern = *self;
+ $ret
}
+ )+
+ }
+
+ impl<$($T:Clone),+> Clone for ($($T,)+) {
+ fn clone(&self) -> ($($T,)+) {
+ ($(self.$get_ref_fn().clone(),)+)
}
+ }
- #[cfg(not(test))]
- impl<$($T:Eq),+> Eq for ($($T,)+) {
- #[inline]
- fn eq(&self, other: &($($T,)+)) -> bool {
- $(*self.$get_ref_fn() == *other.$get_ref_fn())&&+
- }
- #[inline]
- fn ne(&self, other: &($($T,)+)) -> bool {
- $(*self.$get_ref_fn() != *other.$get_ref_fn())||+
- }
+ #[cfg(not(test))]
+ impl<$($T:Eq),+> Eq for ($($T,)+) {
+ #[inline]
+ fn eq(&self, other: &($($T,)+)) -> bool {
+ $(*self.$get_ref_fn() == *other.$get_ref_fn())&&+
+ }
+ #[inline]
+ fn ne(&self, other: &($($T,)+)) -> bool {
+ $(*self.$get_ref_fn() != *other.$get_ref_fn())||+
}
+ }
- #[cfg(not(test))]
- impl<$($T:TotalEq),+> TotalEq for ($($T,)+) {
- #[inline]
- fn equals(&self, other: &($($T,)+)) -> bool {
- $(self.$get_ref_fn().equals(other.$get_ref_fn()))&&+
- }
+ #[cfg(not(test))]
+ impl<$($T:TotalEq),+> TotalEq for ($($T,)+) {
+ #[inline]
+ fn equals(&self, other: &($($T,)+)) -> bool {
+ $(self.$get_ref_fn().equals(other.$get_ref_fn()))&&+
}
+ }
- #[cfg(not(test))]
- impl<$($T:Ord + Eq),+> Ord for ($($T,)+) {
- #[inline]
- fn lt(&self, other: &($($T,)+)) -> bool {
- lexical_ord!(lt, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
- }
- #[inline]
- fn le(&self, other: &($($T,)+)) -> bool {
- lexical_ord!(le, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
- }
- #[inline]
- fn ge(&self, other: &($($T,)+)) -> bool {
- lexical_ord!(ge, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
- }
- #[inline]
- fn gt(&self, other: &($($T,)+)) -> bool {
- lexical_ord!(gt, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
- }
+ #[cfg(not(test))]
+ impl<$($T:Ord + Eq),+> Ord for ($($T,)+) {
+ #[inline]
+ fn lt(&self, other: &($($T,)+)) -> bool {
+ lexical_ord!(lt, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
+ }
+ #[inline]
+ fn le(&self, other: &($($T,)+)) -> bool {
+ lexical_ord!(le, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
+ }
+ #[inline]
+ fn ge(&self, other: &($($T,)+)) -> bool {
+ lexical_ord!(ge, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
}
+ #[inline]
+ fn gt(&self, other: &($($T,)+)) -> bool {
+ lexical_ord!(gt, $(self.$get_ref_fn(), other.$get_ref_fn()),+)
+ }
+ }
- #[cfg(not(test))]
- impl<$($T:TotalOrd),+> TotalOrd for ($($T,)+) {
- #[inline]
- fn cmp(&self, other: &($($T,)+)) -> Ordering {
- lexical_cmp!($(self.$get_ref_fn(), other.$get_ref_fn()),+)
- }
+ #[cfg(not(test))]
+ impl<$($T:TotalOrd),+> TotalOrd for ($($T,)+) {
+ #[inline]
+ fn cmp(&self, other: &($($T,)+)) -> Ordering {
+ lexical_cmp!($(self.$get_ref_fn(), other.$get_ref_fn()),+)
}
+ }
- #[cfg(not(test))]
- impl<$($T:Default),+> Default for ($($T,)+) {
- #[inline]
- fn default() -> ($($T,)+) {
- ($({ let x: $T = Default::default(); x},)+)
- }
+ #[cfg(not(test))]
+ impl<$($T:Default),+> Default for ($($T,)+) {
+ #[inline]
+ fn default() -> ($($T,)+) {
+ ($({ let x: $T = Default::default(); x},)+)
}
+ }
- #[cfg(not(test))]
- impl<$($T:Zero),+> Zero for ($($T,)+) {
- #[inline]
- fn zero() -> ($($T,)+) {
- ($({ let x: $T = Zero::zero(); x},)+)
- }
- #[inline]
- fn is_zero(&self) -> bool {
- $(self.$get_ref_fn().is_zero())&&+
- }
+ #[cfg(not(test))]
+ impl<$($T:Zero),+> Zero for ($($T,)+) {
+ #[inline]
+ fn zero() -> ($($T,)+) {
+ ($({ let x: $T = Zero::zero(); x},)+)
}
- )+
- }
+ #[inline]
+ fn is_zero(&self) -> bool {
+ $(self.$get_ref_fn().is_zero())&&+
+ }
+ }
+ )+
}
}
// This is needed to prevent duplicate lang item definitions.
#[cfg(test)]
-pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
+pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor, TypeId};
pub type GlueFn = extern "Rust" fn(*i8);
/// Gets an identifier which is globally unique to the specified type. This
/// function will return the same value for a type regardless of whichever
/// crate it is invoked in.
+ #[cfg(stage0)]
pub fn type_id<T: 'static>() -> u64;
+ #[cfg(not(stage0))]
+ pub fn type_id<T: 'static>() -> TypeId;
+
/// Create a value initialized to zero.
///
#[cfg(target_endian = "big")] pub fn to_be32(x: i32) -> i32 { x }
#[cfg(target_endian = "little")] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")] pub fn to_be64(x: i64) -> i64 { x }
+
+
+/// `TypeId` represents a globally unique identifier for a type
+#[lang="type_id"] // This needs to be kept in lockstep with the code in trans/intrinsic.rs and
+ // middle/lang_items.rs
+#[deriving(Eq, IterBytes)]
+#[cfg(not(test))]
+pub struct TypeId {
+ priv t: u64,
+}
+
+#[cfg(not(test))]
+impl TypeId {
+ /// Returns the `TypeId` of the type this generic function has been instantiated with
+ #[cfg(not(stage0))]
+ pub fn of<T: 'static>() -> TypeId {
+ unsafe { type_id::<T>() }
+ }
+}
}
macro_rules! iterator {
- /* FIXME: #4375 Cannot attach documentation/attributes to a macro generated struct.
(struct $name:ident -> $ptr:ty, $elem:ty) => {
+ /// An iterator for iterating over a vector.
pub struct $name<'self, T> {
priv ptr: $ptr,
priv end: $ptr,
- priv lifetime: $elem // FIXME: #5922
+ priv lifetime: Option<$elem> // FIXME: #5922
}
- };*/
- (impl $name:ident -> $elem:ty) => {
+
impl<'self, T> Iterator<$elem> for $name<'self, T> {
#[inline]
fn next(&mut self) -> Option<$elem> {
(exact, Some(exact))
}
}
- }
-}
-macro_rules! double_ended_iterator {
- (impl $name:ident -> $elem:ty) => {
impl<'self, T> DoubleEndedIterator<$elem> for $name<'self, T> {
#[inline]
fn next_back(&mut self) -> Option<$elem> {
}
}
-//iterator!{struct VecIterator -> *T, &'self T}
-/// An iterator for iterating over a vector.
-pub struct VecIterator<'self, T> {
- priv ptr: *T,
- priv end: *T,
- priv lifetime: Option<&'self ()> // FIXME: #5922
-}
-iterator!{impl VecIterator -> &'self T}
-double_ended_iterator!{impl VecIterator -> &'self T}
+iterator!{struct VecIterator -> *T, &'self T}
pub type RevIterator<'self, T> = Invert<VecIterator<'self, T>>;
impl<'self, T> ExactSize<&'self T> for VecIterator<'self, T> {}
fn clone(&self) -> VecIterator<'self, T> { *self }
}
-//iterator!{struct VecMutIterator -> *mut T, &'self mut T}
-/// An iterator for mutating the elements of a vector.
-pub struct VecMutIterator<'self, T> {
- priv ptr: *mut T,
- priv end: *mut T,
- priv lifetime: Option<&'self mut ()> // FIXME: #5922
-}
-iterator!{impl VecMutIterator -> &'self mut T}
-double_ended_iterator!{impl VecMutIterator -> &'self mut T}
+iterator!{struct VecMutIterator -> *mut T, &'self mut T}
pub type MutRevIterator<'self, T> = Invert<VecMutIterator<'self, T>>;
/// An iterator that moves out of a vector.
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)];
use util::parser_testing::{string_to_expr, string_to_item};
use util::parser_testing::string_to_stmt;
- #[cfg(test)] fn to_json_str<E : Encodable<extra::json::Encoder>>(val: @E) -> ~str {
- let writer = @mut MemWriter::new();
- let mut encoder = extra::json::Encoder(writer as @mut io::Writer);
+ #[cfg(test)]
+ fn to_json_str<'a, E: Encodable<extra::json::Encoder<'a>>>(val: &E) -> ~str {
+ let mut writer = MemWriter::new();
+ let mut encoder = extra::json::Encoder::init(&mut writer as &mut io::Writer);
val.encode(&mut encoder);
- str::from_utf8(*writer.inner_ref())
+ str::from_utf8_owned(writer.inner())
}
// produce a codemap::span
+++ /dev/null
-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
LLVMRemoveReturnAttribute
LLVMTypeToString
LLVMAddColdAttribute
+LLVMCreateMemoryBufferWithMemoryRange
+LLVMCreateMemoryBufferWithMemoryRangeCopy
// 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;
}
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)
pub mod rustrt {
use std::libc;
+ #[link(name = "rustrt")]
extern {
fn rust_get_test_int() -> libc::intptr_t;
}
// except according to those terms.
use std::unstable::intrinsics;
+use std::unstable::intrinsics::TypeId;
pub struct A;
pub struct B(Option<A>);
pub type G = uint;
pub type H = &'static str;
-pub unsafe fn id_A() -> u64 { intrinsics::type_id::<A>() }
-pub unsafe fn id_B() -> u64 { intrinsics::type_id::<B>() }
-pub unsafe fn id_C() -> u64 { intrinsics::type_id::<C>() }
-pub unsafe fn id_D() -> u64 { intrinsics::type_id::<D>() }
-pub unsafe fn id_E() -> u64 { intrinsics::type_id::<E>() }
-pub unsafe fn id_F() -> u64 { intrinsics::type_id::<F>() }
-pub unsafe fn id_G() -> u64 { intrinsics::type_id::<G>() }
-pub unsafe fn id_H() -> u64 { intrinsics::type_id::<H>() }
+pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
+pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
+pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
+pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
+pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
+pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
+pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
+pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
-pub unsafe fn foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
+pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
// except according to those terms.
use std::unstable::intrinsics;
+use std::unstable::intrinsics::TypeId;
pub struct A;
pub struct B(Option<A>);
pub type G = uint;
pub type H = &'static str;
-pub unsafe fn id_A() -> u64 { intrinsics::type_id::<A>() }
-pub unsafe fn id_B() -> u64 { intrinsics::type_id::<B>() }
-pub unsafe fn id_C() -> u64 { intrinsics::type_id::<C>() }
-pub unsafe fn id_D() -> u64 { intrinsics::type_id::<D>() }
-pub unsafe fn id_E() -> u64 { intrinsics::type_id::<E>() }
-pub unsafe fn id_F() -> u64 { intrinsics::type_id::<F>() }
-pub unsafe fn id_G() -> u64 { intrinsics::type_id::<G>() }
-pub unsafe fn id_H() -> u64 { intrinsics::type_id::<H>() }
+pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
+pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
+pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
+pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
+pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
+pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
+pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
+pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
-pub unsafe fn foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
+pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
--- /dev/null
+-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)
--- /dev/null
+// 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");
+ }
+ }
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+-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
--- /dev/null
+extern mod foo;
+
+fn main() {
+ foo::rsfoo();
+}
--- /dev/null
+int foo() { return 0; }
--- /dev/null
+#[crate_type = "dylib"];
+
+#[link(name = "cfoo")]
+extern {
+ fn foo();
+}
+
+pub fn rsfoo() {
+ unsafe { foo() }
+}
--- /dev/null
+-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
--- /dev/null
+extern mod foo;
+
+fn main() {
+ foo::rsfoo();
+}
--- /dev/null
+int foo() { return 0; }
--- /dev/null
+#[crate_type = "rlib"];
+
+#[link(name = "cfoo")]
+extern {
+ fn foo();
+}
+
+pub fn rsfoo() {
+ unsafe { foo() }
+}
--- /dev/null
+-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)
--- /dev/null
+void foo();
+
+int main() {
+ foo();
+ return 0;
+}
--- /dev/null
+#[crate_type = "dylib"];
+
+#[no_mangle]
+pub extern "C" fn foo() {}
--- /dev/null
+-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)
--- /dev/null
+void foo();
+
+int main() {
+ foo();
+ return 0;
+}
--- /dev/null
+#[crate_type = "staticlib"];
+
+#[no_mangle]
+pub extern "C" fn foo() {}
--- /dev/null
+-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)
--- /dev/null
+extern mod foo;
+
+fn main() {
+ foo::rsfoo();
+}
--- /dev/null
+int foo() { return 0; }
--- /dev/null
+#[crate_type = "dylib"];
+
+#[link(name = "cfoo")]
+extern {
+ fn foo();
+}
+
+pub fn rsfoo() {
+ unsafe { foo() }
+}
--- /dev/null
+-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)
--- /dev/null
+extern mod foo;
+
+fn main() {
+ foo::rsfoo();
+}
--- /dev/null
+int foo() { return 0; }
--- /dev/null
+#[crate_type = "rlib"];
+
+#[link(name = "cfoo")]
+extern {
+ fn foo();
+}
+
+pub fn rsfoo() {
+ unsafe { foo() }
+}
--- /dev/null
+-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)
--- /dev/null
+#[crate_type = "dylib"];
+pub fn m1() {}
--- /dev/null
+#[crate_type = "dylib"];
+extern mod m1;
+
+pub fn m2() { m1::m1() }
--- /dev/null
+#[crate_type = "dylib"];
+extern mod m2;
+
+pub fn m3() { m2::m2() }
--- /dev/null
+extern mod m3;
+
+fn main() { m3::m3() }
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) both.rs
+ $(RUSTC) dylib.rs -Z prefer-dynamic
+ $(RUSTC) prog.rs
+ $(call RUN,prog)
--- /dev/null
+#[crate_type = "rlib"];
+#[crate_type = "dylib"];
+
+pub static foo: int = 4;
--- /dev/null
+#[crate_type = "dylib"];
+extern mod both;
+
+use std::cast;
+
+pub fn addr() -> uint { unsafe { cast::transmute(&both::foo) } }
--- /dev/null
+extern mod dylib;
+extern mod both;
+
+use std::cast;
+
+fn main() {
+ assert_eq!(unsafe { cast::transmute::<&int, uint>(&both::foo) },
+ dylib::addr());
+}
--- /dev/null
+-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
--- /dev/null
+#[crate_type = "dylib"];
+extern mod rlib;
+
+pub fn dylib() { rlib::rlib() }
--- /dev/null
+extern mod dylib;
+extern mod rlib;
+
+fn main() {
+ dylib::dylib();
+ rlib::rlib();
+}
--- /dev/null
+#[crate_type = "rlib"];
+pub fn rlib() {}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) bar.rs --dylib --rlib
+ $(RUSTC) foo.rs -Z prefer-dynamic
+ $(call RUN,foo)
+ rm $(TMPDIR)/*bar*
+ $(call FAILS,foo)
--- /dev/null
+pub fn bar() {}
--- /dev/null
+extern mod bar;
+
+fn main() {
+ bar::bar();
+}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) bar.rs --dylib --rlib
+ ls $(TMPDIR)/$(call RLIB_GLOB,bar)
+ $(RUSTC) foo.rs
+ rm $(TMPDIR)/*bar*
+ $(call RUN,foo)
--- /dev/null
+pub fn bar() {}
--- /dev/null
+extern mod bar;
+
+fn main() {
+ bar::bar();
+}
--- /dev/null
+-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)
--- /dev/null
+#[crate_type = "rlib"];
+pub fn m1() {}
--- /dev/null
+#[crate_type = "rlib"];
+extern mod m1;
+
+pub fn m2() { m1::m1() }
--- /dev/null
+#[crate_type = "rlib"];
+extern mod m2;
+
+pub fn m3() { m2::m2() }
--- /dev/null
+extern mod m3;
+
+fn main() { m3::m3() }
--- /dev/null
+-include ../tools.mk
+all:
+ $(RUSTC) bar.rs --dylib
+ $(RUSTC) foo.rs
+ $(call RUN,foo)
--- /dev/null
+pub fn bar() {}
--- /dev/null
+extern mod bar;
+
+fn main() {
+ bar::bar();
+}
--- /dev/null
+-include ../tools.mk
+all:
+ $(RUSTC) bar.rs --rlib
+ $(RUSTC) foo.rs
+ $(call RUN,foo)
--- /dev/null
+pub fn bar() {}
--- /dev/null
+extern mod bar;
+
+fn main() {
+ bar::bar();
+}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) lib.rs
+ $(RUSTC) main.rs
+ $(call RUN,main)
--- /dev/null
+#[crate_type = "rlib"];
+
+pub static mut statik: int = 0;
+
+struct A;
+impl Drop for A {
+ fn drop(&mut self) {
+ unsafe { statik = 1; }
+ }
+}
+
+pub fn callback(f: ||) {
+ let _a = A;
+ f();
+}
--- /dev/null
+extern mod lib;
+
+use std::task;
+
+static mut statik: int = 0;
+
+struct A;
+impl Drop for A {
+ fn drop(&mut self) {
+ unsafe { statik = 1; }
+ }
+}
+
+fn main() {
+ do task::try {
+ let _a = A;
+ lib::callback(|| fail!());
+ 1
+ };
+
+ unsafe {
+ assert!(lib::statik == 1);
+ assert!(statik == 1);
+ }
+}
--- /dev/null
+RUSTC := $(RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR)
+CC := $(CC) -L $(TMPDIR)
+
+RUN = $(TMPDIR)/$(1)
+FAILS = $(TMPDIR)/$(1) && exit 1 || exit 0
+
+RLIB_GLOB = lib$(1)*.rlib
+STATICLIB = $(TMPDIR)/lib$(1).a
+STATICLIB_GLOB = lib$(1)*.a
+
+ifeq ($(shell uname),Darwin)
+DYLIB_GLOB = lib$(1)*.dylib
+DYLIB = $(TMPDIR)/lib$(1).dylib
+else
+DYLIB_GLOB = lib$(1)*.so
+DYLIB = $(TMPDIR)/lib$(1).so
+endif
+
+%.a: %.o
+ ar crus $@ $<
+%.dylib: %.o
+ $(CC) -dynamiclib -Wl,-dylib -o $@ $<
+%.so: %.o
+ $(CC) -o $@ $< -shared
+$(TMPDIR)/lib%.o: %.c
+ $(CC) -c -o $@ $<
+
// except according to those terms.
// xfail-fast
+// xfail-pretty
// aux-build:anon-extern-mod-cross-crate-1.rs
extern mod anonexternmod;
use anonexternmod::rust_get_test_int;
+#[link(name = "rustrt")] // we have explicitly chosen to require this
+extern {}
+
pub fn main() {
unsafe {
rust_get_test_int();
use std::libc;
-#[link_name = "rustrt"]
+#[link(name = "rustrt")]
extern {
fn rust_get_test_int() -> libc::intptr_t;
}
mod rustrt {
use std::libc;
+ #[link(name = "rustrt")]
extern {
pub fn rust_get_test_int() -> libc::intptr_t;
}
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)
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)
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)
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)
one: u16, two: u16
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s;
}
one: u32, two: u32
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
}
one: u64, two: u64
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
}
one: u8, two: u8
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s;
}
// Test a function that takes/returns a u8.
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
}
// Test a function that takes/returns a u32.
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
}
// Test a call to a function that takes/returns a u64.
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
}
one: u16, two: u16
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
}
one: u32, two: u32
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
}
one: u64, two: u64
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
}
one: u8, two: u8
}
+#[link(name = "rustrt")]
extern {
pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
}
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)
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)
use std::libc;
use std::unstable::run_in_bare_thread;
+#[link(name = "rustrt")]
extern {
fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t),
data: libc::uintptr_t) -> libc::uintptr_t;
mod rustrt1 {
use std::libc;
- #[link_name = "rustrt"]
+ #[link(name = "rustrt")]
extern {
pub fn rust_get_test_int() -> libc::intptr_t;
}
mod rustrt2 {
use std::libc;
- #[link_name = "rustrt"]
+ #[link(name = "rustrt")]
extern {
pub fn rust_get_test_int() -> libc::intptr_t;
}
mod rustrt {
use std::libc;
+ #[link(name = "rustrt")]
extern {
pub fn rust_get_test_int() -> libc::intptr_t;
}
// except according to those terms.
// xfail-fast
+// xfail-pretty
// aux-build:foreign_lib.rs
// The purpose of this test is to check that we can
extern mod foreign_lib;
+#[link(name = "rustrt")] // we have explicitly chosen to require this
+extern {}
+
pub fn main() {
unsafe {
let _foo = foreign_lib::rustrt::rust_get_test_int();
--- /dev/null
+// 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.
+
+pub fn main() {
+ if true {
+ let _a = ~3;
+ }
+ if false {
+ fail!()
+ } else {
+ let _a = ~3;
+ }
+}
fn exec<T: JD>() {
let doc = json::from_str("").unwrap();
- let mut decoder = json::Decoder(doc);
+ let mut decoder = json::Decoder::init(doc);
let _v: T = Decodable::decode(&mut decoder);
fail!()
}
pub fn main() {
let json = json::from_str("[1]").unwrap();
- let mut decoder = json::Decoder(json);
+ let mut decoder = json::Decoder::init(json);
let _x: ~[int] = serialize::Decodable::decode(&mut decoder);
}
use std::libc;
-#[nolink]
+#[link(name = "rustrt")]
extern {
static mut rust_dbg_static_mut: libc::c_int;
pub fn rust_dbg_static_mut_check_four();
mod rustrt {
use super::{Floats, Quad};
- #[nolink]
+ #[link(name = "rustrt")]
extern {
pub fn rust_dbg_abi_1(q: Quad) -> Quad;
pub fn rust_dbg_abi_2(f: Floats) -> Floats;
extern mod other2(name = "typeid-intrinsic2");
use std::unstable::intrinsics;
+use std::unstable::intrinsics::TypeId;
struct A;
+struct Test;
fn main() {
unsafe {
assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
}
+
+ // sanity test of TypeId
+ let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
+ TypeId::of::<Test>());
+ let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
+ TypeId::of::<Test>());
+
+ assert!(a != b);
+ assert!(a != c);
+ assert!(b != c);
+
+ assert_eq!(a, d);
+ assert_eq!(b, e);
+ assert_eq!(c, f);
+
+ // check it has a hash
+ let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>());
+
+ assert_eq!(a.hash(), b.hash());
}